diff options
author | Etienne Samson <samson.etienne@gmail.com> | 2018-08-02 21:38:42 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-06-27 14:33:58 +0200 |
commit | 919501a92dbafac6e6e876aa7160c3f46f8afe55 (patch) | |
tree | ce7ecf3a734a24535e7a6aec34ce943d6b23bdb0 | |
parent | 0668384efe29a4d92ce1e9d1108187599ac9a067 (diff) | |
download | libgit2-919501a92dbafac6e6e876aa7160c3f46f8afe55.tar.gz |
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.
-rw-r--r-- | src/buffer.h | 5 | ||||
-rw-r--r-- | src/commit.c | 1 | ||||
-rw-r--r-- | src/repository.c | 81 | ||||
-rw-r--r-- | src/repository.h | 4 |
4 files changed, 91 insertions, 0 deletions
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]; |