Git fork

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>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
8ee018d8 07242c2a

+69 -32
+7 -4
builtin/rerere.c
··· 4 4 #include "config.h" 5 5 #include "gettext.h" 6 6 #include "parse-options.h" 7 - 8 - #include "string-list.h" 9 7 #include "rerere.h" 8 + #include "strbuf.h" 9 + #include "string-list.h" 10 10 #include "xdiff/xdiff.h" 11 11 #include "xdiff-interface.h" 12 12 #include "pathspec.h" ··· 112 112 merge_rr.items[i].util = NULL; 113 113 } 114 114 } else if (!strcmp(argv[0], "diff")) { 115 + struct strbuf buf = STRBUF_INIT; 115 116 if (setup_rerere(the_repository, &merge_rr, 116 117 flags | RERERE_READONLY) < 0) 117 118 return 0; 118 119 for (size_t i = 0; i < merge_rr.nr; i++) { 119 120 const char *path = merge_rr.items[i].string; 120 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)); 123 124 } 125 + 126 + strbuf_release(&buf); 124 127 } else 125 128 usage_with_options(rerere_usage, options); 126 129
+60 -27
rerere.c
··· 91 91 id->variant = variant; 92 92 } 93 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 95 { 96 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)); 98 99 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); 101 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); 104 106 } 105 107 106 108 static int is_rr_file(const char *name, const char *filename, int *variant) ··· 624 626 { 625 627 enum ll_merge_result ret; 626 628 mmfile_t base = {NULL, 0}, other = {NULL, 0}; 629 + struct strbuf buf = STRBUF_INIT; 627 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"))) { 630 633 ret = LL_MERGE_CONFLICT; 631 634 } else { 632 635 /* ··· 637 640 istate, NULL); 638 641 } 639 642 643 + strbuf_release(&buf); 640 644 free(base.ptr); 641 645 free(other.ptr); 642 646 ··· 657 661 { 658 662 FILE *f; 659 663 int ret; 664 + struct strbuf buf = STRBUF_INIT; 660 665 mmfile_t cur = {NULL, 0}; 661 666 mmbuffer_t result = {NULL, 0}; 662 667 ··· 664 669 * Normalize the conflicts in path and write it out to 665 670 * "thisimage" temporary file. 666 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"))) { 669 674 ret = 1; 670 675 goto out; 671 676 } ··· 678 683 * A successful replay of recorded resolution. 679 684 * Mark that "postimage" was used to help gc. 680 685 */ 681 - if (utime(rerere_path(id, "postimage"), NULL) < 0) 686 + if (utime(rerere_path(&buf, id, "postimage"), NULL) < 0) 682 687 warning_errno(_("failed utime() on '%s'"), 683 - rerere_path(id, "postimage")); 688 + rerere_path(&buf, id, "postimage")); 684 689 685 690 /* Update "path" with the resolution */ 686 691 f = fopen(path, "w"); ··· 694 699 out: 695 700 free(cur.ptr); 696 701 free(result.ptr); 702 + strbuf_release(&buf); 697 703 698 704 return ret; 699 705 } ··· 720 726 721 727 static void remove_variant(struct rerere_id *id) 722 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")); 725 732 id->collection->status[id->variant] = 0; 733 + strbuf_release(&buf); 726 734 } 727 735 728 736 /* ··· 739 747 const char *path = rr_item->string; 740 748 struct rerere_id *id = rr_item->util; 741 749 struct rerere_dir *rr_dir = id->collection; 750 + struct strbuf buf = STRBUF_INIT; 742 751 int variant; 743 752 744 753 variant = id->variant; ··· 746 755 /* Has the user resolved it already? */ 747 756 if (variant >= 0) { 748 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); 750 759 id->collection->status[variant] |= RR_HAS_POSTIMAGE; 751 760 fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); 752 761 free_rerere_id(rr_item); 753 762 rr_item->util = NULL; 754 - return; 763 + goto out; 755 764 } 756 765 /* 757 766 * There may be other variants that can cleanly ··· 787 796 path); 788 797 free_rerere_id(rr_item); 789 798 rr_item->util = NULL; 790 - return; 799 + goto out; 791 800 } 792 801 793 802 /* None of the existing one applies; we need a new variant */ 794 803 assign_variant(id); 795 804 796 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")); 798 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"); 800 809 if (unlink(path)) 801 810 die_errno(_("cannot unlink stray '%s'"), path); 802 811 id->collection->status[variant] &= ~RR_HAS_POSTIMAGE; 803 812 } 804 813 id->collection->status[variant] |= RR_HAS_PREIMAGE; 805 814 fprintf_ln(stderr, _("Recorded preimage for '%s'"), path); 815 + 816 + out: 817 + strbuf_release(&buf); 806 818 } 807 819 808 820 static int do_plain_rerere(struct repository *r, ··· 810 822 { 811 823 struct string_list conflict = STRING_LIST_INIT_DUP; 812 824 struct string_list update = STRING_LIST_INIT_DUP; 825 + struct strbuf buf = STRBUF_INIT; 813 826 int i; 814 827 815 828 find_conflict(r, &conflict); ··· 843 856 string_list_insert(rr, path)->util = id; 844 857 845 858 /* Ensure that the directory exists. */ 846 - mkdir_in_gitdir(rerere_path(id, NULL)); 859 + mkdir_in_gitdir(rerere_path(&buf, id, NULL)); 847 860 } 848 861 849 862 for (i = 0; i < rr->nr; i++) ··· 854 867 855 868 string_list_clear(&conflict, 0); 856 869 string_list_clear(&update, 0); 870 + strbuf_release(&buf); 857 871 return write_rr(rr, fd); 858 872 } 859 873 ··· 1033 1047 struct rerere_id *id; 1034 1048 unsigned char hash[GIT_MAX_RAWSZ]; 1035 1049 int ret; 1050 + struct strbuf buf = STRBUF_INIT; 1036 1051 struct string_list_item *item; 1037 1052 1038 1053 /* ··· 1056 1071 if (!has_rerere_resolution(id)) 1057 1072 continue; 1058 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"))) { 1061 1076 free(cur.ptr); 1062 1077 error(_("failed to update conflicted state in '%s'"), path); 1063 1078 goto fail_exit; ··· 1074 1089 goto fail_exit; 1075 1090 } 1076 1091 1077 - filename = rerere_path(id, "postimage"); 1092 + filename = rerere_path(&buf, id, "postimage"); 1078 1093 if (unlink(filename)) { 1079 1094 if (errno == ENOENT) 1080 1095 error(_("no remembered resolution for '%s'"), path); ··· 1088 1103 * conflict in the working tree, run us again to record 1089 1104 * the postimage. 1090 1105 */ 1091 - handle_cache(istate, path, hash, rerere_path(id, "preimage")); 1106 + handle_cache(istate, path, hash, rerere_path(&buf, id, "preimage")); 1092 1107 fprintf_ln(stderr, _("Updated preimage for '%s'"), path); 1093 1108 1094 1109 /* ··· 1099 1114 free_rerere_id(item); 1100 1115 item->util = id; 1101 1116 fprintf(stderr, _("Forgot resolution for '%s'\n"), path); 1117 + strbuf_release(&buf); 1102 1118 return 0; 1103 1119 1104 1120 fail_exit: 1121 + strbuf_release(&buf); 1105 1122 free(id); 1106 1123 return -1; 1107 1124 } ··· 1147 1164 1148 1165 static timestamp_t rerere_created_at(struct rerere_id *id) 1149 1166 { 1167 + struct strbuf buf = STRBUF_INIT; 1150 1168 struct stat st; 1169 + timestamp_t ret; 1151 1170 1152 - return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; 1171 + ret = stat(rerere_path(&buf, id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; 1172 + 1173 + strbuf_release(&buf); 1174 + return ret; 1153 1175 } 1154 1176 1155 1177 static timestamp_t rerere_last_used_at(struct rerere_id *id) 1156 1178 { 1179 + struct strbuf buf = STRBUF_INIT; 1157 1180 struct stat st; 1181 + timestamp_t ret; 1182 + 1183 + ret = stat(rerere_path(&buf, id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; 1158 1184 1159 - return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; 1185 + strbuf_release(&buf); 1186 + return ret; 1160 1187 } 1161 1188 1162 1189 /* ··· 1164 1191 */ 1165 1192 static void unlink_rr_item(struct rerere_id *id) 1166 1193 { 1167 - unlink_or_warn(rerere_path(id, "thisimage")); 1194 + struct strbuf buf = STRBUF_INIT; 1195 + unlink_or_warn(rerere_path(&buf, id, "thisimage")); 1168 1196 remove_variant(id); 1169 1197 id->collection->status[id->variant] = 0; 1198 + strbuf_release(&buf); 1170 1199 } 1171 1200 1172 1201 static void prune_one(struct rerere_id *id, ··· 1264 1293 1265 1294 for (i = 0; i < merge_rr->nr; i++) { 1266 1295 struct rerere_id *id = merge_rr->items[i].util; 1296 + struct strbuf buf = STRBUF_INIT; 1297 + 1267 1298 if (!has_rerere_resolution(id)) { 1268 1299 unlink_rr_item(id); 1269 - rmdir(rerere_path(id, NULL)); 1300 + rmdir(rerere_path(&buf, id, NULL)); 1270 1301 } 1302 + 1303 + strbuf_release(&buf); 1271 1304 } 1272 1305 unlink_or_warn(git_path_merge_rr(r)); 1273 1306 rollback_lock_file(&write_lock);
+2 -1
rerere.h
··· 32 32 * path to that filesystem entity. With "file" specified with NULL, 33 33 * return the path to the directory that houses these files. 34 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); 36 37 int rerere_forget(struct repository *, struct pathspec *); 37 38 int rerere_remaining(struct repository *, struct string_list *); 38 39 void rerere_clear(struct repository *, struct string_list *);