From 1a2f960907ebeeb703c85c5d2b61de8dbd69a1b5 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 5 Jan 2021 06:24:26 -0800 Subject: commit-graph: Introduce `git_commit_graph_needs_refresh()` This change introduces a function that allows the caller to know whether the `commit-graph` file has not been modified since it was parsed. Part of: #5757 --- src/commit_graph.c | 34 ++++++++++++++++++++++++++++++++++ src/commit_graph.h | 8 ++++++++ tests/graph/commit_graph.c | 1 + 3 files changed, 43 insertions(+) diff --git a/src/commit_graph.c b/src/commit_graph.c index 9740418e2..b301d3d49 100644 --- a/src/commit_graph.c +++ b/src/commit_graph.c @@ -333,6 +333,40 @@ static int git_commit_graph_entry_get_byindex( return 0; } +bool git_commit_graph_needs_refresh(const git_commit_graph_file *cgraph, const char *path) +{ + git_file fd = -1; + struct stat st; + ssize_t bytes_read; + git_oid cgraph_checksum = {{0}}; + + if (path == NULL) + path = git_buf_cstr(&cgraph->filename); + + /* TODO: properly open the file without access time using O_NOATIME */ + fd = git_futils_open_ro(path); + if (fd < 0) + return true; + + if (p_fstat(fd, &st) < 0) { + p_close(fd); + return true; + } + + if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size) + || (size_t)st.st_size != cgraph->graph_map.len) { + p_close(fd); + return true; + } + + bytes_read = p_pread(fd, cgraph_checksum.id, GIT_OID_RAWSZ, st.st_size - GIT_OID_RAWSZ); + p_close(fd); + if (bytes_read != GIT_OID_RAWSZ) + return true; + + return !git_oid_equal(&cgraph_checksum, &cgraph->checksum); +} + int git_commit_graph_entry_find( git_commit_graph_entry *e, const git_commit_graph_file *cgraph, diff --git a/src/commit_graph.h b/src/commit_graph.h index f3a431705..f21a03769 100644 --- a/src/commit_graph.h +++ b/src/commit_graph.h @@ -89,6 +89,14 @@ typedef struct git_commit_graph_entry { } git_commit_graph_entry; int git_commit_graph_open(git_commit_graph_file **cgraph_out, const char *path); + +/* + * Returns whether the commit_graph_file needs to be reloaded since the + * contents of the commit-graph file have changed on disk. If `path` is NULL, + * the filename stored in `cgraph` will be used. + */ +bool git_commit_graph_needs_refresh(const git_commit_graph_file *cgraph, const char *path); + int git_commit_graph_entry_find( git_commit_graph_entry *e, const git_commit_graph_file *cgraph, diff --git a/tests/graph/commit_graph.c b/tests/graph/commit_graph.c index 43f566796..4c7c5a726 100644 --- a/tests/graph/commit_graph.c +++ b/tests/graph/commit_graph.c @@ -15,6 +15,7 @@ void test_graph_commit_graph__parse(void) cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); cl_git_pass(git_buf_joinpath(&commit_graph_path, git_repository_path(repo), "objects/info/commit-graph")); cl_git_pass(git_commit_graph_open(&cgraph, git_buf_cstr(&commit_graph_path))); + cl_assert_equal_i(git_commit_graph_needs_refresh(cgraph, git_buf_cstr(&commit_graph_path)), 0); cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5")); cl_git_pass(git_commit_graph_entry_find(&e, cgraph, &id, GIT_OID_HEXSZ)); -- cgit v1.2.1