summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Samson <samson.etienne@gmail.com>2018-08-02 21:38:42 +0200
committerPatrick Steinhardt <ps@pks.im>2020-06-27 14:33:58 +0200
commit919501a92dbafac6e6e876aa7160c3f46f8afe55 (patch)
treece7ecf3a734a24535e7a6aec34ce943d6b23bdb0
parent0668384efe29a4d92ce1e9d1108187599ac9a067 (diff)
downloadlibgit2-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.h5
-rw-r--r--src/commit.c1
-rw-r--r--src/repository.c81
-rw-r--r--src/repository.h4
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];