rerere: let `rerere_path()` write paths into a caller-provided buffer
Same as with `get_worktree_git_dir()` a couple of commits ago, the `rerere_path()` function returns paths that need not be free'd by the caller because `git_path()` internally uses `get_pathname()`. Refactor the function to instead accept a caller-provided buffer that the path will be written into, passing on ownership to the caller. This refactoring prepares us for the removal of `git_path()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Feb 7, 2025 at 12:03 UTC
8ee018d863e521f32a9cb92db66c25e848b5e0d0
3 files changed
+69
-32
builtin/rerere.c
+7
-4
@@ -4,9 +4,9 @@
4
#include "config.h"
5
#include "gettext.h"
6
#include "parse-options.h"
7
-
8
-#include "string-list.h"
7
#include "rerere.h"
8
+#include "strbuf.h"
9
+#include "string-list.h"
10
#include "xdiff/xdiff.h"
11
#include "xdiff-interface.h"
12
#include "pathspec.h"
@@ -112,15 +112,18 @@ int cmd_rerere(int argc,
112
merge_rr.items[i].util = NULL;
113
}
114
} else if (!strcmp(argv[0], "diff")) {
115
+ struct strbuf buf = STRBUF_INIT;
116
if (setup_rerere(the_repository, &merge_rr,
117
flags | RERERE_READONLY) < 0)
118
return 0;
119
for (size_t i = 0; i < merge_rr.nr; i++) {
120
const char *path = merge_rr.items[i].string;
121
const struct rerere_id *id = merge_rr.items[i].util;
121
- if (diff_two(rerere_path(id, "preimage"), path, path, path))
122
- die(_("unable to generate diff for '%s'"), rerere_path(id, NULL));
122
+ if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path))
123
+ die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL));
124
}
125
+
126
+ strbuf_release(&buf);
127
} else
128
usage_with_options(rerere_usage, options);
129
rerere.c
+60
-27
@@ -91,16 +91,18 @@ static void assign_variant(struct rerere_id *id)
91
id->variant = variant;
92
}
93
94
-const char *rerere_path(const struct rerere_id *id, const char *file)
94
+const char *rerere_path(struct strbuf *buf, const struct rerere_id *id, const char *file)
95
{
96
if (!file)
97
- return git_path("rr-cache/%s", rerere_id_hex(id));
97
+ return repo_git_path_replace(the_repository, buf, "rr-cache/%s",
98
+ rerere_id_hex(id));
99
100
if (id->variant <= 0)
100
- return git_path("rr-cache/%s/%s", rerere_id_hex(id), file);
101
+ return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s",
102
+ rerere_id_hex(id), file);
103
102
- return git_path("rr-cache/%s/%s.%d",
103
- rerere_id_hex(id), file, id->variant);
104
+ return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s.%d",
105
+ rerere_id_hex(id), file, id->variant);
106
}
107
108
static int is_rr_file(const char *name, const char *filename, int *variant)
@@ -624,9 +626,10 @@ static int try_merge(struct index_state *istate,
626
{
627
enum ll_merge_result ret;
628
mmfile_t base = {NULL, 0}, other = {NULL, 0};
629
+ struct strbuf buf = STRBUF_INIT;
630
628
- if (read_mmfile(&base, rerere_path(id, "preimage")) ||
629
- read_mmfile(&other, rerere_path(id, "postimage"))) {
631
+ if (read_mmfile(&base, rerere_path(&buf, id, "preimage")) ||
632
+ read_mmfile(&other, rerere_path(&buf, id, "postimage"))) {
633
ret = LL_MERGE_CONFLICT;
634
} else {
635
/*
@@ -637,6 +640,7 @@ static int try_merge(struct index_state *istate,
640
istate, NULL);
641
}
642
643
+ strbuf_release(&buf);
644
free(base.ptr);
645
free(other.ptr);
646
@@ -657,6 +661,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
661
{
662
FILE *f;
663
int ret;
664
+ struct strbuf buf = STRBUF_INIT;
665
mmfile_t cur = {NULL, 0};
666
mmbuffer_t result = {NULL, 0};
667
@@ -664,8 +669,8 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
669
* Normalize the conflicts in path and write it out to
670
* "thisimage" temporary file.
671
*/
667
- if ((handle_file(istate, path, NULL, rerere_path(id, "thisimage")) < 0) ||
668
- read_mmfile(&cur, rerere_path(id, "thisimage"))) {
672
+ if ((handle_file(istate, path, NULL, rerere_path(&buf, id, "thisimage")) < 0) ||
673
+ read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) {
674
ret = 1;
675
goto out;
676
}
@@ -678,9 +683,9 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
683
* A successful replay of recorded resolution.
684
* Mark that "postimage" was used to help gc.
685
*/
681
- if (utime(rerere_path(id, "postimage"), NULL) < 0)
686
+ if (utime(rerere_path(&buf, id, "postimage"), NULL) < 0)
687
warning_errno(_("failed utime() on '%s'"),
683
- rerere_path(id, "postimage"));
688
+ rerere_path(&buf, id, "postimage"));
689
690
/* Update "path" with the resolution */
691
f = fopen(path, "w");
@@ -694,6 +699,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
699
out:
700
free(cur.ptr);
701
free(result.ptr);
702
+ strbuf_release(&buf);
703
704
return ret;
705
}
@@ -720,9 +726,11 @@ static void update_paths(struct repository *r, struct string_list *update)
726
727
static void remove_variant(struct rerere_id *id)
728
{
723
- unlink_or_warn(rerere_path(id, "postimage"));
724
- unlink_or_warn(rerere_path(id, "preimage"));
729
+ struct strbuf buf = STRBUF_INIT;
730
+ unlink_or_warn(rerere_path(&buf, id, "postimage"));
731
+ unlink_or_warn(rerere_path(&buf, id, "preimage"));
732
id->collection->status[id->variant] = 0;
733
+ strbuf_release(&buf);
734
}
735
736
/*
@@ -739,6 +747,7 @@ static void do_rerere_one_path(struct index_state *istate,
747
const char *path = rr_item->string;
748
struct rerere_id *id = rr_item->util;
749
struct rerere_dir *rr_dir = id->collection;
750
+ struct strbuf buf = STRBUF_INIT;
751
int variant;
752
753
variant = id->variant;
@@ -746,12 +755,12 @@ static void do_rerere_one_path(struct index_state *istate,
755
/* Has the user resolved it already? */
756
if (variant >= 0) {
757
if (!handle_file(istate, path, NULL, NULL)) {
749
- copy_file(rerere_path(id, "postimage"), path, 0666);
758
+ copy_file(rerere_path(&buf, id, "postimage"), path, 0666);
759
id->collection->status[variant] |= RR_HAS_POSTIMAGE;
760
fprintf_ln(stderr, _("Recorded resolution for '%s'."), path);
761
free_rerere_id(rr_item);
762
rr_item->util = NULL;
754
- return;
763
+ goto out;
764
}
765
/*
766
* There may be other variants that can cleanly
@@ -787,22 +796,25 @@ static void do_rerere_one_path(struct index_state *istate,
796
path);
797
free_rerere_id(rr_item);
798
rr_item->util = NULL;
790
- return;
799
+ goto out;
800
}
801
802
/* None of the existing one applies; we need a new variant */
803
assign_variant(id);
804
805
variant = id->variant;
797
- handle_file(istate, path, NULL, rerere_path(id, "preimage"));
806
+ handle_file(istate, path, NULL, rerere_path(&buf, id, "preimage"));
807
if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
799
- const char *path = rerere_path(id, "postimage");
808
+ const char *path = rerere_path(&buf, id, "postimage");
809
if (unlink(path))
810
die_errno(_("cannot unlink stray '%s'"), path);
811
id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;
812
}
813
id->collection->status[variant] |= RR_HAS_PREIMAGE;
814
fprintf_ln(stderr, _("Recorded preimage for '%s'"), path);
815
+
816
+out:
817
+ strbuf_release(&buf);
818
}
819
820
static int do_plain_rerere(struct repository *r,
@@ -810,6 +822,7 @@ static int do_plain_rerere(struct repository *r,
822
{
823
struct string_list conflict = STRING_LIST_INIT_DUP;
824
struct string_list update = STRING_LIST_INIT_DUP;
825
+ struct strbuf buf = STRBUF_INIT;
826
int i;
827
828
find_conflict(r, &conflict);
@@ -843,7 +856,7 @@ static int do_plain_rerere(struct repository *r,
856
string_list_insert(rr, path)->util = id;
857
858
/* Ensure that the directory exists. */
846
- mkdir_in_gitdir(rerere_path(id, NULL));
859
+ mkdir_in_gitdir(rerere_path(&buf, id, NULL));
860
}
861
862
for (i = 0; i < rr->nr; i++)
@@ -854,6 +867,7 @@ static int do_plain_rerere(struct repository *r,
867
868
string_list_clear(&conflict, 0);
869
string_list_clear(&update, 0);
870
+ strbuf_release(&buf);
871
return write_rr(rr, fd);
872
}
873
@@ -1033,6 +1047,7 @@ static int rerere_forget_one_path(struct index_state *istate,
1047
struct rerere_id *id;
1048
unsigned char hash[GIT_MAX_RAWSZ];
1049
int ret;
1050
+ struct strbuf buf = STRBUF_INIT;
1051
struct string_list_item *item;
1052
1053
/*
@@ -1056,8 +1071,8 @@ static int rerere_forget_one_path(struct index_state *istate,
1071
if (!has_rerere_resolution(id))
1072
continue;
1073
1059
- handle_cache(istate, path, hash, rerere_path(id, "thisimage"));
1060
- if (read_mmfile(&cur, rerere_path(id, "thisimage"))) {
1074
+ handle_cache(istate, path, hash, rerere_path(&buf, id, "thisimage"));
1075
+ if (read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) {
1076
free(cur.ptr);
1077
error(_("failed to update conflicted state in '%s'"), path);
1078
goto fail_exit;
@@ -1074,7 +1089,7 @@ static int rerere_forget_one_path(struct index_state *istate,
1089
goto fail_exit;
1090
}
1091
1077
- filename = rerere_path(id, "postimage");
1092
+ filename = rerere_path(&buf, id, "postimage");
1093
if (unlink(filename)) {
1094
if (errno == ENOENT)
1095
error(_("no remembered resolution for '%s'"), path);
@@ -1088,7 +1103,7 @@ static int rerere_forget_one_path(struct index_state *istate,
1103
* conflict in the working tree, run us again to record
1104
* the postimage.
1105
*/
1091
- handle_cache(istate, path, hash, rerere_path(id, "preimage"));
1106
+ handle_cache(istate, path, hash, rerere_path(&buf, id, "preimage"));
1107
fprintf_ln(stderr, _("Updated preimage for '%s'"), path);
1108
1109
/*
@@ -1099,9 +1114,11 @@ static int rerere_forget_one_path(struct index_state *istate,
1114
free_rerere_id(item);
1115
item->util = id;
1116
fprintf(stderr, _("Forgot resolution for '%s'\n"), path);
1117
+ strbuf_release(&buf);
1118
return 0;
1119
1120
fail_exit:
1121
+ strbuf_release(&buf);
1122
free(id);
1123
return -1;
1124
}
@@ -1147,16 +1164,26 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec)
1164
1165
static timestamp_t rerere_created_at(struct rerere_id *id)
1166
{
1167
+ struct strbuf buf = STRBUF_INIT;
1168
struct stat st;
1169
+ timestamp_t ret;
1170
+
1171
+ ret = stat(rerere_path(&buf, id, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
1172
1152
- return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
1173
+ strbuf_release(&buf);
1174
+ return ret;
1175
}
1176
1177
static timestamp_t rerere_last_used_at(struct rerere_id *id)
1178
{
1179
+ struct strbuf buf = STRBUF_INIT;
1180
struct stat st;
1181
+ timestamp_t ret;
1182
+
1183
+ ret = stat(rerere_path(&buf, id, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
1184
1159
- return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
1185
+ strbuf_release(&buf);
1186
+ return ret;
1187
}
1188
1189
/*
@@ -1164,9 +1191,11 @@ static timestamp_t rerere_last_used_at(struct rerere_id *id)
1191
*/
1192
static void unlink_rr_item(struct rerere_id *id)
1193
{
1167
- unlink_or_warn(rerere_path(id, "thisimage"));
1194
+ struct strbuf buf = STRBUF_INIT;
1195
+ unlink_or_warn(rerere_path(&buf, id, "thisimage"));
1196
remove_variant(id);
1197
id->collection->status[id->variant] = 0;
1198
+ strbuf_release(&buf);
1199
}
1200
1201
static void prune_one(struct rerere_id *id,
@@ -1264,10 +1293,14 @@ void rerere_clear(struct repository *r, struct string_list *merge_rr)
1293
1294
for (i = 0; i < merge_rr->nr; i++) {
1295
struct rerere_id *id = merge_rr->items[i].util;
1296
+ struct strbuf buf = STRBUF_INIT;
1297
+
1298
if (!has_rerere_resolution(id)) {
1299
unlink_rr_item(id);
1269
- rmdir(rerere_path(id, NULL));
1300
+ rmdir(rerere_path(&buf, id, NULL));
1301
}
1302
+
1303
+ strbuf_release(&buf);
1304
}
1305
unlink_or_warn(git_path_merge_rr(r));
1306
rollback_lock_file(&write_lock);
rerere.h
+2
-1
@@ -32,7 +32,8 @@ int repo_rerere(struct repository *, int);
32
* path to that filesystem entity. With "file" specified with NULL,
33
* return the path to the directory that houses these files.
34
*/
35
-const char *rerere_path(const struct rerere_id *, const char *file);
35
+const char *rerere_path(struct strbuf *buf, const struct rerere_id *,
36
+ const char *file);
37
int rerere_forget(struct repository *, struct pathspec *);
38
int rerere_remaining(struct repository *, struct string_list *);
39
void rerere_clear(struct repository *, struct string_list *);