Skip to content

Commit 0bd52e2

Browse files
ttaylorrgitster
authored andcommitted
commit-graph.h: store an odb in 'struct write_commit_graph_context'
There are lots of places in 'commit-graph.h' where a function either has (or almost has) a full 'struct object_directory *', accesses '->path', and then throws away the rest of the struct. This can cause headaches when comparing the locations of object directories across alternates (e.g., in the case of deciding if two commit-graph layers can be merged). These paths are normalized with 'normalize_path_copy()' which mitigates some comparison issues, but not all [1]. Replace usage of 'char *object_dir' with 'odb->path' by storing a 'struct object_directory *' in the 'write_commit_graph_context' structure. This is an intermediate step towards getting rid of all path normalization in 'commit-graph.c'. Resolving a user-provided '--object-dir' argument now requires that we compare it to the known alternates for equality. Prior to this patch, an unknown '--object-dir' argument would silently exit with status zero. This can clearly lead to unintended behavior, such as verifying commit-graphs that aren't in a repository's own object store (or one of its alternates), or causing a typo to mask a legitimate commit-graph verification failure. Make this error non-silent by 'die()'-ing when the given '--object-dir' does not match any known alternate object store. [1]: In my testing, for example, I can get one side of the commit-graph code to fill object_dir with "./objects" and the other with just "objects". Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1793280 commit 0bd52e2

File tree

7 files changed

+54
-36
lines changed

7 files changed

+54
-36
lines changed

Documentation/git-commit-graph.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ OPTIONS
2626
file. This parameter exists to specify the location of an alternate
2727
that only has the objects directory, not a full `.git` directory. The
2828
commit-graph file is expected to be in the `<dir>/info` directory and
29-
the packfiles are expected to be in `<dir>/pack`.
29+
the packfiles are expected to be in `<dir>/pack`. If the directory
30+
could not be made into an absolute path, or does not match any known
31+
object directory, `git commit-graph ...` will exit with non-zero
32+
status.
3033

3134
--[no-]progress::
3235
Turn progress on/off explicitly. If neither is specified, progress is

builtin/commit-graph.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,29 @@ static struct opts_commit_graph {
3434
int progress;
3535
} opts;
3636

37+
static struct object_directory *find_odb(struct repository *r,
38+
const char *obj_dir)
39+
{
40+
struct object_directory *odb;
41+
char *obj_dir_real = real_pathdup(obj_dir, 1);
42+
43+
prepare_alt_odb(r);
44+
for (odb = r->objects->odb; odb; odb = odb->next) {
45+
if (!strcmp(obj_dir_real, real_path(odb->path)))
46+
break;
47+
}
48+
49+
free(obj_dir_real);
50+
51+
if (!odb)
52+
die(_("could not find object directory matching %s"), obj_dir);
53+
return odb;
54+
}
55+
3756
static int graph_verify(int argc, const char **argv)
3857
{
3958
struct commit_graph *graph = NULL;
59+
struct object_directory *odb = NULL;
4060
char *graph_name;
4161
int open_ok;
4262
int fd;
@@ -67,7 +87,8 @@ static int graph_verify(int argc, const char **argv)
6787
if (opts.progress)
6888
flags |= COMMIT_GRAPH_WRITE_PROGRESS;
6989

70-
graph_name = get_commit_graph_filename(opts.obj_dir);
90+
odb = find_odb(the_repository, opts.obj_dir);
91+
graph_name = get_commit_graph_filename(odb->path);
7192
open_ok = open_commit_graph(graph_name, &fd, &st);
7293
if (!open_ok && errno != ENOENT)
7394
die_errno(_("Could not open commit-graph '%s'"), graph_name);
@@ -76,8 +97,8 @@ static int graph_verify(int argc, const char **argv)
7697

7798
if (open_ok)
7899
graph = load_commit_graph_one_fd_st(fd, &st);
79-
else
80-
graph = read_commit_graph_one(the_repository, opts.obj_dir);
100+
else
101+
graph = read_commit_graph_one(the_repository, odb->path);
81102

82103
/* Return failure if open_ok predicted success */
83104
if (!graph)
@@ -94,6 +115,7 @@ static int graph_write(int argc, const char **argv)
94115
{
95116
struct string_list *pack_indexes = NULL;
96117
struct string_list *commit_hex = NULL;
118+
struct object_directory *odb = NULL;
97119
struct string_list lines;
98120
int result = 0;
99121
enum commit_graph_write_flags flags = 0;
@@ -145,9 +167,10 @@ static int graph_write(int argc, const char **argv)
145167
flags |= COMMIT_GRAPH_WRITE_PROGRESS;
146168

147169
read_replace_refs = 0;
170+
odb = find_odb(the_repository, opts.obj_dir);
148171

149172
if (opts.reachable) {
150-
if (write_commit_graph_reachable(opts.obj_dir, flags, &split_opts))
173+
if (write_commit_graph_reachable(odb, flags, &split_opts))
151174
return 1;
152175
return 0;
153176
}
@@ -169,7 +192,7 @@ static int graph_write(int argc, const char **argv)
169192
UNLEAK(buf);
170193
}
171194

172-
if (write_commit_graph(opts.obj_dir,
195+
if (write_commit_graph(odb,
173196
pack_indexes,
174197
commit_hex,
175198
flags,

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1688,7 +1688,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16881688
"not exceeded, and then \"git restore --staged :/\" to recover."));
16891689

16901690
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
1691-
write_commit_graph_reachable(get_object_directory(), 0, NULL))
1691+
write_commit_graph_reachable(the_repository->objects->odb, 0, NULL))
16921692
return 1;
16931693

16941694
repo_rerere(the_repository, 0);

builtin/fetch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1870,7 +1870,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
18701870
if (progress)
18711871
commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS;
18721872

1873-
write_commit_graph_reachable(get_object_directory(),
1873+
write_commit_graph_reachable(the_repository->objects->odb,
18741874
commit_graph_flags,
18751875
NULL);
18761876
}

builtin/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
686686

687687
prepare_repo_settings(the_repository);
688688
if (the_repository->settings.gc_write_commit_graph == 1)
689-
write_commit_graph_reachable(get_object_directory(),
689+
write_commit_graph_reachable(the_repository->objects->odb,
690690
!quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
691691
NULL);
692692

commit-graph.c

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ struct packed_oid_list {
772772

773773
struct write_commit_graph_context {
774774
struct repository *r;
775-
char *obj_dir;
775+
struct object_directory *odb;
776776
char *graph_name;
777777
struct packed_oid_list oids;
778778
struct packed_commit_list commits;
@@ -1149,15 +1149,15 @@ static int add_ref_to_list(const char *refname,
11491149
return 0;
11501150
}
11511151

1152-
int write_commit_graph_reachable(const char *obj_dir,
1152+
int write_commit_graph_reachable(struct object_directory *odb,
11531153
enum commit_graph_write_flags flags,
11541154
const struct split_commit_graph_opts *split_opts)
11551155
{
11561156
struct string_list list = STRING_LIST_INIT_DUP;
11571157
int result;
11581158

11591159
for_each_ref(add_ref_to_list, &list);
1160-
result = write_commit_graph(obj_dir, NULL, &list,
1160+
result = write_commit_graph(odb, NULL, &list,
11611161
flags, split_opts);
11621162

11631163
string_list_clear(&list, 0);
@@ -1172,7 +1172,7 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx,
11721172
struct strbuf packname = STRBUF_INIT;
11731173
int dirlen;
11741174

1175-
strbuf_addf(&packname, "%s/pack/", ctx->obj_dir);
1175+
strbuf_addf(&packname, "%s/pack/", ctx->odb->path);
11761176
dirlen = packname.len;
11771177
if (ctx->report_progress) {
11781178
strbuf_addf(&progress_title,
@@ -1368,10 +1368,10 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
13681368

13691369
strbuf_addf(&tmp_file,
13701370
"%s/info/commit-graphs/tmp_graph_XXXXXX",
1371-
ctx->obj_dir);
1371+
ctx->odb->path);
13721372
ctx->graph_name = strbuf_detach(&tmp_file, NULL);
13731373
} else {
1374-
ctx->graph_name = get_commit_graph_filename(ctx->obj_dir);
1374+
ctx->graph_name = get_commit_graph_filename(ctx->odb->path);
13751375
}
13761376

13771377
if (safe_create_leading_directories(ctx->graph_name)) {
@@ -1382,7 +1382,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
13821382
}
13831383

13841384
if (ctx->split) {
1385-
char *lock_name = get_chain_filename(ctx->obj_dir);
1385+
char *lock_name = get_chain_filename(ctx->odb->path);
13861386

13871387
hold_lock_file_for_update(&lk, lock_name, LOCK_DIE_ON_ERROR);
13881388

@@ -1506,12 +1506,12 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
15061506
}
15071507
}
15081508
} else {
1509-
char *graph_name = get_commit_graph_filename(ctx->obj_dir);
1509+
char *graph_name = get_commit_graph_filename(ctx->odb->path);
15101510
unlink(graph_name);
15111511
}
15121512

15131513
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(oid_to_hex(&file_hash));
1514-
final_graph_name = get_split_graph_filename(ctx->obj_dir,
1514+
final_graph_name = get_split_graph_filename(ctx->odb->path,
15151515
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
15161516
ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1] = final_graph_name;
15171517

@@ -1553,7 +1553,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
15531553

15541554
while (g && (g->num_commits <= size_mult * num_commits ||
15551555
(max_commits && num_commits > max_commits))) {
1556-
if (strcmp(g->obj_dir, ctx->obj_dir))
1556+
if (strcmp(g->obj_dir, ctx->odb->path))
15571557
break;
15581558

15591559
num_commits += g->num_commits;
@@ -1568,7 +1568,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
15681568
char *old_graph_name = get_commit_graph_filename(g->obj_dir);
15691569

15701570
if (!strcmp(g->filename, old_graph_name) &&
1571-
strcmp(g->obj_dir, ctx->obj_dir)) {
1571+
strcmp(g->obj_dir, ctx->odb->path)) {
15721572
ctx->num_commit_graphs_after = 1;
15731573
ctx->new_base_graph = NULL;
15741574
}
@@ -1719,13 +1719,13 @@ static void expire_commit_graphs(struct write_commit_graph_context *ctx)
17191719
if (ctx->split_opts && ctx->split_opts->expire_time)
17201720
expire_time -= ctx->split_opts->expire_time;
17211721
if (!ctx->split) {
1722-
char *chain_file_name = get_chain_filename(ctx->obj_dir);
1722+
char *chain_file_name = get_chain_filename(ctx->odb->path);
17231723
unlink(chain_file_name);
17241724
free(chain_file_name);
17251725
ctx->num_commit_graphs_after = 0;
17261726
}
17271727

1728-
strbuf_addstr(&path, ctx->obj_dir);
1728+
strbuf_addstr(&path, ctx->odb->path);
17291729
strbuf_addstr(&path, "/info/commit-graphs");
17301730
dir = opendir(path.buf);
17311731

@@ -1764,30 +1764,22 @@ static void expire_commit_graphs(struct write_commit_graph_context *ctx)
17641764
strbuf_release(&path);
17651765
}
17661766

1767-
int write_commit_graph(const char *obj_dir,
1767+
int write_commit_graph(struct object_directory *odb,
17681768
struct string_list *pack_indexes,
17691769
struct string_list *commit_hex,
17701770
enum commit_graph_write_flags flags,
17711771
const struct split_commit_graph_opts *split_opts)
17721772
{
17731773
struct write_commit_graph_context *ctx;
17741774
uint32_t i, count_distinct = 0;
1775-
size_t len;
17761775
int res = 0;
17771776

17781777
if (!commit_graph_compatible(the_repository))
17791778
return 0;
17801779

17811780
ctx = xcalloc(1, sizeof(struct write_commit_graph_context));
17821781
ctx->r = the_repository;
1783-
1784-
/* normalize object dir with no trailing slash */
1785-
ctx->obj_dir = xmallocz(strlen(obj_dir) + 1);
1786-
normalize_path_copy(ctx->obj_dir, obj_dir);
1787-
len = strlen(ctx->obj_dir);
1788-
if (len && ctx->obj_dir[len - 1] == '/')
1789-
ctx->obj_dir[len - 1] = 0;
1790-
1782+
ctx->odb = odb;
17911783
ctx->append = flags & COMMIT_GRAPH_WRITE_APPEND ? 1 : 0;
17921784
ctx->report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0;
17931785
ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0;
@@ -1824,7 +1816,7 @@ int write_commit_graph(const char *obj_dir,
18241816
ctx->oids.alloc = split_opts->max_commits;
18251817

18261818
if (ctx->append) {
1827-
prepare_commit_graph_one(ctx->r, ctx->obj_dir);
1819+
prepare_commit_graph_one(ctx->r, ctx->odb->path);
18281820
if (ctx->r->objects->commit_graph)
18291821
ctx->oids.alloc += ctx->r->objects->commit_graph->num_commits;
18301822
}
@@ -1898,7 +1890,6 @@ int write_commit_graph(const char *obj_dir,
18981890
free(ctx->graph_name);
18991891
free(ctx->commits.list);
19001892
free(ctx->oids.list);
1901-
free(ctx->obj_dir);
19021893

19031894
if (ctx->commit_graph_filenames_after) {
19041895
for (i = 0; i < ctx->num_commit_graphs_after; i++) {

commit-graph.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "repository.h"
66
#include "string-list.h"
77
#include "cache.h"
8+
#include "object-store.h"
89

910
#define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH"
1011
#define GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD "GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD"
@@ -91,10 +92,10 @@ struct split_commit_graph_opts {
9192
* is not compatible with the commit-graph feature, then the
9293
* methods will return 0 without writing a commit-graph.
9394
*/
94-
int write_commit_graph_reachable(const char *obj_dir,
95+
int write_commit_graph_reachable(struct object_directory *odb,
9596
enum commit_graph_write_flags flags,
9697
const struct split_commit_graph_opts *split_opts);
97-
int write_commit_graph(const char *obj_dir,
98+
int write_commit_graph(struct object_directory *odb,
9899
struct string_list *pack_indexes,
99100
struct string_list *commit_hex,
100101
enum commit_graph_write_flags flags,

0 commit comments

Comments
 (0)