Skip to content

Commit 61df89c

Browse files
avargitster
authored andcommitted
commit-graph: don't early exit(1) on e.g. "git status"
Make the commit-graph loading code work as a library that returns an error code instead of calling exit(1) when the commit-graph is corrupt. This means that e.g. "status" will now report commit-graph corruption as an "error: [...]" at the top of its output, but then proceed to work normally. This required splitting up the load_commit_graph_one() function so that the code that deals with open()-ing and stat()-ing the graph can now be called independently as open_commit_graph(). This is needed because "commit-graph verify" where the graph doesn't exist isn't an error. See the third paragraph in 283e68c ("commit-graph: add 'verify' subcommand", 2018-06-27). There's a bug in that logic where we conflate the intended ENOENT with other errno values (e.g. EACCES), but this change doesn't address that. That'll be addressed in a follow-up change. I'm then splitting most of the logic out of load_commit_graph_one() into load_commit_graph_one_fd_st(), which allows for providing an existing file descriptor and stat information to the loading code. This isn't strictly needed, but it would be redundant and confusing to open() and stat() the file twice for some of the codepaths, this allows for calling open_commit_graph() followed by load_commit_graph_one_fd_st(). The "graph_file" still needs to be passed to that function for the the "graph file %s is too small" error message. This leaves load_commit_graph_one() unused by everything except the internal prepare_commit_graph_one() function, so let's mark it as "static". If someone needs it in the future we can remove the "static" attribute. I could also rewrite its sole remaining user ("prepare_commit_graph_one()") to use load_commit_graph_one_fd_st() instead, but let's leave it at this. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Ramsay Jones <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2ac138d commit 61df89c

File tree

4 files changed

+51
-18
lines changed

4 files changed

+51
-18
lines changed

builtin/commit-graph.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ static int graph_verify(int argc, const char **argv)
4242
{
4343
struct commit_graph *graph = NULL;
4444
char *graph_name;
45+
int open_ok;
46+
int fd;
47+
struct stat st;
4548

4649
static struct option builtin_commit_graph_verify_options[] = {
4750
OPT_STRING(0, "object-dir", &opts.obj_dir,
@@ -58,11 +61,14 @@ static int graph_verify(int argc, const char **argv)
5861
opts.obj_dir = get_object_directory();
5962

6063
graph_name = get_commit_graph_filename(opts.obj_dir);
61-
graph = load_commit_graph_one(graph_name);
64+
open_ok = open_commit_graph(graph_name, &fd, &st);
65+
if (!open_ok)
66+
return 0;
67+
graph = load_commit_graph_one_fd_st(graph_name, fd, &st);
6268
FREE_AND_NULL(graph_name);
6369

6470
if (!graph)
65-
return 0;
71+
return 1;
6672

6773
UNLEAK(graph);
6874
return verify_commit_graph(the_repository, graph);
@@ -72,6 +78,9 @@ static int graph_read(int argc, const char **argv)
7278
{
7379
struct commit_graph *graph = NULL;
7480
char *graph_name;
81+
int open_ok;
82+
int fd;
83+
struct stat st;
7584

7685
static struct option builtin_commit_graph_read_options[] = {
7786
OPT_STRING(0, "object-dir", &opts.obj_dir,
@@ -88,10 +97,14 @@ static int graph_read(int argc, const char **argv)
8897
opts.obj_dir = get_object_directory();
8998

9099
graph_name = get_commit_graph_filename(opts.obj_dir);
91-
graph = load_commit_graph_one(graph_name);
92100

101+
open_ok = open_commit_graph(graph_name, &fd, &st);
102+
if (!open_ok)
103+
die_errno(_("Could not open commit-graph '%s'"), graph_name);
104+
105+
graph = load_commit_graph_one_fd_st(graph_name, fd, &st);
93106
if (!graph)
94-
die("graph file %s does not exist", graph_name);
107+
return 1;
95108

96109
FREE_AND_NULL(graph_name);
97110

commit-graph.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,38 @@ static int commit_graph_compatible(struct repository *r)
8080
return 1;
8181
}
8282

83-
struct commit_graph *load_commit_graph_one(const char *graph_file)
83+
int open_commit_graph(const char *graph_file, int *fd, struct stat *st)
84+
{
85+
*fd = git_open(graph_file);
86+
if (*fd < 0)
87+
return 0;
88+
if (fstat(*fd, st)) {
89+
close(*fd);
90+
return 0;
91+
}
92+
return 1;
93+
}
94+
95+
struct commit_graph *load_commit_graph_one_fd_st(const char *graph_file,
96+
int fd, struct stat *st)
8497
{
8598
void *graph_map;
8699
size_t graph_size;
87-
struct stat st;
88100
struct commit_graph *ret;
89-
int fd = git_open(graph_file);
90101

91-
if (fd < 0)
92-
return NULL;
93-
if (fstat(fd, &st)) {
94-
close(fd);
95-
return NULL;
96-
}
97-
graph_size = xsize_t(st.st_size);
102+
graph_size = xsize_t(st->st_size);
98103

99104
if (graph_size < GRAPH_MIN_SIZE) {
100105
close(fd);
101-
die(_("graph file %s is too small"), graph_file);
106+
error(_("graph file %s is too small"), graph_file);
107+
return NULL;
102108
}
103109
graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
104110
ret = parse_commit_graph(graph_map, fd, graph_size);
105111

106112
if (!ret) {
107113
munmap(graph_map, graph_size);
108114
close(fd);
109-
exit(1);
110115
}
111116

112117
return ret;
@@ -269,6 +274,19 @@ struct commit_graph *parse_commit_graph(void *graph_map, int fd,
269274
return graph;
270275
}
271276

277+
static struct commit_graph *load_commit_graph_one(const char *graph_file)
278+
{
279+
280+
struct stat st;
281+
int fd;
282+
int open_ok = open_commit_graph(graph_file, &fd, &st);
283+
284+
if (!open_ok)
285+
return NULL;
286+
287+
return load_commit_graph_one_fd_st(graph_file, fd, &st);
288+
}
289+
272290
static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
273291
{
274292
char *graph_name;

commit-graph.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
struct commit;
1212

1313
char *get_commit_graph_filename(const char *obj_dir);
14+
int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
1415

1516
/*
1617
* Given a commit struct, try to fill the commit struct info, including:
@@ -52,7 +53,8 @@ struct commit_graph {
5253
const unsigned char *chunk_extra_edges;
5354
};
5455

55-
struct commit_graph *load_commit_graph_one(const char *graph_file);
56+
struct commit_graph *load_commit_graph_one_fd_st(const char *graph_file,
57+
int fd, struct stat *st);
5658

5759
struct commit_graph *parse_commit_graph(void *graph_map, int fd,
5860
size_t graph_size);

t/t5318-commit-graph.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ corrupt_graph_verify() {
377377
test_must_fail git commit-graph verify 2>test_err &&
378378
grep -v "^+" test_err >err &&
379379
test_i18ngrep "$grepstr" err &&
380-
test_might_fail git status --short
380+
git status --short
381381
}
382382

383383
# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]

0 commit comments

Comments
 (0)