From 0668384efe29a4d92ce1e9d1108187599ac9a067 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 2 Aug 2018 21:38:40 +0200 Subject: repo: basic graft API This represents (old-style) grafted commits, a.k.a an array of overridden parents for a commit's OID. --- src/graft.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/graft.h | 29 ++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/graft.c create mode 100644 src/graft.h diff --git a/src/graft.c b/src/graft.c new file mode 100644 index 000000000..21d32fb38 --- /dev/null +++ b/src/graft.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "graft.h" + +int git__graft_register(git_graftmap *grafts, const git_oid *oid, git_array_oid_t parents) +{ + git_commit_graft *graft; + git_oid *parent_oid; + int error; + size_t i; + + assert(grafts && oid); + + graft = git__calloc(1, sizeof(*graft)); + GIT_ERROR_CHECK_ALLOC(graft); + + git_array_init_to_size(graft->parents, git_array_size(parents)); + git_array_foreach(parents, i, parent_oid) { + git_oid *id = git_array_alloc(graft->parents); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, parent_oid); + } + git_oid_cpy(&graft->oid, oid); + + if ((error = git_oidmap_set(grafts, &graft->oid, graft)) < 0) + goto cleanup; + + return 0; + +cleanup: + git_array_clear(graft->parents); + git__free(graft); + return error; +} + +int git__graft_unregister(git_graftmap *grafts, const git_oid *oid) +{ + git_commit_graft *graft; + int error; + + assert(grafts && oid); + + if ((graft = git_oidmap_get(grafts, oid)) == NULL) + return GIT_ENOTFOUND; + + if ((error = git_oidmap_delete(grafts, oid)) < 0) + return error; + + git__free(graft); + + return 0; +} + +void git__graft_clear(git_graftmap *grafts) +{ + git_commit_graft *graft; + + assert(grafts); + + git_oidmap_foreach_value(grafts, graft, { + git__free(graft->parents.ptr); + git__free(graft); + }); + + git_oidmap_clear(grafts); +} + +int git__graft_for_oid(git_commit_graft **out, git_graftmap *grafts, const git_oid *oid) +{ + assert(out && grafts && oid); + if ((*out = git_oidmap_get(grafts, oid)) == NULL) + return GIT_ENOTFOUND; + return 0; +} diff --git a/src/graft.h b/src/graft.h new file mode 100644 index 000000000..e2afb9711 --- /dev/null +++ b/src/graft.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_graft_h__ +#define INCLUDE_graft_h__ + +#include "common.h" +#include "oidarray.h" +#include "oidmap.h" + +/** graft commit */ +typedef struct { + git_oid oid; + git_array_oid_t parents; +} git_commit_graft; + +/* A special type of git_oidmap with git_commit_grafts as values */ +typedef git_oidmap git_graftmap; + +int git__graft_register(git_graftmap *grafts, const git_oid *oid, git_array_oid_t parents); +int git__graft_unregister(git_graftmap *grafts, const git_oid *oid); +void git__graft_clear(git_graftmap *grafts); + +int git__graft_for_oid(git_commit_graft **out, git_graftmap *grafts, const git_oid *oid); + +#endif -- cgit v1.2.1 From 919501a92dbafac6e6e876aa7160c3f46f8afe55 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 2 Aug 2018 21:38:42 +0200 Subject: repo: load grafts on open This wires git_repository to open the .git/info/grafts file and load its contents as git_commit_grafts objects. --- src/buffer.h | 5 ++++ src/commit.c | 1 + src/repository.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 4 +++ 4 files changed, 91 insertions(+) diff --git a/src/buffer.h b/src/buffer.h index 6b717d2e9..fc8fe1400 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -219,4 +219,9 @@ int git_buf_splice( const char *data, size_t nb_to_insert); +/* warning: this will wreck your buf contents */ +#define git_buf_foreach_line(line_start, line_end, line_num, buf) \ + while (((line_start) = git__strsep(&(buf)->ptr, "\n")) != NULL && \ + ((line_end) = (line_start) + strlen((line_start))) != NULL && ++(line_num)) + #endif diff --git a/src/commit.c b/src/commit.c index cf9902d02..e2003d218 100644 --- a/src/commit.c +++ b/src/commit.c @@ -22,6 +22,7 @@ #include "object.h" #include "array.h" #include "oidarray.h" +#include "graft.h" void git_commit__free(void *_commit) { diff --git a/src/repository.c b/src/repository.c index 5e818fb82..bcd91509d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -148,6 +148,9 @@ int git_repository__cleanup(git_repository *repo) git_cache_clear(&repo->objects); git_attr_cache_flush(repo); + git__graft_clear(repo->grafts); + git_oidmap_free(repo->grafts); + set_config(repo, NULL); set_index(repo, NULL); set_odb(repo, NULL); @@ -254,6 +257,9 @@ static git_repository *repository_alloc(void) /* set all the entries in the configmap cache to `unset` */ git_repository__configmap_lookup_cache_clear(repo); + if (git_oidmap_new(&repo->grafts) < 0) + goto on_error; + return repo; on_error: @@ -574,6 +580,78 @@ out: return error; } +static int load_grafts(git_repository *repo) +{ + git_buf graft_path = GIT_BUF_INIT; + git_buf contents = GIT_BUF_INIT; + git_buf dup_contents; + const char *line_start; + const char *line_end; + int line_num = 0; + int error, updated; + git_array_oid_t parents = GIT_ARRAY_INIT; + + if ((error = git_repository_item_path(&graft_path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0) + return error; + + if (git_buf_joinpath(&graft_path, graft_path.ptr, "grafts")) { + git_buf_dispose(&graft_path); + return error; + } + + error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&graft_path), &repo->graft_checksum, &updated); + git_buf_dispose(&graft_path); + + if (error == GIT_ENOTFOUND || !updated) + return 0; + + if (error < 0) + goto cleanup; + + if (updated) { + git__graft_clear(repo->grafts); + } + + dup_contents.ptr = contents.ptr; + git_buf_foreach_line(line_start, line_end, line_num, &dup_contents) { + git_oid graft_oid, parent_oid; + + error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ); + if (error < 0) { + git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); + error = -1; + } + line_start += GIT_OID_HEXSZ; + + if (*(line_start++) == ' ') { + while (git_oid_fromstrn(&parent_oid, line_start, GIT_OID_HEXSZ) == 0) { + git_oid *id = git_array_alloc(parents); + + git_oid_cpy(id, &parent_oid); + line_start += GIT_OID_HEXSZ; + if (line_start >= line_end) { + break; + } + line_start += 1; + } + } + + if (git__graft_register(repo->grafts, &graft_oid, parents) < 0) { + git_error_set(GIT_ERROR_REPOSITORY, "Invalid graft at line %d", line_num); + error = -1; + goto cleanup; + } + git_array_clear(parents); + line_num++; + } + +cleanup: + git_array_clear(parents); + git_buf_dispose(&contents); + + return error; +} + int git_repository_open_bare( git_repository **repo_ptr, const char *bare_path) @@ -863,6 +941,9 @@ int git_repository_open_ext( if ((error = check_extensions(config, version) < 0)) goto cleanup; + if ((error = load_grafts(repo)) < 0) + goto cleanup; + if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) repo->is_bare = 1; else { diff --git a/src/repository.h b/src/repository.h index bafdb5896..98d266d83 100644 --- a/src/repository.h +++ b/src/repository.h @@ -24,6 +24,7 @@ #include "attrcache.h" #include "submodule.h" #include "diff_driver.h" +#include "graft.h" #define DOT_GIT ".git" #define GIT_DIR DOT_GIT "/" @@ -152,6 +153,9 @@ struct git_repository { unsigned int lru_counter; + git_graftmap *grafts; + git_oid graft_checksum; + git_atomic attr_session_key; git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX]; -- cgit v1.2.1 From 3c17f22976d62e5fc2743186b4b1b567aadf104a Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 10 Oct 2019 11:32:16 +0200 Subject: repo: load shallow roots --- include/git2/repository.h | 12 ++++++++ src/repository.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 6 ++++ 3 files changed, 93 insertions(+) diff --git a/include/git2/repository.h b/include/git2/repository.h index 9ddcd3404..5a27cf08e 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "buffer.h" +#include "oidarray.h" /** * @file git2/repository.h @@ -874,6 +875,17 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo); */ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo); +/** + * Determine the shallow roots of the repository + * + * This oidarray is owned by the library. Do not free it. + * + * @param out An array of shallow oids. + * @param repo The repository + * @return 0 on success, an error otherwise. + */ +GIT_EXTERN(int) git_repository_shallow_roots(git_oidarray *out, git_repository *repo); + /** * Retrieve the configured identity to use for reflogs * diff --git a/src/repository.c b/src/repository.c index bcd91509d..da27f545b 100644 --- a/src/repository.c +++ b/src/repository.c @@ -151,6 +151,8 @@ int git_repository__cleanup(git_repository *repo) git__graft_clear(repo->grafts); git_oidmap_free(repo->grafts); + git_array_clear(repo->shallow_oids); + set_config(repo, NULL); set_index(repo, NULL); set_odb(repo, NULL); @@ -2978,6 +2980,79 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } +int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) +{ + git_buf path = GIT_BUF_INIT; + git_buf contents = GIT_BUF_INIT; + int error, updated, line_num = 1; + char *line; + char *buffer; + + assert(out && repo); + + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + return error; + + error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); + git_buf_dispose(&path); + + if (error < 0 && error != GIT_ENOTFOUND) + return error; + + /* cancel out GIT_ENOTFOUND */ + git_error_clear(); + error = 0; + + if (!updated) { + *out = repo->shallow_oids; + goto cleanup; + } + + git_array_clear(repo->shallow_oids); + + buffer = contents.ptr; + while ((line = git__strsep(&buffer, "\n")) != NULL) { + git_oid *oid = git_array_alloc(repo->shallow_oids); + + error = git_oid_fromstr(oid, line); + if (error < 0) { + git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); + git_array_clear(repo->shallow_oids); + error = -1; + goto cleanup; + } + ++line_num; + } + + if (*buffer) { + git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); + git_array_clear(repo->shallow_oids); + error = -1; + goto cleanup; + } + + *out = repo->shallow_oids; + +cleanup: + git_buf_dispose(&contents); + + return error; +} + +int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) +{ + int ret; + git_array_oid_t array = GIT_ARRAY_INIT; + + assert(out); + + ret = git_repository__shallow_roots(&array, repo); + + git_oidarray__from_array(out, &array); + + return ret; +} + int git_repository_is_shallow(git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index 98d266d83..f7c25f589 100644 --- a/src/repository.h +++ b/src/repository.h @@ -25,6 +25,7 @@ #include "submodule.h" #include "diff_driver.h" #include "graft.h" +#include "oidarray.h" #define DOT_GIT ".git" #define GIT_DIR DOT_GIT "/" @@ -156,6 +157,9 @@ struct git_repository { git_graftmap *grafts; git_oid graft_checksum; + git_oid shallow_checksum; + git_array_oid_t shallow_oids; + git_atomic attr_session_key; git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX]; @@ -259,4 +263,6 @@ extern size_t git_repository__reserved_names_posix_len; bool git_repository__reserved_names( git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs); +int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo); + #endif -- cgit v1.2.1 From a8b1d5156cf25c6b24feb084c55e8133b43d6390 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 2 Aug 2018 21:40:51 +0200 Subject: repo: graft shallow roots on open --- src/repository.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/repository.c b/src/repository.c index da27f545b..977c71002 100644 --- a/src/repository.c +++ b/src/repository.c @@ -654,6 +654,27 @@ cleanup: return error; } +static int load_shallow(git_repository *repo) +{ + int error = 0; + git_array_oid_t roots = GIT_ARRAY_INIT; + git_array_oid_t parents = GIT_ARRAY_INIT; + size_t i; + git_oid *graft_oid; + + /* Graft shallow roots */ + if ((error = git_repository__shallow_roots(&roots, repo)) < 0) { + return error; + } + + git_array_foreach(roots, i, graft_oid) { + if ((error = git__graft_register(repo->grafts, graft_oid, parents)) < 0) { + return error; + } + } + return 0; +} + int git_repository_open_bare( git_repository **repo_ptr, const char *bare_path) @@ -946,6 +967,9 @@ int git_repository_open_ext( if ((error = load_grafts(repo)) < 0) goto cleanup; + if ((error = load_shallow(repo)) < 0) + goto cleanup; + if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) repo->is_bare = 1; else { -- cgit v1.2.1 From a35cc402fa615b316ab1a02d700de3c36482ad39 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 2 Aug 2018 21:38:43 +0200 Subject: commit: apply grafts when parsing --- src/commit.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/commit.c b/src/commit.c index e2003d218..ac8fb3250 100644 --- a/src/commit.c +++ b/src/commit.c @@ -412,10 +412,6 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig buffer += tree_len; } - /* - * TODO: commit grafts! - */ - while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { git_oid *new_id = git_array_alloc(commit->parent_ids); GIT_ERROR_CHECK_ALLOC(new_id); @@ -499,7 +495,29 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) { - return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags); + git_repository *repo = git_object_owner((git_object *)commit); + git_commit_graft *graft; + int error; + + if ((error = commit_parse(commit, git_odb_object_data(odb_obj), + git_odb_object_size(odb_obj), flags)) < 0) + return error; + + /* Perform necessary grafts */ + if (git__graft_for_oid(&graft, repo->grafts, git_odb_object_id(odb_obj)) != GIT_ENOTFOUND) { + size_t idx; + git_oid *oid; + git_array_clear(commit->parent_ids); + git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); + git_array_foreach(graft->parents, idx, oid) { + git_oid *id = git_array_alloc(commit->parent_ids); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, oid); + } + } + + return 0; } int git_commit__parse(void *_commit, git_odb_object *odb_obj) -- cgit v1.2.1 From d54c00814bbba7eb39c43a8556e1720674cab3f3 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Thu, 2 Aug 2018 21:38:45 +0200 Subject: tests: graft commits --- tests/grafts/basic.c | 122 +++++++++++++++++++ tests/grafts/shallow.c | 130 +++++++++++++++++++++ tests/repo/shallow.c | 39 ------- tests/resources/grafted.git/HEAD | 1 + tests/resources/grafted.git/config | 6 + tests/resources/grafted.git/info/grafts | 3 + .../05/12adebd3782157f0d5c9b22b043f87b4aaff9e | Bin 0 -> 133 bytes .../1c/18e80a276611bb9b146590616bbc5aebdf2945 | Bin 0 -> 170 bytes .../1c/3f11eca55d76bc1bf7353ca7e4226246d353ed | Bin 0 -> 46 bytes .../2a/f02ebff1fc0142d2380c98758d81c67b365869 | Bin 0 -> 73 bytes .../2b/ecadd3f1ecad07a054392421edf9c0e1c375b2 | Bin 0 -> 74 bytes .../2f/3053cbff8a4ca2f0666de364ddb734a28a31a9 | Bin 0 -> 133 bytes .../45/342912745ba6f8893b1e126df4653a4355df1a | Bin 0 -> 50 bytes .../48/b2b333732644eafb385771a992b923fa88f135 | Bin 0 -> 49 bytes .../5d/31bf4b437e1191b6c709c665f1bd329d0ed0bf | Bin 0 -> 74 bytes .../66/cc22a015f6ca75b34c82d28f78ba663876bade | 2 + .../6c/f192eb71cd3243c9fbbe2551012c4449de3fcf | Bin 0 -> 36 bytes .../7c/9da502b2744b70522bb694cd607fb00104a233 | Bin 0 -> 76 bytes .../8a/00e91619098618be97c0d2ceabb05a2c58edd9 | 2 + .../a0/4de168dd5c43aa2af594d794d62e922f8b3b34 | Bin 0 -> 42 bytes .../b2/b4f9e5fe5dacbb2f98bd71d1dc86c7b571ddd1 | Bin 0 -> 54 bytes .../ba/54010f8d41532eb130eba420f50248881f7fc2 | Bin 0 -> 37 bytes .../d7/224d49d6d5aff6ade596ed74f4bcd4f77b29e2 | 2 + .../db/8e43f297a313c439530c977b733aaa8c10d54e | Bin 0 -> 35 bytes .../e4/14f42f4e6bc6934563a2349a8600f0ab68618e | Bin 0 -> 139 bytes .../e6/7b587a57850c69f6f9351ee10c7c8a41dacc78 | Bin 0 -> 74 bytes .../f0/7330bc2e4ed4bd0bf2301505f6c6bbad01aa2a | Bin 0 -> 77 bytes .../f5/03807ffa920e407a600cfaee96b7152259acc7 | 2 + tests/resources/grafted.git/refs/heads/bottom | 1 + tests/resources/grafted.git/refs/heads/branch | 1 + tests/resources/grafted.git/refs/heads/master | 1 + tests/resources/grafted.git/refs/heads/top | 1 + 32 files changed, 274 insertions(+), 39 deletions(-) create mode 100644 tests/grafts/basic.c create mode 100644 tests/grafts/shallow.c delete mode 100644 tests/repo/shallow.c create mode 100644 tests/resources/grafted.git/HEAD create mode 100644 tests/resources/grafted.git/config create mode 100644 tests/resources/grafted.git/info/grafts create mode 100644 tests/resources/grafted.git/objects/05/12adebd3782157f0d5c9b22b043f87b4aaff9e create mode 100644 tests/resources/grafted.git/objects/1c/18e80a276611bb9b146590616bbc5aebdf2945 create mode 100644 tests/resources/grafted.git/objects/1c/3f11eca55d76bc1bf7353ca7e4226246d353ed create mode 100644 tests/resources/grafted.git/objects/2a/f02ebff1fc0142d2380c98758d81c67b365869 create mode 100644 tests/resources/grafted.git/objects/2b/ecadd3f1ecad07a054392421edf9c0e1c375b2 create mode 100644 tests/resources/grafted.git/objects/2f/3053cbff8a4ca2f0666de364ddb734a28a31a9 create mode 100644 tests/resources/grafted.git/objects/45/342912745ba6f8893b1e126df4653a4355df1a create mode 100644 tests/resources/grafted.git/objects/48/b2b333732644eafb385771a992b923fa88f135 create mode 100644 tests/resources/grafted.git/objects/5d/31bf4b437e1191b6c709c665f1bd329d0ed0bf create mode 100644 tests/resources/grafted.git/objects/66/cc22a015f6ca75b34c82d28f78ba663876bade create mode 100644 tests/resources/grafted.git/objects/6c/f192eb71cd3243c9fbbe2551012c4449de3fcf create mode 100644 tests/resources/grafted.git/objects/7c/9da502b2744b70522bb694cd607fb00104a233 create mode 100644 tests/resources/grafted.git/objects/8a/00e91619098618be97c0d2ceabb05a2c58edd9 create mode 100644 tests/resources/grafted.git/objects/a0/4de168dd5c43aa2af594d794d62e922f8b3b34 create mode 100644 tests/resources/grafted.git/objects/b2/b4f9e5fe5dacbb2f98bd71d1dc86c7b571ddd1 create mode 100644 tests/resources/grafted.git/objects/ba/54010f8d41532eb130eba420f50248881f7fc2 create mode 100644 tests/resources/grafted.git/objects/d7/224d49d6d5aff6ade596ed74f4bcd4f77b29e2 create mode 100644 tests/resources/grafted.git/objects/db/8e43f297a313c439530c977b733aaa8c10d54e create mode 100644 tests/resources/grafted.git/objects/e4/14f42f4e6bc6934563a2349a8600f0ab68618e create mode 100644 tests/resources/grafted.git/objects/e6/7b587a57850c69f6f9351ee10c7c8a41dacc78 create mode 100644 tests/resources/grafted.git/objects/f0/7330bc2e4ed4bd0bf2301505f6c6bbad01aa2a create mode 100644 tests/resources/grafted.git/objects/f5/03807ffa920e407a600cfaee96b7152259acc7 create mode 100644 tests/resources/grafted.git/refs/heads/bottom create mode 100644 tests/resources/grafted.git/refs/heads/branch create mode 100644 tests/resources/grafted.git/refs/heads/master create mode 100644 tests/resources/grafted.git/refs/heads/top diff --git a/tests/grafts/basic.c b/tests/grafts/basic.c new file mode 100644 index 000000000..39755ee82 --- /dev/null +++ b/tests/grafts/basic.c @@ -0,0 +1,122 @@ +#include "clar_libgit2.h" + +#include "futils.h" +#include "graft.h" + +static git_repository *g_repo; + +void test_grafts_basic__initialize(void) +{ + g_repo = cl_git_sandbox_init("grafted.git"); +} + +void test_grafts_basic__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_grafts_basic__graft_add(void) +{ + git_oid oid_src, *oid1; + git_commit_graft *graft; + git_graftmap *grafts; + git_array_oid_t parents = GIT_ARRAY_INIT; + + cl_git_pass(git_oidmap_new(&grafts)); + + cl_assert(oid1 = git_array_alloc(parents)); + cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); + git_oid_cpy(oid1, &oid_src); + + git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git__graft_register(grafts, &oid_src, parents)); + git_array_clear(parents); + + cl_assert_equal_i(1, git_oidmap_size(grafts)); + cl_git_pass(git__graft_for_oid(&graft, grafts, &oid_src)); + cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); + cl_assert_equal_i(1, git_array_size(graft->parents)); + cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); + + git__graft_clear(grafts); + git_oidmap_free(grafts); +} + +void test_grafts_basic__grafted_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + git_commit *commit; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0])); + + cl_assert_equal_i(1, git_commit_parentcount(commit)); + + git_commit_free(commit); + git_revwalk_free(w); +} + +void test_grafts_basic__grafted_objects(void) +{ + git_oid oid; + git_commit *commit; + + cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(4, git_commit_parentcount(commit)); + git_commit_free(commit); +} + +void test_grafts_basic__grafted_merge_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + git_revwalk_free(w); +} diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c new file mode 100644 index 000000000..e4a0f741f --- /dev/null +++ b/tests/grafts/shallow.c @@ -0,0 +1,130 @@ +#include "clar_libgit2.h" +#include "futils.h" + +static git_repository *g_repo; +static git_oid g_shallow_oid; + +void test_grafts_shallow__initialize(void) +{ + cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); +} + +void test_grafts_shallow__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_grafts_shallow__no_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__empty_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_git_mkfile("testrepo.git/shallow", ""); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__shallow_repo(void) +{ + g_repo = cl_git_sandbox_init("shallow.git"); + cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__clears_errors(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); + cl_assert_equal_p(NULL, git_error_last()); +} + +void test_grafts_shallow__shallow_oids(void) +{ + git_oidarray oids, oids2; + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(1, oids.count); + cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + + cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); + cl_assert_equal_p(oids.ids, oids2.ids); +} + +void test_grafts_shallow__cache_clearing(void) +{ + git_oidarray oids, oids2; + git_oid tmp_oid; + + git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000"); + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(1, oids.count); + cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + + cl_git_mkfile("shallow.git/shallow", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" + "0000000000000000000000000000000000000000\n" + ); + + cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); + cl_assert_equal_i(2, oids2.count); + cl_assert_equal_oid(&g_shallow_oid, &oids2.ids[0]); + cl_assert_equal_oid(&tmp_oid, &oids2.ids[1]); + + cl_git_pass(p_unlink("shallow.git/shallow")); + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(0, oids.count); + git_oidarray_free(&oids); +} + +void test_grafts_shallow__errors_on_borked(void) +{ + git_oidarray oids; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_mkfile("shallow.git/shallow", "lolno"); + + cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); + + cl_git_mkfile("shallow.git/shallow", "lolno\n"); + + cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); +} + +void test_grafts_shallow__revwalk_behavior(void) +{ + git_revwalk *w; + git_oid oid_1, oid_2, oid_3; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_head(w)); + + cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644 + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w)); + + cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + + git_revwalk_free(w); +} + +void test_grafts_shallow__grafted_object(void) +{ + git_commit *commit; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid)); + + cl_assert_equal_i(0, git_commit_parentcount(commit)); + + git_commit_free(commit); +} diff --git a/tests/repo/shallow.c b/tests/repo/shallow.c deleted file mode 100644 index adb7a9e44..000000000 --- a/tests/repo/shallow.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" - -static git_repository *g_repo; - -void test_repo_shallow__initialize(void) -{ -} - -void test_repo_shallow__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_repo_shallow__no_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__empty_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_mkfile("testrepo.git/shallow", ""); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__shallow_repo(void) -{ - g_repo = cl_git_sandbox_init("shallow.git"); - cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__clears_errors(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); - cl_assert_equal_p(NULL, git_error_last()); -} diff --git a/tests/resources/grafted.git/HEAD b/tests/resources/grafted.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/grafted.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/grafted.git/config b/tests/resources/grafted.git/config new file mode 100644 index 000000000..e6da23157 --- /dev/null +++ b/tests/resources/grafted.git/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true + precomposeunicode = true diff --git a/tests/resources/grafted.git/info/grafts b/tests/resources/grafted.git/info/grafts new file mode 100644 index 000000000..bb9df8c0a --- /dev/null +++ b/tests/resources/grafted.git/info/grafts @@ -0,0 +1,3 @@ +f503807ffa920e407a600cfaee96b7152259acc7 2f3053cbff8a4ca2f0666de364ddb734a28a31a9 +0512adebd3782157f0d5c9b22b043f87b4aaff9e 2f3053cbff8a4ca2f0666de364ddb734a28a31a9 +66cc22a015f6ca75b34c82d28f78ba663876bade e414f42f4e6bc6934563a2349a8600f0ab68618e 8a00e91619098618be97c0d2ceabb05a2c58edd9 1c18e80a276611bb9b146590616bbc5aebdf2945 2f3053cbff8a4ca2f0666de364ddb734a28a31a9 diff --git a/tests/resources/grafted.git/objects/05/12adebd3782157f0d5c9b22b043f87b4aaff9e b/tests/resources/grafted.git/objects/05/12adebd3782157f0d5c9b22b043f87b4aaff9e new file mode 100644 index 000000000..16880d596 Binary files /dev/null and b/tests/resources/grafted.git/objects/05/12adebd3782157f0d5c9b22b043f87b4aaff9e differ diff --git a/tests/resources/grafted.git/objects/1c/18e80a276611bb9b146590616bbc5aebdf2945 b/tests/resources/grafted.git/objects/1c/18e80a276611bb9b146590616bbc5aebdf2945 new file mode 100644 index 000000000..2c057b85d Binary files /dev/null and b/tests/resources/grafted.git/objects/1c/18e80a276611bb9b146590616bbc5aebdf2945 differ diff --git a/tests/resources/grafted.git/objects/1c/3f11eca55d76bc1bf7353ca7e4226246d353ed b/tests/resources/grafted.git/objects/1c/3f11eca55d76bc1bf7353ca7e4226246d353ed new file mode 100644 index 000000000..b92a3047f Binary files /dev/null and b/tests/resources/grafted.git/objects/1c/3f11eca55d76bc1bf7353ca7e4226246d353ed differ diff --git a/tests/resources/grafted.git/objects/2a/f02ebff1fc0142d2380c98758d81c67b365869 b/tests/resources/grafted.git/objects/2a/f02ebff1fc0142d2380c98758d81c67b365869 new file mode 100644 index 000000000..ed3f874a7 Binary files /dev/null and b/tests/resources/grafted.git/objects/2a/f02ebff1fc0142d2380c98758d81c67b365869 differ diff --git a/tests/resources/grafted.git/objects/2b/ecadd3f1ecad07a054392421edf9c0e1c375b2 b/tests/resources/grafted.git/objects/2b/ecadd3f1ecad07a054392421edf9c0e1c375b2 new file mode 100644 index 000000000..724eedbb2 Binary files /dev/null and b/tests/resources/grafted.git/objects/2b/ecadd3f1ecad07a054392421edf9c0e1c375b2 differ diff --git a/tests/resources/grafted.git/objects/2f/3053cbff8a4ca2f0666de364ddb734a28a31a9 b/tests/resources/grafted.git/objects/2f/3053cbff8a4ca2f0666de364ddb734a28a31a9 new file mode 100644 index 000000000..3d124a673 Binary files /dev/null and b/tests/resources/grafted.git/objects/2f/3053cbff8a4ca2f0666de364ddb734a28a31a9 differ diff --git a/tests/resources/grafted.git/objects/45/342912745ba6f8893b1e126df4653a4355df1a b/tests/resources/grafted.git/objects/45/342912745ba6f8893b1e126df4653a4355df1a new file mode 100644 index 000000000..4a8c471bd Binary files /dev/null and b/tests/resources/grafted.git/objects/45/342912745ba6f8893b1e126df4653a4355df1a differ diff --git a/tests/resources/grafted.git/objects/48/b2b333732644eafb385771a992b923fa88f135 b/tests/resources/grafted.git/objects/48/b2b333732644eafb385771a992b923fa88f135 new file mode 100644 index 000000000..ac640636b Binary files /dev/null and b/tests/resources/grafted.git/objects/48/b2b333732644eafb385771a992b923fa88f135 differ diff --git a/tests/resources/grafted.git/objects/5d/31bf4b437e1191b6c709c665f1bd329d0ed0bf b/tests/resources/grafted.git/objects/5d/31bf4b437e1191b6c709c665f1bd329d0ed0bf new file mode 100644 index 000000000..47a05377e Binary files /dev/null and b/tests/resources/grafted.git/objects/5d/31bf4b437e1191b6c709c665f1bd329d0ed0bf differ diff --git a/tests/resources/grafted.git/objects/66/cc22a015f6ca75b34c82d28f78ba663876bade b/tests/resources/grafted.git/objects/66/cc22a015f6ca75b34c82d28f78ba663876bade new file mode 100644 index 000000000..c68b2cd4f --- /dev/null +++ b/tests/resources/grafted.git/objects/66/cc22a015f6ca75b34c82d28f78ba663876bade @@ -0,0 +1,2 @@ +xœ¥ŽM +Â0F]ç³Ê$™üDÜx=Á4N´Ð4ÒFϯÔ#¸úàñx|©–260dvmñap1° Ñaò}ö¹·N‹hL!E&}ã”BTO^dn ¤)“É$~øê–œ·l,õ=bF|ô:ŠâW{ÔÎm”y¸rYë ‡uÛN~øt/Ñ«M, \ No newline at end of file diff --git a/tests/resources/grafted.git/objects/6c/f192eb71cd3243c9fbbe2551012c4449de3fcf b/tests/resources/grafted.git/objects/6c/f192eb71cd3243c9fbbe2551012c4449de3fcf new file mode 100644 index 000000000..a437f2432 Binary files /dev/null and b/tests/resources/grafted.git/objects/6c/f192eb71cd3243c9fbbe2551012c4449de3fcf differ diff --git a/tests/resources/grafted.git/objects/7c/9da502b2744b70522bb694cd607fb00104a233 b/tests/resources/grafted.git/objects/7c/9da502b2744b70522bb694cd607fb00104a233 new file mode 100644 index 000000000..b363584fd Binary files /dev/null and b/tests/resources/grafted.git/objects/7c/9da502b2744b70522bb694cd607fb00104a233 differ diff --git a/tests/resources/grafted.git/objects/8a/00e91619098618be97c0d2ceabb05a2c58edd9 b/tests/resources/grafted.git/objects/8a/00e91619098618be97c0d2ceabb05a2c58edd9 new file mode 100644 index 000000000..887778a60 --- /dev/null +++ b/tests/resources/grafted.git/objects/8a/00e91619098618be97c0d2ceabb05a2c58edd9 @@ -0,0 +1,2 @@ +xœ¥ŽA +Â0E]ç³Êt’4Dtá <Á$™Ô@“Jï¯Ô#¸úðïý°”’ч¶Š@B§5ú@b$Ñ'ÒØ[´iƒ÷±g&V/^¥6Hõ ]J<ŠAÇbH,2Þõ–ÈŽ‚SünÏe…{ËR«ÀƒË¶T8oûvòÃשpž»°” |›­Ódàˆ„¨Â~µÉ_u‹1× RžÅ¨ßšNC \ No newline at end of file diff --git a/tests/resources/grafted.git/objects/a0/4de168dd5c43aa2af594d794d62e922f8b3b34 b/tests/resources/grafted.git/objects/a0/4de168dd5c43aa2af594d794d62e922f8b3b34 new file mode 100644 index 000000000..1ed3ed906 Binary files /dev/null and b/tests/resources/grafted.git/objects/a0/4de168dd5c43aa2af594d794d62e922f8b3b34 differ diff --git a/tests/resources/grafted.git/objects/b2/b4f9e5fe5dacbb2f98bd71d1dc86c7b571ddd1 b/tests/resources/grafted.git/objects/b2/b4f9e5fe5dacbb2f98bd71d1dc86c7b571ddd1 new file mode 100644 index 000000000..2adc85721 Binary files /dev/null and b/tests/resources/grafted.git/objects/b2/b4f9e5fe5dacbb2f98bd71d1dc86c7b571ddd1 differ diff --git a/tests/resources/grafted.git/objects/ba/54010f8d41532eb130eba420f50248881f7fc2 b/tests/resources/grafted.git/objects/ba/54010f8d41532eb130eba420f50248881f7fc2 new file mode 100644 index 000000000..52a887274 Binary files /dev/null and b/tests/resources/grafted.git/objects/ba/54010f8d41532eb130eba420f50248881f7fc2 differ diff --git a/tests/resources/grafted.git/objects/d7/224d49d6d5aff6ade596ed74f4bcd4f77b29e2 b/tests/resources/grafted.git/objects/d7/224d49d6d5aff6ade596ed74f4bcd4f77b29e2 new file mode 100644 index 000000000..5b41b6778 --- /dev/null +++ b/tests/resources/grafted.git/objects/d7/224d49d6d5aff6ade596ed74f4bcd4f77b29e2 @@ -0,0 +1,2 @@ +xœ¥A +Â0E]ç³ÊdÒDÜx=Á$™h¡I¤ž_­Gpõà/ÿ…šóÔ€,íÚ"ä%pŒ&é/Ñ1Úތԓ–˜Æ€¢ƒqÖ“zð"¥ZMÅGãÒÖ%Œ6ŒžÈcoÒà|ÏœÒ(ŠŸí^8·IJ¸r^kú±“ß|ºežæ.Ô|mÑ u„öHˆ*lW›ü%QÉõ%¦Y „ZÚ§bUoaRj \ No newline at end of file diff --git a/tests/resources/grafted.git/objects/db/8e43f297a313c439530c977b733aaa8c10d54e b/tests/resources/grafted.git/objects/db/8e43f297a313c439530c977b733aaa8c10d54e new file mode 100644 index 000000000..b9cf5947b Binary files /dev/null and b/tests/resources/grafted.git/objects/db/8e43f297a313c439530c977b733aaa8c10d54e differ diff --git a/tests/resources/grafted.git/objects/e4/14f42f4e6bc6934563a2349a8600f0ab68618e b/tests/resources/grafted.git/objects/e4/14f42f4e6bc6934563a2349a8600f0ab68618e new file mode 100644 index 000000000..1a14959c4 Binary files /dev/null and b/tests/resources/grafted.git/objects/e4/14f42f4e6bc6934563a2349a8600f0ab68618e differ diff --git a/tests/resources/grafted.git/objects/e6/7b587a57850c69f6f9351ee10c7c8a41dacc78 b/tests/resources/grafted.git/objects/e6/7b587a57850c69f6f9351ee10c7c8a41dacc78 new file mode 100644 index 000000000..213f9ac22 Binary files /dev/null and b/tests/resources/grafted.git/objects/e6/7b587a57850c69f6f9351ee10c7c8a41dacc78 differ diff --git a/tests/resources/grafted.git/objects/f0/7330bc2e4ed4bd0bf2301505f6c6bbad01aa2a b/tests/resources/grafted.git/objects/f0/7330bc2e4ed4bd0bf2301505f6c6bbad01aa2a new file mode 100644 index 000000000..f2d648892 Binary files /dev/null and b/tests/resources/grafted.git/objects/f0/7330bc2e4ed4bd0bf2301505f6c6bbad01aa2a differ diff --git a/tests/resources/grafted.git/objects/f5/03807ffa920e407a600cfaee96b7152259acc7 b/tests/resources/grafted.git/objects/f5/03807ffa920e407a600cfaee96b7152259acc7 new file mode 100644 index 000000000..21436c177 --- /dev/null +++ b/tests/resources/grafted.git/objects/f5/03807ffa920e407a600cfaee96b7152259acc7 @@ -0,0 +1,2 @@ +xœ¥A +Â0E]ç³J&˜6)ºðž ™™Ô@“@ï¯Ô#¸ú·xŸZ)¹z{ê›D/É‹Mb9PŒ&yyBF&7Òí—™Q…wµ =K­ÏPöVáº;ÈOß–ò:P+3 Õƃ³6Z+:®»üQwæ\Hy£>zAƒ \ No newline at end of file diff --git a/tests/resources/grafted.git/refs/heads/bottom b/tests/resources/grafted.git/refs/heads/bottom new file mode 100644 index 000000000..10513e698 --- /dev/null +++ b/tests/resources/grafted.git/refs/heads/bottom @@ -0,0 +1 @@ +66cc22a015f6ca75b34c82d28f78ba663876bade diff --git a/tests/resources/grafted.git/refs/heads/branch b/tests/resources/grafted.git/refs/heads/branch new file mode 100644 index 000000000..d0fe5c283 --- /dev/null +++ b/tests/resources/grafted.git/refs/heads/branch @@ -0,0 +1 @@ +8a00e91619098618be97c0d2ceabb05a2c58edd9 diff --git a/tests/resources/grafted.git/refs/heads/master b/tests/resources/grafted.git/refs/heads/master new file mode 100644 index 000000000..de809b942 --- /dev/null +++ b/tests/resources/grafted.git/refs/heads/master @@ -0,0 +1 @@ +2f3053cbff8a4ca2f0666de364ddb734a28a31a9 diff --git a/tests/resources/grafted.git/refs/heads/top b/tests/resources/grafted.git/refs/heads/top new file mode 100644 index 000000000..ce226110b --- /dev/null +++ b/tests/resources/grafted.git/refs/heads/top @@ -0,0 +1 @@ +1c18e80a276611bb9b146590616bbc5aebdf2945 -- cgit v1.2.1 From 22f201b158f4a3b7bfcf3bac2324ab3fa77bac06 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 3 Oct 2019 10:40:41 +0200 Subject: grafts: make the structure self-contained and opaque In order to increase maintainability in the future, we should try to make structures as self-contained and opaque to its users as possible. Thus it is probably not a good idea to just typedef `git_graftmap` to `git_oidmap`, as that will make it a lot harder in the future to extend the API in the future, if this need ever arises. Refactor the code to instead declare a real structure `git_grafts`, which is completely opaque to its callers. --- src/commit.c | 4 +- src/graft.c | 80 ----------------------------------- src/graft.h | 29 ------------- src/grafts.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/grafts.h | 31 ++++++++++++++ src/repository.c | 17 +++----- src/repository.h | 4 +- tests/grafts/basic.c | 17 ++++---- 8 files changed, 164 insertions(+), 133 deletions(-) delete mode 100644 src/graft.c delete mode 100644 src/graft.h create mode 100644 src/grafts.c create mode 100644 src/grafts.h diff --git a/src/commit.c b/src/commit.c index ac8fb3250..e06faafe7 100644 --- a/src/commit.c +++ b/src/commit.c @@ -22,7 +22,7 @@ #include "object.h" #include "array.h" #include "oidarray.h" -#include "graft.h" +#include "grafts.h" void git_commit__free(void *_commit) { @@ -504,7 +504,7 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned return error; /* Perform necessary grafts */ - if (git__graft_for_oid(&graft, repo->grafts, git_odb_object_id(odb_obj)) != GIT_ENOTFOUND) { + if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) != GIT_ENOTFOUND) { size_t idx; git_oid *oid; git_array_clear(commit->parent_ids); diff --git a/src/graft.c b/src/graft.c deleted file mode 100644 index 21d32fb38..000000000 --- a/src/graft.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "graft.h" - -int git__graft_register(git_graftmap *grafts, const git_oid *oid, git_array_oid_t parents) -{ - git_commit_graft *graft; - git_oid *parent_oid; - int error; - size_t i; - - assert(grafts && oid); - - graft = git__calloc(1, sizeof(*graft)); - GIT_ERROR_CHECK_ALLOC(graft); - - git_array_init_to_size(graft->parents, git_array_size(parents)); - git_array_foreach(parents, i, parent_oid) { - git_oid *id = git_array_alloc(graft->parents); - GIT_ERROR_CHECK_ALLOC(id); - - git_oid_cpy(id, parent_oid); - } - git_oid_cpy(&graft->oid, oid); - - if ((error = git_oidmap_set(grafts, &graft->oid, graft)) < 0) - goto cleanup; - - return 0; - -cleanup: - git_array_clear(graft->parents); - git__free(graft); - return error; -} - -int git__graft_unregister(git_graftmap *grafts, const git_oid *oid) -{ - git_commit_graft *graft; - int error; - - assert(grafts && oid); - - if ((graft = git_oidmap_get(grafts, oid)) == NULL) - return GIT_ENOTFOUND; - - if ((error = git_oidmap_delete(grafts, oid)) < 0) - return error; - - git__free(graft); - - return 0; -} - -void git__graft_clear(git_graftmap *grafts) -{ - git_commit_graft *graft; - - assert(grafts); - - git_oidmap_foreach_value(grafts, graft, { - git__free(graft->parents.ptr); - git__free(graft); - }); - - git_oidmap_clear(grafts); -} - -int git__graft_for_oid(git_commit_graft **out, git_graftmap *grafts, const git_oid *oid) -{ - assert(out && grafts && oid); - if ((*out = git_oidmap_get(grafts, oid)) == NULL) - return GIT_ENOTFOUND; - return 0; -} diff --git a/src/graft.h b/src/graft.h deleted file mode 100644 index e2afb9711..000000000 --- a/src/graft.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#ifndef INCLUDE_graft_h__ -#define INCLUDE_graft_h__ - -#include "common.h" -#include "oidarray.h" -#include "oidmap.h" - -/** graft commit */ -typedef struct { - git_oid oid; - git_array_oid_t parents; -} git_commit_graft; - -/* A special type of git_oidmap with git_commit_grafts as values */ -typedef git_oidmap git_graftmap; - -int git__graft_register(git_graftmap *grafts, const git_oid *oid, git_array_oid_t parents); -int git__graft_unregister(git_graftmap *grafts, const git_oid *oid); -void git__graft_clear(git_graftmap *grafts); - -int git__graft_for_oid(git_commit_graft **out, git_graftmap *grafts, const git_oid *oid); - -#endif diff --git a/src/grafts.c b/src/grafts.c new file mode 100644 index 000000000..90490d0ac --- /dev/null +++ b/src/grafts.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "grafts.h" + +struct git_grafts { + /* Map of `git_commit_graft`s */ + git_oidmap *commits; +}; + +int git_grafts_new(git_grafts **out) +{ + git_grafts *grafts; + + grafts = git__calloc(1, sizeof(*grafts)); + GIT_ERROR_CHECK_ALLOC(grafts); + + if ((git_oidmap_new(&grafts->commits)) < 0) { + git__free(grafts); + return -1; + } + + *out = grafts; + return 0; +} + +void git_grafts_free(git_grafts *grafts) +{ + if (!grafts) + return; + git_grafts_clear(grafts); + git_oidmap_free(grafts->commits); + git__free(grafts); +} + +void git_grafts_clear(git_grafts *grafts) +{ + git_commit_graft *graft; + + assert(grafts); + + git_oidmap_foreach_value(grafts->commits, graft, { + git__free(graft->parents.ptr); + git__free(graft); + }); + + git_oidmap_clear(grafts->commits); +} + +int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents) +{ + git_commit_graft *graft; + git_oid *parent_oid; + int error; + size_t i; + + assert(grafts && oid); + + graft = git__calloc(1, sizeof(*graft)); + GIT_ERROR_CHECK_ALLOC(graft); + + git_array_init_to_size(graft->parents, git_array_size(parents)); + git_array_foreach(parents, i, parent_oid) { + git_oid *id = git_array_alloc(graft->parents); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, parent_oid); + } + git_oid_cpy(&graft->oid, oid); + + if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0) + goto cleanup; + + return 0; + +cleanup: + git_array_clear(graft->parents); + git__free(graft); + return error; +} + +int git_grafts_remove(git_grafts *grafts, const git_oid *oid) +{ + git_commit_graft *graft; + int error; + + assert(grafts && oid); + + if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL) + return GIT_ENOTFOUND; + + if ((error = git_oidmap_delete(grafts->commits, oid)) < 0) + return error; + + git__free(graft); + + return 0; +} + +int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid) +{ + assert(out && grafts && oid); + if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL) + return GIT_ENOTFOUND; + return 0; +} + +size_t git_grafts_size(git_grafts *grafts) +{ + return git_oidmap_size(grafts->commits); +} diff --git a/src/grafts.h b/src/grafts.h new file mode 100644 index 000000000..76e8d3f29 --- /dev/null +++ b/src/grafts.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_graft_h__ +#define INCLUDE_graft_h__ + +#include "common.h" +#include "oidarray.h" +#include "oidmap.h" + +/** graft commit */ +typedef struct { + git_oid oid; + git_array_oid_t parents; +} git_commit_graft; + +typedef struct git_grafts git_grafts; + +int git_grafts_new(git_grafts **out); +void git_grafts_free(git_grafts *grafts); +void git_grafts_clear(git_grafts *grafts); + +int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); +int git_grafts_remove(git_grafts *grafts, const git_oid *oid); +int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); +size_t git_grafts_size(git_grafts *grafts); + +#endif diff --git a/src/repository.c b/src/repository.c index 977c71002..57b914107 100644 --- a/src/repository.c +++ b/src/repository.c @@ -147,10 +147,7 @@ int git_repository__cleanup(git_repository *repo) git_repository_submodule_cache_clear(repo); git_cache_clear(&repo->objects); git_attr_cache_flush(repo); - - git__graft_clear(repo->grafts); - git_oidmap_free(repo->grafts); - + git_grafts_free(repo->grafts); git_array_clear(repo->shallow_oids); set_config(repo, NULL); @@ -259,7 +256,7 @@ static git_repository *repository_alloc(void) /* set all the entries in the configmap cache to `unset` */ git_repository__configmap_lookup_cache_clear(repo); - if (git_oidmap_new(&repo->grafts) < 0) + if (git_grafts_new(&repo->grafts) < 0) goto on_error; return repo; @@ -610,9 +607,8 @@ static int load_grafts(git_repository *repo) if (error < 0) goto cleanup; - if (updated) { - git__graft_clear(repo->grafts); - } + if (updated) + git_grafts_clear(repo->grafts); dup_contents.ptr = contents.ptr; git_buf_foreach_line(line_start, line_end, line_num, &dup_contents) { @@ -638,7 +634,7 @@ static int load_grafts(git_repository *repo) } } - if (git__graft_register(repo->grafts, &graft_oid, parents) < 0) { + if (git_grafts_add(repo->grafts, &graft_oid, parents) < 0) { git_error_set(GIT_ERROR_REPOSITORY, "Invalid graft at line %d", line_num); error = -1; goto cleanup; @@ -668,9 +664,8 @@ static int load_shallow(git_repository *repo) } git_array_foreach(roots, i, graft_oid) { - if ((error = git__graft_register(repo->grafts, graft_oid, parents)) < 0) { + if ((error = git_grafts_add(repo->grafts, graft_oid, parents)) < 0) return error; - } } return 0; } diff --git a/src/repository.h b/src/repository.h index f7c25f589..fd7c274a8 100644 --- a/src/repository.h +++ b/src/repository.h @@ -24,7 +24,7 @@ #include "attrcache.h" #include "submodule.h" #include "diff_driver.h" -#include "graft.h" +#include "grafts.h" #include "oidarray.h" #define DOT_GIT ".git" @@ -154,7 +154,7 @@ struct git_repository { unsigned int lru_counter; - git_graftmap *grafts; + git_grafts *grafts; git_oid graft_checksum; git_oid shallow_checksum; diff --git a/tests/grafts/basic.c b/tests/grafts/basic.c index 39755ee82..f91397002 100644 --- a/tests/grafts/basic.c +++ b/tests/grafts/basic.c @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "futils.h" -#include "graft.h" +#include "grafts.h" static git_repository *g_repo; @@ -17,29 +17,28 @@ void test_grafts_basic__cleanup(void) void test_grafts_basic__graft_add(void) { + git_array_oid_t parents = GIT_ARRAY_INIT; git_oid oid_src, *oid1; git_commit_graft *graft; - git_graftmap *grafts; - git_array_oid_t parents = GIT_ARRAY_INIT; + git_grafts *grafts; - cl_git_pass(git_oidmap_new(&grafts)); + cl_git_pass(git_grafts_new(&grafts)); cl_assert(oid1 = git_array_alloc(parents)); cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); git_oid_cpy(oid1, &oid_src); git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git__graft_register(grafts, &oid_src, parents)); + cl_git_pass(git_grafts_add(grafts, &oid_src, parents)); git_array_clear(parents); - cl_assert_equal_i(1, git_oidmap_size(grafts)); - cl_git_pass(git__graft_for_oid(&graft, grafts, &oid_src)); + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &oid_src)); cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); cl_assert_equal_i(1, git_array_size(graft->parents)); cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); - git__graft_clear(grafts); - git_oidmap_free(grafts); + git_grafts_free(grafts); } void test_grafts_basic__grafted_revwalk(void) -- cgit v1.2.1 From 14a309ab384a8732f692e468ac56c0d1831fce2f Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 3 Oct 2019 11:17:10 +0200 Subject: repository: convert grafts parsing to use parse context Instead of using the newly introduced `git_buf_foreach_line`, which modifies the buffer itself, we should try to use our existing parsing infrastructure in "parse.h". Convert the grafts parsing code to make use of `git_parse_ctx`. Remove the `git_buf_foreach_line` macro, as grafts have been its sole user. --- src/buffer.h | 5 ----- src/repository.c | 68 ++++++++++++++++++++++++++------------------------------ 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/buffer.h b/src/buffer.h index fc8fe1400..6b717d2e9 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -219,9 +219,4 @@ int git_buf_splice( const char *data, size_t nb_to_insert); -/* warning: this will wreck your buf contents */ -#define git_buf_foreach_line(line_start, line_end, line_num, buf) \ - while (((line_start) = git__strsep(&(buf)->ptr, "\n")) != NULL && \ - ((line_end) = (line_start) + strlen((line_start))) != NULL && ++(line_num)) - #endif diff --git a/src/repository.c b/src/repository.c index 57b914107..4465d8e79 100644 --- a/src/repository.c +++ b/src/repository.c @@ -31,6 +31,7 @@ #include "annotated_commit.h" #include "submodule.h" #include "worktree.h" +#include "parse.h" #include "strmap.h" @@ -581,14 +582,11 @@ out: static int load_grafts(git_repository *repo) { + git_array_oid_t parents = GIT_ARRAY_INIT; git_buf graft_path = GIT_BUF_INIT; git_buf contents = GIT_BUF_INIT; - git_buf dup_contents; - const char *line_start; - const char *line_end; - int line_num = 0; + git_parse_ctx parser; int error, updated; - git_array_oid_t parents = GIT_ARRAY_INIT; if ((error = git_repository_item_path(&graft_path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0) return error; @@ -598,54 +596,52 @@ static int load_grafts(git_repository *repo) return error; } - error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&graft_path), &repo->graft_checksum, &updated); - git_buf_dispose(&graft_path); + error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&graft_path), + &repo->graft_checksum, &updated); + if (error < 0 || error == GIT_ENOTFOUND || !updated) { + if (error == GIT_ENOTFOUND) + error = 0; + goto cleanup; + } - if (error == GIT_ENOTFOUND || !updated) - return 0; + git_grafts_clear(repo->grafts); - if (error < 0) + if ((error = git_parse_ctx_init(&parser, contents.ptr, contents.size)) < 0) goto cleanup; - if (updated) - git_grafts_clear(repo->grafts); - - dup_contents.ptr = contents.ptr; - git_buf_foreach_line(line_start, line_end, line_num, &dup_contents) { - git_oid graft_oid, parent_oid; + for (; parser.remain_len; git_parse_advance_line(&parser)) { + const char *line_start = parser.line, *line_end = parser.line + parser.line_len; + git_oid graft_oid; - error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ); - if (error < 0) { - git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); - error = -1; - } + if (git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ) < 0) + goto invalid_oid; line_start += GIT_OID_HEXSZ; - if (*(line_start++) == ' ') { - while (git_oid_fromstrn(&parent_oid, line_start, GIT_OID_HEXSZ) == 0) { - git_oid *id = git_array_alloc(parents); + while (line_start < line_end && *line_start == ' ') { + git_oid *id = git_array_alloc(parents); + GIT_ERROR_CHECK_ALLOC(id); - git_oid_cpy(id, &parent_oid); - line_start += GIT_OID_HEXSZ; - if (line_start >= line_end) { - break; - } - line_start += 1; - } + if (git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ) < 0) + goto invalid_oid; + line_start += GIT_OID_HEXSZ; } - if (git_grafts_add(repo->grafts, &graft_oid, parents) < 0) { - git_error_set(GIT_ERROR_REPOSITORY, "Invalid graft at line %d", line_num); - error = -1; + if ((error = git_grafts_add(repo->grafts, &graft_oid, parents)) < 0) goto cleanup; - } + git_array_clear(parents); - line_num++; + continue; + +invalid_oid: + git_error_set(GIT_ERROR_REPOSITORY, "invalid OID at line %" PRIuZ, parser.line_num); + error = -1; + goto cleanup; } cleanup: git_array_clear(parents); git_buf_dispose(&contents); + git_buf_dispose(&graft_path); return error; } -- cgit v1.2.1 From 05e286fba318d21147347a572b05b0d1dac79610 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 12 May 2020 11:30:27 +0200 Subject: grafts: move parsing into grafts module Parsing of grafts files is currently contained in the repository code. To make grafts-related logic more self-contained, move it into "grafts.c" instead. --- include/git2/errors.h | 3 +- src/grafts.c | 46 ++++++++++++++++ src/grafts.h | 1 + src/repository.c | 37 +------------ tests/grafts/parse.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 199 insertions(+), 37 deletions(-) create mode 100644 tests/grafts/parse.c diff --git a/include/git2/errors.h b/include/git2/errors.h index 8887b3299..47a79b76c 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -108,7 +108,8 @@ typedef enum { GIT_ERROR_WORKTREE, GIT_ERROR_SHA1, GIT_ERROR_HTTP, - GIT_ERROR_INTERNAL + GIT_ERROR_INTERNAL, + GIT_ERROR_GRAFTS } git_error_t; /** diff --git a/src/grafts.c b/src/grafts.c index 90490d0ac..8ae39f4ac 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -7,6 +7,8 @@ #include "grafts.h" +#include "parse.h" + struct git_grafts { /* Map of `git_commit_graft`s */ git_oidmap *commits; @@ -51,6 +53,50 @@ void git_grafts_clear(git_grafts *grafts) git_oidmap_clear(grafts->commits); } +int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) +{ + git_array_oid_t parents = GIT_ARRAY_INIT; + git_parse_ctx parser; + int error; + + git_grafts_clear(grafts); + + if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0) + goto error; + + for (; parser.remain_len; git_parse_advance_line(&parser)) { + const char *line_start = parser.line, *line_end = parser.line + parser.line_len; + git_oid graft_oid; + + if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) { + git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); + goto error; + } + line_start += GIT_OID_HEXSZ; + + while (line_start < line_end && *line_start == ' ') { + git_oid *id = git_array_alloc(parents); + GIT_ERROR_CHECK_ALLOC(id); + + if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) { + git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); + goto error; + } + + line_start += GIT_OID_HEXSZ; + } + + if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0) + goto error; + + git_array_clear(parents); + } + +error: + git_array_clear(parents); + return error; +} + int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents) { git_commit_graft *graft; diff --git a/src/grafts.h b/src/grafts.h index 76e8d3f29..723792ded 100644 --- a/src/grafts.h +++ b/src/grafts.h @@ -23,6 +23,7 @@ int git_grafts_new(git_grafts **out); void git_grafts_free(git_grafts *grafts); void git_grafts_clear(git_grafts *grafts); +int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen); int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); diff --git a/src/repository.c b/src/repository.c index 4465d8e79..7721c3cd0 100644 --- a/src/repository.c +++ b/src/repository.c @@ -31,7 +31,6 @@ #include "annotated_commit.h" #include "submodule.h" #include "worktree.h" -#include "parse.h" #include "strmap.h" @@ -582,10 +581,8 @@ out: static int load_grafts(git_repository *repo) { - git_array_oid_t parents = GIT_ARRAY_INIT; git_buf graft_path = GIT_BUF_INIT; git_buf contents = GIT_BUF_INIT; - git_parse_ctx parser; int error, updated; if ((error = git_repository_item_path(&graft_path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0) @@ -604,42 +601,10 @@ static int load_grafts(git_repository *repo) goto cleanup; } - git_grafts_clear(repo->grafts); - - if ((error = git_parse_ctx_init(&parser, contents.ptr, contents.size)) < 0) - goto cleanup; - - for (; parser.remain_len; git_parse_advance_line(&parser)) { - const char *line_start = parser.line, *line_end = parser.line + parser.line_len; - git_oid graft_oid; - - if (git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ) < 0) - goto invalid_oid; - line_start += GIT_OID_HEXSZ; - - while (line_start < line_end && *line_start == ' ') { - git_oid *id = git_array_alloc(parents); - GIT_ERROR_CHECK_ALLOC(id); - - if (git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ) < 0) - goto invalid_oid; - line_start += GIT_OID_HEXSZ; - } - - if ((error = git_grafts_add(repo->grafts, &graft_oid, parents)) < 0) - goto cleanup; - - git_array_clear(parents); - continue; - -invalid_oid: - git_error_set(GIT_ERROR_REPOSITORY, "invalid OID at line %" PRIuZ, parser.line_num); - error = -1; + if ((error = git_grafts_parse(repo->grafts, contents.ptr, contents.size)) < 0) goto cleanup; - } cleanup: - git_array_clear(parents); git_buf_dispose(&contents); git_buf_dispose(&graft_path); diff --git a/tests/grafts/parse.c b/tests/grafts/parse.c new file mode 100644 index 000000000..de110c901 --- /dev/null +++ b/tests/grafts/parse.c @@ -0,0 +1,149 @@ +#include "clar_libgit2.h" + +#include "grafts.h" + +#define OID0 "c0368f9f9743e950e6cfe1f45a649f8a9dfcd97e" +#define OID1 "cfc50a0db87ce908fb8a8c5b8f7b4ab96eee8643" +#define OID2 "6914d97cd08b9edf5e855fca211c750fa82fd80a" +#define OID3 "516521937d0e9ce9d0d836149a0702671f326b4a" +#define OID4 "e2c29d67ef2f217650196f94c796f0532b8caad6" +#define OID5 "79bcb936596cb50353fe7be28b7444e66e4a2842" +#define OID6 "b9c54107d57c17dbcaf646c4d52f66eb9e69d23d" +#define OID7 "9f8a746e9ad7b58cc840016bc3944d5ad262acb5" +#define OID8 "392f4beef7d0d15b2bc5b1abe1a754eba0ec36da" + +#define OID_TRUNCATED "392f4beef7d0d15b2bc5b1abe1a754eba0ec36d" +#define OID_NONHEX "9f8a746e9ax7b58cc840016bc3944d5ad262acb5" + +static git_grafts *grafts; + +void test_grafts_parse__initialize(void) +{ + cl_git_pass(git_grafts_new(&grafts)); +} + +void test_grafts_parse__cleanup(void) +{ + git_grafts_free(grafts); + grafts = NULL; +} + +static void assert_parse_succeeds(git_grafts *grafts, const char *string, size_t n) +{ + cl_git_pass(git_grafts_parse(grafts, string, strlen(string))); + cl_assert_equal_i(git_grafts_size(grafts), n); +} + +static void assert_parse_fails(git_grafts *grafts, const char *string) +{ + cl_git_fail(git_grafts_parse(grafts, string, strlen(string))); +} + +static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t n, ...) +{ + git_commit_graft *commit; + git_oid oid; + va_list ap; + size_t i = 0; + + cl_git_pass(git_oid_fromstr(&oid, graft)); + cl_git_pass(git_grafts_get(&commit, grafts, &oid)); + cl_assert_equal_oid(&commit->oid, &oid); + cl_assert_equal_i(commit->parents.size, n); + + va_start(ap, n); + while (i < n) { + cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *))); + cl_assert_equal_oid(&commit->parents.ptr[i], &oid); + i++; + } + va_end(ap); +} + +void test_grafts_parse__single_oid(void) +{ + assert_parse_succeeds(grafts, OID1, 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__single_oid_with_newline(void) +{ + assert_parse_succeeds(grafts, OID1 "\n", 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__multiple_oids(void) +{ + assert_parse_succeeds(grafts, OID1 "\n" OID2 "\n" OID3, 3); + assert_graft_contains(grafts, OID1, 0); + assert_graft_contains(grafts, OID2, 0); + assert_graft_contains(grafts, OID3, 0); +} + +void test_grafts_parse__same_oid(void) +{ + assert_parse_succeeds(grafts, OID1 "\n" OID1, 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__oid_with_parent(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2, 1); + assert_graft_contains(grafts, OID1, 1, OID2); +} + +void test_grafts_parse__oid_with_parent_and_newline(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2 "\n", 1); + assert_graft_contains(grafts, OID1, 1, OID2); +} + +void test_grafts_parse__oid_with_multiple_parents(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2 " " OID3 " " OID4 " " OID5, 1); + assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); +} + +void test_grafts_parse__multiple_oids_with_multiple_parents(void) +{ + assert_parse_succeeds(grafts, + OID1 " " OID2 " " OID3 " " OID4 " " OID5 "\n" + OID6 " " OID7 " " OID8 "\n" , 2); + assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); + assert_graft_contains(grafts, OID6, 2, OID7, OID8); +} + +void test_grafts_parse__multiple_spaces_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID2); +} + +void test_grafts_parse__trailing_space_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID2 " "); +} + +void test_grafts_parse__invalid_character_inbetween_fails(void) +{ + assert_parse_fails(grafts, OID1 " x " OID2); +} + +void test_grafts_parse__truncated_oid_fails(void) +{ + assert_parse_fails(grafts, OID_TRUNCATED); +} + +void test_grafts_parse__truncated_parent_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID_TRUNCATED); +} + +void test_grafts_parse__invalid_oid_fails(void) +{ + assert_parse_fails(grafts, OID_NONHEX); +} + +void test_grafts_parse__invalid_parent_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID_NONHEX); +} -- cgit v1.2.1 From a11026ecbb3575b02638ae060b20e77227e2291c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 24 Oct 2019 13:30:24 +0200 Subject: repository: reuse grafts for shallow roots The shallow roots are in fact another user of the grafting mechanism, and in essence they do use the same file format for grafted commits. Thus, instead of hand-coding the parsing logic a second time, we can just reuse the `git_grafts` structure for shallow commits, as well. --- include/git2/repository.h | 3 +- src/grafts.c | 21 ++++++++++ src/grafts.h | 1 + src/repository.c | 103 ++++++++++++++-------------------------------- src/repository.h | 4 +- tests/grafts/shallow.c | 21 ++++++---- 6 files changed, 68 insertions(+), 85 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 5a27cf08e..59e938710 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -878,7 +878,8 @@ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo); /** * Determine the shallow roots of the repository * - * This oidarray is owned by the library. Do not free it. + * The resulting OID array needs to be free'd by calling + * `git_oidarray_free`. * * @param out An array of shallow oids. * @param repo The repository diff --git a/src/grafts.c b/src/grafts.c index 8ae39f4ac..23b012ce8 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -7,6 +7,7 @@ #include "grafts.h" +#include "oidarray.h" #include "parse.h" struct git_grafts { @@ -155,6 +156,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi return 0; } +int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts) +{ + git_array_oid_t oids = GIT_ARRAY_INIT; + const git_oid *oid; + size_t i = 0; + int error; + + assert(out && grafts); + + while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { + git_oid *cpy = git_array_alloc(oids); + GIT_ERROR_CHECK_ALLOC(cpy); + git_oid_cpy(cpy, oid); + } + + git_oidarray__from_array(out, &oids); + + return 0; +} + size_t git_grafts_size(git_grafts *grafts) { return git_oidmap_size(grafts->commits); diff --git a/src/grafts.h b/src/grafts.h index 723792ded..305b0d61a 100644 --- a/src/grafts.h +++ b/src/grafts.h @@ -27,6 +27,7 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); +int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts); size_t git_grafts_size(git_grafts *grafts); #endif diff --git a/src/repository.c b/src/repository.c index 7721c3cd0..fc14ef4d6 100644 --- a/src/repository.c +++ b/src/repository.c @@ -148,7 +148,7 @@ int git_repository__cleanup(git_repository *repo) git_cache_clear(&repo->objects); git_attr_cache_flush(repo); git_grafts_free(repo->grafts); - git_array_clear(repo->shallow_oids); + git_grafts_free(repo->shallow_grafts); set_config(repo, NULL); set_index(repo, NULL); @@ -613,22 +613,22 @@ cleanup: static int load_shallow(git_repository *repo) { - int error = 0; - git_array_oid_t roots = GIT_ARRAY_INIT; git_array_oid_t parents = GIT_ARRAY_INIT; + git_oidarray roots; + int error; size_t i; - git_oid *graft_oid; /* Graft shallow roots */ - if ((error = git_repository__shallow_roots(&roots, repo)) < 0) { - return error; - } + if ((error = git_repository_shallow_roots(&roots, repo)) < 0) + goto out; - git_array_foreach(roots, i, graft_oid) { - if ((error = git_grafts_add(repo->grafts, graft_oid, parents)) < 0) - return error; - } - return 0; + for (i = 0; i < roots.count; i++) + if ((error = git_grafts_add(repo->grafts, &roots.ids[i], parents)) < 0) + goto out; + +out: + git_oidarray_free(&roots); + return error; } int git_repository_open_bare( @@ -2960,79 +2960,38 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) +int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) { - git_buf path = GIT_BUF_INIT; - git_buf contents = GIT_BUF_INIT; - int error, updated, line_num = 1; - char *line; - char *buffer; - - assert(out && repo); - - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) - return error; - - error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); - git_buf_dispose(&path); + git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT; + int error, updated = 0; - if (error < 0 && error != GIT_ENOTFOUND) - return error; - - /* cancel out GIT_ENOTFOUND */ - git_error_clear(); - error = 0; - - if (!updated) { - *out = repo->shallow_oids; - goto cleanup; - } + assert(out && repo); - git_array_clear(repo->shallow_oids); + memset(out, 0, sizeof(*out)); - buffer = contents.ptr; - while ((line = git__strsep(&buffer, "\n")) != NULL) { - git_oid *oid = git_array_alloc(repo->shallow_oids); + if (!repo->shallow_grafts && (error = git_grafts_new(&repo->shallow_grafts)) < 0) + goto error; - error = git_oid_fromstr(oid, line); - if (error < 0) { - git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); - git_array_clear(repo->shallow_oids); - error = -1; - goto cleanup; - } - ++line_num; + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0 || + (error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), + &repo->shallow_checksum, &updated)) < 0) { + if (error == GIT_ENOTFOUND) + error = 0; + goto error; } - if (*buffer) { - git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); - git_array_clear(repo->shallow_oids); - error = -1; - goto cleanup; - } + if (updated && (error = git_grafts_parse(repo->shallow_grafts, contents.ptr, contents.size)) < 0) + goto error; - *out = repo->shallow_oids; + if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) + goto error; -cleanup: +error: + git_buf_dispose(&path); git_buf_dispose(&contents); - return error; } -int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) -{ - int ret; - git_array_oid_t array = GIT_ARRAY_INIT; - - assert(out); - - ret = git_repository__shallow_roots(&array, repo); - - git_oidarray__from_array(out, &array); - - return ret; -} - int git_repository_is_shallow(git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index fd7c274a8..14b266567 100644 --- a/src/repository.h +++ b/src/repository.h @@ -157,8 +157,8 @@ struct git_repository { git_grafts *grafts; git_oid graft_checksum; + git_grafts *shallow_grafts; git_oid shallow_checksum; - git_array_oid_t shallow_oids; git_atomic attr_session_key; @@ -263,6 +263,4 @@ extern size_t git_repository__reserved_names_posix_len; bool git_repository__reserved_names( git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs); -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo); - #endif diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c index e4a0f741f..fc74de438 100644 --- a/tests/grafts/shallow.c +++ b/tests/grafts/shallow.c @@ -42,38 +42,41 @@ void test_grafts_shallow__clears_errors(void) void test_grafts_shallow__shallow_oids(void) { - git_oidarray oids, oids2; + git_oidarray oids; g_repo = cl_git_sandbox_init("shallow.git"); cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); cl_assert_equal_i(1, oids.count); cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); - cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); - cl_assert_equal_p(oids.ids, oids2.ids); + git_oidarray_free(&oids); } void test_grafts_shallow__cache_clearing(void) { - git_oidarray oids, oids2; + git_oidarray oids; git_oid tmp_oid; - git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000"); + cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000")); g_repo = cl_git_sandbox_init("shallow.git"); cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); cl_assert_equal_i(1, oids.count); cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + git_oidarray_free(&oids); cl_git_mkfile("shallow.git/shallow", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" "0000000000000000000000000000000000000000\n" ); - cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); - cl_assert_equal_i(2, oids2.count); - cl_assert_equal_oid(&g_shallow_oid, &oids2.ids[0]); - cl_assert_equal_oid(&tmp_oid, &oids2.ids[1]); + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(2, oids.count); + cl_assert((git_oid_equal(&g_shallow_oid, &oids.ids[0]) && + git_oid_equal(&tmp_oid, &oids.ids[1])) || + (git_oid_equal(&g_shallow_oid, &oids.ids[1]) && + git_oid_equal(&tmp_oid, &oids.ids[0]))); + git_oidarray_free(&oids); cl_git_pass(p_unlink("shallow.git/shallow")); cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); -- cgit v1.2.1 From 70867f7c594ea6960c07d10fef32c932f7fa3bbb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 3 Oct 2019 13:08:24 +0200 Subject: repository: disentangle shallow and normal grafts When loading shallow grafts, we add each of the grafting commits to the grafts backed by ".git/info/grafts". Keeping track of both grafts separately, but partially storing them in a common grafts structure is likely to lead to inconsistencies. In fact, there already are inconsistencies if refreshing shallow grafts at a later point, as we only refresh the shallows, but not the normal grafts in that case. Disentangle both grafting stores and instead check both separately when parsing commits. --- src/commit.c | 3 ++- src/repository.c | 11 ++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/commit.c b/src/commit.c index e06faafe7..b498fd77e 100644 --- a/src/commit.c +++ b/src/commit.c @@ -504,7 +504,8 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned return error; /* Perform necessary grafts */ - if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) != GIT_ENOTFOUND) { + if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || + git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { size_t idx; git_oid *oid; git_array_clear(commit->parent_ids); diff --git a/src/repository.c b/src/repository.c index fc14ef4d6..cad80845d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -613,22 +613,15 @@ cleanup: static int load_shallow(git_repository *repo) { - git_array_oid_t parents = GIT_ARRAY_INIT; git_oidarray roots; int error; - size_t i; /* Graft shallow roots */ if ((error = git_repository_shallow_roots(&roots, repo)) < 0) - goto out; - - for (i = 0; i < roots.count; i++) - if ((error = git_grafts_add(repo->grafts, &roots.ids[i], parents)) < 0) - goto out; + return error; -out: git_oidarray_free(&roots); - return error; + return 0; } int git_repository_open_bare( -- cgit v1.2.1 From fd2398b2fc09e3ae292fb33f2ec2a45b6bf8e3e9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 3 Oct 2019 13:24:25 +0200 Subject: grafts: move refresh logic into grafts code The refresh logic for both "normal" and shallow grafts are currently part of the repository code and implemented twice. Unify them into the grafts code by introducing two new functions to create grafts from a file and to refresh a grafts structure. --- src/grafts.c | 55 ++++++++++++++++++++++++++++++++++++++++++ src/grafts.h | 2 ++ src/repository.c | 73 ++++++++++++-------------------------------------------- src/repository.h | 3 --- 4 files changed, 72 insertions(+), 61 deletions(-) diff --git a/src/grafts.c b/src/grafts.c index 23b012ce8..da5bd1050 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -7,12 +7,17 @@ #include "grafts.h" +#include "futils.h" #include "oidarray.h" #include "parse.h" struct git_grafts { /* Map of `git_commit_graft`s */ git_oidmap *commits; + + /* File backing the graft. NULL if it's an in-memory graft */ + char *path; + git_oid path_checksum; }; int git_grafts_new(git_grafts **out) @@ -31,10 +36,32 @@ int git_grafts_new(git_grafts **out) return 0; } +int git_grafts_from_file(git_grafts **out, const char *path) +{ + git_grafts *grafts = NULL; + int error; + + if ((error = git_grafts_new(&grafts)) < 0) + goto error; + + grafts->path = git__strdup(path); + GIT_ERROR_CHECK_ALLOC(grafts->path); + + if ((error = git_grafts_refresh(grafts)) < 0) + goto error; + + *out = grafts; +error: + if (error < 0) + git_grafts_free(grafts); + return error; +} + void git_grafts_free(git_grafts *grafts) { if (!grafts) return; + git__free(grafts->path); git_grafts_clear(grafts); git_oidmap_free(grafts->commits); git__free(grafts); @@ -54,6 +81,34 @@ void git_grafts_clear(git_grafts *grafts) git_oidmap_clear(grafts->commits); } +int git_grafts_refresh(git_grafts *grafts) +{ + git_buf contents = GIT_BUF_INIT; + int error, updated = 0; + + assert(grafts); + + if (!grafts->path) + return 0; + + error = git_futils_readbuffer_updated(&contents, grafts->path, + &grafts->path_checksum, &updated); + if (error < 0 || error == GIT_ENOTFOUND || !updated) { + if (error == GIT_ENOTFOUND) { + git_grafts_clear(grafts); + error = 0; + } + goto cleanup; + } + + if ((error = git_grafts_parse(grafts, contents.ptr, contents.size)) < 0) + goto cleanup; + +cleanup: + git_buf_dispose(&contents); + return error; +} + int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) { git_array_oid_t parents = GIT_ARRAY_INIT; diff --git a/src/grafts.h b/src/grafts.h index 305b0d61a..30062725e 100644 --- a/src/grafts.h +++ b/src/grafts.h @@ -20,9 +20,11 @@ typedef struct { typedef struct git_grafts git_grafts; int git_grafts_new(git_grafts **out); +int git_grafts_from_file(git_grafts **out, const char *path); void git_grafts_free(git_grafts *grafts); void git_grafts_clear(git_grafts *grafts); +int git_grafts_refresh(git_grafts *grafts); int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen); int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); diff --git a/src/repository.c b/src/repository.c index cad80845d..730f19c20 100644 --- a/src/repository.c +++ b/src/repository.c @@ -256,9 +256,6 @@ static git_repository *repository_alloc(void) /* set all the entries in the configmap cache to `unset` */ git_repository__configmap_lookup_cache_clear(repo); - if (git_grafts_new(&repo->grafts) < 0) - goto on_error; - return repo; on_error: @@ -581,49 +578,25 @@ out: static int load_grafts(git_repository *repo) { - git_buf graft_path = GIT_BUF_INIT; - git_buf contents = GIT_BUF_INIT; - int error, updated; - - if ((error = git_repository_item_path(&graft_path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0) - return error; - - if (git_buf_joinpath(&graft_path, graft_path.ptr, "grafts")) { - git_buf_dispose(&graft_path); - return error; - } + git_buf path = GIT_BUF_INIT; + int error; - error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&graft_path), - &repo->graft_checksum, &updated); - if (error < 0 || error == GIT_ENOTFOUND || !updated) { - if (error == GIT_ENOTFOUND) - error = 0; - goto cleanup; - } + if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + (error = git_buf_joinpath(&path, path.ptr, "grafts")) < 0 || + (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) + goto error; - if ((error = git_grafts_parse(repo->grafts, contents.ptr, contents.size)) < 0) - goto cleanup; + git_buf_clear(&path); -cleanup: - git_buf_dispose(&contents); - git_buf_dispose(&graft_path); + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0 || + (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0) + goto error; +error: + git_buf_dispose(&path); return error; } -static int load_shallow(git_repository *repo) -{ - git_oidarray roots; - int error; - - /* Graft shallow roots */ - if ((error = git_repository_shallow_roots(&roots, repo)) < 0) - return error; - - git_oidarray_free(&roots); - return 0; -} - int git_repository_open_bare( git_repository **repo_ptr, const char *bare_path) @@ -916,9 +889,6 @@ int git_repository_open_ext( if ((error = load_grafts(repo)) < 0) goto cleanup; - if ((error = load_shallow(repo)) < 0) - goto cleanup; - if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) repo->is_bare = 1; else { @@ -2956,27 +2926,14 @@ int git_repository_state_cleanup(git_repository *repo) int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) { git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT; - int error, updated = 0; + int error; assert(out && repo); memset(out, 0, sizeof(*out)); - if (!repo->shallow_grafts && (error = git_grafts_new(&repo->shallow_grafts)) < 0) - goto error; - - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0 || - (error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), - &repo->shallow_checksum, &updated)) < 0) { - if (error == GIT_ENOTFOUND) - error = 0; - goto error; - } - - if (updated && (error = git_grafts_parse(repo->shallow_grafts, contents.ptr, contents.size)) < 0) - goto error; - - if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) + if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0 || + (error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) goto error; error: diff --git a/src/repository.h b/src/repository.h index 14b266567..81f2bc101 100644 --- a/src/repository.h +++ b/src/repository.h @@ -155,10 +155,7 @@ struct git_repository { unsigned int lru_counter; git_grafts *grafts; - git_oid graft_checksum; - git_grafts *shallow_grafts; - git_oid shallow_checksum; git_atomic attr_session_key; -- cgit v1.2.1 From a4803c3c5ae2d3e038d56fcfe52215bc2364521a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 10 Oct 2019 13:40:22 +0200 Subject: grafts: fix memory leak if replacing pre-existing graft If replacing an already existing graft in the grafts map, then we need to free the previous `git_commit_graft` structure. --- src/grafts.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/grafts.c b/src/grafts.c index da5bd1050..55eb33615 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -174,6 +174,8 @@ int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t paren } git_oid_cpy(&graft->oid, oid); + if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND) + goto cleanup; if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0) goto cleanup; @@ -198,6 +200,7 @@ int git_grafts_remove(git_grafts *grafts, const git_oid *oid) if ((error = git_oidmap_delete(grafts->commits, oid)) < 0) return error; + git__free(graft->parents.ptr); git__free(graft); return 0; -- cgit v1.2.1 From 79af067665c37b6dc0b31edb35596c362b0cd9a0 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 24 Oct 2019 13:54:42 +0200 Subject: repository: do not expose grafting mechanism Currently, we expose the function `git_repository_shallow_roots` to get all grafted roots of the repository. This already paints us into a corner, though, as we certainly need to experiment with some functionality of the grafting mechanism before we can happily expose some of its functionality. Most importantly, we need to get right when to refresh grafts and when not. Thus, this commit removes the public function with no public replacement. We should first try and see what usecases people come up with to e.g. expose the `git_grafts` mechanism directly in the future or do something different altogether. Instead, we provide an internal interface to get weak pointers to the grafting structs part of the repository itself. --- include/git2/repository.h | 12 ----------- src/repository.c | 33 +++++++++++++---------------- src/repository.h | 2 ++ tests/grafts/shallow.c | 53 ++++++++++++++++++++++++----------------------- 4 files changed, 43 insertions(+), 57 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 59e938710..aa81e3843 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -875,18 +875,6 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo); */ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo); -/** - * Determine the shallow roots of the repository - * - * The resulting OID array needs to be free'd by calling - * `git_oidarray_free`. - * - * @param out An array of shallow oids. - * @param repo The repository - * @return 0 on success, an error otherwise. - */ -GIT_EXTERN(int) git_repository_shallow_roots(git_oidarray *out, git_repository *repo); - /** * Retrieve the configured identity to use for reflogs * diff --git a/src/repository.c b/src/repository.c index 730f19c20..bc5ee6ac0 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1263,6 +1263,20 @@ int git_repository_set_index(git_repository *repo, git_index *index) return 0; } +int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo) +{ + assert(out && repo && repo->shallow_grafts); + *out = repo->grafts; + return 0; +} + +int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo) +{ + assert(out && repo && repo->shallow_grafts); + *out = repo->shallow_grafts; + return 0; +} + int git_repository_set_namespace(git_repository *repo, const char *namespace) { git__free(repo->namespace); @@ -2923,25 +2937,6 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) -{ - git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT; - int error; - - assert(out && repo); - - memset(out, 0, sizeof(*out)); - - if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0 || - (error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) - goto error; - -error: - git_buf_dispose(&path); - git_buf_dispose(&contents); - return error; -} - int git_repository_is_shallow(git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index 81f2bc101..5922bf02a 100644 --- a/src/repository.h +++ b/src/repository.h @@ -211,6 +211,8 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo); int git_repository_odb__weakptr(git_odb **out, git_repository *repo); int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo); int git_repository_index__weakptr(git_index **out, git_repository *repo); +int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo); +int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo); /* * Configuration map cache diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c index fc74de438..8fe3421f2 100644 --- a/tests/grafts/shallow.c +++ b/tests/grafts/shallow.c @@ -1,5 +1,8 @@ #include "clar_libgit2.h" + #include "futils.h" +#include "grafts.h" +#include "repository.h" static git_repository *g_repo; static git_oid g_shallow_oid; @@ -42,61 +45,59 @@ void test_grafts_shallow__clears_errors(void) void test_grafts_shallow__shallow_oids(void) { - git_oidarray oids; - g_repo = cl_git_sandbox_init("shallow.git"); + git_commit_graft *graft; + git_grafts *grafts; - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(1, oids.count); - cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + g_repo = cl_git_sandbox_init("shallow.git"); - git_oidarray_free(&oids); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); } void test_grafts_shallow__cache_clearing(void) { - git_oidarray oids; + git_commit_graft *graft; + git_grafts *grafts; git_oid tmp_oid; cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000")); g_repo = cl_git_sandbox_init("shallow.git"); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(1, oids.count); - cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); - git_oidarray_free(&oids); + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); cl_git_mkfile("shallow.git/shallow", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" "0000000000000000000000000000000000000000\n" ); - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(2, oids.count); - cl_assert((git_oid_equal(&g_shallow_oid, &oids.ids[0]) && - git_oid_equal(&tmp_oid, &oids.ids[1])) || - (git_oid_equal(&g_shallow_oid, &oids.ids[1]) && - git_oid_equal(&tmp_oid, &oids.ids[0]))); - git_oidarray_free(&oids); + cl_git_pass(git_grafts_refresh(grafts)); + cl_assert_equal_i(2, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); + cl_git_pass(git_grafts_get(&graft, grafts, &tmp_oid)); cl_git_pass(p_unlink("shallow.git/shallow")); - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(0, oids.count); - git_oidarray_free(&oids); + cl_git_pass(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); } void test_grafts_shallow__errors_on_borked(void) { - git_oidarray oids; + git_grafts *grafts; g_repo = cl_git_sandbox_init("shallow.git"); cl_git_mkfile("shallow.git/shallow", "lolno"); - - cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_git_fail(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); cl_git_mkfile("shallow.git/shallow", "lolno\n"); - - cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_git_fail(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); } void test_grafts_shallow__revwalk_behavior(void) -- cgit v1.2.1 From 13bd14d930006bc01b89f9fd4d0b074c387ef92f Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 10:56:02 +0100 Subject: add feature flag for shallow clone support --- include/git2/common.h | 6 +++++- src/libgit2.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/git2/common.h b/include/git2/common.h index 2ee829025..dff64103d 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -211,7 +211,8 @@ typedef enum { GIT_OPT_SET_ODB_PACKED_PRIORITY, GIT_OPT_SET_ODB_LOOSE_PRIORITY, GIT_OPT_GET_EXTENSIONS, - GIT_OPT_SET_EXTENSIONS + GIT_OPT_SET_EXTENSIONS, + GIT_OPT_ENABLE_SHALLOW } git_libgit2_opt_t; /** @@ -448,6 +449,9 @@ typedef enum { * > { "!noop", "newext" } indicates that the caller does not want * > to support repositories with the `noop` extension but does want * > to support repositories with the `newext` extension. + * + * opts(GIT_OPT_ENABLE_SHALLOW, int enabled) + * > Enable or disable shallow clone support completely. * * @param option Option key * @param ... value to set the option diff --git a/src/libgit2.c b/src/libgit2.c index cc793b458..4eef2c618 100644 --- a/src/libgit2.c +++ b/src/libgit2.c @@ -390,6 +390,10 @@ int git_libgit2_opts(int key, ...) } break; + case GIT_OPT_ENABLE_SHALLOW: + git_cache__enabled = (va_arg(ap, int) != 0); + break; + default: git_error_set(GIT_ERROR_INVALID, "invalid option key"); error = -1; -- cgit v1.2.1 From 7a936258ddc93e012be8182a08f3c3e220bc6cbc Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 13:35:46 +0100 Subject: add test for shallow feature flag --- tests/shallow/feature_flag.c | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/shallow/feature_flag.c diff --git a/tests/shallow/feature_flag.c b/tests/shallow/feature_flag.c new file mode 100644 index 000000000..25d283a44 --- /dev/null +++ b/tests/shallow/feature_flag.c @@ -0,0 +1,11 @@ +#include "clar_libgit2.h" + +void test_shallow_feature_flag__set_feature_flag(void) +{ + cl_must_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); +} + +void test_shallow_feature_flag__unset_feature_flag(void) +{ + cl_must_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); +} -- cgit v1.2.1 From 89494f6787407269c1eaa868058e30e35145b02f Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 14:10:32 +0100 Subject: add shallow.h --- src/libgit2.c | 2 +- src/shallow.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/shallow.h diff --git a/src/libgit2.c b/src/libgit2.c index 4eef2c618..b6d2f0a80 100644 --- a/src/libgit2.c +++ b/src/libgit2.c @@ -391,7 +391,7 @@ int git_libgit2_opts(int key, ...) break; case GIT_OPT_ENABLE_SHALLOW: - git_cache__enabled = (va_arg(ap, int) != 0); + git_shallow__enabled = (va_arg(ap, int) != 0); break; default: diff --git a/src/shallow.h b/src/shallow.h new file mode 100644 index 000000000..6e2bbbb5f --- /dev/null +++ b/src/shallow.h @@ -0,0 +1,3 @@ +#include "common.h" + +extern bool git_shallow__enabled; -- cgit v1.2.1 From 562246b415edf6abe9988d44e9044a8504989868 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 15:34:35 +0100 Subject: move declaration of feature flag to graft.h/graft.c --- src/grafts.c | 2 ++ src/grafts.h | 2 ++ src/shallow.h | 3 --- 3 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 src/shallow.h diff --git a/src/grafts.c b/src/grafts.c index 55eb33615..94bbf7de2 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -11,6 +11,8 @@ #include "oidarray.h" #include "parse.h" +bool git_cache__enabled = true; + struct git_grafts { /* Map of `git_commit_graft`s */ git_oidmap *commits; diff --git a/src/grafts.h b/src/grafts.h index 30062725e..fd9ef6736 100644 --- a/src/grafts.h +++ b/src/grafts.h @@ -19,6 +19,8 @@ typedef struct { typedef struct git_grafts git_grafts; +extern bool git_shallow__enabled; + int git_grafts_new(git_grafts **out); int git_grafts_from_file(git_grafts **out, const char *path); void git_grafts_free(git_grafts *grafts); diff --git a/src/shallow.h b/src/shallow.h deleted file mode 100644 index 6e2bbbb5f..000000000 --- a/src/shallow.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "common.h" - -extern bool git_shallow__enabled; -- cgit v1.2.1 From 6bab22f4d3c659a7d4282080ac4d662066411f55 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 15:49:54 +0100 Subject: move feature flag tests to tests/grafts/shallow.c --- src/libgit2.c | 1 + tests/grafts/shallow.c | 10 ++++++++++ tests/shallow/feature_flag.c | 11 ----------- 3 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 tests/shallow/feature_flag.c diff --git a/src/libgit2.c b/src/libgit2.c index b6d2f0a80..a4f0b4007 100644 --- a/src/libgit2.c +++ b/src/libgit2.c @@ -12,6 +12,7 @@ #include "cache.h" #include "common.h" #include "filter.h" +#include "grafts.h" #include "hash.h" #include "index.h" #include "merge_driver.h" diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c index 8fe3421f2..ac1d686af 100644 --- a/tests/grafts/shallow.c +++ b/tests/grafts/shallow.c @@ -7,6 +7,16 @@ static git_repository *g_repo; static git_oid g_shallow_oid; +void test_grafts_shallow__set_feature_flag(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); +} + +void test_grafts_shallow__unset_feature_flag(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); +} + void test_grafts_shallow__initialize(void) { cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); diff --git a/tests/shallow/feature_flag.c b/tests/shallow/feature_flag.c deleted file mode 100644 index 25d283a44..000000000 --- a/tests/shallow/feature_flag.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "clar_libgit2.h" - -void test_shallow_feature_flag__set_feature_flag(void) -{ - cl_must_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); -} - -void test_shallow_feature_flag__unset_feature_flag(void) -{ - cl_must_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); -} -- cgit v1.2.1 From ad5635525131b3435a6dffab29eae439e932f2cd Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 16:27:00 +0100 Subject: use shallow feature flag in shallow clone support source code --- src/commit.c | 38 ++++++++++++++++++++++---------------- src/repository.c | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/commit.c b/src/commit.c index 2a1bafae2..ab6863481 100644 --- a/src/commit.c +++ b/src/commit.c @@ -500,29 +500,35 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) { - git_repository *repo = git_object_owner((git_object *)commit); - git_commit_graft *graft; - int error; + int error; + if ((error = commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags)) < 0) return error; - /* Perform necessary grafts */ - if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || - git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { - size_t idx; - git_oid *oid; - git_array_clear(commit->parent_ids); - git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); - git_array_foreach(graft->parents, idx, oid) { - git_oid *id = git_array_alloc(commit->parent_ids); - GIT_ERROR_CHECK_ALLOC(id); - - git_oid_cpy(id, oid); + if (GIT_OPT_ENABLE_SHALLOW) { + + git_repository *repo = git_object_owner((git_object *)commit); + git_commit_graft *graft; + + /* Perform necessary grafts */ + if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || + git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { + size_t idx; + git_oid *oid; + git_array_clear(commit->parent_ids); + git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); + git_array_foreach(graft->parents, idx, oid) { + git_oid *id = git_array_alloc(commit->parent_ids); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, oid); + } } - } + } + return 0; } diff --git a/src/repository.c b/src/repository.c index 5297a8840..f9b34445c 100644 --- a/src/repository.c +++ b/src/repository.c @@ -926,7 +926,7 @@ int git_repository_open_ext( if ((error = check_extensions(config, version)) < 0) goto cleanup; - if ((error = load_grafts(repo)) < 0) + if (GIT_OPT_ENABLE_SHALLOW && (error = load_grafts(repo)) < 0) goto cleanup; if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) -- cgit v1.2.1 From c4cd9a54b83700bd9166a78af3986df0e42e1e92 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 27 Jun 2022 16:31:22 +0100 Subject: correct naming of feature flag --- src/grafts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grafts.c b/src/grafts.c index 94bbf7de2..0ffe4677a 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -11,7 +11,7 @@ #include "oidarray.h" #include "parse.h" -bool git_cache__enabled = true; +bool git_shallow__enabled = true; struct git_grafts { /* Map of `git_commit_graft`s */ -- cgit v1.2.1 From 59189757116e2f793f0901afdfa0dea916d34444 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 28 Jun 2022 09:29:10 +0100 Subject: disable shallow clone support by default --- src/grafts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grafts.c b/src/grafts.c index 0ffe4677a..003522616 100644 --- a/src/grafts.c +++ b/src/grafts.c @@ -11,7 +11,7 @@ #include "oidarray.h" #include "parse.h" -bool git_shallow__enabled = true; +bool git_shallow__enabled = false; struct git_grafts { /* Map of `git_commit_graft`s */ -- cgit v1.2.1 From 397753f01701ed7e5148f147e3a126a0abbd33e4 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 28 Jun 2022 09:29:55 +0100 Subject: enable shallow clone support in tests when necessary --- tests/grafts/basic.c | 1 + tests/grafts/shallow.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/grafts/basic.c b/tests/grafts/basic.c index f91397002..3d3c65aeb 100644 --- a/tests/grafts/basic.c +++ b/tests/grafts/basic.c @@ -7,6 +7,7 @@ static git_repository *g_repo; void test_grafts_basic__initialize(void) { + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); g_repo = cl_git_sandbox_init("grafted.git"); } diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c index ac1d686af..339235860 100644 --- a/tests/grafts/shallow.c +++ b/tests/grafts/shallow.c @@ -19,6 +19,7 @@ void test_grafts_shallow__unset_feature_flag(void) void test_grafts_shallow__initialize(void) { + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); } -- cgit v1.2.1 From 9d1507d1d36d640669d82f80d2b0151e11dbab2f Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 28 Jun 2022 09:35:51 +0100 Subject: correct use of feature flag --- src/commit.c | 36 +++++++++++++++++------------------- src/repository.c | 3 ++- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/commit.c b/src/commit.c index ab6863481..a4899ed57 100644 --- a/src/commit.c +++ b/src/commit.c @@ -502,31 +502,29 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned { int error; - if ((error = commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags)) < 0) return error; - if (GIT_OPT_ENABLE_SHALLOW) { - - git_repository *repo = git_object_owner((git_object *)commit); - git_commit_graft *graft; - - /* Perform necessary grafts */ - if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || - git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { - size_t idx; - git_oid *oid; - git_array_clear(commit->parent_ids); - git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); - git_array_foreach(graft->parents, idx, oid) { - git_oid *id = git_array_alloc(commit->parent_ids); - GIT_ERROR_CHECK_ALLOC(id); + if (!git_shallow__enabled) + return 0; - git_oid_cpy(id, oid); - } + git_repository *repo = git_object_owner((git_object *)commit); + git_commit_graft *graft; + + /* Perform necessary grafts */ + if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || + git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { + size_t idx; + git_oid *oid; + git_array_clear(commit->parent_ids); + git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); + git_array_foreach(graft->parents, idx, oid) { + git_oid *id = git_array_alloc(commit->parent_ids); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, oid); } - } return 0; diff --git a/src/repository.c b/src/repository.c index f9b34445c..87874fece 100644 --- a/src/repository.c +++ b/src/repository.c @@ -14,6 +14,7 @@ #include "common.h" #include "commit.h" +#include "grafts.h" #include "tag.h" #include "blob.h" #include "futils.h" @@ -926,7 +927,7 @@ int git_repository_open_ext( if ((error = check_extensions(config, version)) < 0) goto cleanup; - if (GIT_OPT_ENABLE_SHALLOW && (error = load_grafts(repo)) < 0) + if (git_shallow__enabled && (error = load_grafts(repo)) < 0) goto cleanup; if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) -- cgit v1.2.1 From 06eacb91679f4d7c828c64c71081500219926f22 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 28 Jun 2022 11:23:59 +0100 Subject: fix graft assertion --- src/repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repository.c b/src/repository.c index 87874fece..ab5753795 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1315,7 +1315,7 @@ int git_repository_set_index(git_repository *repo, git_index *index) int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo) { - assert(out && repo && repo->shallow_grafts); + assert(out && repo && repo->grafts); *out = repo->grafts; return 0; } -- cgit v1.2.1 From 70a332a51b6364507d19bd1821b22fabbd1f2e08 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 28 Jun 2022 11:57:50 +0100 Subject: disable shallow clone feature flag in test cleanup --- tests/grafts/basic.c | 1 + tests/grafts/shallow.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/grafts/basic.c b/tests/grafts/basic.c index 3d3c65aeb..4be4a12bf 100644 --- a/tests/grafts/basic.c +++ b/tests/grafts/basic.c @@ -13,6 +13,7 @@ void test_grafts_basic__initialize(void) void test_grafts_basic__cleanup(void) { + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); cl_git_sandbox_cleanup(); } diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c index 339235860..a75b5a051 100644 --- a/tests/grafts/shallow.c +++ b/tests/grafts/shallow.c @@ -25,6 +25,7 @@ void test_grafts_shallow__initialize(void) void test_grafts_shallow__cleanup(void) { + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); cl_git_sandbox_cleanup(); } -- cgit v1.2.1 From afa79ca05862c24baa0360324ab7b63c0df90689 Mon Sep 17 00:00:00 2001 From: yuangli Date: Mon, 4 Jul 2022 17:08:04 +0100 Subject: Merge branch 'pr/tiennou/4747' into transportPR --- include/git2/remote.h | 7 ++- include/git2/repository.h | 11 ++++ include/git2/sys/transport.h | 17 +++++- src/array.h | 4 +- src/fetch.c | 22 ++++++- src/object.c | 21 ++++++- src/object.h | 6 ++ src/remote.h | 1 + src/repository.c | 89 ++++++++++++++++++++++++++++ src/repository.h | 3 + src/transports/local.c | 6 +- src/transports/smart.c | 28 +++++++++ src/transports/smart.h | 21 +++++-- src/transports/smart_pkt.c | 90 ++++++++++++++++++++++++++--- src/transports/smart_protocol.c | 63 ++++++++++++++++++-- tests/clone/shallow.c | 55 ++++++++++++++++++ tests/repo/grafts.c | 119 ++++++++++++++++++++++++++++++++++++++ tests/repo/shallow.c | 125 ++++++++++++++++++++++++++++++++++++++++ 18 files changed, 659 insertions(+), 29 deletions(-) create mode 100644 tests/clone/shallow.c create mode 100644 tests/repo/grafts.c create mode 100644 tests/repo/shallow.c diff --git a/include/git2/remote.h b/include/git2/remote.h index 4d57eaaf7..e577f8a7b 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -738,11 +738,16 @@ typedef struct { * Extra headers for this fetch operation */ git_strarray custom_headers; + + /** + * Depth of the fetch to perform + */ + int depth; } git_fetch_options; #define GIT_FETCH_OPTIONS_VERSION 1 #define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \ - GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT } + GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, { NULL }, -1 } /** * Initialize git_fetch_options structure diff --git a/include/git2/repository.h b/include/git2/repository.h index ec8adfb29..bbf3ae4cd 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -920,6 +920,17 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo); */ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo); +/** + * Determine the shallow roots of the repository + * + * This oidarray is owned by the library. Do not free it. + * + * @param out An array of shallow oids. + * @param repo The repository + * @return 0 on success, an error otherwise. + */ +GIT_EXTERN(int) git_repository_shallow_roots(git_oidarray *out, git_repository *repo); + /** * Retrieve the configured identity to use for reflogs * diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index fee34544f..ea8bcb64b 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -33,6 +33,15 @@ typedef enum { GIT_TRANSPORTFLAGS_NONE = 0, } git_transport_flags_t; +typedef struct git_shallowarray git_shallowarray; + +typedef struct { + const git_remote_head * const *refs; + size_t count; + git_shallowarray *shallow_roots; + int depth; +} git_fetch_negotiation; + struct git_transport { unsigned int version; /**< The struct version */ @@ -87,8 +96,7 @@ struct git_transport { int GIT_CALLBACK(negotiate_fetch)( git_transport *transport, git_repository *repo, - const git_remote_head * const *refs, - size_t count); + const git_fetch_negotiation *fetch_data); /** * Start downloading the packfile from the remote repository. @@ -435,6 +443,11 @@ GIT_EXTERN(int) git_smart_subtransport_ssh( git_transport *owner, void *param); +GIT_EXTERN(size_t) git_shallowarray_count(git_shallowarray *array); +GIT_EXTERN(const git_oid *) git_shallowarray_get(git_shallowarray *array, size_t idx); +GIT_EXTERN(int) git_shallowarray_add(git_shallowarray *array, git_oid *oid); +GIT_EXTERN(int) git_shallowarray_remove(git_shallowarray *array, git_oid *oid); + /** @} */ GIT_END_DECL #endif diff --git a/src/array.h b/src/array.h index e97688b36..3d6c9113c 100644 --- a/src/array.h +++ b/src/array.h @@ -85,12 +85,14 @@ on_oom: #define git_array_foreach(a, i, element) \ for ((i) = 0; (i) < (a).size && ((element) = &(a).ptr[(i)]); (i)++) +typedef int (*git_array_compare_cb)(const void *, const void *); + GIT_INLINE(int) git_array__search( size_t *out, void *array_ptr, size_t item_size, size_t array_len, - int (*compare)(const void *, const void *), + git_array_compare_cb compare, const void *key) { size_t lim; diff --git a/src/fetch.c b/src/fetch.c index dedbb54fa..e08671db3 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -18,6 +18,7 @@ #include "netops.h" #include "repository.h" #include "refs.h" +#include "transports/smart.h" static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec, git_remote_autotag_option_t tagopt) { @@ -128,10 +129,18 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) * Now we have everything set up so we can start tell the * server what we want and what we have. */ + remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; + remote->nego.count = remote->refs.length; + remote->nego.depth = opts->depth; + remote->nego.shallow_roots = git__malloc(sizeof(git_shallowarray)); + + git_array_init(remote->nego.shallow_roots->array); + + git_repository__shallow_roots(&remote->nego.shallow_roots->array, remote->repo); + return t->negotiate_fetch(t, remote->repo, - (const git_remote_head * const *)remote->refs.contents, - remote->refs.length); + &remote->nego); } int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks) @@ -139,6 +148,7 @@ int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *call git_transport *t = remote->transport; git_indexer_progress_cb progress = NULL; void *payload = NULL; + int error; if (!remote->need_pack) return 0; @@ -148,7 +158,13 @@ int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *call payload = callbacks->payload; } - return t->download_pack(t, remote->repo, &remote->stats, progress, payload); + if ((error = t->download_pack(t, remote->repo, &remote->stats, progress, payload)) < 0) + return error; + + if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) < 0) + return error; + + return 0; } int git_fetch_options_init(git_fetch_options *opts, unsigned int version) diff --git a/src/object.c b/src/object.c index 42e1e46bc..b58f01a34 100644 --- a/src/object.c +++ b/src/object.c @@ -104,15 +104,13 @@ int git_object__from_raw( return 0; } -int git_object__from_odb_object( +int git_object__init_from_odb_object( git_object **object_out, git_repository *repo, git_odb_object *odb_obj, git_object_t type) { - int error; size_t object_size; - git_object_def *def; git_object *object = NULL; GIT_ASSERT_ARG(object_out); @@ -139,6 +137,23 @@ int git_object__from_odb_object( object->cached.size = odb_obj->cached.size; object->repo = repo; + *object_out = object; + return 0; +} + +int git_object__from_odb_object( + git_object **object_out, + git_repository *repo, + git_odb_object *odb_obj, + git_object_t type) +{ + int error; + git_object_def *def; + git_object *object = NULL; + + if ((error = git_object__init_from_odb_object(&object, repo, odb_obj, type)) < 0) + return error; + /* Parse raw object data */ def = &git_objects_table[odb_obj->cached.type]; GIT_ASSERT(def->free && def->parse); diff --git a/src/object.h b/src/object.h index 4b6793612..71a966a92 100644 --- a/src/object.h +++ b/src/object.h @@ -35,6 +35,12 @@ int git_object__from_raw( size_t size, git_object_t type); +int git_object__init_from_odb_object( + git_object **object_out, + git_repository *repo, + git_odb_object *odb_obj, + git_object_t type); + int git_object__from_odb_object( git_object **object_out, git_repository *repo, diff --git a/src/remote.h b/src/remote.h index ce92db76a..8297af197 100644 --- a/src/remote.h +++ b/src/remote.h @@ -35,6 +35,7 @@ struct git_remote { git_remote_autotag_option_t download_tags; int prune_refs; int passed_refspecs; + git_fetch_negotiation nego; }; typedef struct git_remote_connection_opts { diff --git a/src/repository.c b/src/repository.c index ab5753795..537622273 100644 --- a/src/repository.c +++ b/src/repository.c @@ -3192,6 +3192,95 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } +int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) +{ + git_buf path = GIT_BUF_INIT; + git_buf contents = GIT_BUF_INIT; + int error, updated, line_num = 1; + char *line; + char *buffer; + + assert(out && repo); + + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + return error; + + error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); + git_buf_dispose(&path); + + if (error < 0 && error != GIT_ENOTFOUND) + return error; + + /* cancel out GIT_ENOTFOUND */ + git_error_clear(); + error = 0; + + if (!updated) { + *out = repo->shallow_oids; + goto cleanup; + } + + git_array_clear(repo->shallow_oids); + + buffer = contents.ptr; + while ((line = git__strsep(&buffer, "\n")) != NULL) { + git_oid *oid = git_array_alloc(repo->shallow_oids); + + error = git_oid_fromstr(oid, line); + if (error < 0) { + git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); + git_array_clear(repo->shallow_oids); + error = -1; + goto cleanup; + } + ++line_num; + } + + if (*buffer) { + git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); + git_array_clear(repo->shallow_oids); + error = -1; + goto cleanup; + } + + *out = repo->shallow_oids; + +cleanup: + git_buf_dispose(&contents); + + return error; +} + +int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) +{ + git_filebuf file = GIT_FILEBUF_INIT; + git_buf path = GIT_BUF_INIT; + int error = 0; + size_t idx; + git_oid *oid; + + assert(repo); + + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + return error; + + if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) + return error; + + git_array_foreach(roots, idx, oid) { + git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); + git_filebuf_write(&file, "\n", 1); + } + + git_filebuf_commit(&file); + + /* WIP: reload shallow */ + if (load_shallow(repo) < 0) + return -1; + + return 0; +} + int git_repository_is_shallow(git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/src/repository.h b/src/repository.h index 8da65652d..4b6004bea 100644 --- a/src/repository.h +++ b/src/repository.h @@ -242,6 +242,9 @@ extern size_t git_repository__reserved_names_posix_len; bool git_repository__reserved_names( git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs); +int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo); +int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots); + /* * The default branch for the repository; the `init.defaultBranch` * configuration option, if set, or `master` if it is not. diff --git a/src/transports/local.c b/src/transports/local.c index bb31b1345..17905d222 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -268,15 +268,13 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t static int local_negotiate_fetch( git_transport *transport, git_repository *repo, - const git_remote_head * const *refs, - size_t count) + const git_fetch_negotiation *wants) { transport_local *t = (transport_local*)transport; git_remote_head *rhead; unsigned int i; - GIT_UNUSED(refs); - GIT_UNUSED(count); + GIT_UNUSED(wants); /* Fill in the loids */ git_vector_foreach(&t->refs, i, rhead) { diff --git a/src/transports/smart.c b/src/transports/smart.c index 587f14358..a26bf79ec 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -558,3 +558,31 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) *out = (git_transport *) t; return 0; } + +size_t git_shallowarray_count(git_shallowarray *array) +{ + return git_array_size(array->array); +} + +const git_oid * git_shallowarray_get(git_shallowarray *array, size_t idx) +{ + return git_array_get(array->array, idx); +} + +int git_shallowarray_add(git_shallowarray *array, git_oid *oid) +{ + size_t oid_index; + if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, &oid) < 0) { + git_oid *tmp = git_array_alloc(array->array); + git_oid_cpy(tmp, oid); + } + return 0; +} + +int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) +{ + GIT_UNUSED(array); + GIT_UNUSED(oid); + /* no git_array_remove… meh */ + return -1; +} diff --git a/src/transports/smart.h b/src/transports/smart.h index a05d4c9e3..6e49237ea 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -14,6 +14,7 @@ #include "netops.h" #include "buffer.h" #include "push.h" +#include "oidarray.h" #include "git2/sys/transport.h" #define GIT_SIDE_BAND_DATA 1 @@ -30,6 +31,7 @@ #define GIT_CAP_REPORT_STATUS "report-status" #define GIT_CAP_THIN_PACK "thin-pack" #define GIT_CAP_SYMREF "symref" +#define GIT_CAP_SHALLOW "shallow" extern bool git_smart__ofs_delta_enabled; @@ -47,6 +49,8 @@ typedef enum { GIT_PKT_OK, GIT_PKT_NG, GIT_PKT_UNPACK, + GIT_PKT_SHALLOW, + GIT_PKT_UNSHALLOW, } git_pkt_type; /* Used for multi_ack and multi_ack_detailed */ @@ -118,6 +122,11 @@ typedef struct { int unpack_ok; } git_pkt_unpack; +typedef struct { + git_pkt_type type; + git_oid oid; +} git_pkt_shallow; + typedef struct transport_smart_caps { int common:1, ofs_delta:1, @@ -128,7 +137,8 @@ typedef struct transport_smart_caps { include_tag:1, delete_refs:1, report_status:1, - thin_pack:1; + thin_pack:1, + shallow:1; } transport_smart_caps; typedef int (*packetsize_cb)(size_t received, void *payload); @@ -171,8 +181,7 @@ int git_smart__push(git_transport *transport, git_push *push, const git_remote_c int git_smart__negotiate_fetch( git_transport *transport, git_repository *repo, - const git_remote_head * const *refs, - size_t count); + const git_fetch_negotiation *wants); int git_smart__download_pack( git_transport *transport, @@ -192,8 +201,12 @@ int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, si int git_pkt_buffer_flush(git_buf *buf); int git_pkt_send_flush(GIT_SOCKET s); int git_pkt_buffer_done(git_buf *buf); -int git_pkt_buffer_wants(const git_remote_head * const *refs, size_t count, transport_smart_caps *caps, git_buf *buf); +int git_pkt_buffer_wants(const git_fetch_negotiation *wants, transport_smart_caps *caps, git_buf *buf); int git_pkt_buffer_have(git_oid *oid, git_buf *buf); void git_pkt_free(git_pkt *pkt); +struct git_shallowarray { + git_array_oid_t array; +}; + #endif diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index 56b680d28..6a1e842ee 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -363,6 +363,50 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len) return 0; } +static int shallow_pkt(git_pkt **out, const char *line, size_t len) +{ + git_pkt_shallow *pkt; + + pkt = git__calloc(1, sizeof(git_pkt_shallow)); + GIT_ERROR_CHECK_ALLOC(pkt); + + pkt->type = GIT_PKT_SHALLOW; + line += 7; + len -= 7; + + if (len >= GIT_OID_HEXSZ) { + git_oid_fromstr(&pkt->oid, line + 1); + line += GIT_OID_HEXSZ + 1; + len -= GIT_OID_HEXSZ + 1; + } + + *out = (git_pkt *) pkt; + + return 0; +} + +static int unshallow_pkt(git_pkt **out, const char *line, size_t len) +{ + git_pkt_shallow *pkt; + + pkt = git__calloc(1, sizeof(git_pkt_shallow)); + GIT_ERROR_CHECK_ALLOC(pkt); + + pkt->type = GIT_PKT_UNSHALLOW; + line += 9; + len -= 9; + + if (len >= GIT_OID_HEXSZ) { + git_oid_fromstr(&pkt->oid, line + 1); + line += GIT_OID_HEXSZ + 1; + len -= GIT_OID_HEXSZ + 1; + } + + *out = (git_pkt *) pkt; + + return 0; +} + static int parse_len(size_t *out, const char *line, size_t linelen) { char num[PKT_LEN_SIZE + 1]; @@ -489,6 +533,10 @@ int git_pkt_parse_line( error = ng_pkt(pkt, line, len); else if (!git__prefixncmp(line, len, "unpack")) error = unpack_pkt(pkt, line, len); + else if (!git__prefixcmp(line, "shallow")) + error = shallow_pkt(pkt, line, len); + else if (!git__prefixcmp(line, "unshallow")) + error = unshallow_pkt(pkt, line, len); else error = ref_pkt(pkt, line, len); @@ -554,6 +602,9 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca if (caps->ofs_delta) git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); + if (caps->shallow) + git_buf_puts(&str, GIT_CAP_SHALLOW " "); + if (git_buf_oom(&str)) return -1; @@ -583,8 +634,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca */ int git_pkt_buffer_wants( - const git_remote_head * const *refs, - size_t count, + const git_fetch_negotiation *wants, transport_smart_caps *caps, git_buf *buf) { @@ -592,22 +642,22 @@ int git_pkt_buffer_wants( const git_remote_head *head; if (caps->common) { - for (; i < count; ++i) { - head = refs[i]; + for (; i < wants->count; ++i) { + head = wants->refs[i]; if (!head->local) break; } - if (buffer_want_with_caps(refs[i], caps, buf) < 0) + if (buffer_want_with_caps(wants->refs[i], caps, buf) < 0) return -1; i++; } - for (; i < count; ++i) { + for (; i < wants->count; ++i) { char oid[GIT_OID_HEXSZ]; - head = refs[i]; + head = wants->refs[i]; if (head->local) continue; @@ -619,6 +669,32 @@ int git_pkt_buffer_wants( return -1; } + /* Tell the server about our shallow objects */ + for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { + char oid[GIT_OID_HEXSZ]; + git_buf shallow_buf = GIT_BUF_INIT; + + git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i)); + git_buf_puts(&shallow_buf, "shallow "); + git_buf_put(&shallow_buf, oid, GIT_OID_HEXSZ); + git_buf_putc(&shallow_buf, '\n'); + + git_buf_printf(buf, "%04x%s", (unsigned int)git_buf_len(&shallow_buf) + 4, git_buf_cstr(&shallow_buf)); + + if (git_buf_oom(buf)) + return -1; + } + + if (wants->depth > 0) { + git_buf deepen_buf = GIT_BUF_INIT; + + git_buf_printf(&deepen_buf, "deepen %d\n", wants->depth); + git_buf_printf(buf,"%04x%s", (unsigned int)git_buf_len(&deepen_buf) + 4, git_buf_cstr(&deepen_buf)); + + if (git_buf_oom(buf)) + return -1; + } + return git_pkt_buffer_flush(buf); } diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 91de163e9..df1931191 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -205,6 +205,12 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec continue; } + if (!git__prefixcmp(ptr, GIT_CAP_SHALLOW)) { + caps->common = caps->shallow = 1; + ptr += strlen(GIT_CAP_SHALLOW); + continue; + } + /* We don't know this capability, so skip it */ ptr = strchr(ptr, ' '); } @@ -305,7 +311,26 @@ static int wait_while_ack(gitno_buffer *buf) return 0; } -int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count) +static int cap_not_sup_err(const char *cap_name) +{ + git_error_set(GIT_ERROR_NET, "server doesn't support %s", cap_name); + return GIT_EINVALID; +} + +/* Disables server capabilities we're not interested in */ +static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants) +{ + if (wants->depth) { + if (!caps->shallow) + return cap_not_sup_err(GIT_CAP_SHALLOW); + } else { + caps->shallow = 0; + } + + return 0; +} + +int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_fetch_negotiation *wants) { transport_smart *t = (transport_smart *)transport; git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; @@ -317,7 +342,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c unsigned int i; git_oid oid; - if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) + if ((error = setup_caps(&t->caps, wants)) < 0) + return error; + + if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) return error; if ((error = git_revwalk_new(&walk, repo)) < 0) @@ -327,6 +355,33 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c if ((error = git_revwalk__push_glob(walk, "refs/*", &opts)) < 0) goto on_error; + if (wants->depth > 0) { + git_pkt_shallow *pkt; + + if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0) + goto on_error; + + while ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) == 0) { + + if (pkt->type == GIT_PKT_SHALLOW) { + printf("shallow %s\n", git_oid_tostr_s(&pkt->oid)); + git_shallowarray_add(wants->shallow_roots, &pkt->oid); + } else if (pkt->type == GIT_PKT_UNSHALLOW) { + printf("unshallow %s\n", git_oid_tostr_s(&pkt->oid)); + git_shallowarray_remove(wants->shallow_roots, &pkt->oid); + } else if (pkt->type == GIT_PKT_FLUSH) { + /* Server is done, stop processing shallow oids */ + break; + } else { + git_error_set(GIT_ERROR_NET, "Unexpected pkt type"); + goto on_error; + } + } + + if (error < 0) { + goto on_error; + } + } /* * Our support for ACK extensions is simply to parse them. On * the first ACK we will accept that as enough common @@ -389,7 +444,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_pkt_ack *pkt; unsigned int j; - if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) + if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) goto on_error; git_vector_foreach(&t->common, j, pkt) { @@ -409,7 +464,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_pkt_ack *pkt; unsigned int j; - if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) + if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) goto on_error; git_vector_foreach(&t->common, j, pkt) { diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c new file mode 100644 index 000000000..d05272065 --- /dev/null +++ b/tests/clone/shallow.c @@ -0,0 +1,55 @@ +#include "clar_libgit2.h" +#include "futils.h" + +void test_clone_shallow__initialize(void) +{ + +} + +void test_clone_shallow__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +#define CLONE_DEPTH 5 + +void test_clone_shallow__clone_depth(void) +{ + git_buf path = GIT_BUF_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + git_oidarray roots; + size_t depth = 0; + int error = 0; + + clone_opts.fetch_opts.depth = CLONE_DEPTH; + + git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository_shallow_roots(&roots, repo)); + cl_assert_equal_i(1, roots.count); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[0])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + if (depth + 1 > CLONE_DEPTH) + cl_fail("expected depth mismatch"); + depth++; + } + + cl_git_pass(error); + + git_buf_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} diff --git a/tests/repo/grafts.c b/tests/repo/grafts.c new file mode 100644 index 000000000..82bd0ad7a --- /dev/null +++ b/tests/repo/grafts.c @@ -0,0 +1,119 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "grafts.h" + +static git_repository *g_repo; + +void test_repo_grafts__initialize(void) +{ + g_repo = cl_git_sandbox_init("grafted.git"); +} + +void test_repo_grafts__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_repo_grafts__graft_register(void) +{ + git_oid oid_src; + git_commit_graft *graft; + git_graftmap *grafts = git_oidmap_alloc(); + git_array_oid_t parents = GIT_ARRAY_INIT; + + git_oid *oid1 = git_array_alloc(parents); + cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); + git_oid_cpy(oid1, &oid_src); + + git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git__graft_register(grafts, &oid_src, parents)); + git_array_clear(parents); + + cl_assert_equal_i(1, git_oidmap_size(grafts)); + cl_git_pass(git__graft_for_oid(&graft, grafts, &oid_src)); + cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); + cl_assert_equal_i(1, git_array_size(graft->parents)); + cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); + + git__graft_clear(grafts); + git_oidmap_free(grafts); +} + +void test_repo_grafts__grafted_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + git_commit *commit; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0])); + + cl_assert_equal_i(1, git_commit_parentcount(commit)); + + git_commit_free(commit); + git_revwalk_free(w); +} + +void test_repo_grafts__grafted_objects(void) +{ + git_oid oid; + git_commit *commit; + + cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(4, git_commit_parentcount(commit)); + git_commit_free(commit); +} + +void test_repo_grafts__grafted_merge_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + git_revwalk_free(w); +} diff --git a/tests/repo/shallow.c b/tests/repo/shallow.c new file mode 100644 index 000000000..a73dfc013 --- /dev/null +++ b/tests/repo/shallow.c @@ -0,0 +1,125 @@ +#include "clar_libgit2.h" +#include "futils.h" + +static git_repository *g_repo; +static git_oid g_shallow_oid; + +void test_repo_shallow__initialize(void) +{ + cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); +} + +void test_repo_shallow__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_repo_shallow__no_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_repo_shallow__empty_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_git_mkfile("testrepo.git/shallow", ""); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_repo_shallow__shallow_repo(void) +{ + g_repo = cl_git_sandbox_init("shallow.git"); + cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); +} + +void test_repo_shallow__clears_errors(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); + cl_assert_equal_p(NULL, git_error_last()); +} + +void test_repo_shallow__shallow_oids(void) +{ + git_oidarray oids, oids2; + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(1, oids.count); + cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + + cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); + cl_assert_equal_p(oids.ids, oids2.ids); +} + +void test_repo_shallow__cache_clearing(void) +{ + git_oidarray oids, oids2; + git_oid tmp_oid; + + git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000"); + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); + cl_assert_equal_i(1, oids.count); + cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); + + cl_git_mkfile("shallow.git/shallow", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" + "0000000000000000000000000000000000000000\n" + ); + + cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); + cl_assert_equal_i(2, oids2.count); + cl_assert_equal_oid(&g_shallow_oid, &oids2.ids[0]); + cl_assert_equal_oid(&tmp_oid, &oids2.ids[1]); +} + +void test_repo_shallow__errors_on_borked(void) +{ + git_oidarray oids; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_mkfile("shallow.git/shallow", "lolno"); + + cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); + + cl_git_mkfile("shallow.git/shallow", "lolno\n"); + + cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); +} + +void test_repo_shallow__revwalk_behavior(void) +{ + git_revwalk *w; + git_oid oid_1, oid_2, oid_3; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_head(w)); + + cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644 + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w)); + + cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + + git_revwalk_free(w); +} + +void test_repo_shallow__grafted_object(void) +{ + git_commit *commit; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid)); + + cl_assert_equal_i(0, git_commit_parentcount(commit)); + + git_commit_free(commit); +} -- cgit v1.2.1 From 10e2573550b0753f4aa0728bb2bbacf57d2377d0 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 5 Jul 2022 09:22:31 +0100 Subject: attempt to build --- src/repository.c | 148 +++++++++++++++++++++++++------------------------- tests/clone/shallow.c | 3 +- tests/repo/grafts.c | 119 ---------------------------------------- tests/repo/shallow.c | 125 ------------------------------------------ 4 files changed, 77 insertions(+), 318 deletions(-) delete mode 100644 tests/repo/grafts.c delete mode 100644 tests/repo/shallow.c diff --git a/src/repository.c b/src/repository.c index 537622273..bef719f4a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -3194,89 +3194,91 @@ int git_repository_state_cleanup(git_repository *repo) int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { - git_buf path = GIT_BUF_INIT; - git_buf contents = GIT_BUF_INIT; - int error, updated, line_num = 1; - char *line; - char *buffer; - - assert(out && repo); - - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) - return error; - - error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); - git_buf_dispose(&path); - - if (error < 0 && error != GIT_ENOTFOUND) - return error; - - /* cancel out GIT_ENOTFOUND */ - git_error_clear(); - error = 0; - - if (!updated) { - *out = repo->shallow_oids; - goto cleanup; - } - - git_array_clear(repo->shallow_oids); - - buffer = contents.ptr; - while ((line = git__strsep(&buffer, "\n")) != NULL) { - git_oid *oid = git_array_alloc(repo->shallow_oids); - - error = git_oid_fromstr(oid, line); - if (error < 0) { - git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); - git_array_clear(repo->shallow_oids); - error = -1; - goto cleanup; - } - ++line_num; - } - - if (*buffer) { - git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); - git_array_clear(repo->shallow_oids); - error = -1; - goto cleanup; - } - - *out = repo->shallow_oids; - -cleanup: - git_buf_dispose(&contents); - - return error; +// git_buf path = GIT_BUF_INIT; +// git_buf contents = GIT_BUF_INIT; +// int error, updated, line_num = 1; +// char *line; +// char *buffer; + +// assert(out && repo); + +// if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) +// return error; + +// //error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); +// error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated); +// git_buf_dispose(&path); + +// if (error < 0 && error != GIT_ENOTFOUND) +// return error; + +// /* cancel out GIT_ENOTFOUND */ +// git_error_clear(); +// error = 0; + +// if (!updated) { +// out = repo->shallow_grafts; +// goto cleanup; +// } + +// git_array_clear(repo->shallow_grafts); + +// buffer = contents.ptr; +// while ((line = git__strsep(&buffer, "\n")) != NULL) { +// git_oid *oid = git_array_alloc(repo->shallow_grafts); + +// error = git_oid_fromstr(oid, line); +// if (error < 0) { +// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); +// git_array_clear(repo->shallow_grafts); +// error = -1; +// goto cleanup; +// } +// ++line_num; +// } + +// if (*buffer) { +// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); +// git_array_clear(repo->shallow_grafts); +// error = -1; +// goto cleanup; +// } + +// *out = repo->shallow_grafts; + +// cleanup: +// git_buf_dispose(&contents); + + // return error; + return 0; } int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) { - git_filebuf file = GIT_FILEBUF_INIT; - git_buf path = GIT_BUF_INIT; - int error = 0; - size_t idx; - git_oid *oid; + // git_filebuf file = GIT_FILEBUF_INIT; + // git_buf path = GIT_BUF_INIT; + // int error = 0; + // size_t idx; + // git_oid *oid; - assert(repo); + // assert(repo); - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) - return error; + // if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + // return error; - if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) - return error; + // if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) + // return error; - git_array_foreach(roots, idx, oid) { - git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); - git_filebuf_write(&file, "\n", 1); - } + // git_array_foreach(roots, idx, oid) { + // git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); + // git_filebuf_write(&file, "\n", 1); + // } - git_filebuf_commit(&file); + // git_filebuf_commit(&file); - /* WIP: reload shallow */ - if (load_shallow(repo) < 0) - return -1; + // /* WIP: reload shallow */ + // if (load_shallow(repo) < 0) + // return -1; return 0; } diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c index d05272065..6bd98ab0a 100644 --- a/tests/clone/shallow.c +++ b/tests/clone/shallow.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "futils.h" +#include "repository.h" void test_clone_shallow__initialize(void) { @@ -33,7 +34,7 @@ void test_clone_shallow__clone_depth(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository_shallow_roots(&roots, repo)); + cl_git_pass(git_repository__shallow_roots(&roots, repo)); cl_assert_equal_i(1, roots.count); cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[0])); diff --git a/tests/repo/grafts.c b/tests/repo/grafts.c deleted file mode 100644 index 82bd0ad7a..000000000 --- a/tests/repo/grafts.c +++ /dev/null @@ -1,119 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" -#include "grafts.h" - -static git_repository *g_repo; - -void test_repo_grafts__initialize(void) -{ - g_repo = cl_git_sandbox_init("grafted.git"); -} - -void test_repo_grafts__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_repo_grafts__graft_register(void) -{ - git_oid oid_src; - git_commit_graft *graft; - git_graftmap *grafts = git_oidmap_alloc(); - git_array_oid_t parents = GIT_ARRAY_INIT; - - git_oid *oid1 = git_array_alloc(parents); - cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); - git_oid_cpy(oid1, &oid_src); - - git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git__graft_register(grafts, &oid_src, parents)); - git_array_clear(parents); - - cl_assert_equal_i(1, git_oidmap_size(grafts)); - cl_git_pass(git__graft_for_oid(&graft, grafts, &oid_src)); - cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); - cl_assert_equal_i(1, git_array_size(graft->parents)); - cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); - - git__graft_clear(grafts); - git_oidmap_free(grafts); -} - -void test_repo_grafts__grafted_revwalk(void) -{ - git_revwalk *w; - git_oid oids[10]; - size_t i = 0; - git_commit *commit; - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch")); - - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); - - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0])); - - cl_assert_equal_i(1, git_commit_parentcount(commit)); - - git_commit_free(commit); - git_revwalk_free(w); -} - -void test_repo_grafts__grafted_objects(void) -{ - git_oid oid; - git_commit *commit; - - cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(1, git_commit_parentcount(commit)); - git_commit_free(commit); - - cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(1, git_commit_parentcount(commit)); - git_commit_free(commit); - - cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(4, git_commit_parentcount(commit)); - git_commit_free(commit); -} - -void test_repo_grafts__grafted_merge_revwalk(void) -{ - git_revwalk *w; - git_oid oids[10]; - size_t i = 0; - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom")); - - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); - - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); - - git_revwalk_free(w); -} diff --git a/tests/repo/shallow.c b/tests/repo/shallow.c deleted file mode 100644 index a73dfc013..000000000 --- a/tests/repo/shallow.c +++ /dev/null @@ -1,125 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" - -static git_repository *g_repo; -static git_oid g_shallow_oid; - -void test_repo_shallow__initialize(void) -{ - cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); -} - -void test_repo_shallow__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_repo_shallow__no_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__empty_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_mkfile("testrepo.git/shallow", ""); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__shallow_repo(void) -{ - g_repo = cl_git_sandbox_init("shallow.git"); - cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__clears_errors(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); - cl_assert_equal_p(NULL, git_error_last()); -} - -void test_repo_shallow__shallow_oids(void) -{ - git_oidarray oids, oids2; - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(1, oids.count); - cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); - - cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); - cl_assert_equal_p(oids.ids, oids2.ids); -} - -void test_repo_shallow__cache_clearing(void) -{ - git_oidarray oids, oids2; - git_oid tmp_oid; - - git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000"); - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_repository_shallow_roots(&oids, g_repo)); - cl_assert_equal_i(1, oids.count); - cl_assert_equal_oid(&g_shallow_oid, &oids.ids[0]); - - cl_git_mkfile("shallow.git/shallow", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" - "0000000000000000000000000000000000000000\n" - ); - - cl_git_pass(git_repository_shallow_roots(&oids2, g_repo)); - cl_assert_equal_i(2, oids2.count); - cl_assert_equal_oid(&g_shallow_oid, &oids2.ids[0]); - cl_assert_equal_oid(&tmp_oid, &oids2.ids[1]); -} - -void test_repo_shallow__errors_on_borked(void) -{ - git_oidarray oids; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_mkfile("shallow.git/shallow", "lolno"); - - cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); - - cl_git_mkfile("shallow.git/shallow", "lolno\n"); - - cl_git_fail_with(-1, git_repository_shallow_roots(&oids, g_repo)); -} - -void test_repo_shallow__revwalk_behavior(void) -{ - git_revwalk *w; - git_oid oid_1, oid_2, oid_3; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_head(w)); - - cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644 - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w)); - - cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - - git_revwalk_free(w); -} - -void test_repo_shallow__grafted_object(void) -{ - git_commit *commit; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid)); - - cl_assert_equal_i(0, git_commit_parentcount(commit)); - - git_commit_free(commit); -} -- cgit v1.2.1 From 3e64f150ccfae3b7828a293fdd78daaf61e76ccf Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 7 Jul 2022 09:26:18 +0100 Subject: rewrite shallow_root --- src/repository.c | 110 +++++++++++++++++++++++++++++++++++++++----------- tests/clone/shallow.c | 10 +++-- 2 files changed, 94 insertions(+), 26 deletions(-) diff --git a/src/repository.c b/src/repository.c index bef719f4a..42ee263a3 100644 --- a/src/repository.c +++ b/src/repository.c @@ -3192,13 +3192,56 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) -{ +// int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) +// { // git_buf path = GIT_BUF_INIT; // git_buf contents = GIT_BUF_INIT; // int error, updated, line_num = 1; // char *line; -// char *buffer; +// chror = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated); +// git_buf_dispose(&path); + +// if (error < 0 && error != GIT_ENOTFOUND) +// return error; + +// /* cancel out GIT_ENOTFOUND */ +// git_error_clear(); +// error = 0; + +// if (!updated) { +// out = repo->shallow_grafts; +// goto cleanup; +// } + +// git_array_clear(repo->shallow_grafts); + +// buffer = contents.ptr; +// while ((line = git__strsep(&buffer, "\n")) != NULL) { +// git_oid *oid = git_array_alloc(repo->shallow_grafts); + +// error = git_oid_fromstr(oid, line); +// if (error < 0) { +// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); +// git_array_clear(repo->shallow_grafts); +// error = -1; +// goto cleanup; +// } +// ++line_num; +// } + +// if (*buffer) { +// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); +// git_array_clear(repo->shallow_grafts); +// error = -1; +// goto cleanup; +// } + +// *out = repo->shallow_grafts; + +// cleanup: +// git_buf_dispose(&contents); + +// return error;ar *buffer; // assert(out && repo); @@ -3249,40 +3292,61 @@ int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) // cleanup: // git_buf_dispose(&contents); - // return error; - return 0; +// return error; +// } + +int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { + int error =0; + if (!repo->shallow_grafts) + load_grafts(repo); + + git_grafts_refresh(repo->shallow_grafts); + return git_grafts_get_oids(out, repo->shallow_grafts); } int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) { - // git_filebuf file = GIT_FILEBUF_INIT; - // git_buf path = GIT_BUF_INIT; - // int error = 0; - // size_t idx; - // git_oid *oid; + git_filebuf file = GIT_FILEBUF_INIT; + git_buf path = GIT_BUF_INIT; + int error = 0; + size_t idx; + git_oid *oid; - // assert(repo); + assert(repo); - // if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) - // return error; + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + return error; - // if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) - // return error; + if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) + return error; - // git_array_foreach(roots, idx, oid) { - // git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); - // git_filebuf_write(&file, "\n", 1); - // } + git_array_foreach(roots, idx, oid) { + git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); + git_filebuf_write(&file, "\n", 1); + } - // git_filebuf_commit(&file); + git_filebuf_commit(&file); - // /* WIP: reload shallow */ - // if (load_shallow(repo) < 0) - // return -1; + if (load_grafts(repo) < 0) + return -1; return 0; } +int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) +{ + int ret; + git_array_oid_t array = GIT_ARRAY_INIT; + + assert(out); + + ret = git_repository__shallow_roots(&array, repo); + + git_oidarray__from_array(out, &array); + + return ret; +} + int git_repository_is_shallow(git_repository *repo) { git_buf path = GIT_BUF_INIT; diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c index 6bd98ab0a..b41e28d66 100644 --- a/tests/clone/shallow.c +++ b/tests/clone/shallow.c @@ -34,7 +34,7 @@ void test_clone_shallow__clone_depth(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_git_pass(git_repository_shallow_roots(&roots, repo)); cl_assert_equal_i(1, roots.count); cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[0])); @@ -43,8 +43,12 @@ void test_clone_shallow__clone_depth(void) git_revwalk_push_head(walk); while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - if (depth + 1 > CLONE_DEPTH) - cl_fail("expected depth mismatch"); + //if (depth + 1 > CLONE_DEPTH) + //cl_fail("expected depth mismatch"); + char str[GIT_OID_HEXSZ +1]; + git_oid_fmt(str, &oid); + printf(str); + printf("\n"); depth++; } -- cgit v1.2.1 From c652f3d13372398fc86c72a7b05c90002d1cc763 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 19 Jul 2022 13:54:33 +0100 Subject: enable cloning of shallow repo --- src/clone.c | 3 ++- tests/clone/shallow.c | 25 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/clone.c b/src/clone.c index 752df3b92..5750a71af 100644 --- a/src/clone.c +++ b/src/clone.c @@ -409,7 +409,8 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; - fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; + if (fetch_opts.depth == -1) + fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_buf_cstr(&reflog_message))) != 0) diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c index b41e28d66..b3e8f1617 100644 --- a/tests/clone/shallow.c +++ b/tests/clone/shallow.c @@ -15,6 +15,15 @@ void test_clone_shallow__cleanup(void) #define CLONE_DEPTH 5 +static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) +{ + GIT_UNUSED(payload); + + cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master")); + + return 0; +} + void test_clone_shallow__clone_depth(void) { git_buf path = GIT_BUF_INIT; @@ -27,6 +36,7 @@ void test_clone_shallow__clone_depth(void) int error = 0; clone_opts.fetch_opts.depth = CLONE_DEPTH; + clone_opts.remote_cb = remote_single_branch; git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone"); @@ -35,21 +45,18 @@ void test_clone_shallow__clone_depth(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); cl_git_pass(git_repository_shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.count); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[0])); + cl_assert_equal_i(3, roots.count); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ids[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ids[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[2])); git_revwalk_new(&walk, repo); git_revwalk_push_head(walk); while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - //if (depth + 1 > CLONE_DEPTH) - //cl_fail("expected depth mismatch"); - char str[GIT_OID_HEXSZ +1]; - git_oid_fmt(str, &oid); - printf(str); - printf("\n"); - depth++; + if (depth + 1 > CLONE_DEPTH) + cl_fail("expected depth mismatch"); } cl_git_pass(error); -- cgit v1.2.1 From f19ffc8a6d88432146a87cd3fb2ca21528478be4 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 19 Jul 2022 15:42:12 +0100 Subject: add test for shallow repo depth 1 --- tests/clone/shallow.c | 60 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c index b3e8f1617..01852dfed 100644 --- a/tests/clone/shallow.c +++ b/tests/clone/shallow.c @@ -4,17 +4,15 @@ void test_clone_shallow__initialize(void) { - + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); } void test_clone_shallow__cleanup(void) { + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); cl_git_sandbox_cleanup(); } - -#define CLONE_DEPTH 5 - static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) { GIT_UNUSED(payload); @@ -24,7 +22,47 @@ static int remote_single_branch(git_remote **out, git_repository *repo, const ch return 0; } -void test_clone_shallow__clone_depth(void) +void test_clone_shallow__clone_depth_one(void) +{ + git_buf path = GIT_BUF_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + git_oidarray roots; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 1; + clone_opts.remote_cb = remote_single_branch; + + git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_1"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository_shallow_roots(&roots, repo)); + cl_assert_equal_i(1, roots.count); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ids[0])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 1); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_buf_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} + +void test_clone_shallow__clone_depth_five(void) { git_buf path = GIT_BUF_INIT; git_repository *repo; @@ -32,13 +70,13 @@ void test_clone_shallow__clone_depth(void) git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; git_oidarray roots; - size_t depth = 0; + size_t num_commits = 0; int error = 0; - clone_opts.fetch_opts.depth = CLONE_DEPTH; + clone_opts.fetch_opts.depth = 5; clone_opts.remote_cb = remote_single_branch; - git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone"); + git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_5"); cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts)); @@ -55,11 +93,11 @@ void test_clone_shallow__clone_depth(void) git_revwalk_push_head(walk); while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - if (depth + 1 > CLONE_DEPTH) - cl_fail("expected depth mismatch"); + num_commits++; } - cl_git_pass(error); + cl_assert_equal_i(num_commits, 13); + cl_assert_equal_i(error, GIT_ITEROVER); git_buf_dispose(&path); git_revwalk_free(walk); -- cgit v1.2.1 From 7f46bfac14f0502711f8441348fd361175953fd5 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 26 Jul 2022 13:59:00 +0100 Subject: unset GIT_RAND_GETENTROPY to avoid linux GLIBC issues (#3) --- src/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e108b2e79..b81ad272f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,7 +70,11 @@ check_function_exists(qsort_s GIT_QSORT_S) # random / entropy data -check_function_exists(getentropy GIT_RAND_GETENTROPY) +# The flag has been unset to prevent issues +# related to Linux GLIBC version dependency + +# check_function_exists(getentropy GIT_RAND_GETENTROPY) +unset(GIT_RAND_GETENTROPY) check_function_exists(getloadavg GIT_RAND_GETLOADAVG) # determine architecture of the machine -- cgit v1.2.1 From 83f71b12e1f26943d3c544901846fb1d55785735 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 26 Jul 2022 16:57:30 +0100 Subject: fix build errors --- .gitignore | 1 + include/git2/common.h | 2 +- src/grafts.c | 242 ----------------------------------------------- src/grafts.h | 37 -------- src/libgit2/grafts.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++ src/libgit2/grafts.h | 37 ++++++++ src/libgit2/repository.c | 6 +- 7 files changed, 284 insertions(+), 283 deletions(-) delete mode 100644 src/grafts.c delete mode 100644 src/grafts.h create mode 100644 src/libgit2/grafts.c create mode 100644 src/libgit2/grafts.h diff --git a/.gitignore b/.gitignore index 1b482f038..d43bd9c78 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ CMakeSettings.json .vs .idea +.cache diff --git a/include/git2/common.h b/include/git2/common.h index ac035f0af..4e47488d7 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -227,7 +227,7 @@ typedef enum { GIT_OPT_GET_EXTENSIONS, GIT_OPT_SET_EXTENSIONS, GIT_OPT_GET_OWNER_VALIDATION, - GIT_OPT_SET_OWNER_VALIDATION + GIT_OPT_SET_OWNER_VALIDATION, GIT_OPT_ENABLE_SHALLOW } git_libgit2_opt_t; diff --git a/src/grafts.c b/src/grafts.c deleted file mode 100644 index 003522616..000000000 --- a/src/grafts.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "grafts.h" - -#include "futils.h" -#include "oidarray.h" -#include "parse.h" - -bool git_shallow__enabled = false; - -struct git_grafts { - /* Map of `git_commit_graft`s */ - git_oidmap *commits; - - /* File backing the graft. NULL if it's an in-memory graft */ - char *path; - git_oid path_checksum; -}; - -int git_grafts_new(git_grafts **out) -{ - git_grafts *grafts; - - grafts = git__calloc(1, sizeof(*grafts)); - GIT_ERROR_CHECK_ALLOC(grafts); - - if ((git_oidmap_new(&grafts->commits)) < 0) { - git__free(grafts); - return -1; - } - - *out = grafts; - return 0; -} - -int git_grafts_from_file(git_grafts **out, const char *path) -{ - git_grafts *grafts = NULL; - int error; - - if ((error = git_grafts_new(&grafts)) < 0) - goto error; - - grafts->path = git__strdup(path); - GIT_ERROR_CHECK_ALLOC(grafts->path); - - if ((error = git_grafts_refresh(grafts)) < 0) - goto error; - - *out = grafts; -error: - if (error < 0) - git_grafts_free(grafts); - return error; -} - -void git_grafts_free(git_grafts *grafts) -{ - if (!grafts) - return; - git__free(grafts->path); - git_grafts_clear(grafts); - git_oidmap_free(grafts->commits); - git__free(grafts); -} - -void git_grafts_clear(git_grafts *grafts) -{ - git_commit_graft *graft; - - assert(grafts); - - git_oidmap_foreach_value(grafts->commits, graft, { - git__free(graft->parents.ptr); - git__free(graft); - }); - - git_oidmap_clear(grafts->commits); -} - -int git_grafts_refresh(git_grafts *grafts) -{ - git_buf contents = GIT_BUF_INIT; - int error, updated = 0; - - assert(grafts); - - if (!grafts->path) - return 0; - - error = git_futils_readbuffer_updated(&contents, grafts->path, - &grafts->path_checksum, &updated); - if (error < 0 || error == GIT_ENOTFOUND || !updated) { - if (error == GIT_ENOTFOUND) { - git_grafts_clear(grafts); - error = 0; - } - goto cleanup; - } - - if ((error = git_grafts_parse(grafts, contents.ptr, contents.size)) < 0) - goto cleanup; - -cleanup: - git_buf_dispose(&contents); - return error; -} - -int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) -{ - git_array_oid_t parents = GIT_ARRAY_INIT; - git_parse_ctx parser; - int error; - - git_grafts_clear(grafts); - - if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0) - goto error; - - for (; parser.remain_len; git_parse_advance_line(&parser)) { - const char *line_start = parser.line, *line_end = parser.line + parser.line_len; - git_oid graft_oid; - - if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) { - git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); - goto error; - } - line_start += GIT_OID_HEXSZ; - - while (line_start < line_end && *line_start == ' ') { - git_oid *id = git_array_alloc(parents); - GIT_ERROR_CHECK_ALLOC(id); - - if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) { - git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); - goto error; - } - - line_start += GIT_OID_HEXSZ; - } - - if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0) - goto error; - - git_array_clear(parents); - } - -error: - git_array_clear(parents); - return error; -} - -int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents) -{ - git_commit_graft *graft; - git_oid *parent_oid; - int error; - size_t i; - - assert(grafts && oid); - - graft = git__calloc(1, sizeof(*graft)); - GIT_ERROR_CHECK_ALLOC(graft); - - git_array_init_to_size(graft->parents, git_array_size(parents)); - git_array_foreach(parents, i, parent_oid) { - git_oid *id = git_array_alloc(graft->parents); - GIT_ERROR_CHECK_ALLOC(id); - - git_oid_cpy(id, parent_oid); - } - git_oid_cpy(&graft->oid, oid); - - if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND) - goto cleanup; - if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0) - goto cleanup; - - return 0; - -cleanup: - git_array_clear(graft->parents); - git__free(graft); - return error; -} - -int git_grafts_remove(git_grafts *grafts, const git_oid *oid) -{ - git_commit_graft *graft; - int error; - - assert(grafts && oid); - - if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL) - return GIT_ENOTFOUND; - - if ((error = git_oidmap_delete(grafts->commits, oid)) < 0) - return error; - - git__free(graft->parents.ptr); - git__free(graft); - - return 0; -} - -int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid) -{ - assert(out && grafts && oid); - if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL) - return GIT_ENOTFOUND; - return 0; -} - -int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts) -{ - git_array_oid_t oids = GIT_ARRAY_INIT; - const git_oid *oid; - size_t i = 0; - int error; - - assert(out && grafts); - - while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { - git_oid *cpy = git_array_alloc(oids); - GIT_ERROR_CHECK_ALLOC(cpy); - git_oid_cpy(cpy, oid); - } - - git_oidarray__from_array(out, &oids); - - return 0; -} - -size_t git_grafts_size(git_grafts *grafts) -{ - return git_oidmap_size(grafts->commits); -} diff --git a/src/grafts.h b/src/grafts.h deleted file mode 100644 index fd9ef6736..000000000 --- a/src/grafts.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#ifndef INCLUDE_graft_h__ -#define INCLUDE_graft_h__ - -#include "common.h" -#include "oidarray.h" -#include "oidmap.h" - -/** graft commit */ -typedef struct { - git_oid oid; - git_array_oid_t parents; -} git_commit_graft; - -typedef struct git_grafts git_grafts; - -extern bool git_shallow__enabled; - -int git_grafts_new(git_grafts **out); -int git_grafts_from_file(git_grafts **out, const char *path); -void git_grafts_free(git_grafts *grafts); -void git_grafts_clear(git_grafts *grafts); - -int git_grafts_refresh(git_grafts *grafts); -int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen); -int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); -int git_grafts_remove(git_grafts *grafts, const git_oid *oid); -int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); -int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts); -size_t git_grafts_size(git_grafts *grafts); - -#endif diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c new file mode 100644 index 000000000..003522616 --- /dev/null +++ b/src/libgit2/grafts.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "grafts.h" + +#include "futils.h" +#include "oidarray.h" +#include "parse.h" + +bool git_shallow__enabled = false; + +struct git_grafts { + /* Map of `git_commit_graft`s */ + git_oidmap *commits; + + /* File backing the graft. NULL if it's an in-memory graft */ + char *path; + git_oid path_checksum; +}; + +int git_grafts_new(git_grafts **out) +{ + git_grafts *grafts; + + grafts = git__calloc(1, sizeof(*grafts)); + GIT_ERROR_CHECK_ALLOC(grafts); + + if ((git_oidmap_new(&grafts->commits)) < 0) { + git__free(grafts); + return -1; + } + + *out = grafts; + return 0; +} + +int git_grafts_from_file(git_grafts **out, const char *path) +{ + git_grafts *grafts = NULL; + int error; + + if ((error = git_grafts_new(&grafts)) < 0) + goto error; + + grafts->path = git__strdup(path); + GIT_ERROR_CHECK_ALLOC(grafts->path); + + if ((error = git_grafts_refresh(grafts)) < 0) + goto error; + + *out = grafts; +error: + if (error < 0) + git_grafts_free(grafts); + return error; +} + +void git_grafts_free(git_grafts *grafts) +{ + if (!grafts) + return; + git__free(grafts->path); + git_grafts_clear(grafts); + git_oidmap_free(grafts->commits); + git__free(grafts); +} + +void git_grafts_clear(git_grafts *grafts) +{ + git_commit_graft *graft; + + assert(grafts); + + git_oidmap_foreach_value(grafts->commits, graft, { + git__free(graft->parents.ptr); + git__free(graft); + }); + + git_oidmap_clear(grafts->commits); +} + +int git_grafts_refresh(git_grafts *grafts) +{ + git_buf contents = GIT_BUF_INIT; + int error, updated = 0; + + assert(grafts); + + if (!grafts->path) + return 0; + + error = git_futils_readbuffer_updated(&contents, grafts->path, + &grafts->path_checksum, &updated); + if (error < 0 || error == GIT_ENOTFOUND || !updated) { + if (error == GIT_ENOTFOUND) { + git_grafts_clear(grafts); + error = 0; + } + goto cleanup; + } + + if ((error = git_grafts_parse(grafts, contents.ptr, contents.size)) < 0) + goto cleanup; + +cleanup: + git_buf_dispose(&contents); + return error; +} + +int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) +{ + git_array_oid_t parents = GIT_ARRAY_INIT; + git_parse_ctx parser; + int error; + + git_grafts_clear(grafts); + + if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0) + goto error; + + for (; parser.remain_len; git_parse_advance_line(&parser)) { + const char *line_start = parser.line, *line_end = parser.line + parser.line_len; + git_oid graft_oid; + + if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) { + git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); + goto error; + } + line_start += GIT_OID_HEXSZ; + + while (line_start < line_end && *line_start == ' ') { + git_oid *id = git_array_alloc(parents); + GIT_ERROR_CHECK_ALLOC(id); + + if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) { + git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); + goto error; + } + + line_start += GIT_OID_HEXSZ; + } + + if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0) + goto error; + + git_array_clear(parents); + } + +error: + git_array_clear(parents); + return error; +} + +int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents) +{ + git_commit_graft *graft; + git_oid *parent_oid; + int error; + size_t i; + + assert(grafts && oid); + + graft = git__calloc(1, sizeof(*graft)); + GIT_ERROR_CHECK_ALLOC(graft); + + git_array_init_to_size(graft->parents, git_array_size(parents)); + git_array_foreach(parents, i, parent_oid) { + git_oid *id = git_array_alloc(graft->parents); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, parent_oid); + } + git_oid_cpy(&graft->oid, oid); + + if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND) + goto cleanup; + if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0) + goto cleanup; + + return 0; + +cleanup: + git_array_clear(graft->parents); + git__free(graft); + return error; +} + +int git_grafts_remove(git_grafts *grafts, const git_oid *oid) +{ + git_commit_graft *graft; + int error; + + assert(grafts && oid); + + if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL) + return GIT_ENOTFOUND; + + if ((error = git_oidmap_delete(grafts->commits, oid)) < 0) + return error; + + git__free(graft->parents.ptr); + git__free(graft); + + return 0; +} + +int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid) +{ + assert(out && grafts && oid); + if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL) + return GIT_ENOTFOUND; + return 0; +} + +int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts) +{ + git_array_oid_t oids = GIT_ARRAY_INIT; + const git_oid *oid; + size_t i = 0; + int error; + + assert(out && grafts); + + while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { + git_oid *cpy = git_array_alloc(oids); + GIT_ERROR_CHECK_ALLOC(cpy); + git_oid_cpy(cpy, oid); + } + + git_oidarray__from_array(out, &oids); + + return 0; +} + +size_t git_grafts_size(git_grafts *grafts) +{ + return git_oidmap_size(grafts->commits); +} diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h new file mode 100644 index 000000000..fd9ef6736 --- /dev/null +++ b/src/libgit2/grafts.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_graft_h__ +#define INCLUDE_graft_h__ + +#include "common.h" +#include "oidarray.h" +#include "oidmap.h" + +/** graft commit */ +typedef struct { + git_oid oid; + git_array_oid_t parents; +} git_commit_graft; + +typedef struct git_grafts git_grafts; + +extern bool git_shallow__enabled; + +int git_grafts_new(git_grafts **out); +int git_grafts_from_file(git_grafts **out, const char *path); +void git_grafts_free(git_grafts *grafts); +void git_grafts_clear(git_grafts *grafts); + +int git_grafts_refresh(git_grafts *grafts); +int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen); +int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); +int git_grafts_remove(git_grafts *grafts, const git_oid *oid); +int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); +int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts); +size_t git_grafts_size(git_grafts *grafts); + +#endif diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 2ecc510b2..e58ab529a 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -736,13 +736,13 @@ static int load_grafts(git_repository *repo) int error; if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || - (error = git_buf_joinpath(&path, path.ptr, "grafts")) < 0 || + (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) goto error; - git_buf_clear(&path); + git_str_clear(&path); - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0 || + if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 || (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0) goto error; -- cgit v1.2.1 From cfc2ae68b4792f0c64152888869ef69d868079d7 Mon Sep 17 00:00:00 2001 From: yuangli Date: Wed, 27 Jul 2022 11:53:37 +0100 Subject: eliminate build warnings --- src/libgit2/commit.c | 7 +- src/libgit2/grafts.c | 6 +- src/libgit2/libgit2.c | 2 + src/libgit2/repository.c | 6 +- tests/grafts/basic.c | 123 ---------------------------------- tests/grafts/parse.c | 149 ----------------------------------------- tests/grafts/shallow.c | 146 ---------------------------------------- tests/libgit2/grafts/basic.c | 123 ++++++++++++++++++++++++++++++++++ tests/libgit2/grafts/parse.c | 149 +++++++++++++++++++++++++++++++++++++++++ tests/libgit2/grafts/shallow.c | 146 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 429 insertions(+), 428 deletions(-) delete mode 100644 tests/grafts/basic.c delete mode 100644 tests/grafts/parse.c delete mode 100644 tests/grafts/shallow.c create mode 100644 tests/libgit2/grafts/basic.c create mode 100644 tests/libgit2/grafts/parse.c create mode 100644 tests/libgit2/grafts/shallow.c diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index 7432ef4ec..2138d6eb2 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -501,8 +501,10 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) { - + git_repository *repo = git_object_owner((git_object *)commit); + git_commit_graft *graft; int error; + if ((error = commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags)) < 0) return error; @@ -510,9 +512,6 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned if (!git_shallow__enabled) return 0; - git_repository *repo = git_object_owner((git_object *)commit); - git_commit_graft *graft; - /* Perform necessary grafts */ if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 003522616..8bcefbab9 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -85,7 +85,7 @@ void git_grafts_clear(git_grafts *grafts) int git_grafts_refresh(git_grafts *grafts) { - git_buf contents = GIT_BUF_INIT; + git_str contents = GIT_STR_INIT; int error, updated = 0; assert(grafts); @@ -94,7 +94,7 @@ int git_grafts_refresh(git_grafts *grafts) return 0; error = git_futils_readbuffer_updated(&contents, grafts->path, - &grafts->path_checksum, &updated); + (grafts->path_checksum).id, &updated); if (error < 0 || error == GIT_ENOTFOUND || !updated) { if (error == GIT_ENOTFOUND) { git_grafts_clear(grafts); @@ -107,7 +107,7 @@ int git_grafts_refresh(git_grafts *grafts) goto cleanup; cleanup: - git_buf_dispose(&contents); + git_str_dispose(&contents); return error; } diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c index b76728e0c..2537730cf 100644 --- a/src/libgit2/libgit2.c +++ b/src/libgit2/libgit2.c @@ -413,6 +413,8 @@ int git_libgit2_opts(int key, ...) case GIT_OPT_SET_OWNER_VALIDATION: git_repository__validate_ownership = (va_arg(ap, int) != 0); + break; + case GIT_OPT_ENABLE_SHALLOW: git_shallow__enabled = (va_arg(ap, int) != 0); break; diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index e58ab529a..809617276 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -732,10 +732,10 @@ out: static int load_grafts(git_repository *repo) { - git_buf path = GIT_BUF_INIT; + git_str path = GIT_STR_INIT; int error; - if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) goto error; @@ -747,7 +747,7 @@ static int load_grafts(git_repository *repo) goto error; error: - git_buf_dispose(&path); + git_str_dispose(&path); return error; } diff --git a/tests/grafts/basic.c b/tests/grafts/basic.c deleted file mode 100644 index 4be4a12bf..000000000 --- a/tests/grafts/basic.c +++ /dev/null @@ -1,123 +0,0 @@ -#include "clar_libgit2.h" - -#include "futils.h" -#include "grafts.h" - -static git_repository *g_repo; - -void test_grafts_basic__initialize(void) -{ - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); - g_repo = cl_git_sandbox_init("grafted.git"); -} - -void test_grafts_basic__cleanup(void) -{ - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); - cl_git_sandbox_cleanup(); -} - -void test_grafts_basic__graft_add(void) -{ - git_array_oid_t parents = GIT_ARRAY_INIT; - git_oid oid_src, *oid1; - git_commit_graft *graft; - git_grafts *grafts; - - cl_git_pass(git_grafts_new(&grafts)); - - cl_assert(oid1 = git_array_alloc(parents)); - cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); - git_oid_cpy(oid1, &oid_src); - - git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git_grafts_add(grafts, &oid_src, parents)); - git_array_clear(parents); - - cl_assert_equal_i(1, git_grafts_size(grafts)); - cl_git_pass(git_grafts_get(&graft, grafts, &oid_src)); - cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); - cl_assert_equal_i(1, git_array_size(graft->parents)); - cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); - - git_grafts_free(grafts); -} - -void test_grafts_basic__grafted_revwalk(void) -{ - git_revwalk *w; - git_oid oids[10]; - size_t i = 0; - git_commit *commit; - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch")); - - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); - - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0])); - - cl_assert_equal_i(1, git_commit_parentcount(commit)); - - git_commit_free(commit); - git_revwalk_free(w); -} - -void test_grafts_basic__grafted_objects(void) -{ - git_oid oid; - git_commit *commit; - - cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(1, git_commit_parentcount(commit)); - git_commit_free(commit); - - cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(1, git_commit_parentcount(commit)); - git_commit_free(commit); - - cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_assert_equal_i(4, git_commit_parentcount(commit)); - git_commit_free(commit); -} - -void test_grafts_basic__grafted_merge_revwalk(void) -{ - git_revwalk *w; - git_oid oids[10]; - size_t i = 0; - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom")); - - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7"); - cl_git_pass(git_revwalk_next(&oids[i++], w)); - cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); - - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); - - git_revwalk_free(w); -} diff --git a/tests/grafts/parse.c b/tests/grafts/parse.c deleted file mode 100644 index de110c901..000000000 --- a/tests/grafts/parse.c +++ /dev/null @@ -1,149 +0,0 @@ -#include "clar_libgit2.h" - -#include "grafts.h" - -#define OID0 "c0368f9f9743e950e6cfe1f45a649f8a9dfcd97e" -#define OID1 "cfc50a0db87ce908fb8a8c5b8f7b4ab96eee8643" -#define OID2 "6914d97cd08b9edf5e855fca211c750fa82fd80a" -#define OID3 "516521937d0e9ce9d0d836149a0702671f326b4a" -#define OID4 "e2c29d67ef2f217650196f94c796f0532b8caad6" -#define OID5 "79bcb936596cb50353fe7be28b7444e66e4a2842" -#define OID6 "b9c54107d57c17dbcaf646c4d52f66eb9e69d23d" -#define OID7 "9f8a746e9ad7b58cc840016bc3944d5ad262acb5" -#define OID8 "392f4beef7d0d15b2bc5b1abe1a754eba0ec36da" - -#define OID_TRUNCATED "392f4beef7d0d15b2bc5b1abe1a754eba0ec36d" -#define OID_NONHEX "9f8a746e9ax7b58cc840016bc3944d5ad262acb5" - -static git_grafts *grafts; - -void test_grafts_parse__initialize(void) -{ - cl_git_pass(git_grafts_new(&grafts)); -} - -void test_grafts_parse__cleanup(void) -{ - git_grafts_free(grafts); - grafts = NULL; -} - -static void assert_parse_succeeds(git_grafts *grafts, const char *string, size_t n) -{ - cl_git_pass(git_grafts_parse(grafts, string, strlen(string))); - cl_assert_equal_i(git_grafts_size(grafts), n); -} - -static void assert_parse_fails(git_grafts *grafts, const char *string) -{ - cl_git_fail(git_grafts_parse(grafts, string, strlen(string))); -} - -static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t n, ...) -{ - git_commit_graft *commit; - git_oid oid; - va_list ap; - size_t i = 0; - - cl_git_pass(git_oid_fromstr(&oid, graft)); - cl_git_pass(git_grafts_get(&commit, grafts, &oid)); - cl_assert_equal_oid(&commit->oid, &oid); - cl_assert_equal_i(commit->parents.size, n); - - va_start(ap, n); - while (i < n) { - cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *))); - cl_assert_equal_oid(&commit->parents.ptr[i], &oid); - i++; - } - va_end(ap); -} - -void test_grafts_parse__single_oid(void) -{ - assert_parse_succeeds(grafts, OID1, 1); - assert_graft_contains(grafts, OID1, 0); -} - -void test_grafts_parse__single_oid_with_newline(void) -{ - assert_parse_succeeds(grafts, OID1 "\n", 1); - assert_graft_contains(grafts, OID1, 0); -} - -void test_grafts_parse__multiple_oids(void) -{ - assert_parse_succeeds(grafts, OID1 "\n" OID2 "\n" OID3, 3); - assert_graft_contains(grafts, OID1, 0); - assert_graft_contains(grafts, OID2, 0); - assert_graft_contains(grafts, OID3, 0); -} - -void test_grafts_parse__same_oid(void) -{ - assert_parse_succeeds(grafts, OID1 "\n" OID1, 1); - assert_graft_contains(grafts, OID1, 0); -} - -void test_grafts_parse__oid_with_parent(void) -{ - assert_parse_succeeds(grafts, OID1 " " OID2, 1); - assert_graft_contains(grafts, OID1, 1, OID2); -} - -void test_grafts_parse__oid_with_parent_and_newline(void) -{ - assert_parse_succeeds(grafts, OID1 " " OID2 "\n", 1); - assert_graft_contains(grafts, OID1, 1, OID2); -} - -void test_grafts_parse__oid_with_multiple_parents(void) -{ - assert_parse_succeeds(grafts, OID1 " " OID2 " " OID3 " " OID4 " " OID5, 1); - assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); -} - -void test_grafts_parse__multiple_oids_with_multiple_parents(void) -{ - assert_parse_succeeds(grafts, - OID1 " " OID2 " " OID3 " " OID4 " " OID5 "\n" - OID6 " " OID7 " " OID8 "\n" , 2); - assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); - assert_graft_contains(grafts, OID6, 2, OID7, OID8); -} - -void test_grafts_parse__multiple_spaces_fails(void) -{ - assert_parse_fails(grafts, OID1 " " OID2); -} - -void test_grafts_parse__trailing_space_fails(void) -{ - assert_parse_fails(grafts, OID1 " " OID2 " "); -} - -void test_grafts_parse__invalid_character_inbetween_fails(void) -{ - assert_parse_fails(grafts, OID1 " x " OID2); -} - -void test_grafts_parse__truncated_oid_fails(void) -{ - assert_parse_fails(grafts, OID_TRUNCATED); -} - -void test_grafts_parse__truncated_parent_fails(void) -{ - assert_parse_fails(grafts, OID1 " " OID_TRUNCATED); -} - -void test_grafts_parse__invalid_oid_fails(void) -{ - assert_parse_fails(grafts, OID_NONHEX); -} - -void test_grafts_parse__invalid_parent_fails(void) -{ - assert_parse_fails(grafts, OID1 " " OID_NONHEX); -} diff --git a/tests/grafts/shallow.c b/tests/grafts/shallow.c deleted file mode 100644 index a75b5a051..000000000 --- a/tests/grafts/shallow.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "clar_libgit2.h" - -#include "futils.h" -#include "grafts.h" -#include "repository.h" - -static git_repository *g_repo; -static git_oid g_shallow_oid; - -void test_grafts_shallow__set_feature_flag(void) -{ - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); -} - -void test_grafts_shallow__unset_feature_flag(void) -{ - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); -} - -void test_grafts_shallow__initialize(void) -{ - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); - cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); -} - -void test_grafts_shallow__cleanup(void) -{ - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); - cl_git_sandbox_cleanup(); -} - -void test_grafts_shallow__no_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_grafts_shallow__empty_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_mkfile("testrepo.git/shallow", ""); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_grafts_shallow__shallow_repo(void) -{ - g_repo = cl_git_sandbox_init("shallow.git"); - cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); -} - -void test_grafts_shallow__clears_errors(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); - cl_assert_equal_p(NULL, git_error_last()); -} - -void test_grafts_shallow__shallow_oids(void) -{ - git_commit_graft *graft; - git_grafts *grafts; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); - cl_assert_equal_i(1, git_grafts_size(grafts)); - cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); -} - -void test_grafts_shallow__cache_clearing(void) -{ - git_commit_graft *graft; - git_grafts *grafts; - git_oid tmp_oid; - - cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000")); - g_repo = cl_git_sandbox_init("shallow.git"); - cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); - - cl_assert_equal_i(1, git_grafts_size(grafts)); - cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); - - cl_git_mkfile("shallow.git/shallow", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" - "0000000000000000000000000000000000000000\n" - ); - - cl_git_pass(git_grafts_refresh(grafts)); - cl_assert_equal_i(2, git_grafts_size(grafts)); - cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); - cl_git_pass(git_grafts_get(&graft, grafts, &tmp_oid)); - - cl_git_pass(p_unlink("shallow.git/shallow")); - cl_git_pass(git_grafts_refresh(grafts)); - cl_assert_equal_i(0, git_grafts_size(grafts)); -} - -void test_grafts_shallow__errors_on_borked(void) -{ - git_grafts *grafts; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_mkfile("shallow.git/shallow", "lolno"); - cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); - cl_git_fail(git_grafts_refresh(grafts)); - cl_assert_equal_i(0, git_grafts_size(grafts)); - - cl_git_mkfile("shallow.git/shallow", "lolno\n"); - cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); - cl_git_fail(git_grafts_refresh(grafts)); - cl_assert_equal_i(0, git_grafts_size(grafts)); -} - -void test_grafts_shallow__revwalk_behavior(void) -{ - git_revwalk *w; - git_oid oid_1, oid_2, oid_3; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_revwalk_new(&w, g_repo)); - cl_git_pass(git_revwalk_push_head(w)); - - cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644 - cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w)); - - cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - - git_revwalk_free(w); -} - -void test_grafts_shallow__grafted_object(void) -{ - git_commit *commit; - - g_repo = cl_git_sandbox_init("shallow.git"); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid)); - - cl_assert_equal_i(0, git_commit_parentcount(commit)); - - git_commit_free(commit); -} diff --git a/tests/libgit2/grafts/basic.c b/tests/libgit2/grafts/basic.c new file mode 100644 index 000000000..4be4a12bf --- /dev/null +++ b/tests/libgit2/grafts/basic.c @@ -0,0 +1,123 @@ +#include "clar_libgit2.h" + +#include "futils.h" +#include "grafts.h" + +static git_repository *g_repo; + +void test_grafts_basic__initialize(void) +{ + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); + g_repo = cl_git_sandbox_init("grafted.git"); +} + +void test_grafts_basic__cleanup(void) +{ + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); + cl_git_sandbox_cleanup(); +} + +void test_grafts_basic__graft_add(void) +{ + git_array_oid_t parents = GIT_ARRAY_INIT; + git_oid oid_src, *oid1; + git_commit_graft *graft; + git_grafts *grafts; + + cl_git_pass(git_grafts_new(&grafts)); + + cl_assert(oid1 = git_array_alloc(parents)); + cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); + git_oid_cpy(oid1, &oid_src); + + git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_grafts_add(grafts, &oid_src, parents)); + git_array_clear(parents); + + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &oid_src)); + cl_assert_equal_s("f503807ffa920e407a600cfaee96b7152259acc7", git_oid_tostr_s(&graft->oid)); + cl_assert_equal_i(1, git_array_size(graft->parents)); + cl_assert_equal_s("2f3053cbff8a4ca2f0666de364ddb734a28a31a9", git_oid_tostr_s(git_array_get(graft->parents, 0))); + + git_grafts_free(grafts); +} + +void test_grafts_basic__grafted_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + git_commit *commit; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/branch")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[0]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[2]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &oids[0])); + + cl_assert_equal_i(1, git_commit_parentcount(commit)); + + git_commit_free(commit); + git_revwalk_free(w); +} + +void test_grafts_basic__grafted_objects(void) +{ + git_oid oid; + git_commit *commit; + + cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(1, git_commit_parentcount(commit)); + git_commit_free(commit); + + cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_assert_equal_i(4, git_commit_parentcount(commit)); + git_commit_free(commit); +} + +void test_grafts_basic__grafted_merge_revwalk(void) +{ + git_revwalk *w; + git_oid oids[10]; + size_t i = 0; + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_ref(w, "refs/heads/bottom")); + + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "66cc22a015f6ca75b34c82d28f78ba663876bade"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "e414f42f4e6bc6934563a2349a8600f0ab68618e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "8a00e91619098618be97c0d2ceabb05a2c58edd9"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "1c18e80a276611bb9b146590616bbc5aebdf2945"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "d7224d49d6d5aff6ade596ed74f4bcd4f77b29e2"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "0512adebd3782157f0d5c9b22b043f87b4aaff9e"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "f503807ffa920e407a600cfaee96b7152259acc7"); + cl_git_pass(git_revwalk_next(&oids[i++], w)); + cl_assert_equal_s(git_oid_tostr_s(&oids[i - 1]), "2f3053cbff8a4ca2f0666de364ddb734a28a31a9"); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oids[i++], w)); + + git_revwalk_free(w); +} diff --git a/tests/libgit2/grafts/parse.c b/tests/libgit2/grafts/parse.c new file mode 100644 index 000000000..de110c901 --- /dev/null +++ b/tests/libgit2/grafts/parse.c @@ -0,0 +1,149 @@ +#include "clar_libgit2.h" + +#include "grafts.h" + +#define OID0 "c0368f9f9743e950e6cfe1f45a649f8a9dfcd97e" +#define OID1 "cfc50a0db87ce908fb8a8c5b8f7b4ab96eee8643" +#define OID2 "6914d97cd08b9edf5e855fca211c750fa82fd80a" +#define OID3 "516521937d0e9ce9d0d836149a0702671f326b4a" +#define OID4 "e2c29d67ef2f217650196f94c796f0532b8caad6" +#define OID5 "79bcb936596cb50353fe7be28b7444e66e4a2842" +#define OID6 "b9c54107d57c17dbcaf646c4d52f66eb9e69d23d" +#define OID7 "9f8a746e9ad7b58cc840016bc3944d5ad262acb5" +#define OID8 "392f4beef7d0d15b2bc5b1abe1a754eba0ec36da" + +#define OID_TRUNCATED "392f4beef7d0d15b2bc5b1abe1a754eba0ec36d" +#define OID_NONHEX "9f8a746e9ax7b58cc840016bc3944d5ad262acb5" + +static git_grafts *grafts; + +void test_grafts_parse__initialize(void) +{ + cl_git_pass(git_grafts_new(&grafts)); +} + +void test_grafts_parse__cleanup(void) +{ + git_grafts_free(grafts); + grafts = NULL; +} + +static void assert_parse_succeeds(git_grafts *grafts, const char *string, size_t n) +{ + cl_git_pass(git_grafts_parse(grafts, string, strlen(string))); + cl_assert_equal_i(git_grafts_size(grafts), n); +} + +static void assert_parse_fails(git_grafts *grafts, const char *string) +{ + cl_git_fail(git_grafts_parse(grafts, string, strlen(string))); +} + +static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t n, ...) +{ + git_commit_graft *commit; + git_oid oid; + va_list ap; + size_t i = 0; + + cl_git_pass(git_oid_fromstr(&oid, graft)); + cl_git_pass(git_grafts_get(&commit, grafts, &oid)); + cl_assert_equal_oid(&commit->oid, &oid); + cl_assert_equal_i(commit->parents.size, n); + + va_start(ap, n); + while (i < n) { + cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *))); + cl_assert_equal_oid(&commit->parents.ptr[i], &oid); + i++; + } + va_end(ap); +} + +void test_grafts_parse__single_oid(void) +{ + assert_parse_succeeds(grafts, OID1, 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__single_oid_with_newline(void) +{ + assert_parse_succeeds(grafts, OID1 "\n", 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__multiple_oids(void) +{ + assert_parse_succeeds(grafts, OID1 "\n" OID2 "\n" OID3, 3); + assert_graft_contains(grafts, OID1, 0); + assert_graft_contains(grafts, OID2, 0); + assert_graft_contains(grafts, OID3, 0); +} + +void test_grafts_parse__same_oid(void) +{ + assert_parse_succeeds(grafts, OID1 "\n" OID1, 1); + assert_graft_contains(grafts, OID1, 0); +} + +void test_grafts_parse__oid_with_parent(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2, 1); + assert_graft_contains(grafts, OID1, 1, OID2); +} + +void test_grafts_parse__oid_with_parent_and_newline(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2 "\n", 1); + assert_graft_contains(grafts, OID1, 1, OID2); +} + +void test_grafts_parse__oid_with_multiple_parents(void) +{ + assert_parse_succeeds(grafts, OID1 " " OID2 " " OID3 " " OID4 " " OID5, 1); + assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); +} + +void test_grafts_parse__multiple_oids_with_multiple_parents(void) +{ + assert_parse_succeeds(grafts, + OID1 " " OID2 " " OID3 " " OID4 " " OID5 "\n" + OID6 " " OID7 " " OID8 "\n" , 2); + assert_graft_contains(grafts, OID1, 4, OID2, OID3, OID4, OID5); + assert_graft_contains(grafts, OID6, 2, OID7, OID8); +} + +void test_grafts_parse__multiple_spaces_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID2); +} + +void test_grafts_parse__trailing_space_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID2 " "); +} + +void test_grafts_parse__invalid_character_inbetween_fails(void) +{ + assert_parse_fails(grafts, OID1 " x " OID2); +} + +void test_grafts_parse__truncated_oid_fails(void) +{ + assert_parse_fails(grafts, OID_TRUNCATED); +} + +void test_grafts_parse__truncated_parent_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID_TRUNCATED); +} + +void test_grafts_parse__invalid_oid_fails(void) +{ + assert_parse_fails(grafts, OID_NONHEX); +} + +void test_grafts_parse__invalid_parent_fails(void) +{ + assert_parse_fails(grafts, OID1 " " OID_NONHEX); +} diff --git a/tests/libgit2/grafts/shallow.c b/tests/libgit2/grafts/shallow.c new file mode 100644 index 000000000..a75b5a051 --- /dev/null +++ b/tests/libgit2/grafts/shallow.c @@ -0,0 +1,146 @@ +#include "clar_libgit2.h" + +#include "futils.h" +#include "grafts.h" +#include "repository.h" + +static git_repository *g_repo; +static git_oid g_shallow_oid; + +void test_grafts_shallow__set_feature_flag(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); +} + +void test_grafts_shallow__unset_feature_flag(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); +} + +void test_grafts_shallow__initialize(void) +{ + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); + cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); +} + +void test_grafts_shallow__cleanup(void) +{ + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); + cl_git_sandbox_cleanup(); +} + +void test_grafts_shallow__no_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__empty_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_git_mkfile("testrepo.git/shallow", ""); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__shallow_repo(void) +{ + g_repo = cl_git_sandbox_init("shallow.git"); + cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); +} + +void test_grafts_shallow__clears_errors(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); + cl_assert_equal_p(NULL, git_error_last()); +} + +void test_grafts_shallow__shallow_oids(void) +{ + git_commit_graft *graft; + git_grafts *grafts; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); +} + +void test_grafts_shallow__cache_clearing(void) +{ + git_commit_graft *graft; + git_grafts *grafts; + git_oid tmp_oid; + + cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000")); + g_repo = cl_git_sandbox_init("shallow.git"); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + + cl_assert_equal_i(1, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); + + cl_git_mkfile("shallow.git/shallow", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644\n" + "0000000000000000000000000000000000000000\n" + ); + + cl_git_pass(git_grafts_refresh(grafts)); + cl_assert_equal_i(2, git_grafts_size(grafts)); + cl_git_pass(git_grafts_get(&graft, grafts, &g_shallow_oid)); + cl_git_pass(git_grafts_get(&graft, grafts, &tmp_oid)); + + cl_git_pass(p_unlink("shallow.git/shallow")); + cl_git_pass(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); +} + +void test_grafts_shallow__errors_on_borked(void) +{ + git_grafts *grafts; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_mkfile("shallow.git/shallow", "lolno"); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_git_fail(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); + + cl_git_mkfile("shallow.git/shallow", "lolno\n"); + cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); + cl_git_fail(git_grafts_refresh(grafts)); + cl_assert_equal_i(0, git_grafts_size(grafts)); +} + +void test_grafts_shallow__revwalk_behavior(void) +{ + git_revwalk *w; + git_oid oid_1, oid_2, oid_3; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_revwalk_new(&w, g_repo)); + cl_git_pass(git_revwalk_push_head(w)); + + cl_git_pass(git_revwalk_next(&oid_1, w)); // a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + cl_git_pass(git_revwalk_next(&oid_2, w)); // be3563ae3f795b2b4353bcce3a527ad0a4f7f644 + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid_3, w)); + + cl_assert_equal_s(git_oid_tostr_s(&oid_1), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_assert_equal_s(git_oid_tostr_s(&oid_2), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + + git_revwalk_free(w); +} + +void test_grafts_shallow__grafted_object(void) +{ + git_commit *commit; + + g_repo = cl_git_sandbox_init("shallow.git"); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &g_shallow_oid)); + + cl_assert_equal_i(0, git_commit_parentcount(commit)); + + git_commit_free(commit); +} -- cgit v1.2.1 From c01b7841b77c08189eae916d21d591027962a831 Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 28 Jul 2022 14:24:18 +0100 Subject: improve error handling --- .gitignore | 1 - include/git2/repository.h | 1 - src/libgit2/grafts.c | 10 +++++++--- src/libgit2/repository.c | 7 ------- src/libgit2/repository.h | 1 - 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index d43bd9c78..1b482f038 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,3 @@ CMakeSettings.json .vs .idea -.cache diff --git a/include/git2/repository.h b/include/git2/repository.h index 258b9ac00..c87f3c962 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -11,7 +11,6 @@ #include "types.h" #include "oid.h" #include "buffer.h" -#include "oidarray.h" /** * @file git2/repository.h diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 8bcefbab9..82be2a680 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -93,13 +93,17 @@ int git_grafts_refresh(git_grafts *grafts) if (!grafts->path) return 0; - error = git_futils_readbuffer_updated(&contents, grafts->path, - (grafts->path_checksum).id, &updated); - if (error < 0 || error == GIT_ENOTFOUND || !updated) { + if ((error = git_futils_readbuffer_updated(&contents, grafts->path, + (grafts->path_checksum).id, &updated)) < 0) { if (error == GIT_ENOTFOUND) { git_grafts_clear(grafts); error = 0; } + + goto cleanup; + } + + if (!updated) { goto cleanup; } diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 809617276..c36666c43 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -735,13 +735,6 @@ static int load_grafts(git_repository *repo) git_str path = GIT_STR_INIT; int error; - if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || - (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || - (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) - goto error; - - git_str_clear(&path); - if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 || (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0) goto error; diff --git a/src/libgit2/repository.h b/src/libgit2/repository.h index 6d39bb92a..3cca53b3e 100644 --- a/src/libgit2/repository.h +++ b/src/libgit2/repository.h @@ -25,7 +25,6 @@ #include "submodule.h" #include "diff_driver.h" #include "grafts.h" -#include "oidarray.h" #define DOT_GIT ".git" #define GIT_DIR DOT_GIT "/" -- cgit v1.2.1 From 14d2a60a5bdb6fe62b65751bda0ce01a66ac5e99 Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 28 Jul 2022 14:30:30 +0100 Subject: fix load_grafts --- src/libgit2/repository.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index c36666c43..809617276 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -735,6 +735,13 @@ static int load_grafts(git_repository *repo) git_str path = GIT_STR_INIT; int error; + if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || + (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) + goto error; + + git_str_clear(&path); + if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 || (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0) goto error; -- cgit v1.2.1 From 62cc77a16d62410140e31960189e566f16b22772 Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 28 Jul 2022 16:03:59 +0100 Subject: refactor commit parent assignment with graft --- src/libgit2/commit.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index 2138d6eb2..6f689e362 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -499,6 +499,22 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) return commit_parse(commit, data, size, 0); } +static int assign_parents_from_graft(git_commit *commit, git_commit_graft *graft) { + size_t idx; + git_oid *oid; + + git_array_clear(commit->parent_ids); + git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); + git_array_foreach(graft->parents, idx, oid) { + git_oid *id = git_array_alloc(commit->parent_ids); + GIT_ERROR_CHECK_ALLOC(id); + + git_oid_cpy(id, oid); + } + + return 0; +} + int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) { git_repository *repo = git_object_owner((git_object *)commit); @@ -513,21 +529,11 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned return 0; /* Perform necessary grafts */ - if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) == 0 || - git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) == 0) { - size_t idx; - git_oid *oid; - git_array_clear(commit->parent_ids); - git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents)); - git_array_foreach(graft->parents, idx, oid) { - git_oid *id = git_array_alloc(commit->parent_ids); - GIT_ERROR_CHECK_ALLOC(id); - - git_oid_cpy(id, oid); - } - } - - return 0; + if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) != 0 && + git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) != 0) + return 0; + + return assign_parents_from_graft(commit, graft); } int git_commit__parse(void *_commit, git_odb_object *odb_obj) -- cgit v1.2.1 From a544a91058cc310a0e36e290debe5ad59040fab1 Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 28 Jul 2022 16:05:21 +0100 Subject: rename function assign_parents_from_graft --- src/libgit2/commit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index 6f689e362..43d04b2c0 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -499,7 +499,7 @@ int git_commit__parse_raw(void *commit, const char *data, size_t size) return commit_parse(commit, data, size, 0); } -static int assign_parents_from_graft(git_commit *commit, git_commit_graft *graft) { +static int assign_commit_parents_from_graft(git_commit *commit, git_commit_graft *graft) { size_t idx; git_oid *oid; @@ -533,7 +533,7 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) != 0) return 0; - return assign_parents_from_graft(commit, graft); + return assign_commit_parents_from_graft(commit, graft); } int git_commit__parse(void *_commit, git_odb_object *odb_obj) -- cgit v1.2.1 From 73d25f0e7b026d7b744e249d922f248376bcce5d Mon Sep 17 00:00:00 2001 From: yuangli Date: Fri, 29 Jul 2022 13:53:29 +0100 Subject: remove build errors --- include/git2/remote.h | 12 ++-- include/git2/repository.h | 1 + src/libgit2/clone.c | 2 +- src/libgit2/commit.c | 2 +- src/libgit2/fetch.c | 7 +-- src/libgit2/repository.c | 109 +------------------------------------ src/libgit2/transports/smart_pkt.c | 16 +++--- 7 files changed, 21 insertions(+), 128 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 871d898e5..33f5103ce 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -743,6 +743,11 @@ typedef struct { */ git_proxy_options proxy_opts; + /** + * Depth of the fetch to perform + */ + int depth; + /** * Whether to allow off-site redirects. If this is not * specified, the `http.followRedirects` configuration setting @@ -754,16 +759,11 @@ typedef struct { * Extra headers for this fetch operation */ git_strarray custom_headers; - - /** - * Depth of the fetch to perform - */ - int depth; } git_fetch_options; #define GIT_FETCH_OPTIONS_VERSION 1 #define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \ - GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, { NULL }, -1 } + GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, -1 } /** * Initialize git_fetch_options structure diff --git a/include/git2/repository.h b/include/git2/repository.h index 24a94118b..d6b054dc3 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "buffer.h" +#include "oidarray.h" /** * @file git2/repository.h diff --git a/src/libgit2/clone.c b/src/libgit2/clone.c index 101c741b1..ee1f2b892 100644 --- a/src/libgit2/clone.c +++ b/src/libgit2/clone.c @@ -411,7 +411,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch fetch_opts.update_fetchhead = 0; if (fetch_opts.depth == -1) fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; - git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); + git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_str_cstr(&reflog_message))) != 0) goto cleanup; diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index 75cc8837c..528d8beb7 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -422,7 +422,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig buffer += tree_len; } - while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { + while (git_object__parse_oid_header(&parent_id, &buffer, buffer_end, "parent ", GIT_OID_SHA1) == 0) { git_oid *new_id = git_array_alloc(commit->parent_ids); GIT_ERROR_CHECK_ALLOC(new_id); diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 10155662d..e4a8f0382 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -209,12 +209,7 @@ int git_fetch_download_pack(git_remote *remote) if (!remote->need_pack) return 0; - if (callbacks) { - progress = callbacks->transfer_progress; - payload = callbacks->payload; - } - - if ((error = t->download_pack(t, remote->repo, &remote->stats, progress, payload)) < 0) + if ((error = t->download_pack(t, remote->repo, &remote->stats)) < 0) return error; if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) < 0) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index adb4721ad..d9bc537fe 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3340,109 +3340,6 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -// int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) -// { -// git_buf path = GIT_BUF_INIT; -// git_buf contents = GIT_BUF_INIT; -// int error, updated, line_num = 1; -// char *line; -// chror = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated); -// git_buf_dispose(&path); - -// if (error < 0 && error != GIT_ENOTFOUND) -// return error; - -// /* cancel out GIT_ENOTFOUND */ -// git_error_clear(); -// error = 0; - -// if (!updated) { -// out = repo->shallow_grafts; -// goto cleanup; -// } - -// git_array_clear(repo->shallow_grafts); - -// buffer = contents.ptr; -// while ((line = git__strsep(&buffer, "\n")) != NULL) { -// git_oid *oid = git_array_alloc(repo->shallow_grafts); - -// error = git_oid_fromstr(oid, line); -// if (error < 0) { -// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); -// git_array_clear(repo->shallow_grafts); -// error = -1; -// goto cleanup; -// } -// ++line_num; -// } - -// if (*buffer) { -// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); -// git_array_clear(repo->shallow_grafts); -// error = -1; -// goto cleanup; -// } - -// *out = repo->shallow_grafts; - -// cleanup: -// git_buf_dispose(&contents); - -// return error;ar *buffer; - -// assert(out && repo); - -// if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) -// return error; - -// //error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_checksum, &updated); -// error = git_futils_readbuffer_updated(&contents, git_buf_cstr(&path), &repo->shallow_grafts->git_grafts->path_checksum, &updated); -// git_buf_dispose(&path); - -// if (error < 0 && error != GIT_ENOTFOUND) -// return error; - -// /* cancel out GIT_ENOTFOUND */ -// git_error_clear(); -// error = 0; - -// if (!updated) { -// out = repo->shallow_grafts; -// goto cleanup; -// } - -// git_array_clear(repo->shallow_grafts); - -// buffer = contents.ptr; -// while ((line = git__strsep(&buffer, "\n")) != NULL) { -// git_oid *oid = git_array_alloc(repo->shallow_grafts); - -// error = git_oid_fromstr(oid, line); -// if (error < 0) { -// git_error_set(GIT_ERROR_REPOSITORY, "Invalid OID at line %d", line_num); -// git_array_clear(repo->shallow_grafts); -// error = -1; -// goto cleanup; -// } -// ++line_num; -// } - -// if (*buffer) { -// git_error_set(GIT_ERROR_REPOSITORY, "No EOL at line %d", line_num); -// git_array_clear(repo->shallow_grafts); -// error = -1; -// goto cleanup; -// } - -// *out = repo->shallow_grafts; - -// cleanup: -// git_buf_dispose(&contents); - -// return error; -// } - int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { int error =0; if (!repo->shallow_grafts) @@ -3455,17 +3352,17 @@ int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) { git_filebuf file = GIT_FILEBUF_INIT; - git_buf path = GIT_BUF_INIT; + git_str path = GIT_STR_INIT; int error = 0; size_t idx; git_oid *oid; assert(repo); - if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) + if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0) return error; - if ((error = git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) + if ((error = git_filebuf_open(&file, git_str_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) return error; git_array_foreach(roots, idx, oid) { diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index e368cb7e2..f9fde00f1 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -678,23 +678,23 @@ int git_pkt_buffer_wants( git_buf shallow_buf = GIT_BUF_INIT; git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i)); - git_buf_puts(&shallow_buf, "shallow "); - git_buf_put(&shallow_buf, oid, GIT_OID_HEXSZ); - git_buf_putc(&shallow_buf, '\n'); + git_str_puts(&shallow_buf, "shallow "); + git_str_put(&shallow_buf, oid, GIT_OID_HEXSZ); + git_str_putc(&shallow_buf, '\n'); - git_buf_printf(buf, "%04x%s", (unsigned int)git_buf_len(&shallow_buf) + 4, git_buf_cstr(&shallow_buf)); + git_str_printf(buf, "%04x%s", (unsigned int)git_str_len(&shallow_buf) + 4, git_str_cstr(&shallow_buf)); - if (git_buf_oom(buf)) + if (git_str_oom(buf)) return -1; } if (wants->depth > 0) { git_buf deepen_buf = GIT_BUF_INIT; - git_buf_printf(&deepen_buf, "deepen %d\n", wants->depth); - git_buf_printf(buf,"%04x%s", (unsigned int)git_buf_len(&deepen_buf) + 4, git_buf_cstr(&deepen_buf)); + git_str_printf(&deepen_buf, "deepen %d\n", wants->depth); + git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); - if (git_buf_oom(buf)) + if (git_str_oom(buf)) return -1; } -- cgit v1.2.1 From 598ec303c6862f581c22c49228d543442e30257a Mon Sep 17 00:00:00 2001 From: yuangli Date: Fri, 29 Jul 2022 15:04:17 +0100 Subject: eliminate build warnings --- src/libgit2/fetch.c | 2 - src/libgit2/grafts.c | 7 +-- src/libgit2/grafts.h | 2 +- src/libgit2/repository.c | 18 +++++-- src/libgit2/transports/smart_pkt.c | 4 +- tests/clone/shallow.c | 105 ------------------------------------- tests/libgit2/clone/shallow.c | 105 +++++++++++++++++++++++++++++++++++++ 7 files changed, 123 insertions(+), 120 deletions(-) delete mode 100644 tests/clone/shallow.c create mode 100644 tests/libgit2/clone/shallow.c diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index e4a8f0382..b90ce2ee8 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -202,8 +202,6 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) int git_fetch_download_pack(git_remote *remote) { git_transport *t = remote->transport; - git_indexer_progress_cb progress = NULL; - void *payload = NULL; int error; if (!remote->need_pack) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 82be2a680..f1054fa36 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -220,9 +220,8 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi return 0; } -int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts) +int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts) { - git_array_oid_t oids = GIT_ARRAY_INIT; const git_oid *oid; size_t i = 0; int error; @@ -230,13 +229,11 @@ int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts) assert(out && grafts); while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { - git_oid *cpy = git_array_alloc(oids); + git_oid *cpy = git_array_alloc(*out); GIT_ERROR_CHECK_ALLOC(cpy); git_oid_cpy(cpy, oid); } - git_oidarray__from_array(out, &oids); - return 0; } diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index fd9ef6736..4139438bb 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -31,7 +31,7 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); -int git_grafts_get_oids(git_oidarray *out, git_grafts *grafts); +int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts); size_t git_grafts_size(git_grafts *grafts); #endif diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index d9bc537fe..bc2aba324 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3341,12 +3341,20 @@ int git_repository_state_cleanup(git_repository *repo) } int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { - int error =0; - if (!repo->shallow_grafts) - load_grafts(repo); + int error = 0; + + if (!repo->shallow_grafts && (error = load_grafts(repo)) < 0) + return error; + + if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0) { + return error; + } - git_grafts_refresh(repo->shallow_grafts); - return git_grafts_get_oids(out, repo->shallow_grafts); + if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) { + return error; + } + + return 0; } int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index f9fde00f1..951356c29 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -675,7 +675,7 @@ int git_pkt_buffer_wants( /* Tell the server about our shallow objects */ for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { char oid[GIT_OID_HEXSZ]; - git_buf shallow_buf = GIT_BUF_INIT; + git_str shallow_buf = GIT_STR_INIT; git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i)); git_str_puts(&shallow_buf, "shallow "); @@ -689,7 +689,7 @@ int git_pkt_buffer_wants( } if (wants->depth > 0) { - git_buf deepen_buf = GIT_BUF_INIT; + git_str deepen_buf = GIT_STR_INIT; git_str_printf(&deepen_buf, "deepen %d\n", wants->depth); git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); diff --git a/tests/clone/shallow.c b/tests/clone/shallow.c deleted file mode 100644 index 01852dfed..000000000 --- a/tests/clone/shallow.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" -#include "repository.h" - -void test_clone_shallow__initialize(void) -{ - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); -} - -void test_clone_shallow__cleanup(void) -{ - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); - cl_git_sandbox_cleanup(); -} - -static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) -{ - GIT_UNUSED(payload); - - cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master")); - - return 0; -} - -void test_clone_shallow__clone_depth_one(void) -{ - git_buf path = GIT_BUF_INIT; - git_repository *repo; - git_revwalk *walk; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_oid oid; - git_oidarray roots; - size_t num_commits = 0; - int error = 0; - - clone_opts.fetch_opts.depth = 1; - clone_opts.remote_cb = remote_single_branch; - - git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_1"); - - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts)); - - cl_assert_equal_b(true, git_repository_is_shallow(repo)); - - cl_git_pass(git_repository_shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.count); - cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ids[0])); - - git_revwalk_new(&walk, repo); - - git_revwalk_push_head(walk); - - while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - num_commits++; - } - - cl_assert_equal_i(num_commits, 1); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_buf_dispose(&path); - git_revwalk_free(walk); - git_repository_free(repo); -} - -void test_clone_shallow__clone_depth_five(void) -{ - git_buf path = GIT_BUF_INIT; - git_repository *repo; - git_revwalk *walk; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_oid oid; - git_oidarray roots; - size_t num_commits = 0; - int error = 0; - - clone_opts.fetch_opts.depth = 5; - clone_opts.remote_cb = remote_single_branch; - - git_buf_joinpath(&path, clar_sandbox_path(), "shallowclone_5"); - - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_buf_cstr(&path), &clone_opts)); - - cl_assert_equal_b(true, git_repository_is_shallow(repo)); - - cl_git_pass(git_repository_shallow_roots(&roots, repo)); - cl_assert_equal_i(3, roots.count); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ids[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ids[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[2])); - - git_revwalk_new(&walk, repo); - - git_revwalk_push_head(walk); - - while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - num_commits++; - } - - cl_assert_equal_i(num_commits, 13); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_buf_dispose(&path); - git_revwalk_free(walk); - git_repository_free(repo); -} diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c new file mode 100644 index 000000000..2cd3d6cac --- /dev/null +++ b/tests/libgit2/clone/shallow.c @@ -0,0 +1,105 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "repository.h" + +void test_clone_shallow__initialize(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); +} + +void test_clone_shallow__cleanup(void) +{ + git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); + cl_git_sandbox_cleanup(); +} + +static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) +{ + GIT_UNUSED(payload); + + cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master")); + + return 0; +} + +void test_clone_shallow__clone_depth_one(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + roots; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 1; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_1"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository_shallow_roots(&roots, repo)); + cl_assert_equal_i(1, roots.count); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ids[0])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 1); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} + +void test_clone_shallow__clone_depth_five(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + git_oidarray roots; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 5; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_5"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository_shallow_roots(&roots, repo)); + cl_assert_equal_i(3, roots.count); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ids[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ids[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[2])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 13); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} -- cgit v1.2.1 From 179aac788d45d3683a93ad478bfb7371c549ca98 Mon Sep 17 00:00:00 2001 From: yuangli Date: Fri, 29 Jul 2022 16:04:43 +0100 Subject: fix clone::shallow test behaviour --- src/libgit2/transports/smart_protocol.c | 2 -- tests/libgit2/clone/shallow.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index cd90db43f..f2a6ac508 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -375,10 +375,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c while ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) == 0) { if (pkt->type == GIT_PKT_SHALLOW) { - printf("shallow %s\n", git_oid_tostr_s(&pkt->oid)); git_shallowarray_add(wants->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_UNSHALLOW) { - printf("unshallow %s\n", git_oid_tostr_s(&pkt->oid)); git_shallowarray_remove(wants->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_FLUSH) { /* Server is done, stop processing shallow oids */ diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index 2cd3d6cac..4b27b27a9 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -29,7 +29,7 @@ void test_clone_shallow__clone_depth_one(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - roots; + git_oidarray roots; size_t num_commits = 0; int error = 0; -- cgit v1.2.1 From e7294e870398d72b79a436b628170ffcaaa1713c Mon Sep 17 00:00:00 2001 From: yuangli Date: Mon, 1 Aug 2022 21:42:11 +0100 Subject: fix memory leaks about packets --- src/libgit2/transports/smart_pkt.c | 2 ++ src/libgit2/transports/smart_protocol.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index 951356c29..5808b8816 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -694,6 +694,8 @@ int git_pkt_buffer_wants( git_str_printf(&deepen_buf, "deepen %d\n", wants->depth); git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); + git_str_dispose(&deepen_buf); + if (git_str_oom(buf)) return -1; } diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index f2a6ac508..a44d0c853 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -385,8 +385,12 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_error_set(GIT_ERROR_NET, "Unexpected pkt type"); goto on_error; } + + git_pkt_free((git_pkt *) pkt); } + git_pkt_free((git_pkt *) pkt); + if (error < 0) { goto on_error; } -- cgit v1.2.1 From 2d33fe78858354c508afb77d80f32a5a747b801e Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 13:15:22 +0100 Subject: refactor git_fetch_option.depth and usage --- include/git2/remote.h | 4 +++- src/libgit2/clone.c | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 33f5103ce..f3415d843 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -744,7 +744,9 @@ typedef struct { git_proxy_options proxy_opts; /** - * Depth of the fetch to perform + * Depth of the fetch to perform, has to be a positive integer. + * + * The default is -1, which will fetch the full history. */ int depth; diff --git a/src/libgit2/clone.c b/src/libgit2/clone.c index ee1f2b892..95bddeae6 100644 --- a/src/libgit2/clone.c +++ b/src/libgit2/clone.c @@ -389,6 +389,11 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c return error; } +static int git_fetch_is_shallow(git_fetch_options *opts) +{ + return opts->depth > 0; +} + static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch) { int error; @@ -409,8 +414,10 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; - if (fetch_opts.depth == -1) + + if (!git_fetch_is_shallow(opts)) fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; + git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_str_cstr(&reflog_message))) != 0) -- cgit v1.2.1 From 4536477ee1f884501717b3a4a67da3bc4974e7f8 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 14:35:08 +0100 Subject: fix memory leak --- src/libgit2/repository.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index bc2aba324..105ea647f 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3380,6 +3380,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro git_filebuf_commit(&file); + git_str_dispose(&path); + if (load_grafts(repo) < 0) return -1; -- cgit v1.2.1 From e93d0815a8de2806667851e31dbd06578db00f95 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 14:35:27 +0100 Subject: attempt to fix nego.shallowarray memory leak --- src/libgit2/remote.c | 3 +++ src/libgit2/transports/smart.c | 6 ++++++ src/libgit2/transports/smart.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/libgit2/remote.c b/src/libgit2/remote.c index 02d271d7d..c3d3af530 100644 --- a/src/libgit2/remote.c +++ b/src/libgit2/remote.c @@ -22,6 +22,7 @@ #include "git2/types.h" #include "git2/oid.h" #include "git2/net.h" +#include "transports/smart.h" #define CONFIG_URL_FMT "remote.%s.url" #define CONFIG_PUSHURL_FMT "remote.%s.pushurl" @@ -2163,6 +2164,8 @@ void git_remote_free(git_remote *remote) free_heads(&remote->local_heads); git_vector_free(&remote->local_heads); + git_shallowarray_free((remote->nego).shallow_roots); + git_push_free(remote->push); git__free(remote->url); git__free(remote->pushurl); diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index 9d1afeb05..df8e4da4a 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -510,3 +510,9 @@ int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) /* no git_array_remove… meh */ return -1; } + +void git_shallowarray_free(git_shallowarray *array) +{ + git_array_clear(array->array); + git__free(array); +} diff --git a/src/libgit2/transports/smart.h b/src/libgit2/transports/smart.h index bc072d2fe..f9577cdee 100644 --- a/src/libgit2/transports/smart.h +++ b/src/libgit2/transports/smart.h @@ -203,4 +203,6 @@ struct git_shallowarray { git_array_oid_t array; }; +void git_shallowarray_free(git_shallowarray *array); + #endif -- cgit v1.2.1 From da04d3fc5e737b990e884129241f2ea3cba4cf6a Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 16:30:48 +0100 Subject: fix grafts and shallowarray memory leaks --- src/libgit2/grafts.c | 3 +++ src/libgit2/remote.c | 7 +++++-- src/libgit2/repository.c | 6 ++---- src/libgit2/transports/smart.c | 6 ------ src/libgit2/transports/smart.h | 2 -- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index f1054fa36..dd1be3434 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -43,6 +43,9 @@ int git_grafts_from_file(git_grafts **out, const char *path) git_grafts *grafts = NULL; int error; + if (*out) + return git_grafts_refresh(*out); + if ((error = git_grafts_new(&grafts)) < 0) goto error; diff --git a/src/libgit2/remote.c b/src/libgit2/remote.c index c3d3af530..63346e941 100644 --- a/src/libgit2/remote.c +++ b/src/libgit2/remote.c @@ -2150,6 +2150,11 @@ void git_remote_free(git_remote *remote) remote->transport = NULL; } + if (remote->nego.shallow_roots) { + git_array_clear(remote->nego.shallow_roots->array); + git__free(remote->nego.shallow_roots); + } + git_vector_free(&remote->refs); free_refspecs(&remote->refspecs); @@ -2164,8 +2169,6 @@ void git_remote_free(git_remote *remote) free_heads(&remote->local_heads); git_vector_free(&remote->local_heads); - git_shallowarray_free((remote->nego).shallow_roots); - git_push_free(remote->push); git__free(remote->url); git__free(remote->pushurl); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 105ea647f..0d149a626 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3346,13 +3346,11 @@ int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { if (!repo->shallow_grafts && (error = load_grafts(repo)) < 0) return error; - if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0) { + if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0) return error; - } - if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) { + if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) return error; - } return 0; } diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index df8e4da4a..9d1afeb05 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -510,9 +510,3 @@ int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) /* no git_array_remove… meh */ return -1; } - -void git_shallowarray_free(git_shallowarray *array) -{ - git_array_clear(array->array); - git__free(array); -} diff --git a/src/libgit2/transports/smart.h b/src/libgit2/transports/smart.h index f9577cdee..bc072d2fe 100644 --- a/src/libgit2/transports/smart.h +++ b/src/libgit2/transports/smart.h @@ -203,6 +203,4 @@ struct git_shallowarray { git_array_oid_t array; }; -void git_shallowarray_free(git_shallowarray *array); - #endif -- cgit v1.2.1 From 8ef492fafcc05ccfa90481057eccc8ba4f5e730a Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 16:46:44 +0100 Subject: fix build warning --- src/libgit2/clone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libgit2/clone.c b/src/libgit2/clone.c index 95bddeae6..5e07dc733 100644 --- a/src/libgit2/clone.c +++ b/src/libgit2/clone.c @@ -389,7 +389,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c return error; } -static int git_fetch_is_shallow(git_fetch_options *opts) +static int git_fetch_is_shallow(const git_fetch_options *opts) { return opts->depth > 0; } -- cgit v1.2.1 From 829555a9382f74af5280ab6cc2ac505534a4cecb Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 2 Aug 2022 16:47:01 +0100 Subject: edit tests for shallow clones --- tests/libgit2/clone/shallow.c | 48 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index 4b27b27a9..7fb056f91 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -22,6 +22,32 @@ static int remote_single_branch(git_remote **out, git_repository *repo, const ch return 0; } +void test_clone_shallow__clone_depth_zero(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_array_oid_t roots = GIT_ARRAY_INIT; + + clone_opts.fetch_opts.depth = 0; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_0"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + /* cloning with depth 0 results in a full clone. */ + cl_assert_equal_b(false, git_repository_is_shallow(repo)); + + /* full clones do not have shallow roots. */ + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(0, roots.size); + + git_array_clear(roots); + git_str_dispose(&path); + git_repository_free(repo); +} + void test_clone_shallow__clone_depth_one(void) { git_str path = GIT_STR_INIT; @@ -29,7 +55,7 @@ void test_clone_shallow__clone_depth_one(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_oidarray roots; + git_array_oid_t roots = GIT_ARRAY_INIT; size_t num_commits = 0; int error = 0; @@ -42,9 +68,9 @@ void test_clone_shallow__clone_depth_one(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository_shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.count); - cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ids[0])); + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(1, roots.size); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); git_revwalk_new(&walk, repo); @@ -57,6 +83,7 @@ void test_clone_shallow__clone_depth_one(void) cl_assert_equal_i(num_commits, 1); cl_assert_equal_i(error, GIT_ITEROVER); + git_array_clear(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); @@ -69,7 +96,7 @@ void test_clone_shallow__clone_depth_five(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_oidarray roots; + git_array_oid_t roots = GIT_ARRAY_INIT; size_t num_commits = 0; int error = 0; @@ -82,11 +109,11 @@ void test_clone_shallow__clone_depth_five(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository_shallow_roots(&roots, repo)); - cl_assert_equal_i(3, roots.count); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ids[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ids[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ids[2])); + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(3, roots.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); git_revwalk_new(&walk, repo); @@ -99,6 +126,7 @@ void test_clone_shallow__clone_depth_five(void) cl_assert_equal_i(num_commits, 13); cl_assert_equal_i(error, GIT_ITEROVER); + git_array_clear(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); -- cgit v1.2.1 From 09b3d33d6dba7f4804b478a72dec3258405856c2 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 9 Aug 2022 19:23:54 +0100 Subject: fix memory leak --- src/libgit2/transports/smart_pkt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index 5808b8816..832da450c 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -684,6 +684,8 @@ int git_pkt_buffer_wants( git_str_printf(buf, "%04x%s", (unsigned int)git_str_len(&shallow_buf) + 4, git_str_cstr(&shallow_buf)); + git_str_dispose(&shallow_buf); + if (git_str_oom(buf)) return -1; } -- cgit v1.2.1 From df5eb3239b1419b3f4382d7bcca9a5d85611d7d3 Mon Sep 17 00:00:00 2001 From: yuangli Date: Tue, 9 Aug 2022 19:24:57 +0100 Subject: support fetch unshallow option on shallow repos --- include/git2/remote.h | 9 ++++- src/libgit2/clone.c | 7 +--- src/libgit2/fetch.c | 9 +++-- src/libgit2/repository.c | 19 ++++++---- src/libgit2/transports/smart.c | 26 +++++++++++--- tests/libgit2/clone/shallow.c | 41 +++++++++++++++++++++ tests/libgit2/transports/smart/shallowarray.c | 52 +++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 tests/libgit2/transports/smart/shallowarray.c diff --git a/include/git2/remote.h b/include/git2/remote.h index f3415d843..240e5aa4e 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -750,6 +750,13 @@ typedef struct { */ int depth; + /** + * Unshallow flag of the fetch to perform. + * + * The default is 0, which means the flag is off. + */ + int unshallow; + /** * Whether to allow off-site redirects. If this is not * specified, the `http.followRedirects` configuration setting @@ -765,7 +772,7 @@ typedef struct { #define GIT_FETCH_OPTIONS_VERSION 1 #define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \ - GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, -1 } + GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, -1, 0 } /** * Initialize git_fetch_options structure diff --git a/src/libgit2/clone.c b/src/libgit2/clone.c index 5e07dc733..6f34cb7ca 100644 --- a/src/libgit2/clone.c +++ b/src/libgit2/clone.c @@ -389,11 +389,6 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c return error; } -static int git_fetch_is_shallow(const git_fetch_options *opts) -{ - return opts->depth > 0; -} - static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch) { int error; @@ -415,7 +410,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; - if (!git_fetch_is_shallow(opts)) + if (opts->depth <= 0) fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index b90ce2ee8..a015cfbd3 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -61,7 +61,7 @@ static int mark_local(git_remote *remote) git_vector_foreach(&remote->refs, i, head) { /* If we have the object, mark it so we don't ask for it */ - if (git_odb_exists(odb, &head->oid)) + if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid)) head->local = 1; else remote->need_pack = 1; @@ -173,6 +173,7 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) git_transport *t = remote->transport; remote->need_pack = 0; + remote->nego.depth = opts->unshallow ? INT_MAX : opts->depth; if (filter_wants(remote, opts) < 0) return -1; @@ -181,13 +182,17 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) if (!remote->need_pack) return 0; + if (opts->unshallow && opts->depth > 0) { + git_error_set(GIT_ERROR_INVALID, "options '--depth' and '--unshallow' cannot be used together"); + return -1; + } + /* * Now we have everything set up so we can start tell the * server what we want and what we have. */ remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; remote->nego.count = remote->refs.length; - remote->nego.depth = opts->depth; remote->nego.shallow_roots = git__malloc(sizeof(git_shallowarray)); git_array_init(remote->nego.shallow_roots->array); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 0d149a626..13559ef07 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3366,10 +3366,10 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro assert(repo); if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0) - return error; + goto on_error; if ((error = git_filebuf_open(&file, git_str_cstr(&path), GIT_FILEBUF_HASH_CONTENTS, 0666)) < 0) - return error; + goto on_error; git_array_foreach(roots, idx, oid) { git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); @@ -3378,12 +3378,19 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro git_filebuf_commit(&file); - git_str_dispose(&path); + if ((error = load_grafts(repo)) < 0) { + error = -1; + goto on_error; + } - if (load_grafts(repo) < 0) - return -1; + if (git_array_size(roots) == 0) { + remove(path.ptr); + } - return 0; +on_error: + git_str_dispose(&path); + + return error; } int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index 9d1afeb05..b0925c8bb 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -496,17 +496,35 @@ const git_oid * git_shallowarray_get(git_shallowarray *array, size_t idx) int git_shallowarray_add(git_shallowarray *array, git_oid *oid) { size_t oid_index; + if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, &oid) < 0) { git_oid *tmp = git_array_alloc(array->array); + GIT_ERROR_CHECK_ALLOC(tmp); + git_oid_cpy(tmp, oid); } + return 0; } int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) { - GIT_UNUSED(array); - GIT_UNUSED(oid); - /* no git_array_remove… meh */ - return -1; + git_array_oid_t new_array = GIT_ARRAY_INIT; + git_oid *element; + git_oid *tmp; + size_t i; + + git_array_foreach(array->array, i, element) { + if (git_oid_cmp(oid, element)) { + tmp = git_array_alloc(new_array); + GIT_ERROR_CHECK_ALLOC(tmp); + + git_oid_cpy(tmp, element); + } + } + + git_array_clear(array->array); + array->array = new_array; + + return 0; } diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index 7fb056f91..2a88d5d05 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -131,3 +131,44 @@ void test_clone_shallow__clone_depth_five(void) git_revwalk_free(walk); git_repository_free(repo); } + +void test_clone_shallow__unshallow(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; + git_remote *origin = NULL; + git_oid oid; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 5; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "unshallow"); + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + fetch_opts.unshallow = 1; + cl_git_pass(git_remote_lookup(&origin, repo, "origin")); + + cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL)); + cl_assert_equal_b(false, git_repository_is_shallow(repo)); + + git_revwalk_new(&walk, repo); + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 21); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_remote_free(origin); + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} diff --git a/tests/libgit2/transports/smart/shallowarray.c b/tests/libgit2/transports/smart/shallowarray.c new file mode 100644 index 000000000..c51e62713 --- /dev/null +++ b/tests/libgit2/transports/smart/shallowarray.c @@ -0,0 +1,52 @@ +#include "clar_libgit2.h" + +#include "git2/oid.h" +#include "git2/transport.h" + +#include "common.h" +#include "transports/smart.h" +#include "oid.h" + +#include + +#define oid_0 "c070ad8c08840c8116da865b2d65593a6bb9cd2a" +#define oid_1 "0966a434eb1a025db6b71485ab63a3bfbea520b6" +#define oid_2 "83834a7afdaa1a1260568567f6ad90020389f664" + +void test_transports_smart_shallowarray__add_and_remove_oid_from_shallowarray(void) +{ + git_oid oid_0_obj, oid_1_obj, oid_2_obj; + git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); + git_array_init(shallow_roots->array); + + git_oid_fromstr(&oid_0_obj, oid_0); + git_oid_fromstr(&oid_1_obj, oid_1); + git_oid_fromstr(&oid_2_obj, oid_2); + + git_shallowarray_add(shallow_roots, &oid_0_obj); + git_shallowarray_add(shallow_roots, &oid_1_obj); + git_shallowarray_add(shallow_roots, &oid_2_obj); + + cl_assert_equal_i(3, shallow_roots->array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&shallow_roots->array.ptr[2])); + + git_shallowarray_remove(shallow_roots, &oid_2_obj); + + cl_assert_equal_i(2, shallow_roots->array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); + + git_shallowarray_remove(shallow_roots, &oid_1_obj); + + cl_assert_equal_i(1, shallow_roots->array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); + + git_shallowarray_remove(shallow_roots, &oid_0_obj); + + cl_assert_equal_i(0, shallow_roots->array.size); + + git_array_clear(shallow_roots->array); + git__free(shallow_roots); +} -- cgit v1.2.1 From 49e641be8c5549f6f5731d6d72e9e6902e71d0e1 Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 11 Aug 2022 09:32:28 +0100 Subject: remove unused api --- include/git2/remote.h | 2 +- include/git2/repository.h | 11 ----------- src/libgit2/repository.c | 14 -------------- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 240e5aa4e..f1cee17aa 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -751,7 +751,7 @@ typedef struct { int depth; /** - * Unshallow flag of the fetch to perform. + * Convert a shallow repository to a full repository. * * The default is 0, which means the flag is off. */ diff --git a/include/git2/repository.h b/include/git2/repository.h index d6b054dc3..258b9ac00 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -923,17 +923,6 @@ GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo); */ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo); -/** - * Determine the shallow roots of the repository - * - * This oidarray is owned by the library. Do not free it. - * - * @param out An array of shallow oids. - * @param repo The repository - * @return 0 on success, an error otherwise. - */ -GIT_EXTERN(int) git_repository_shallow_roots(git_oidarray *out, git_repository *repo); - /** * Retrieve the configured identity to use for reflogs * diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 13559ef07..6b77007aa 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3393,20 +3393,6 @@ on_error: return error; } -int git_repository_shallow_roots(git_oidarray *out, git_repository *repo) -{ - int ret; - git_array_oid_t array = GIT_ARRAY_INIT; - - assert(out); - - ret = git_repository__shallow_roots(&array, repo); - - git_oidarray__from_array(out, &array); - - return ret; -} - int git_repository_is_shallow(git_repository *repo) { git_str path = GIT_STR_INIT; -- cgit v1.2.1 From 8b521f018b734f58db2b9aec184e0f96422f140e Mon Sep 17 00:00:00 2001 From: yuangli Date: Thu, 11 Aug 2022 09:38:21 +0100 Subject: document unshallow behaviour in fetch.c --- src/libgit2/fetch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index a015cfbd3..3216b261c 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -60,7 +60,9 @@ static int mark_local(git_remote *remote) return -1; git_vector_foreach(&remote->refs, i, head) { - /* If we have the object, mark it so we don't ask for it */ + /* If we have the object, mark it so we don't ask for it. + However if we are unshallowing, we need to ask for it + even though the head exists locally. */ if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid)) head->local = 1; else -- cgit v1.2.1 From a3bfd284c2d49ef148a7e12fbeb0134b5246b5e6 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 11:09:49 +0100 Subject: Use GIT_OID_SHA1_HEXSIZE --- src/libgit2/grafts.c | 8 ++++---- src/libgit2/repository.c | 2 +- src/libgit2/transports/smart_pkt.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index dd1be3434..5b078b01d 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -133,22 +133,22 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) const char *line_start = parser.line, *line_end = parser.line + parser.line_len; git_oid graft_oid; - if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_HEXSZ)) < 0) { + if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_SHA1_HEXSIZE)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); goto error; } - line_start += GIT_OID_HEXSZ; + line_start += GIT_OID_SHA1_HEXSIZE; while (line_start < line_end && *line_start == ' ') { git_oid *id = git_array_alloc(parents); GIT_ERROR_CHECK_ALLOC(id); - if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_HEXSZ)) < 0) { + if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_SHA1_HEXSIZE)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); goto error; } - line_start += GIT_OID_HEXSZ; + line_start += GIT_OID_SHA1_HEXSIZE; } if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 6b77007aa..0eb16c223 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3372,7 +3372,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro goto on_error; git_array_foreach(roots, idx, oid) { - git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_HEXSZ); + git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_SHA1_HEXSIZE); git_filebuf_write(&file, "\n", 1); } diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index 832da450c..cfdf36244 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -377,10 +377,10 @@ static int shallow_pkt(git_pkt **out, const char *line, size_t len) line += 7; len -= 7; - if (len >= GIT_OID_HEXSZ) { + if (len >= GIT_OID_SHA1_HEXSIZE) { git_oid_fromstr(&pkt->oid, line + 1); - line += GIT_OID_HEXSZ + 1; - len -= GIT_OID_HEXSZ + 1; + line += GIT_OID_SHA1_HEXSIZE + 1; + len -= GIT_OID_SHA1_HEXSIZE + 1; } *out = (git_pkt *) pkt; @@ -399,10 +399,10 @@ static int unshallow_pkt(git_pkt **out, const char *line, size_t len) line += 9; len -= 9; - if (len >= GIT_OID_HEXSZ) { + if (len >= GIT_OID_SHA1_HEXSIZE) { git_oid_fromstr(&pkt->oid, line + 1); - line += GIT_OID_HEXSZ + 1; - len -= GIT_OID_HEXSZ + 1; + line += GIT_OID_SHA1_HEXSIZE + 1; + len -= GIT_OID_SHA1_HEXSIZE + 1; } *out = (git_pkt *) pkt; @@ -674,12 +674,12 @@ int git_pkt_buffer_wants( /* Tell the server about our shallow objects */ for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { - char oid[GIT_OID_HEXSZ]; + char oid[GIT_OID_SHA1_HEXSIZE]; git_str shallow_buf = GIT_STR_INIT; git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i)); git_str_puts(&shallow_buf, "shallow "); - git_str_put(&shallow_buf, oid, GIT_OID_HEXSZ); + git_str_put(&shallow_buf, oid, GIT_OID_SHA1_HEXSIZE); git_str_putc(&shallow_buf, '\n'); git_str_printf(buf, "%04x%s", (unsigned int)git_str_len(&shallow_buf) + 4, git_str_cstr(&shallow_buf)); -- cgit v1.2.1 From 01cb90be1578b2308f7c69be3b34dd44b0dbbe95 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 14:32:09 +0100 Subject: restore GIT_RAND_GETENTROPY --- src/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b81ad272f..14ffa6c40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,11 +70,6 @@ check_function_exists(qsort_s GIT_QSORT_S) # random / entropy data -# The flag has been unset to prevent issues -# related to Linux GLIBC version dependency - -# check_function_exists(getentropy GIT_RAND_GETENTROPY) -unset(GIT_RAND_GETENTROPY) check_function_exists(getloadavg GIT_RAND_GETLOADAVG) # determine architecture of the machine -- cgit v1.2.1 From b20f013c129a27a86b5207a2f6ad1d858113f46c Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 14:33:59 +0100 Subject: restore getentropy --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 14ffa6c40..e108b2e79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,7 @@ check_function_exists(qsort_s GIT_QSORT_S) # random / entropy data +check_function_exists(getentropy GIT_RAND_GETENTROPY) check_function_exists(getloadavg GIT_RAND_GETLOADAVG) # determine architecture of the machine -- cgit v1.2.1 From f1f9b45dd20b408953eac2d515e8dfa0264aa631 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 15:34:06 +0100 Subject: fix test failures --- src/libgit2/fetch.c | 6 ++++-- src/libgit2/grafts.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 3216b261c..69794ed1f 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -21,6 +21,7 @@ #include "repository.h" #include "refs.h" #include "transports/smart.h" +#include static int maybe_want(git_remote *remote, git_remote_head *head, git_refspec *tagspec, git_remote_autotag_option_t tagopt) { @@ -175,7 +176,8 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) git_transport *t = remote->transport; remote->need_pack = 0; - remote->nego.depth = opts->unshallow ? INT_MAX : opts->depth; + + remote->nego.depth = (opts && !opts->unshallow) ? opts->depth : INT_MAX; if (filter_wants(remote, opts) < 0) return -1; @@ -184,7 +186,7 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) if (!remote->need_pack) return 0; - if (opts->unshallow && opts->depth > 0) { + if (opts && opts->unshallow && opts->depth > 0) { git_error_set(GIT_ERROR_INVALID, "options '--depth' and '--unshallow' cannot be used together"); return -1; } diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 5b078b01d..6662f5009 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -133,7 +133,7 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) const char *line_start = parser.line, *line_end = parser.line + parser.line_len; git_oid graft_oid; - if ((error = git_oid_fromstrn(&graft_oid, line_start, GIT_OID_SHA1_HEXSIZE)) < 0) { + if ((error = git_oid__fromstrn(&graft_oid, line_start, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); goto error; } @@ -143,7 +143,7 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) git_oid *id = git_array_alloc(parents); GIT_ERROR_CHECK_ALLOC(id); - if ((error = git_oid_fromstrn(id, ++line_start, GIT_OID_SHA1_HEXSIZE)) < 0) { + if ((error = git_oid__fromstrn(id, ++line_start, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); goto error; } -- cgit v1.2.1 From 6c46b58e9b284c536168c8b333bbcf50c3431f83 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 15:39:33 +0100 Subject: include oid.h in grafts.c --- src/libgit2/grafts.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 6662f5009..7cbb1dd76 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -8,6 +8,7 @@ #include "grafts.h" #include "futils.h" +#include "oid.h" #include "oidarray.h" #include "parse.h" -- cgit v1.2.1 From 4cf19add64e2a705bdf1c87ece4874edef77d290 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 16:02:42 +0100 Subject: refactor smart_pkt --- src/libgit2/transports/smart_pkt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index cfdf36244..9e9bda020 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -378,7 +378,7 @@ static int shallow_pkt(git_pkt **out, const char *line, size_t len) len -= 7; if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid_fromstr(&pkt->oid, line + 1); + git_oid__fromstr(&pkt->oid, line + 1, GIT_OID_SHA1); line += GIT_OID_SHA1_HEXSIZE + 1; len -= GIT_OID_SHA1_HEXSIZE + 1; } @@ -400,7 +400,7 @@ static int unshallow_pkt(git_pkt **out, const char *line, size_t len) len -= 9; if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid_fromstr(&pkt->oid, line + 1); + git_oid__fromstr(&pkt->oid, line + 1, GIT_OID_SHA1); line += GIT_OID_SHA1_HEXSIZE + 1; len -= GIT_OID_SHA1_HEXSIZE + 1; } -- cgit v1.2.1 From d0eba8ae58092f0db061e3776f194256d0a56fde Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 17:03:53 +0100 Subject: fix shallowarray test --- tests/libgit2/transports/smart/shallowarray.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/libgit2/transports/smart/shallowarray.c b/tests/libgit2/transports/smart/shallowarray.c index c51e62713..ec4388e42 100644 --- a/tests/libgit2/transports/smart/shallowarray.c +++ b/tests/libgit2/transports/smart/shallowarray.c @@ -19,9 +19,9 @@ void test_transports_smart_shallowarray__add_and_remove_oid_from_shallowarray(vo git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); git_array_init(shallow_roots->array); - git_oid_fromstr(&oid_0_obj, oid_0); - git_oid_fromstr(&oid_1_obj, oid_1); - git_oid_fromstr(&oid_2_obj, oid_2); + git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); + git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); + git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); git_shallowarray_add(shallow_roots, &oid_0_obj); git_shallowarray_add(shallow_roots, &oid_1_obj); -- cgit v1.2.1 From 89c1b019b7026406834ce0f68a18f255f4b36f99 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Wed, 31 Aug 2022 17:28:27 +0100 Subject: fix free error --- tests/libgit2/clone/nonetwork.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/libgit2/clone/nonetwork.c b/tests/libgit2/clone/nonetwork.c index eab633635..0c4e5a87d 100644 --- a/tests/libgit2/clone/nonetwork.c +++ b/tests/libgit2/clone/nonetwork.c @@ -296,8 +296,6 @@ void test_clone_nonetwork__clone_tag_to_tree(void) cl_git_pass(git_tree_entry_bypath(&tentry, tree, file_path)); git_tree_entry_free(tentry); git_tree_free(tree); - - cl_fixture_cleanup("testrepo.git"); } static void assert_correct_reflog(const char *name) -- cgit v1.2.1 From 34de5c87fb118ffa177bf2e6a023aee72c4f46f7 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 5 Sep 2022 10:38:53 +0100 Subject: fix seg faults --- tests/libgit2/clone/nonetwork.c | 2 ++ tests/libgit2/clone/shallow.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/libgit2/clone/nonetwork.c b/tests/libgit2/clone/nonetwork.c index 0c4e5a87d..eab633635 100644 --- a/tests/libgit2/clone/nonetwork.c +++ b/tests/libgit2/clone/nonetwork.c @@ -296,6 +296,8 @@ void test_clone_nonetwork__clone_tag_to_tree(void) cl_git_pass(git_tree_entry_bypath(&tentry, tree, file_path)); git_tree_entry_free(tentry); git_tree_free(tree); + + cl_fixture_cleanup("testrepo.git"); } static void assert_correct_reflog(const char *name) diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index 2a88d5d05..b0114081c 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -10,7 +10,7 @@ void test_clone_shallow__initialize(void) void test_clone_shallow__cleanup(void) { git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); - cl_git_sandbox_cleanup(); + /*cl_git_sandbox_cleanup();*/ } static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) -- cgit v1.2.1 From 7122fcd2e4da67905df0d293d0223371b4ffdf01 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 5 Sep 2022 16:24:38 +0100 Subject: fix depth initialisation --- src/libgit2/fetch.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 69794ed1f..df8f0a154 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -62,8 +62,8 @@ static int mark_local(git_remote *remote) git_vector_foreach(&remote->refs, i, head) { /* If we have the object, mark it so we don't ask for it. - However if we are unshallowing, we need to ask for it - even though the head exists locally. */ + However if we are unshallowing, we need to ask for it + even though the head exists locally. */ if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid)) head->local = 1; else @@ -177,7 +177,10 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) remote->need_pack = 0; - remote->nego.depth = (opts && !opts->unshallow) ? opts->depth : INT_MAX; + if (!opts) + remote->nego.depth = -1; + else + remote->nego.depth = opts->unshallow ? INT_MAX : opts->depth; if (filter_wants(remote, opts) < 0) return -1; -- cgit v1.2.1 From 47f36a937f2ea5c3dc33ed940057134af967b062 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 5 Sep 2022 19:28:29 +0100 Subject: fix error handling --- src/libgit2/fetch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index df8f0a154..874813b4e 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -219,10 +219,10 @@ int git_fetch_download_pack(git_remote *remote) if (!remote->need_pack) return 0; - if ((error = t->download_pack(t, remote->repo, &remote->stats)) < 0) + if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0) return error; - if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) < 0) + if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) != 0) return error; return 0; -- cgit v1.2.1 From d23a7903d107528f9d62608f9b236251d9756b00 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Mon, 5 Sep 2022 19:44:49 +0100 Subject: remove unused statements --- src/libgit2/fetch.c | 1 - tests/libgit2/clone/shallow.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 874813b4e..2a419534e 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -21,7 +21,6 @@ #include "repository.h" #include "refs.h" #include "transports/smart.h" -#include static int maybe_want(git_remote *remote, git_remote_head *head, git_refspec *tagspec, git_remote_autotag_option_t tagopt) { diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index b0114081c..eacfe1bcf 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -10,7 +10,6 @@ void test_clone_shallow__initialize(void) void test_clone_shallow__cleanup(void) { git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); - /*cl_git_sandbox_cleanup();*/ } static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) -- cgit v1.2.1 From 4f2f91a34f2e66a4511ebf0a650f379bd1c0e41f Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 6 Sep 2022 15:45:07 +0100 Subject: fix shallow array search --- src/libgit2/transports/smart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index b0925c8bb..04ee7e740 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -497,7 +497,7 @@ int git_shallowarray_add(git_shallowarray *array, git_oid *oid) { size_t oid_index; - if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, &oid) < 0) { + if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, oid) < 0) { git_oid *tmp = git_array_alloc(array->array); GIT_ERROR_CHECK_ALLOC(tmp); -- cgit v1.2.1 From a9793ac643a0cd82b00970d0d6e0b67681ec3112 Mon Sep 17 00:00:00 2001 From: Yuang Li Date: Tue, 6 Sep 2022 16:01:52 +0100 Subject: refactor grafts tests --- tests/libgit2/grafts/basic.c | 10 +++++----- tests/libgit2/grafts/parse.c | 4 ++-- tests/libgit2/grafts/shallow.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/libgit2/grafts/basic.c b/tests/libgit2/grafts/basic.c index 4be4a12bf..5ad437b19 100644 --- a/tests/libgit2/grafts/basic.c +++ b/tests/libgit2/grafts/basic.c @@ -27,10 +27,10 @@ void test_grafts_basic__graft_add(void) cl_git_pass(git_grafts_new(&grafts)); cl_assert(oid1 = git_array_alloc(parents)); - cl_git_pass(git_oid_fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9")); + cl_git_pass(git_oid__fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9", GIT_OID_SHA1)); git_oid_cpy(oid1, &oid_src); - git_oid_fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7"); + git_oid__fromstr(&oid_src, "f503807ffa920e407a600cfaee96b7152259acc7", GIT_OID_SHA1); cl_git_pass(git_grafts_add(grafts, &oid_src, parents)); git_array_clear(parents); @@ -75,17 +75,17 @@ void test_grafts_basic__grafted_objects(void) git_oid oid; git_commit *commit; - cl_git_pass(git_oid_fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7")); + cl_git_pass(git_oid__fromstr(&oid, "f503807ffa920e407a600cfaee96b7152259acc7", GIT_OID_SHA1)); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); cl_assert_equal_i(1, git_commit_parentcount(commit)); git_commit_free(commit); - cl_git_pass(git_oid_fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e")); + cl_git_pass(git_oid__fromstr(&oid, "0512adebd3782157f0d5c9b22b043f87b4aaff9e", GIT_OID_SHA1)); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); cl_assert_equal_i(1, git_commit_parentcount(commit)); git_commit_free(commit); - cl_git_pass(git_oid_fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade")); + cl_git_pass(git_oid__fromstr(&oid, "66cc22a015f6ca75b34c82d28f78ba663876bade", GIT_OID_SHA1)); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); cl_assert_equal_i(4, git_commit_parentcount(commit)); git_commit_free(commit); diff --git a/tests/libgit2/grafts/parse.c b/tests/libgit2/grafts/parse.c index de110c901..149b01c8c 100644 --- a/tests/libgit2/grafts/parse.c +++ b/tests/libgit2/grafts/parse.c @@ -46,14 +46,14 @@ static void assert_graft_contains(git_grafts *grafts, const char *graft, size_t va_list ap; size_t i = 0; - cl_git_pass(git_oid_fromstr(&oid, graft)); + cl_git_pass(git_oid__fromstr(&oid, graft, GIT_OID_SHA1)); cl_git_pass(git_grafts_get(&commit, grafts, &oid)); cl_assert_equal_oid(&commit->oid, &oid); cl_assert_equal_i(commit->parents.size, n); va_start(ap, n); while (i < n) { - cl_git_pass(git_oid_fromstr(&oid, va_arg(ap, const char *))); + cl_git_pass(git_oid__fromstr(&oid, va_arg(ap, const char *), GIT_OID_SHA1)); cl_assert_equal_oid(&commit->parents.ptr[i], &oid); i++; } diff --git a/tests/libgit2/grafts/shallow.c b/tests/libgit2/grafts/shallow.c index a75b5a051..8c2723922 100644 --- a/tests/libgit2/grafts/shallow.c +++ b/tests/libgit2/grafts/shallow.c @@ -20,7 +20,7 @@ void test_grafts_shallow__unset_feature_flag(void) void test_grafts_shallow__initialize(void) { git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); - cl_git_pass(git_oid_fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_oid__fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", GIT_OID_SHA1)); } void test_grafts_shallow__cleanup(void) @@ -73,7 +73,7 @@ void test_grafts_shallow__cache_clearing(void) git_grafts *grafts; git_oid tmp_oid; - cl_git_pass(git_oid_fromstr(&tmp_oid, "0000000000000000000000000000000000000000")); + cl_git_pass(git_oid__fromstr(&tmp_oid, "0000000000000000000000000000000000000000", GIT_OID_SHA1)); g_repo = cl_git_sandbox_init("shallow.git"); cl_git_pass(git_repository_shallow_grafts__weakptr(&grafts, g_repo)); -- cgit v1.2.1 From 1cc2979a71ba042c20ea3e18484d4a50c4fdf10d Mon Sep 17 00:00:00 2001 From: lmcglash Date: Fri, 10 Mar 2023 08:56:49 +0000 Subject: Fix merge error --- src/libgit2/commit.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index 017c60303..a7d831115 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -517,6 +517,18 @@ int git_commit__parse( return git_commit__parse_ext(commit, odb_obj, &parse_options); } +int git_commit__parse_raw( + void *commit, + const char *data, + size_t size, + git_oid_t oid_type) +{ + git_commit__parse_options parse_options = {0}; + parse_options.oid_type = oid_type; + + return commit_parse(commit, data, size, &parse_options); +} + static int assign_commit_parents_from_graft(git_commit *commit, git_commit_graft *graft) { size_t idx; git_oid *oid; @@ -533,14 +545,17 @@ static int assign_commit_parents_from_graft(git_commit *commit, git_commit_graft return 0; } -int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) +int git_commit__parse_ext( + git_commit *commit, + git_odb_object *odb_obj, + git_commit__parse_options *parse_opts) { git_repository *repo = git_object_owner((git_object *)commit); git_commit_graft *graft; int error; if ((error = commit_parse(commit, git_odb_object_data(odb_obj), - git_odb_object_size(odb_obj), flags)) < 0) + git_odb_object_size(odb_obj), parse_opts)) < 0) return error; if (!git_shallow__enabled) @@ -554,30 +569,6 @@ int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned return assign_commit_parents_from_graft(commit, graft); } -int git_commit__parse_raw( - void *commit, - const char *data, - size_t size, - git_oid_t oid_type) -{ - git_commit__parse_options parse_options = {0}; - parse_options.oid_type = oid_type; - - return commit_parse(commit, data, size, &parse_options); -} - -int git_commit__parse_ext( - git_commit *commit, - git_odb_object *odb_obj, - git_commit__parse_options *parse_opts) -{ - return commit_parse( - commit, - git_odb_object_data(odb_obj), - git_odb_object_size(odb_obj), - parse_opts); -} - #define GIT_COMMIT_GETTER(_rvalue, _name, _return, _invalid) \ _rvalue git_commit_##_name(const git_commit *commit) \ {\ -- cgit v1.2.1 From 2da3e8c16629cee9736965556a50dc7502e1dec7 Mon Sep 17 00:00:00 2001 From: lmcglash Date: Fri, 10 Mar 2023 09:06:26 +0000 Subject: Remove stray comma --- src/libgit2/transports/smart.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libgit2/transports/smart.h b/src/libgit2/transports/smart.h index 15b6c9a0a..8e06d03ef 100644 --- a/src/libgit2/transports/smart.h +++ b/src/libgit2/transports/smart.h @@ -54,7 +54,7 @@ typedef enum { GIT_PKT_NG, GIT_PKT_UNPACK, GIT_PKT_SHALLOW, - GIT_PKT_UNSHALLOW, + GIT_PKT_UNSHALLOW } git_pkt_type; /* Used for multi_ack and multi_ack_detailed */ @@ -144,7 +144,7 @@ typedef struct transport_smart_caps { thin_pack:1, want_tip_sha1:1, want_reachable_sha1:1, - shallow:1; + shallow:1; char *object_format; char *agent; } transport_smart_caps; -- cgit v1.2.1 From d935773743f8f0ed50027bfe3b66133174610cc9 Mon Sep 17 00:00:00 2001 From: lmcglash Date: Fri, 10 Mar 2023 09:30:02 +0000 Subject: Remove unused git_transport_flags_t --- include/git2/sys/transport.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index 8a8451592..062bcd0ed 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -25,15 +25,6 @@ GIT_BEGIN_DECL -/** - * Flags to pass to transport - * - * Currently unused. - */ -typedef enum { - GIT_TRANSPORTFLAGS_NONE = 0, -} git_transport_flags_t; - typedef struct git_shallowarray git_shallowarray; typedef struct { -- cgit v1.2.1 From 79ed94e0f86daae2d839f89789952f0e99eef32a Mon Sep 17 00:00:00 2001 From: Laurence McGlashan Date: Fri, 10 Mar 2023 09:30:29 +0000 Subject: Apply suggestions from code review Co-authored-by: Qix --- include/git2/remote.h | 4 ++-- src/libgit2/transports/smart_protocol.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index f1cee17aa..9e4043f87 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -744,9 +744,9 @@ typedef struct { git_proxy_options proxy_opts; /** - * Depth of the fetch to perform, has to be a positive integer. + * Depth of the fetch to perform. Depth <= 0 fetches the full history. * - * The default is -1, which will fetch the full history. + * The default is -1. */ int depth; diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index 2ec390101..c37c3cc8d 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -359,7 +359,7 @@ static int cap_not_sup_err(const char *cap_name) /* Disables server capabilities we're not interested in */ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants) { - if (wants->depth) { + if (wants->depth > 0) { if (!caps->shallow) return cap_not_sup_err(GIT_CAP_SHALLOW); } else { -- cgit v1.2.1 From 5b711335603b6d6abe6ae9bf09f570ada66232ef Mon Sep 17 00:00:00 2001 From: Laurence McGlashan Date: Fri, 10 Mar 2023 09:32:33 +0000 Subject: Update src/libgit2/fetch.c Co-authored-by: Qix --- src/libgit2/fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 3a574e857..6bf16bc0f 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -195,7 +195,7 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) */ remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; remote->nego.count = remote->refs.length; - remote->nego.shallow_roots = git__malloc(sizeof(git_shallowarray)); + remote->nego.shallow_roots = git__malloc(sizeof(*remote->nego.shallow_roots)); git_array_init(remote->nego.shallow_roots->array); -- cgit v1.2.1 From e288f874a3a73ef31f88bb524f6d25d5ff3c5a3a Mon Sep 17 00:00:00 2001 From: lmcglash Date: Mon, 13 Mar 2023 08:46:59 +0000 Subject: Remove unnecessary include. --- include/git2/repository.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 0de4d7557..560e70ab6 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -11,7 +11,6 @@ #include "types.h" #include "oid.h" #include "buffer.h" -#include "oidarray.h" /** * @file git2/repository.h -- cgit v1.2.1 From dd15c615bde54eb02c5cec17257a83dcd8528371 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 22 Apr 2023 23:19:59 +0100 Subject: shallow: remove feature flag The opt mechanism isn't _really_ meant to be for feature flags, and it's weird to feature flag shallow / unshallow at all. --- include/git2/common.h | 6 +----- src/libgit2/commit.c | 5 +---- src/libgit2/grafts.c | 6 ++---- src/libgit2/grafts.h | 2 -- src/libgit2/libgit2.c | 4 ---- src/libgit2/repository.c | 2 +- tests/libgit2/clone/shallow.c | 2 -- tests/libgit2/grafts/basic.c | 2 -- tests/libgit2/grafts/shallow.c | 12 ------------ 9 files changed, 5 insertions(+), 36 deletions(-) diff --git a/include/git2/common.h b/include/git2/common.h index b09b078a1..f968deb23 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -224,8 +224,7 @@ typedef enum { GIT_OPT_GET_OWNER_VALIDATION, GIT_OPT_SET_OWNER_VALIDATION, GIT_OPT_GET_HOMEDIR, - GIT_OPT_SET_HOMEDIR, - GIT_OPT_ENABLE_SHALLOW + GIT_OPT_SET_HOMEDIR } git_libgit2_opt_t; /** @@ -462,9 +461,6 @@ typedef enum { * > { "!noop", "newext" } indicates that the caller does not want * > to support repositories with the `noop` extension but does want * > to support repositories with the `newext` extension. - * - * opts(GIT_OPT_ENABLE_SHALLOW, int enabled) - * > Enable or disable shallow clone support completely. * * opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled) * > Gets the owner validation setting for repository diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c index a7d831115..f7be73acf 100644 --- a/src/libgit2/commit.c +++ b/src/libgit2/commit.c @@ -553,14 +553,11 @@ int git_commit__parse_ext( git_repository *repo = git_object_owner((git_object *)commit); git_commit_graft *graft; int error; - + if ((error = commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), parse_opts)) < 0) return error; - if (!git_shallow__enabled) - return 0; - /* Perform necessary grafts */ if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) != 0 && git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) != 0) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 7cbb1dd76..13c33aad0 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -12,8 +12,6 @@ #include "oidarray.h" #include "parse.h" -bool git_shallow__enabled = false; - struct git_grafts { /* Map of `git_commit_graft`s */ git_oidmap *commits; @@ -97,13 +95,13 @@ int git_grafts_refresh(git_grafts *grafts) if (!grafts->path) return 0; - if ((error = git_futils_readbuffer_updated(&contents, grafts->path, + if ((error = git_futils_readbuffer_updated(&contents, grafts->path, (grafts->path_checksum).id, &updated)) < 0) { if (error == GIT_ENOTFOUND) { git_grafts_clear(grafts); error = 0; } - + goto cleanup; } diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index 4139438bb..fc61468f5 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -19,8 +19,6 @@ typedef struct { typedef struct git_grafts git_grafts; -extern bool git_shallow__enabled; - int git_grafts_new(git_grafts **out); int git_grafts_from_file(git_grafts **out, const char *path); void git_grafts_free(git_grafts *grafts); diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c index c5a9287fb..178880c9e 100644 --- a/src/libgit2/libgit2.c +++ b/src/libgit2/libgit2.c @@ -436,10 +436,6 @@ int git_libgit2_opts(int key, ...) error = git_sysdir_set(GIT_SYSDIR_HOME, va_arg(ap, const char *)); break; - case GIT_OPT_ENABLE_SHALLOW: - git_shallow__enabled = (va_arg(ap, int) != 0); - break; - default: git_error_set(GIT_ERROR_INVALID, "invalid option key"); error = -1; diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 1e356c84e..99982b724 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -1099,7 +1099,7 @@ int git_repository_open_ext( if (error < 0) goto cleanup; - if (git_shallow__enabled && (error = load_grafts(repo)) < 0) + if ((error = load_grafts(repo)) < 0) goto cleanup; if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) { diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c index eacfe1bcf..28b0116fa 100644 --- a/tests/libgit2/clone/shallow.c +++ b/tests/libgit2/clone/shallow.c @@ -4,12 +4,10 @@ void test_clone_shallow__initialize(void) { - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); } void test_clone_shallow__cleanup(void) { - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); } static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) diff --git a/tests/libgit2/grafts/basic.c b/tests/libgit2/grafts/basic.c index 5ad437b19..fe7477097 100644 --- a/tests/libgit2/grafts/basic.c +++ b/tests/libgit2/grafts/basic.c @@ -7,13 +7,11 @@ static git_repository *g_repo; void test_grafts_basic__initialize(void) { - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); g_repo = cl_git_sandbox_init("grafted.git"); } void test_grafts_basic__cleanup(void) { - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); cl_git_sandbox_cleanup(); } diff --git a/tests/libgit2/grafts/shallow.c b/tests/libgit2/grafts/shallow.c index 8c2723922..5911a26aa 100644 --- a/tests/libgit2/grafts/shallow.c +++ b/tests/libgit2/grafts/shallow.c @@ -7,25 +7,13 @@ static git_repository *g_repo; static git_oid g_shallow_oid; -void test_grafts_shallow__set_feature_flag(void) -{ - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1)); -} - -void test_grafts_shallow__unset_feature_flag(void) -{ - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0)); -} - void test_grafts_shallow__initialize(void) { - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 1); cl_git_pass(git_oid__fromstr(&g_shallow_oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", GIT_OID_SHA1)); } void test_grafts_shallow__cleanup(void) { - git_libgit2_opts(GIT_OPT_ENABLE_SHALLOW, 0); cl_git_sandbox_cleanup(); } -- cgit v1.2.1 From 6cec01b4d8498203ae3a03949ffd480845269a3d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 22 Apr 2023 23:38:52 +0100 Subject: shallow: move tests to online --- tests/libgit2/clone/shallow.c | 171 ----------------------------------------- tests/libgit2/online/shallow.c | 163 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 171 deletions(-) delete mode 100644 tests/libgit2/clone/shallow.c create mode 100644 tests/libgit2/online/shallow.c diff --git a/tests/libgit2/clone/shallow.c b/tests/libgit2/clone/shallow.c deleted file mode 100644 index 28b0116fa..000000000 --- a/tests/libgit2/clone/shallow.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" -#include "repository.h" - -void test_clone_shallow__initialize(void) -{ -} - -void test_clone_shallow__cleanup(void) -{ -} - -static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) -{ - GIT_UNUSED(payload); - - cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master")); - - return 0; -} - -void test_clone_shallow__clone_depth_zero(void) -{ - git_str path = GIT_STR_INIT; - git_repository *repo; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_array_oid_t roots = GIT_ARRAY_INIT; - - clone_opts.fetch_opts.depth = 0; - clone_opts.remote_cb = remote_single_branch; - - git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_0"); - - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); - - /* cloning with depth 0 results in a full clone. */ - cl_assert_equal_b(false, git_repository_is_shallow(repo)); - - /* full clones do not have shallow roots. */ - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(0, roots.size); - - git_array_clear(roots); - git_str_dispose(&path); - git_repository_free(repo); -} - -void test_clone_shallow__clone_depth_one(void) -{ - git_str path = GIT_STR_INIT; - git_repository *repo; - git_revwalk *walk; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; - size_t num_commits = 0; - int error = 0; - - clone_opts.fetch_opts.depth = 1; - clone_opts.remote_cb = remote_single_branch; - - git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_1"); - - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); - - cl_assert_equal_b(true, git_repository_is_shallow(repo)); - - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.size); - cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); - - git_revwalk_new(&walk, repo); - - git_revwalk_push_head(walk); - - while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - num_commits++; - } - - cl_assert_equal_i(num_commits, 1); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_array_clear(roots); - git_str_dispose(&path); - git_revwalk_free(walk); - git_repository_free(repo); -} - -void test_clone_shallow__clone_depth_five(void) -{ - git_str path = GIT_STR_INIT; - git_repository *repo; - git_revwalk *walk; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; - size_t num_commits = 0; - int error = 0; - - clone_opts.fetch_opts.depth = 5; - clone_opts.remote_cb = remote_single_branch; - - git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_5"); - - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); - - cl_assert_equal_b(true, git_repository_is_shallow(repo)); - - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(3, roots.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); - - git_revwalk_new(&walk, repo); - - git_revwalk_push_head(walk); - - while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - num_commits++; - } - - cl_assert_equal_i(num_commits, 13); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_array_clear(roots); - git_str_dispose(&path); - git_revwalk_free(walk); - git_repository_free(repo); -} - -void test_clone_shallow__unshallow(void) -{ - git_str path = GIT_STR_INIT; - git_repository *repo; - git_revwalk *walk; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; - git_remote *origin = NULL; - git_oid oid; - size_t num_commits = 0; - int error = 0; - - clone_opts.fetch_opts.depth = 5; - clone_opts.remote_cb = remote_single_branch; - - git_str_joinpath(&path, clar_sandbox_path(), "unshallow"); - cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); - cl_assert_equal_b(true, git_repository_is_shallow(repo)); - - fetch_opts.unshallow = 1; - cl_git_pass(git_remote_lookup(&origin, repo, "origin")); - - cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL)); - cl_assert_equal_b(false, git_repository_is_shallow(repo)); - - git_revwalk_new(&walk, repo); - git_revwalk_push_head(walk); - - while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { - num_commits++; - } - - cl_assert_equal_i(num_commits, 21); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_remote_free(origin); - git_str_dispose(&path); - git_revwalk_free(walk); - git_repository_free(repo); -} diff --git a/tests/libgit2/online/shallow.c b/tests/libgit2/online/shallow.c new file mode 100644 index 000000000..a889a68cd --- /dev/null +++ b/tests/libgit2/online/shallow.c @@ -0,0 +1,163 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "repository.h" + +static int remote_single_branch(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) +{ + GIT_UNUSED(payload); + + cl_git_pass(git_remote_create_with_fetchspec(out, repo, name, url, "+refs/heads/master:refs/remotes/origin/master")); + + return 0; +} + +void test_online_shallow__clone_depth_zero(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_array_oid_t roots = GIT_ARRAY_INIT; + + clone_opts.fetch_opts.depth = 0; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_0"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + /* cloning with depth 0 results in a full clone. */ + cl_assert_equal_b(false, git_repository_is_shallow(repo)); + + /* full clones do not have shallow roots. */ + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(0, roots.size); + + git_array_clear(roots); + git_str_dispose(&path); + git_repository_free(repo); +} + +void test_online_shallow__clone_depth_one(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + git_array_oid_t roots = GIT_ARRAY_INIT; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 1; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_1"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(1, roots.size); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 1); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_array_clear(roots); + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} + +void test_online_shallow__clone_depth_five(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_oid oid; + git_array_oid_t roots = GIT_ARRAY_INIT; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 5; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "shallowclone_5"); + + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + cl_git_pass(git_repository__shallow_roots(&roots, repo)); + cl_assert_equal_i(3, roots.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); + + git_revwalk_new(&walk, repo); + + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 13); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_array_clear(roots); + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} + +void test_online_shallow__unshallow(void) +{ + git_str path = GIT_STR_INIT; + git_repository *repo; + git_revwalk *walk; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; + git_remote *origin = NULL; + git_oid oid; + size_t num_commits = 0; + int error = 0; + + clone_opts.fetch_opts.depth = 5; + clone_opts.remote_cb = remote_single_branch; + + git_str_joinpath(&path, clar_sandbox_path(), "unshallow"); + cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); + cl_assert_equal_b(true, git_repository_is_shallow(repo)); + + fetch_opts.unshallow = 1; + cl_git_pass(git_remote_lookup(&origin, repo, "origin")); + + cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL)); + cl_assert_equal_b(false, git_repository_is_shallow(repo)); + + git_revwalk_new(&walk, repo); + git_revwalk_push_head(walk); + + while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) { + num_commits++; + } + + cl_assert_equal_i(num_commits, 21); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_remote_free(origin); + git_str_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} -- cgit v1.2.1 From 48273490e7ccfaa56b784c69cb488111bd06f357 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 22 Apr 2023 23:42:41 +0100 Subject: shallow: use GIT_ASSERT (not assert) --- src/libgit2/grafts.c | 13 +++++++------ src/libgit2/repository.c | 11 ++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 13c33aad0..1bfdc500e 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -75,7 +75,8 @@ void git_grafts_clear(git_grafts *grafts) { git_commit_graft *graft; - assert(grafts); + if (!grafts) + return; git_oidmap_foreach_value(grafts->commits, graft, { git__free(graft->parents.ptr); @@ -90,7 +91,7 @@ int git_grafts_refresh(git_grafts *grafts) git_str contents = GIT_STR_INIT; int error, updated = 0; - assert(grafts); + GIT_ASSERT_ARG(grafts); if (!grafts->path) return 0; @@ -168,7 +169,7 @@ int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t paren int error; size_t i; - assert(grafts && oid); + GIT_ASSERT_ARG(grafts && oid); graft = git__calloc(1, sizeof(*graft)); GIT_ERROR_CHECK_ALLOC(graft); @@ -200,7 +201,7 @@ int git_grafts_remove(git_grafts *grafts, const git_oid *oid) git_commit_graft *graft; int error; - assert(grafts && oid); + GIT_ASSERT_ARG(grafts && oid); if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL) return GIT_ENOTFOUND; @@ -216,7 +217,7 @@ int git_grafts_remove(git_grafts *grafts, const git_oid *oid) int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid) { - assert(out && grafts && oid); + GIT_ASSERT_ARG(out && grafts && oid); if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL) return GIT_ENOTFOUND; return 0; @@ -228,7 +229,7 @@ int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts) size_t i = 0; int error; - assert(out && grafts); + GIT_ASSERT_ARG(out && grafts); while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { git_oid *cpy = git_array_alloc(*out); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 99982b724..3b6ecae24 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -1613,14 +1613,16 @@ int git_repository_set_index(git_repository *repo, git_index *index) int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo) { - assert(out && repo && repo->grafts); + GIT_ASSERT_ARG(out && repo); + GIT_ASSERT(repo->grafts); *out = repo->grafts; return 0; } int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo) { - assert(out && repo && repo->shallow_grafts); + GIT_ASSERT_ARG(out && repo); + GIT_ASSERT(repo->shallow_grafts); *out = repo->shallow_grafts; return 0; } @@ -3672,7 +3674,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro git_oid *oid; int filebuf_hash, error = 0; - assert(repo); + GIT_ASSERT_ARG(repo); filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(GIT_OID_SHA1)); GIT_ASSERT(filebuf_hash); @@ -3695,9 +3697,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro goto on_error; } - if (git_array_size(roots) == 0) { + if (git_array_size(roots) == 0) remove(path.ptr); - } on_error: git_str_dispose(&path); -- cgit v1.2.1 From 3853ba8de64a0e774c6e73aacb5831707f841621 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 22 Apr 2023 23:55:44 +0100 Subject: smart: validate shallow/unshallow pkts --- src/libgit2/transports/smart_pkt.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index ec9764a87..e8c87cb8d 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -444,11 +444,15 @@ static int shallow_pkt(git_pkt **out, const char *line, size_t len) GIT_ERROR_CHECK_ALLOC(pkt); pkt->type = GIT_PKT_SHALLOW; - line += 7; - len -= 7; + + if (git__prefixncmp(line, len, "shallow ")) + goto out_err; + + line += 8; + len -= 8; if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid__fromstr(&pkt->oid, line + 1, GIT_OID_SHA1); + git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1); line += GIT_OID_SHA1_HEXSIZE + 1; len -= GIT_OID_SHA1_HEXSIZE + 1; } @@ -456,6 +460,11 @@ static int shallow_pkt(git_pkt **out, const char *line, size_t len) *out = (git_pkt *) pkt; return 0; + +out_err: + git_error_set(GIT_ERROR_NET, "invalid packet line"); + git__free(pkt); + return -1; } static int unshallow_pkt(git_pkt **out, const char *line, size_t len) @@ -466,11 +475,15 @@ static int unshallow_pkt(git_pkt **out, const char *line, size_t len) GIT_ERROR_CHECK_ALLOC(pkt); pkt->type = GIT_PKT_UNSHALLOW; - line += 9; - len -= 9; + + if (git__prefixncmp(line, len, "unshallow ")) + goto out_err; + + line += 10; + len -= 10; if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid__fromstr(&pkt->oid, line + 1, GIT_OID_SHA1); + git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1); line += GIT_OID_SHA1_HEXSIZE + 1; len -= GIT_OID_SHA1_HEXSIZE + 1; } @@ -478,6 +491,11 @@ static int unshallow_pkt(git_pkt **out, const char *line, size_t len) *out = (git_pkt *) pkt; return 0; + +out_err: + git_error_set(GIT_ERROR_NET, "invalid packet line"); + git__free(pkt); + return -1; } static int parse_len(size_t *out, const char *line, size_t linelen) -- cgit v1.2.1 From 72139ef289383dafeea355ace222359c48d98563 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 23 Apr 2023 00:07:06 +0100 Subject: shallow: don't assume SHA1 --- src/libgit2/repository.c | 6 ++-- src/libgit2/transports/smart_pkt.c | 66 ++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 3b6ecae24..a60fb23fa 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3670,13 +3670,14 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro { git_filebuf file = GIT_FILEBUF_INIT; git_str path = GIT_STR_INIT; + char oid_str[GIT_OID_MAX_HEXSIZE + 1]; size_t idx; git_oid *oid; int filebuf_hash, error = 0; GIT_ASSERT_ARG(repo); - filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(GIT_OID_SHA1)); + filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(repo->oid_type)); GIT_ASSERT(filebuf_hash); if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0) @@ -3686,7 +3687,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro goto on_error; git_array_foreach(roots, idx, oid) { - git_filebuf_write(&file, git_oid_tostr_s(oid), GIT_OID_SHA1_HEXSIZE); + git_oid_tostr(oid_str, sizeof(oid_str), oid); + git_filebuf_write(&file, oid_str, git_oid_hexsize(repo->oid_type)); git_filebuf_write(&file, "\n", 1); } diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index e8c87cb8d..3199c18f0 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -44,9 +44,14 @@ static int flush_pkt(git_pkt **out) } /* the rest of the line will be useful for multi_ack and multi_ack_detailed */ -static int ack_pkt(git_pkt **out, const char *line, size_t len) +static int ack_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) { git_pkt_ack *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); pkt = git__calloc(1, sizeof(git_pkt_ack)); GIT_ERROR_CHECK_ALLOC(pkt); @@ -57,11 +62,11 @@ static int ack_pkt(git_pkt **out, const char *line, size_t len) line += 4; len -= 4; - if (len < GIT_OID_SHA1_HEXSIZE || - git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1) < 0) + if (len < oid_hexsize || + git_oid__fromstr(&pkt->oid, line, data->oid_type) < 0) goto out_err; - line += GIT_OID_SHA1_HEXSIZE; - len -= GIT_OID_SHA1_HEXSIZE; + line += oid_hexsize; + len -= oid_hexsize; if (len && line[0] == ' ') { line++; @@ -436,9 +441,14 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len) return 0; } -static int shallow_pkt(git_pkt **out, const char *line, size_t len) +static int shallow_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) { git_pkt_shallow *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); pkt = git__calloc(1, sizeof(git_pkt_shallow)); GIT_ERROR_CHECK_ALLOC(pkt); @@ -451,13 +461,14 @@ static int shallow_pkt(git_pkt **out, const char *line, size_t len) line += 8; len -= 8; - if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1); - line += GIT_OID_SHA1_HEXSIZE + 1; - len -= GIT_OID_SHA1_HEXSIZE + 1; - } + if (len != oid_hexsize) + goto out_err; - *out = (git_pkt *) pkt; + git_oid__fromstr(&pkt->oid, line, data->oid_type); + line += oid_hexsize + 1; + len -= oid_hexsize + 1; + + *out = (git_pkt *)pkt; return 0; @@ -467,9 +478,14 @@ out_err: return -1; } -static int unshallow_pkt(git_pkt **out, const char *line, size_t len) +static int unshallow_pkt( + git_pkt **out, + const char *line, + size_t len, + git_pkt_parse_data *data) { git_pkt_shallow *pkt; + size_t oid_hexsize = git_oid_hexsize(data->oid_type); pkt = git__calloc(1, sizeof(git_pkt_shallow)); GIT_ERROR_CHECK_ALLOC(pkt); @@ -482,11 +498,12 @@ static int unshallow_pkt(git_pkt **out, const char *line, size_t len) line += 10; len -= 10; - if (len >= GIT_OID_SHA1_HEXSIZE) { - git_oid__fromstr(&pkt->oid, line, GIT_OID_SHA1); - line += GIT_OID_SHA1_HEXSIZE + 1; - len -= GIT_OID_SHA1_HEXSIZE + 1; - } + if (len != oid_hexsize) + goto out_err; + + git_oid__fromstr(&pkt->oid, line, data->oid_type); + line += oid_hexsize + 1; + len -= oid_hexsize + 1; *out = (git_pkt *) pkt; @@ -615,7 +632,7 @@ int git_pkt_parse_line( else if (*line == GIT_SIDE_BAND_ERROR) error = sideband_error_pkt(pkt, line, len); else if (!git__prefixncmp(line, len, "ACK")) - error = ack_pkt(pkt, line, len); + error = ack_pkt(pkt, line, len, data); else if (!git__prefixncmp(line, len, "NAK")) error = nak_pkt(pkt); else if (!git__prefixncmp(line, len, "ERR")) @@ -629,9 +646,9 @@ int git_pkt_parse_line( else if (!git__prefixncmp(line, len, "unpack")) error = unpack_pkt(pkt, line, len); else if (!git__prefixcmp(line, "shallow")) - error = shallow_pkt(pkt, line, len); + error = shallow_pkt(pkt, line, len, data); else if (!git__prefixcmp(line, "unshallow")) - error = unshallow_pkt(pkt, line, len); + error = unshallow_pkt(pkt, line, len, data); else error = ref_pkt(pkt, line, len, data); @@ -788,12 +805,13 @@ int git_pkt_buffer_wants( /* Tell the server about our shallow objects */ for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { - char oid[GIT_OID_SHA1_HEXSIZE]; + char oid[GIT_OID_MAX_HEXSIZE + 1]; git_str shallow_buf = GIT_STR_INIT; - git_oid_fmt(oid, git_shallowarray_get(wants->shallow_roots, i)); + git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, + git_shallowarray_get(wants->shallow_roots, i)); git_str_puts(&shallow_buf, "shallow "); - git_str_put(&shallow_buf, oid, GIT_OID_SHA1_HEXSIZE); + git_str_puts(&shallow_buf, oid); git_str_putc(&shallow_buf, '\n'); git_str_printf(buf, "%04x%s", (unsigned int)git_str_len(&shallow_buf) + 4, git_str_cstr(&shallow_buf)); -- cgit v1.2.1 From d69c7a72386c9e01f4b0c8945724f870bf9aa4f6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 24 Apr 2023 11:43:03 +0100 Subject: transport: transports understand oid type Teach the smart transport more about oid types, instead of assuming SHA1. --- src/libgit2/transports/smart_pkt.c | 6 ++++++ src/libgit2/transports/smart_protocol.c | 26 ++++++++++++++++---------- tests/libgit2/transports/smart/packet.c | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index 3199c18f0..f2c9eea8e 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -53,6 +53,8 @@ static int ack_pkt( git_pkt_ack *pkt; size_t oid_hexsize = git_oid_hexsize(data->oid_type); + GIT_ASSERT(data && data->oid_type); + pkt = git__calloc(1, sizeof(git_pkt_ack)); GIT_ERROR_CHECK_ALLOC(pkt); pkt->type = GIT_PKT_ACK; @@ -450,6 +452,8 @@ static int shallow_pkt( git_pkt_shallow *pkt; size_t oid_hexsize = git_oid_hexsize(data->oid_type); + GIT_ASSERT(data && data->oid_type); + pkt = git__calloc(1, sizeof(git_pkt_shallow)); GIT_ERROR_CHECK_ALLOC(pkt); @@ -487,6 +491,8 @@ static int unshallow_pkt( git_pkt_shallow *pkt; size_t oid_hexsize = git_oid_hexsize(data->oid_type); + GIT_ASSERT(data && data->oid_type); + pkt = git__calloc(1, sizeof(git_pkt_shallow)); GIT_ERROR_CHECK_ALLOC(pkt); diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index c37c3cc8d..eb2bc5be4 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -256,13 +256,20 @@ int git_smart__detect_caps( return 0; } -static int recv_pkt(git_pkt **out_pkt, git_pkt_type *out_type, gitno_buffer *buf) +static int recv_pkt( + git_pkt **out_pkt, + git_pkt_type *out_type, + transport_smart *t, + gitno_buffer *buf) { const char *ptr = buf->data, *line_end = ptr; git_pkt *pkt = NULL; git_pkt_parse_data pkt_parse_data = { 0 }; int error = 0, ret; + pkt_parse_data.oid_type = t->owner->repo->oid_type; + pkt_parse_data.seen_capabilities = 1; + do { if (buf->offset > 0) error = git_pkt_parse_line(&pkt, &line_end, ptr, buf->offset, &pkt_parse_data); @@ -303,7 +310,7 @@ static int store_common(transport_smart *t) int error; do { - if ((error = recv_pkt(&pkt, NULL, buf)) < 0) + if ((error = recv_pkt(&pkt, NULL, t, buf)) < 0) return error; if (pkt->type != GIT_PKT_ACK) { @@ -320,7 +327,7 @@ static int store_common(transport_smart *t) return 0; } -static int wait_while_ack(gitno_buffer *buf) +static int wait_while_ack(transport_smart *t, gitno_buffer *buf) { int error; git_pkt *pkt = NULL; @@ -329,7 +336,7 @@ static int wait_while_ack(gitno_buffer *buf) while (1) { git_pkt_free(pkt); - if ((error = recv_pkt(&pkt, NULL, buf)) < 0) + if ((error = recv_pkt(&pkt, NULL, t, buf)) < 0) return error; if (pkt->type == GIT_PKT_NAK) @@ -400,8 +407,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0) goto on_error; - while ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) == 0) { - + while ((error = recv_pkt((git_pkt **)&pkt, NULL, t, buf)) == 0) { if (pkt->type == GIT_PKT_SHALLOW) { git_shallowarray_add(wants->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_UNSHALLOW) { @@ -463,7 +469,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c if ((error = store_common(t)) < 0) goto on_error; } else { - if ((error = recv_pkt(NULL, &pkt_type, buf)) < 0) + if ((error = recv_pkt(NULL, &pkt_type, t, buf)) < 0) goto on_error; if (pkt_type == GIT_PKT_ACK) { @@ -535,7 +541,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c /* Now let's eat up whatever the server gives us */ if (!t->caps.multi_ack && !t->caps.multi_ack_detailed) { - if ((error = recv_pkt(NULL, &pkt_type, buf)) < 0) + if ((error = recv_pkt(NULL, &pkt_type, t, buf)) < 0) return error; if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) { @@ -543,7 +549,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c return -1; } } else { - error = wait_while_ack(buf); + error = wait_while_ack(t, buf); } return error; @@ -659,7 +665,7 @@ int git_smart__download_pack( goto done; } - if ((error = recv_pkt(&pkt, NULL, buf)) >= 0) { + if ((error = recv_pkt(&pkt, NULL, t, buf)) >= 0) { /* Check cancellation after network call */ if (t->cancelled.val) { git_error_clear(); diff --git a/tests/libgit2/transports/smart/packet.c b/tests/libgit2/transports/smart/packet.c index 2035e3b65..a775a4cfa 100644 --- a/tests/libgit2/transports/smart/packet.c +++ b/tests/libgit2/transports/smart/packet.c @@ -25,7 +25,7 @@ static void assert_data_pkt_parses(const char *line, const char *expected_data, size_t linelen = strlen(line) + 1; const char *endptr; git_pkt_data *pkt; - git_pkt_parse_data pkt_parse_data = { 0 }; + git_pkt_parse_data pkt_parse_data = { 1, GIT_OID_SHA1 }; cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen, &pkt_parse_data)); cl_assert_equal_i(pkt->type, GIT_PKT_DATA); @@ -71,7 +71,7 @@ static void assert_ack_parses(const char *line, const char *expected_oid, enum g const char *endptr; git_pkt_ack *pkt; git_oid oid; - git_pkt_parse_data pkt_parse_data = { 0 }; + git_pkt_parse_data pkt_parse_data = { 1, GIT_OID_SHA1 }; cl_git_pass(git_oid__fromstr(&oid, expected_oid, GIT_OID_SHA1)); -- cgit v1.2.1 From 8f7fc2ee505a0abe2186270a79b287e321c748c4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 24 Apr 2023 11:16:47 +0100 Subject: shallow: avoid unnecessary pkt free Looks like a double-free here. --- src/libgit2/transports/smart_protocol.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index eb2bc5be4..6167a8074 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -408,26 +408,28 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c goto on_error; while ((error = recv_pkt((git_pkt **)&pkt, NULL, t, buf)) == 0) { + bool complete = false; + if (pkt->type == GIT_PKT_SHALLOW) { git_shallowarray_add(wants->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_UNSHALLOW) { git_shallowarray_remove(wants->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_FLUSH) { /* Server is done, stop processing shallow oids */ - break; + complete = true; } else { - git_error_set(GIT_ERROR_NET, "Unexpected pkt type"); - goto on_error; + git_error_set(GIT_ERROR_NET, "unexpected packet type"); + error = -1; } git_pkt_free((git_pkt *) pkt); - } - git_pkt_free((git_pkt *) pkt); + if (complete || error < 0) + break; + } - if (error < 0) { + if (error < 0) goto on_error; - } } /* * Our support for ACK extensions is simply to parse them. On -- cgit v1.2.1 From 6a02b459ab1d9ca6eaeda96cce94ba5ce6f8eaea Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 24 Apr 2023 12:15:11 +0100 Subject: futils: use SHA256 for checksums always Use SHA256 for file checksums. SHA1 makes no sense as a default in 2023. Given that we're just looking at a file checksum to see if it's changed, this does not need to take repository's OID type into account or otherwise be configurable. --- src/libgit2/grafts.c | 5 +++-- src/util/futils.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 1bfdc500e..ef314550d 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -18,7 +18,7 @@ struct git_grafts { /* File backing the graft. NULL if it's an in-memory graft */ char *path; - git_oid path_checksum; + unsigned char path_checksum[GIT_HASH_SHA256_SIZE]; }; int git_grafts_new(git_grafts **out) @@ -97,7 +97,8 @@ int git_grafts_refresh(git_grafts *grafts) return 0; if ((error = git_futils_readbuffer_updated(&contents, grafts->path, - (grafts->path_checksum).id, &updated)) < 0) { + grafts->path_checksum, &updated)) < 0) { + if (error == GIT_ENOTFOUND) { git_grafts_clear(grafts); error = 0; diff --git a/src/util/futils.c b/src/util/futils.c index 084f1cd28..7b5a24b30 100644 --- a/src/util/futils.c +++ b/src/util/futils.c @@ -221,14 +221,14 @@ int git_futils_readbuffer_fd_full(git_str *buf, git_file fd) int git_futils_readbuffer_updated( git_str *out, const char *path, - unsigned char checksum[GIT_HASH_SHA1_SIZE], + unsigned char checksum[GIT_HASH_SHA256_SIZE], int *updated) { int error; git_file fd; struct stat st; git_str buf = GIT_STR_INIT; - unsigned char checksum_new[GIT_HASH_SHA1_SIZE]; + unsigned char checksum_new[GIT_HASH_SHA256_SIZE]; GIT_ASSERT_ARG(out); GIT_ASSERT_ARG(path && *path); @@ -261,7 +261,10 @@ int git_futils_readbuffer_updated( p_close(fd); if (checksum) { - if ((error = git_hash_buf(checksum_new, buf.ptr, buf.size, GIT_HASH_ALGORITHM_SHA1)) < 0) { + error = git_hash_buf(checksum_new, buf.ptr, + buf.size, GIT_HASH_ALGORITHM_SHA256); + + if (error < 0) { git_str_dispose(&buf); return error; } @@ -269,7 +272,7 @@ int git_futils_readbuffer_updated( /* * If we were given a checksum, we only want to use it if it's different */ - if (!memcmp(checksum, checksum_new, GIT_HASH_SHA1_SIZE)) { + if (!memcmp(checksum, checksum_new, GIT_HASH_SHA256_SIZE)) { git_str_dispose(&buf); if (updated) *updated = 0; @@ -277,7 +280,7 @@ int git_futils_readbuffer_updated( return 0; } - memcpy(checksum, checksum_new, GIT_HASH_SHA1_SIZE); + memcpy(checksum, checksum_new, GIT_HASH_SHA256_SIZE); } /* -- cgit v1.2.1 From 69592bde1f2789162b215b612df7c8a13956b722 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 24 Apr 2023 13:09:15 +0100 Subject: grafts: use `git_parse` to parse object IDs Don't mix parsing by hand and using `git_parse` to parse. --- src/libgit2/grafts.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index ef314550d..d46fc12c1 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -119,7 +119,7 @@ cleanup: return error; } -int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) +int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len) { git_array_oid_t parents = GIT_ARRAY_INIT; git_parse_ctx parser; @@ -127,29 +127,26 @@ int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen) git_grafts_clear(grafts); - if ((error = git_parse_ctx_init(&parser, content, contentlen)) < 0) + if ((error = git_parse_ctx_init(&parser, buf, len)) < 0) goto error; for (; parser.remain_len; git_parse_advance_line(&parser)) { - const char *line_start = parser.line, *line_end = parser.line + parser.line_len; git_oid graft_oid; - if ((error = git_oid__fromstrn(&graft_oid, line_start, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1)) < 0) { + if ((error = git_parse_advance_oid(&graft_oid, &parser, GIT_OID_SHA1)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); goto error; } - line_start += GIT_OID_SHA1_HEXSIZE; - while (line_start < line_end && *line_start == ' ') { + while (parser.line_len && git_parse_advance_expected(&parser, "\n", 1) != 0) { git_oid *id = git_array_alloc(parents); GIT_ERROR_CHECK_ALLOC(id); - if ((error = git_oid__fromstrn(id, ++line_start, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1)) < 0) { + if ((error = git_parse_advance_expected(&parser, " ", 1)) < 0 || + (error = git_parse_advance_oid(id, &parser, GIT_OID_SHA1)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); goto error; } - - line_start += GIT_OID_SHA1_HEXSIZE; } if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0) @@ -186,6 +183,7 @@ int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t paren if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND) goto cleanup; + if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0) goto cleanup; -- cgit v1.2.1 From 7d7f3059decbd6b4730bfd09da54726c1b3ed8ea Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 24 Apr 2023 13:32:43 +0100 Subject: grafts: handle SHA256 graft files --- src/libgit2/grafts.c | 22 +++++++++++++++++----- src/libgit2/grafts.h | 6 +++--- src/libgit2/repository.c | 4 ++-- tests/libgit2/grafts/basic.c | 2 +- tests/libgit2/grafts/parse.c | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index d46fc12c1..00de03e8b 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -16,15 +16,20 @@ struct git_grafts { /* Map of `git_commit_graft`s */ git_oidmap *commits; + /* Type of object IDs */ + git_oid_t oid_type; + /* File backing the graft. NULL if it's an in-memory graft */ char *path; unsigned char path_checksum[GIT_HASH_SHA256_SIZE]; }; -int git_grafts_new(git_grafts **out) +int git_grafts_new(git_grafts **out, git_oid_t oid_type) { git_grafts *grafts; + GIT_ASSERT_ARG(out && oid_type); + grafts = git__calloc(1, sizeof(*grafts)); GIT_ERROR_CHECK_ALLOC(grafts); @@ -33,19 +38,26 @@ int git_grafts_new(git_grafts **out) return -1; } + grafts->oid_type = oid_type; + *out = grafts; return 0; } -int git_grafts_from_file(git_grafts **out, const char *path) +int git_grafts_from_file( + git_grafts **out, + const char *path, + git_oid_t oid_type) { git_grafts *grafts = NULL; int error; + GIT_ASSERT_ARG(path && oid_type); + if (*out) return git_grafts_refresh(*out); - if ((error = git_grafts_new(&grafts)) < 0) + if ((error = git_grafts_new(&grafts, oid_type)) < 0) goto error; grafts->path = git__strdup(path); @@ -133,7 +145,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len) for (; parser.remain_len; git_parse_advance_line(&parser)) { git_oid graft_oid; - if ((error = git_parse_advance_oid(&graft_oid, &parser, GIT_OID_SHA1)) < 0) { + if ((error = git_parse_advance_oid(&graft_oid, &parser, grafts->oid_type)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num); goto error; } @@ -143,7 +155,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len) GIT_ERROR_CHECK_ALLOC(id); if ((error = git_parse_advance_expected(&parser, " ", 1)) < 0 || - (error = git_parse_advance_oid(id, &parser, GIT_OID_SHA1)) < 0) { + (error = git_parse_advance_oid(id, &parser, grafts->oid_type)) < 0) { git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num); goto error; } diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index fc61468f5..0c0e9cecb 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -19,13 +19,13 @@ typedef struct { typedef struct git_grafts git_grafts; -int git_grafts_new(git_grafts **out); -int git_grafts_from_file(git_grafts **out, const char *path); +int git_grafts_new(git_grafts **out, git_oid_t oid_type); +int git_grafts_from_file(git_grafts **out, const char *path, git_oid_t oid_type); void git_grafts_free(git_grafts *grafts); void git_grafts_clear(git_grafts *grafts); int git_grafts_refresh(git_grafts *grafts); -int git_grafts_parse(git_grafts *grafts, const char *content, size_t contentlen); +int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len); int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index a60fb23fa..5778a86f7 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -852,13 +852,13 @@ static int load_grafts(git_repository *repo) if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || - (error = git_grafts_from_file(&repo->grafts, path.ptr)) < 0) + (error = git_grafts_from_file(&repo->grafts, path.ptr, repo->oid_type)) < 0) goto error; git_str_clear(&path); if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 || - (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr)) < 0) + (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr, repo->oid_type)) < 0) goto error; error: diff --git a/tests/libgit2/grafts/basic.c b/tests/libgit2/grafts/basic.c index fe7477097..30c87f908 100644 --- a/tests/libgit2/grafts/basic.c +++ b/tests/libgit2/grafts/basic.c @@ -22,7 +22,7 @@ void test_grafts_basic__graft_add(void) git_commit_graft *graft; git_grafts *grafts; - cl_git_pass(git_grafts_new(&grafts)); + cl_git_pass(git_grafts_new(&grafts, GIT_OID_SHA1)); cl_assert(oid1 = git_array_alloc(parents)); cl_git_pass(git_oid__fromstr(&oid_src, "2f3053cbff8a4ca2f0666de364ddb734a28a31a9", GIT_OID_SHA1)); diff --git a/tests/libgit2/grafts/parse.c b/tests/libgit2/grafts/parse.c index 149b01c8c..3b0618a1d 100644 --- a/tests/libgit2/grafts/parse.c +++ b/tests/libgit2/grafts/parse.c @@ -19,7 +19,7 @@ static git_grafts *grafts; void test_grafts_parse__initialize(void) { - cl_git_pass(git_grafts_new(&grafts)); + cl_git_pass(git_grafts_new(&grafts, GIT_OID_SHA1)); } void test_grafts_parse__cleanup(void) -- cgit v1.2.1 From 3388f5ba1b821e9683d21ca41c34ed752d2db222 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 25 Apr 2023 09:31:34 +0100 Subject: shallow: don't default to -1 for depth Depth of `0` should indicate full depth. Disallow negative values (they may have a future meaning) and use `0` as the default. --- include/git2/remote.h | 6 +++--- src/libgit2/clone.c | 2 +- src/libgit2/fetch.c | 13 +++++-------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 9e4043f87..8d6127014 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -744,9 +744,9 @@ typedef struct { git_proxy_options proxy_opts; /** - * Depth of the fetch to perform. Depth <= 0 fetches the full history. + * Depth of the fetch to perform, or 0 for full history. * - * The default is -1. + * The default is 0. */ int depth; @@ -772,7 +772,7 @@ typedef struct { #define GIT_FETCH_OPTIONS_VERSION 1 #define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \ - GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT, -1, 0 } + GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT } /** * Initialize git_fetch_options structure diff --git a/src/libgit2/clone.c b/src/libgit2/clone.c index 43341a493..fca0ca0cc 100644 --- a/src/libgit2/clone.c +++ b/src/libgit2/clone.c @@ -421,7 +421,7 @@ static int clone_into( memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; - if (opts->depth <= 0) + if (!opts->depth) fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; if ((error = git_remote_connect_options__from_fetch_opts(&connect_opts, remote, &fetch_opts)) < 0) diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index d66892ca0..86b650a60 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -172,10 +172,12 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) remote->need_pack = 0; - if (!opts) - remote->nego.depth = -1; - else + if (opts) { + GIT_ASSERT_ARG(opts->unshallow == 0 || opts->depth == 0); + GIT_ASSERT_ARG(opts->depth >= 0); + remote->nego.depth = opts->unshallow ? INT_MAX : opts->depth; + } if (filter_wants(remote, opts) < 0) return -1; @@ -184,11 +186,6 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) if (!remote->need_pack) return 0; - if (opts && opts->unshallow && opts->depth > 0) { - git_error_set(GIT_ERROR_INVALID, "options '--depth' and '--unshallow' cannot be used together"); - return -1; - } - /* * Now we have everything set up so we can start tell the * server what we want and what we have. -- cgit v1.2.1 From 19ccab005ed2a65ddcd3f50a2a09214a5849871d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 25 Apr 2023 09:33:24 +0100 Subject: shallow: cleanup whitespace in tests --- tests/libgit2/transports/smart/shallowarray.c | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/libgit2/transports/smart/shallowarray.c b/tests/libgit2/transports/smart/shallowarray.c index ec4388e42..34511c5f6 100644 --- a/tests/libgit2/transports/smart/shallowarray.c +++ b/tests/libgit2/transports/smart/shallowarray.c @@ -15,37 +15,37 @@ void test_transports_smart_shallowarray__add_and_remove_oid_from_shallowarray(void) { - git_oid oid_0_obj, oid_1_obj, oid_2_obj; - git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); - git_array_init(shallow_roots->array); + git_oid oid_0_obj, oid_1_obj, oid_2_obj; + git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); + git_array_init(shallow_roots->array); - git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); - git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); - git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); + git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); + git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); + git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); - git_shallowarray_add(shallow_roots, &oid_0_obj); - git_shallowarray_add(shallow_roots, &oid_1_obj); - git_shallowarray_add(shallow_roots, &oid_2_obj); + git_shallowarray_add(shallow_roots, &oid_0_obj); + git_shallowarray_add(shallow_roots, &oid_1_obj); + git_shallowarray_add(shallow_roots, &oid_2_obj); - cl_assert_equal_i(3, shallow_roots->array.size); + cl_assert_equal_i(3, shallow_roots->array.size); cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&shallow_roots->array.ptr[2])); - git_shallowarray_remove(shallow_roots, &oid_2_obj); + git_shallowarray_remove(shallow_roots, &oid_2_obj); - cl_assert_equal_i(2, shallow_roots->array.size); + cl_assert_equal_i(2, shallow_roots->array.size); cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); - git_shallowarray_remove(shallow_roots, &oid_1_obj); + git_shallowarray_remove(shallow_roots, &oid_1_obj); - cl_assert_equal_i(1, shallow_roots->array.size); + cl_assert_equal_i(1, shallow_roots->array.size); cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - git_shallowarray_remove(shallow_roots, &oid_0_obj); + git_shallowarray_remove(shallow_roots, &oid_0_obj); - cl_assert_equal_i(0, shallow_roots->array.size); + cl_assert_equal_i(0, shallow_roots->array.size); git_array_clear(shallow_roots->array); git__free(shallow_roots); -- cgit v1.2.1 From 43db928895fa85e4ee104dc8757275400d5acc2a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 25 Apr 2023 10:48:33 +0100 Subject: grafts: make `from_file` be `open_or_refresh` The semantics of `from_file` are weird - it looks like a function that just opens a file, but it actually inspects the pointer, which is unexpected and could make things very crashy. Make an `open` function that just does an open, and move the magic to `open_or_refresh` whose name better indicates that it may do weird stuff. --- src/libgit2/grafts.c | 19 ++++++++++++++----- src/libgit2/grafts.h | 3 ++- src/libgit2/repository.c | 4 ++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 00de03e8b..83f5b2ab4 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -44,7 +44,7 @@ int git_grafts_new(git_grafts **out, git_oid_t oid_type) return 0; } -int git_grafts_from_file( +int git_grafts_open( git_grafts **out, const char *path, git_oid_t oid_type) @@ -52,10 +52,7 @@ int git_grafts_from_file( git_grafts *grafts = NULL; int error; - GIT_ASSERT_ARG(path && oid_type); - - if (*out) - return git_grafts_refresh(*out); + GIT_ASSERT_ARG(out && path && oid_type); if ((error = git_grafts_new(&grafts, oid_type)) < 0) goto error; @@ -67,12 +64,24 @@ int git_grafts_from_file( goto error; *out = grafts; + error: if (error < 0) git_grafts_free(grafts); + return error; } +int git_grafts_open_or_refresh( + git_grafts **out, + const char *path, + git_oid_t oid_type) +{ + GIT_ASSERT_ARG(out && path && oid_type); + + return *out ? git_grafts_refresh(*out) : git_grafts_open(out, path, oid_type); +} + void git_grafts_free(git_grafts *grafts) { if (!grafts) diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index 0c0e9cecb..0d561fc25 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -20,7 +20,8 @@ typedef struct { typedef struct git_grafts git_grafts; int git_grafts_new(git_grafts **out, git_oid_t oid_type); -int git_grafts_from_file(git_grafts **out, const char *path, git_oid_t oid_type); +int git_grafts_open(git_grafts **out, const char *path, git_oid_t oid_type); +int git_grafts_open_or_refresh(git_grafts **out, const char *path, git_oid_t oid_type); void git_grafts_free(git_grafts *grafts); void git_grafts_clear(git_grafts *grafts); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 5778a86f7..763b62375 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -852,13 +852,13 @@ static int load_grafts(git_repository *repo) if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 || - (error = git_grafts_from_file(&repo->grafts, path.ptr, repo->oid_type)) < 0) + (error = git_grafts_open_or_refresh(&repo->grafts, path.ptr, repo->oid_type)) < 0) goto error; git_str_clear(&path); if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 || - (error = git_grafts_from_file(&repo->shallow_grafts, path.ptr, repo->oid_type)) < 0) + (error = git_grafts_open_or_refresh(&repo->shallow_grafts, path.ptr, repo->oid_type)) < 0) goto error; error: -- cgit v1.2.1 From 04cddffea9d00d5788b4f41a7dce3356089228ab Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 25 Apr 2023 13:29:35 +0100 Subject: cli: add --depth option to clone --- src/cli/cmd_clone.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/cli/cmd_clone.c b/src/cli/cmd_clone.c index a382b5875..e4776256c 100644 --- a/src/cli/cmd_clone.c +++ b/src/cli/cmd_clone.c @@ -18,7 +18,7 @@ #define COMMAND_NAME "clone" -static char *branch, *remote_path, *local_path; +static char *branch, *remote_path, *local_path, *depth; static int show_help, quiet, checkout = 1, bare; static bool local_path_exists; static cli_progress progress = CLI_PROGRESS_INIT; @@ -36,6 +36,8 @@ static const cli_opt_spec opts[] = { CLI_OPT_USAGE_DEFAULT, NULL, "don't create a working directory" }, { CLI_OPT_TYPE_VALUE, "branch", 'b', &branch, 0, CLI_OPT_USAGE_DEFAULT, "name", "branch to check out" }, + { CLI_OPT_TYPE_VALUE, "depth", 0, &depth, 0, + CLI_OPT_USAGE_DEFAULT, "depth", "commit depth to check out " }, { CLI_OPT_TYPE_LITERAL }, { CLI_OPT_TYPE_ARG, "repository", 0, &remote_path, 0, CLI_OPT_USAGE_REQUIRED, "repository", "repository path" }, @@ -71,6 +73,22 @@ static char *compute_local_path(const char *orig_path) return local_path; } +static int compute_depth(const char *depth) +{ + int64_t i; + const char *endptr; + + if (!depth) + return 0; + + if (git__strntol64(&i, depth, strlen(depth), &endptr, 10) < 0 || i < 0 || i > INT_MAX || *endptr) { + fprintf(stderr, "fatal: depth '%s' is not valid.\n", depth); + exit(128); + } + + return (int)i; +} + static bool validate_local_path(const char *path) { if (!git_fs_path_exists(path)) @@ -127,11 +145,9 @@ int cmd_clone(int argc, char **argv) goto done; } - if (bare) - clone_opts.bare = 1; - - if (branch) - clone_opts.checkout_branch = branch; + clone_opts.bare = !!bare; + clone_opts.checkout_branch = branch; + clone_opts.fetch_opts.depth = compute_depth(depth); if (!checkout) clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; -- cgit v1.2.1 From 0a7e32b2326c02a91f9560dfd209e56ea9fb9d49 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 8 May 2023 10:07:11 +0100 Subject: oid: use an oid array instead of shallowarray Users should provide us an array of object ids; we don't need a separate type. And especially, we should not be mutating user-providing values. Instead, use `git_oid *` in the shallow code. --- include/git2/sys/transport.h | 22 +++--- src/libgit2/fetch.c | 29 +++++--- src/libgit2/grafts.c | 16 +++-- src/libgit2/grafts.h | 2 +- src/libgit2/oidarray.c | 52 +++++++++++++- src/libgit2/oidarray.h | 6 +- src/libgit2/remote.c | 5 -- src/libgit2/repository.c | 20 +++--- src/libgit2/repository.h | 4 +- src/libgit2/transports/local.c | 11 +++ src/libgit2/transports/smart.c | 49 +------------- src/libgit2/transports/smart.h | 7 +- src/libgit2/transports/smart_pkt.c | 13 ++-- src/libgit2/transports/smart_protocol.c | 56 +++++++++++++-- src/util/array.h | 3 + tests/libgit2/core/oidarray.c | 98 +++++++++++++++++++++++++++ tests/libgit2/online/shallow.c | 35 +++++----- tests/libgit2/transports/smart/shallowarray.c | 52 -------------- 18 files changed, 304 insertions(+), 176 deletions(-) create mode 100644 tests/libgit2/core/oidarray.c delete mode 100644 tests/libgit2/transports/smart/shallowarray.c diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index 062bcd0ed..96a35d08c 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -25,12 +25,11 @@ GIT_BEGIN_DECL -typedef struct git_shallowarray git_shallowarray; - typedef struct { const git_remote_head * const *refs; - size_t count; - git_shallowarray *shallow_roots; + size_t refs_len; + git_oid *shallow_roots; + size_t shallow_roots_len; int depth; } git_fetch_negotiation; @@ -107,6 +106,16 @@ struct git_transport { git_repository *repo, const git_fetch_negotiation *fetch_data); + /** + * Return the shallow roots of the remote. + * + * This function may be called after a successful call to + * `negotiate_fetch`. + */ + int GIT_CALLBACK(shallow_roots)( + git_oidarray *out, + git_transport *transport); + /** * Start downloading the packfile from the remote repository. * @@ -450,11 +459,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh( git_transport *owner, void *param); -GIT_EXTERN(size_t) git_shallowarray_count(git_shallowarray *array); -GIT_EXTERN(const git_oid *) git_shallowarray_get(git_shallowarray *array, size_t idx); -GIT_EXTERN(int) git_shallowarray_add(git_shallowarray *array, git_oid *oid); -GIT_EXTERN(int) git_shallowarray_remove(git_shallowarray *array, git_oid *oid); - /** @} */ GIT_END_DECL #endif diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 86b650a60..b43425215 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -61,7 +61,7 @@ static int mark_local(git_remote *remote) git_vector_foreach(&remote->refs, i, head) { /* If we have the object, mark it so we don't ask for it. - However if we are unshallowing, we need to ask for it + However if we are unshallowing, we need to ask for it even though the head exists locally. */ if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid)) head->local = 1; @@ -169,6 +169,7 @@ cleanup: int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) { git_transport *t = remote->transport; + int error; remote->need_pack = 0; @@ -191,33 +192,39 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) * server what we want and what we have. */ remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; - remote->nego.count = remote->refs.length; - remote->nego.shallow_roots = git__malloc(sizeof(*remote->nego.shallow_roots)); - - git_array_init(remote->nego.shallow_roots->array); + remote->nego.refs_len = remote->refs.length; - git_repository__shallow_roots(&remote->nego.shallow_roots->array, remote->repo); + if (git_repository__shallow_roots(&remote->nego.shallow_roots, + &remote->nego.shallow_roots_len, + remote->repo) < 0) + return -1; - return t->negotiate_fetch(t, + error = t->negotiate_fetch(t, remote->repo, &remote->nego); + + git__free(remote->nego.shallow_roots); + + return error; } int git_fetch_download_pack(git_remote *remote) { + git_oidarray shallow_roots = { NULL }; git_transport *t = remote->transport; int error; if (!remote->need_pack) return 0; - if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0) + if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0 || + (error = t->shallow_roots(&shallow_roots, t)) != 0) return error; - if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) != 0) - return error; + error = git_repository__shallow_roots_write(remote->repo, &shallow_roots); - return 0; + git_oidarray_dispose(&shallow_roots); + return error; } int git_fetch_options_init(git_fetch_options *opts, unsigned int version) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 83f5b2ab4..1d9373a56 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -243,20 +243,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi return 0; } -int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts) +int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts) { + git_array_oid_t array = GIT_ARRAY_INIT; const git_oid *oid; - size_t i = 0; - int error; + size_t existing, i = 0; GIT_ASSERT_ARG(out && grafts); - while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { - git_oid *cpy = git_array_alloc(*out); + if ((existing = git_oidmap_size(grafts->commits)) > 0) + git_array_init_to_size(array, existing); + + while (git_oidmap_iterate(NULL, grafts->commits, &i, &oid) == 0) { + git_oid *cpy = git_array_alloc(array); GIT_ERROR_CHECK_ALLOC(cpy); git_oid_cpy(cpy, oid); } + *out = array.ptr; + *out_len = array.size; + return 0; } diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index 0d561fc25..394867fd6 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -30,7 +30,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len); int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); -int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts); +int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts); size_t git_grafts_size(git_grafts *grafts); #endif diff --git a/src/libgit2/oidarray.c b/src/libgit2/oidarray.c index 583017c4e..37f67756a 100644 --- a/src/libgit2/oidarray.c +++ b/src/libgit2/oidarray.c @@ -15,10 +15,17 @@ void git_oidarray_dispose(git_oidarray *arr) git__free(arr->ids); } -void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array) +void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array) { - arr->count = array->size; - arr->ids = array->ptr; + out->count = array->size; + out->ids = array->ptr; +} + +void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array) +{ + out->ptr = array->ids; + out->size = array->count; + out->asize = array->count; } void git_oidarray__reverse(git_oidarray *arr) @@ -33,6 +40,45 @@ void git_oidarray__reverse(git_oidarray *arr) } } +int git_oidarray__add(git_array_oid_t *arr, git_oid *id) +{ + git_oid *add, *iter; + size_t i; + + git_array_foreach(*arr, i, iter) { + if (git_oid_cmp(iter, id) == 0) + return 0; + } + + if ((add = git_array_alloc(*arr)) == NULL) + return -1; + + git_oid_cpy(add, id); + return 0; +} + +bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id) +{ + bool found = false; + size_t remain, i; + git_oid *iter; + + git_array_foreach(*arr, i, iter) { + if (git_oid_cmp(iter, id) == 0) { + arr->size--; + remain = arr->size - i; + + if (remain > 0) + memmove(&arr->ptr[i], &arr->ptr[i+1], remain * sizeof(git_oid)); + + found = true; + break; + } + } + + return found; +} + #ifndef GIT_DEPRECATE_HARD void git_oidarray_free(git_oidarray *arr) diff --git a/src/libgit2/oidarray.h b/src/libgit2/oidarray.h index eed3a1091..8f1543a32 100644 --- a/src/libgit2/oidarray.h +++ b/src/libgit2/oidarray.h @@ -15,6 +15,10 @@ typedef git_array_t(git_oid) git_array_oid_t; extern void git_oidarray__reverse(git_oidarray *arr); -extern void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array); +extern void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array); +extern void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array); + +int git_oidarray__add(git_array_oid_t *arr, git_oid *id); +bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id); #endif diff --git a/src/libgit2/remote.c b/src/libgit2/remote.c index ef414209f..fee2a7f39 100644 --- a/src/libgit2/remote.c +++ b/src/libgit2/remote.c @@ -2167,11 +2167,6 @@ void git_remote_free(git_remote *remote) remote->transport = NULL; } - if (remote->nego.shallow_roots) { - git_array_clear(remote->nego.shallow_roots->array); - git__free(remote->nego.shallow_roots); - } - git_vector_free(&remote->refs); free_refspecs(&remote->refspecs); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 763b62375..8fcc4e2ba 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3651,7 +3651,11 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { +int git_repository__shallow_roots( + git_oid **out, + size_t *out_len, + git_repository *repo) +{ int error = 0; if (!repo->shallow_grafts && (error = load_grafts(repo)) < 0) @@ -3660,19 +3664,18 @@ int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0) return error; - if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) + if ((error = git_grafts_oids(out, out_len, repo->shallow_grafts)) < 0) return error; return 0; } -int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) +int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots) { git_filebuf file = GIT_FILEBUF_INIT; git_str path = GIT_STR_INIT; char oid_str[GIT_OID_MAX_HEXSIZE + 1]; - size_t idx; - git_oid *oid; + size_t i; int filebuf_hash, error = 0; GIT_ASSERT_ARG(repo); @@ -3686,8 +3689,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro if ((error = git_filebuf_open(&file, git_str_cstr(&path), filebuf_hash, 0666)) < 0) goto on_error; - git_array_foreach(roots, idx, oid) { - git_oid_tostr(oid_str, sizeof(oid_str), oid); + for (i = 0; i < roots->count; i++) { + git_oid_tostr(oid_str, sizeof(oid_str), &roots->ids[i]); git_filebuf_write(&file, oid_str, git_oid_hexsize(repo->oid_type)); git_filebuf_write(&file, "\n", 1); } @@ -3699,7 +3702,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro goto on_error; } - if (git_array_size(roots) == 0) + if (!roots->count) remove(path.ptr); on_error: @@ -3727,6 +3730,7 @@ int git_repository_is_shallow(git_repository *repo) if (error < 0) return error; + return st.st_size == 0 ? 0 : 1; } diff --git a/src/libgit2/repository.h b/src/libgit2/repository.h index d86b36271..8dc20324d 100644 --- a/src/libgit2/repository.h +++ b/src/libgit2/repository.h @@ -246,8 +246,8 @@ extern size_t git_repository__reserved_names_posix_len; bool git_repository__reserved_names( git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs); -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo); -int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots); +int git_repository__shallow_roots(git_oid **out, size_t *out_len, git_repository *repo); +int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots); /* * The default branch for the repository; the `init.defaultBranch` diff --git a/src/libgit2/transports/local.c b/src/libgit2/transports/local.c index f576682a7..64c21afbd 100644 --- a/src/libgit2/transports/local.c +++ b/src/libgit2/transports/local.c @@ -320,6 +320,16 @@ static int local_negotiate_fetch( return 0; } +static int local_shallow_roots( + git_oidarray *out, + git_transport *transport) +{ + GIT_UNUSED(out); + GIT_UNUSED(transport); + + return 0; +} + static int local_push_update_remote_ref( git_repository *remote_repo, const char *lref, @@ -745,6 +755,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param) t->parent.oid_type = local_oid_type; #endif t->parent.negotiate_fetch = local_negotiate_fetch; + t->parent.shallow_roots = local_shallow_roots; t->parent.download_pack = local_download_pack; t->parent.push = local_push; t->parent.close = local_close; diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index da6dca039..a56524bff 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -416,6 +416,8 @@ static void git_smart__free(git_transport *transport) git_remote_connect_options_dispose(&t->connect_opts); + git_array_dispose(t->shallow_roots); + git__free(t->caps.object_format); git__free(t->caps.agent); git__free(t); @@ -490,6 +492,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) t->parent.close = git_smart__close; t->parent.free = git_smart__free; t->parent.negotiate_fetch = git_smart__negotiate_fetch; + t->parent.shallow_roots = git_smart__shallow_roots; t->parent.download_pack = git_smart__download_pack; t->parent.push = git_smart__push; t->parent.ls = git_smart__ls; @@ -517,49 +520,3 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) *out = (git_transport *) t; return 0; } - -size_t git_shallowarray_count(git_shallowarray *array) -{ - return git_array_size(array->array); -} - -const git_oid * git_shallowarray_get(git_shallowarray *array, size_t idx) -{ - return git_array_get(array->array, idx); -} - -int git_shallowarray_add(git_shallowarray *array, git_oid *oid) -{ - size_t oid_index; - - if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, oid) < 0) { - git_oid *tmp = git_array_alloc(array->array); - GIT_ERROR_CHECK_ALLOC(tmp); - - git_oid_cpy(tmp, oid); - } - - return 0; -} - -int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) -{ - git_array_oid_t new_array = GIT_ARRAY_INIT; - git_oid *element; - git_oid *tmp; - size_t i; - - git_array_foreach(array->array, i, element) { - if (git_oid_cmp(oid, element)) { - tmp = git_array_alloc(new_array); - GIT_ERROR_CHECK_ALLOC(tmp); - - git_oid_cpy(tmp, element); - } - } - - git_array_clear(array->array); - array->array = new_array; - - return 0; -} diff --git a/src/libgit2/transports/smart.h b/src/libgit2/transports/smart.h index 8e06d03ef..34e27ea8e 100644 --- a/src/libgit2/transports/smart.h +++ b/src/libgit2/transports/smart.h @@ -163,6 +163,7 @@ typedef struct { git_vector refs; git_vector heads; git_vector common; + git_array_oid_t shallow_roots; git_atomic32 cancelled; packetsize_cb packetsize_cb; void *packetsize_payload; @@ -183,6 +184,8 @@ int git_smart__negotiate_fetch( git_repository *repo, const git_fetch_negotiation *wants); +int git_smart__shallow_roots(git_oidarray *out, git_transport *transport); + int git_smart__download_pack( git_transport *transport, git_repository *repo, @@ -208,8 +211,4 @@ int git_pkt_buffer_wants(const git_fetch_negotiation *wants, transport_smart_cap int git_pkt_buffer_have(git_oid *oid, git_str *buf); void git_pkt_free(git_pkt *pkt); -struct git_shallowarray { - git_array_oid_t array; -}; - #endif diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index f2c9eea8e..9127ad5fe 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -770,7 +770,7 @@ int git_pkt_buffer_wants( size_t oid_hexsize, want_len, i = 0; #ifdef GIT_EXPERIMENTAL_SHA256 - oid_type = wants->count > 0 ? wants->refs[0]->oid.type : GIT_OID_SHA1; + oid_type = wants->refs_len > 0 ? wants->refs[0]->oid.type : GIT_OID_SHA1; #else oid_type = GIT_OID_SHA1; #endif @@ -781,7 +781,7 @@ int git_pkt_buffer_wants( oid_hexsize + 1 /* LF */; if (caps->common) { - for (; i < wants->count; ++i) { + for (; i < wants->refs_len; ++i) { head = wants->refs[i]; if (!head->local) break; @@ -793,7 +793,7 @@ int git_pkt_buffer_wants( i++; } - for (; i < wants->count; ++i) { + for (; i < wants->refs_len; ++i) { head = wants->refs[i]; if (head->local) @@ -810,12 +810,11 @@ int git_pkt_buffer_wants( } /* Tell the server about our shallow objects */ - for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { + for (i = 0; i < wants->shallow_roots_len; i++) { char oid[GIT_OID_MAX_HEXSIZE + 1]; git_str shallow_buf = GIT_STR_INIT; - git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, - git_shallowarray_get(wants->shallow_roots, i)); + git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, &wants->shallow_roots[i]); git_str_puts(&shallow_buf, "shallow "); git_str_puts(&shallow_buf, oid); git_str_putc(&shallow_buf, '\n'); @@ -835,7 +834,7 @@ int git_pkt_buffer_wants( git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); git_str_dispose(&deepen_buf); - + if (git_str_oom(buf)) return -1; } diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index 6167a8074..488ef07c0 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -364,7 +364,9 @@ static int cap_not_sup_err(const char *cap_name) } /* Disables server capabilities we're not interested in */ -static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants) +static int setup_caps( + transport_smart_caps *caps, + const git_fetch_negotiation *wants) { if (wants->depth > 0) { if (!caps->shallow) @@ -376,7 +378,27 @@ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *w return 0; } -int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_fetch_negotiation *wants) +static int setup_shallow_roots( + git_array_oid_t *out, + const git_fetch_negotiation *wants) +{ + git_array_clear(*out); + + if (wants->shallow_roots_len > 0) { + git_array_init_to_size(*out, wants->shallow_roots_len); + GIT_ERROR_CHECK_ALLOC(out->ptr); + + memcpy(out->ptr, wants->shallow_roots, + sizeof(git_oid) * wants->shallow_roots_len); + } + + return 0; +} + +int git_smart__negotiate_fetch( + git_transport *transport, + git_repository *repo, + const git_fetch_negotiation *wants) { transport_smart *t = (transport_smart *)transport; git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; @@ -388,7 +410,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c unsigned int i; git_oid oid; - if ((error = setup_caps(&t->caps, wants)) < 0) + if ((error = setup_caps(&t->caps, wants)) < 0 || + (error = setup_shallow_roots(&t->shallow_roots, wants)) < 0) return error; if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) @@ -411,9 +434,9 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c bool complete = false; if (pkt->type == GIT_PKT_SHALLOW) { - git_shallowarray_add(wants->shallow_roots, &pkt->oid); + error = git_oidarray__add(&t->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_UNSHALLOW) { - git_shallowarray_remove(wants->shallow_roots, &pkt->oid); + git_oidarray__remove(&t->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_FLUSH) { /* Server is done, stop processing shallow oids */ complete = true; @@ -431,6 +454,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c if (error < 0) goto on_error; } + /* * Our support for ACK extensions is simply to parse them. On * the first ACK we will accept that as enough common @@ -531,10 +555,11 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c goto on_error; if (t->cancelled.val) { - git_error_set(GIT_ERROR_NET, "The fetch was cancelled by the user"); + git_error_set(GIT_ERROR_NET, "the fetch was cancelled"); error = GIT_EUSER; goto on_error; } + if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0) goto on_error; @@ -562,6 +587,25 @@ on_error: return error; } +int git_smart__shallow_roots(git_oidarray *out, git_transport *transport) +{ + transport_smart *t = (transport_smart *)transport; + size_t len; + + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&len, t->shallow_roots.size, sizeof(git_oid)); + + out->count = t->shallow_roots.size; + + if (len) { + out->ids = git__malloc(len); + memcpy(out->ids, t->shallow_roots.ptr, len); + } else { + out->ids = NULL; + } + + return 0; +} + static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_indexer_progress *stats) { int recvd; diff --git a/src/util/array.h b/src/util/array.h index bf66e1c5a..633d598ee 100644 --- a/src/util/array.h +++ b/src/util/array.h @@ -33,6 +33,9 @@ #define git_array_init_to_size(a, desired) \ do { (a).size = 0; (a).asize = desired; (a).ptr = git__calloc(desired, sizeof(*(a).ptr)); } while (0) +#define git_array_dispose(a) \ + do { git__free((a).ptr); } while (0) + #define git_array_clear(a) \ do { git__free((a).ptr); git_array_init(a); } while (0) diff --git a/tests/libgit2/core/oidarray.c b/tests/libgit2/core/oidarray.c new file mode 100644 index 000000000..4a9e47c70 --- /dev/null +++ b/tests/libgit2/core/oidarray.c @@ -0,0 +1,98 @@ +#include "clar_libgit2.h" + +#include "git2/oid.h" +#include "git2/transport.h" + +#include "common.h" +#include "transports/smart.h" +#include "oid.h" +#include "oidarray.h" + +#include + +#define oid_0 "c070ad8c08840c8116da865b2d65593a6bb9cd2a" +#define oid_1 "0966a434eb1a025db6b71485ab63a3bfbea520b6" +#define oid_2 "83834a7afdaa1a1260568567f6ad90020389f664" +#define oid_3 "746fb4c91a7b6190bc4761adf7410afc4b59812c" + +void test_core_oidarray__add_and_remove_oid_from_shallowarray(void) +{ + git_oid oid_0_obj, oid_1_obj, oid_2_obj, oid_3_obj; + git_array_oid_t array = GIT_ARRAY_INIT; + + git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); + git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); + git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); + git_oid__fromstr(&oid_3_obj, oid_3, GIT_OID_SHA1); + + /* add some initial ids */ + git_oidarray__add(&array, &oid_0_obj); + git_oidarray__add(&array, &oid_1_obj); + git_oidarray__add(&array, &oid_2_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&array.ptr[2])); + + /* don't duplicate existing ids */ + git_oidarray__add(&array, &oid_1_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&array.ptr[2])); + + /* remove the last id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_2_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + + /* add another id */ + git_oidarray__add(&array, &oid_3_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[2])); + + /* remove the first id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_0_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[1])); + + /* removing a nonexistent oid does nothing */ + cl_assert_equal_i(0, git_oidarray__remove(&array, &oid_2_obj)); + + /* add another id */ + git_oidarray__add(&array, &oid_0_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[2])); + + /* remove another id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_3_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[1])); + + /* remove another id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_1_obj)); + + cl_assert_equal_i(1, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + + /* remove the final id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_0_obj)); + + cl_assert_equal_i(0, array.size); + + git_array_clear(array); +} diff --git a/tests/libgit2/online/shallow.c b/tests/libgit2/online/shallow.c index a889a68cd..12ef7748b 100644 --- a/tests/libgit2/online/shallow.c +++ b/tests/libgit2/online/shallow.c @@ -16,7 +16,8 @@ void test_online_shallow__clone_depth_zero(void) git_str path = GIT_STR_INIT; git_repository *repo; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; clone_opts.fetch_opts.depth = 0; clone_opts.remote_cb = remote_single_branch; @@ -29,10 +30,10 @@ void test_online_shallow__clone_depth_zero(void) cl_assert_equal_b(false, git_repository_is_shallow(repo)); /* full clones do not have shallow roots. */ - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(0, roots.size); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(0, roots_len); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_repository_free(repo); } @@ -44,7 +45,8 @@ void test_online_shallow__clone_depth_one(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; size_t num_commits = 0; int error = 0; @@ -57,9 +59,9 @@ void test_online_shallow__clone_depth_one(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.size); - cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(1, roots_len); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots[0])); git_revwalk_new(&walk, repo); @@ -72,7 +74,7 @@ void test_online_shallow__clone_depth_one(void) cl_assert_equal_i(num_commits, 1); cl_assert_equal_i(error, GIT_ITEROVER); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); @@ -85,7 +87,8 @@ void test_online_shallow__clone_depth_five(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; size_t num_commits = 0; int error = 0; @@ -98,11 +101,11 @@ void test_online_shallow__clone_depth_five(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(3, roots.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(3, roots_len); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots[2])); git_revwalk_new(&walk, repo); @@ -115,7 +118,7 @@ void test_online_shallow__clone_depth_five(void) cl_assert_equal_i(num_commits, 13); cl_assert_equal_i(error, GIT_ITEROVER); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); diff --git a/tests/libgit2/transports/smart/shallowarray.c b/tests/libgit2/transports/smart/shallowarray.c deleted file mode 100644 index 34511c5f6..000000000 --- a/tests/libgit2/transports/smart/shallowarray.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/oid.h" -#include "git2/transport.h" - -#include "common.h" -#include "transports/smart.h" -#include "oid.h" - -#include - -#define oid_0 "c070ad8c08840c8116da865b2d65593a6bb9cd2a" -#define oid_1 "0966a434eb1a025db6b71485ab63a3bfbea520b6" -#define oid_2 "83834a7afdaa1a1260568567f6ad90020389f664" - -void test_transports_smart_shallowarray__add_and_remove_oid_from_shallowarray(void) -{ - git_oid oid_0_obj, oid_1_obj, oid_2_obj; - git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); - git_array_init(shallow_roots->array); - - git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); - git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); - git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); - - git_shallowarray_add(shallow_roots, &oid_0_obj); - git_shallowarray_add(shallow_roots, &oid_1_obj); - git_shallowarray_add(shallow_roots, &oid_2_obj); - - cl_assert_equal_i(3, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&shallow_roots->array.ptr[2])); - - git_shallowarray_remove(shallow_roots, &oid_2_obj); - - cl_assert_equal_i(2, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); - - git_shallowarray_remove(shallow_roots, &oid_1_obj); - - cl_assert_equal_i(1, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - - git_shallowarray_remove(shallow_roots, &oid_0_obj); - - cl_assert_equal_i(0, shallow_roots->array.size); - - git_array_clear(shallow_roots->array); - git__free(shallow_roots); -} -- cgit v1.2.1 From 437c5f5a0b6ae6068168081ac6422dba44cff31d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 8 May 2023 10:17:11 +0100 Subject: fetch: remove `unshallow` option The `depth` field is suitable to specify unshallowing; provide an enum to aide in specifying the `unshallow` value. --- include/git2/remote.h | 22 +++++++++++++--------- src/libgit2/fetch.c | 4 +--- tests/libgit2/online/shallow.c | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 8d6127014..e9065b250 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -702,6 +702,15 @@ typedef enum { GIT_REMOTE_DOWNLOAD_TAGS_ALL } git_remote_autotag_option_t; +/** Constants for fetch depth (shallowness of fetch). */ +typedef enum { + /** The fetch is "full" (not shallow). This is the default. */ + GIT_FETCH_DEPTH_FULL = 0, + + /** The fetch should "unshallow" and fetch missing data. */ + GIT_FETCH_DEPTH_UNSHALLOW = 2147483647 +} git_fetch_depth_t; + /** * Fetch options structure. * @@ -744,19 +753,14 @@ typedef struct { git_proxy_options proxy_opts; /** - * Depth of the fetch to perform, or 0 for full history. + * Depth of the fetch to perform, or `GIT_FETCH_DEPTH_FULL` + * (or `0`) for full history, or `GIT_FETCH_DEPTH_UNSHALLOW` + * to "unshallow" a shallow repository. * - * The default is 0. + * The default is full (`GIT_FETCH_DEPTH_FULL` or `0`). */ int depth; - /** - * Convert a shallow repository to a full repository. - * - * The default is 0, which means the flag is off. - */ - int unshallow; - /** * Whether to allow off-site redirects. If this is not * specified, the `http.followRedirects` configuration setting diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index b43425215..5bbef87f4 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -174,10 +174,8 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) remote->need_pack = 0; if (opts) { - GIT_ASSERT_ARG(opts->unshallow == 0 || opts->depth == 0); GIT_ASSERT_ARG(opts->depth >= 0); - - remote->nego.depth = opts->unshallow ? INT_MAX : opts->depth; + remote->nego.depth = opts->depth; } if (filter_wants(remote, opts) < 0) diff --git a/tests/libgit2/online/shallow.c b/tests/libgit2/online/shallow.c index 12ef7748b..5c0e6565b 100644 --- a/tests/libgit2/online/shallow.c +++ b/tests/libgit2/online/shallow.c @@ -143,7 +143,7 @@ void test_online_shallow__unshallow(void) cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts)); cl_assert_equal_b(true, git_repository_is_shallow(repo)); - fetch_opts.unshallow = 1; + fetch_opts.depth = GIT_FETCH_DEPTH_UNSHALLOW; cl_git_pass(git_remote_lookup(&origin, repo, "origin")); cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL)); -- cgit v1.2.1