Git fork

Merge branch 'ab/plug-leak-in-revisions'

Plug the memory leaks from the trickiest API of all, the revision
walker.

* ab/plug-leak-in-revisions: (27 commits)
revisions API: add a TODO for diff_free(&revs->diffopt)
revisions API: have release_revisions() release "topo_walk_info"
revisions API: have release_revisions() release "date_mode"
revisions API: call diff_free(&revs->pruning) in revisions_release()
revisions API: release "reflog_info" in release revisions()
revisions API: clear "boundary_commits" in release_revisions()
revisions API: have release_revisions() release "prune_data"
revisions API: have release_revisions() release "grep_filter"
revisions API: have release_revisions() release "filter"
revisions API: have release_revisions() release "cmdline"
revisions API: have release_revisions() release "mailmap"
revisions API: have release_revisions() release "commits"
revisions API users: use release_revisions() for "prune_data" users
revisions API users: use release_revisions() with UNLEAK()
revisions API users: use release_revisions() in builtin/log.c
revisions API users: use release_revisions() in http-push.c
revisions API users: add "goto cleanup" for release_revisions()
stash: always have the owner of "stash_info" free it
revisions API users: use release_revisions() needing REV_INFO_INIT
revision.[ch]: document and move code declared around "init"
...

+500 -190
+1 -2
add-interactive.c
··· 568 568 run_diff_files(&rev, 0); 569 569 } 570 570 571 - if (ps) 572 - clear_pathspec(&rev.prune_data); 571 + release_revisions(&rev); 573 572 } 574 573 hashmap_clear_and_free(&s.file_map, struct pathname_entry, ent); 575 574 if (unmerged_count)
+14 -6
bisect.c
··· 884 884 /* Clean up objects used, as they will be reused. */ 885 885 clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS); 886 886 887 + release_revisions(&revs); 887 888 return res; 888 889 } 889 890 ··· 964 965 965 966 setup_revisions(ARRAY_SIZE(argv) - 1, argv, &opt, NULL); 966 967 log_tree_commit(&opt, commit); 968 + release_revisions(&opt); 967 969 } 968 970 969 971 /* ··· 1008 1010 */ 1009 1011 enum bisect_error bisect_next_all(struct repository *r, const char *prefix) 1010 1012 { 1011 - struct rev_info revs; 1013 + struct rev_info revs = REV_INFO_INIT; 1012 1014 struct commit_list *tried; 1013 1015 int reaches = 0, all = 0, nr, steps; 1014 1016 enum bisect_error res = BISECT_OK; ··· 1033 1035 1034 1036 res = check_good_are_ancestors_of_bad(r, prefix, no_checkout); 1035 1037 if (res) 1036 - return res; 1038 + goto cleanup; 1037 1039 1038 1040 bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); 1039 1041 ··· 1058 1060 term_good, 1059 1061 term_bad); 1060 1062 1061 - return BISECT_FAILED; 1063 + res = BISECT_FAILED; 1064 + goto cleanup; 1062 1065 } 1063 1066 1064 1067 if (!all) { 1065 1068 fprintf(stderr, _("No testable commit found.\n" 1066 1069 "Maybe you started with bad path arguments?\n")); 1067 1070 1068 - return BISECT_NO_TESTABLE_COMMIT; 1071 + res = BISECT_NO_TESTABLE_COMMIT; 1072 + goto cleanup; 1069 1073 } 1070 1074 1071 1075 bisect_rev = &revs.commits->item->object.oid; ··· 1085 1089 * for negative return values for early returns up 1086 1090 * until the cmd_bisect__helper() caller. 1087 1091 */ 1088 - return BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND; 1092 + res = BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND; 1093 + goto cleanup; 1089 1094 } 1090 1095 1091 1096 nr = all - reaches - 1; ··· 1104 1109 /* Clean up objects used, as they will be reused. */ 1105 1110 repo_clear_commit_marks(r, ALL_REV_FLAGS); 1106 1111 1107 - return bisect_checkout(bisect_rev, no_checkout); 1112 + res = bisect_checkout(bisect_rev, no_checkout); 1113 + cleanup: 1114 + release_revisions(&revs); 1115 + return res; 1108 1116 } 1109 1117 1110 1118 static inline int log2i(int n)
+2 -1
builtin/add.c
··· 151 151 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED); 152 152 end_odb_transaction(); 153 153 154 - clear_pathspec(&rev.prune_data); 154 + release_revisions(&rev); 155 155 return !!data.add_errors; 156 156 } 157 157 ··· 344 344 345 345 unlink(file); 346 346 free(file); 347 + release_revisions(&rev); 347 348 return 0; 348 349 } 349 350
+3
builtin/am.c
··· 1397 1397 add_pending_object(&rev_info, &commit->object, ""); 1398 1398 diff_setup_done(&rev_info.diffopt); 1399 1399 log_tree_commit(&rev_info, commit); 1400 + release_revisions(&rev_info); 1400 1401 } 1401 1402 1402 1403 /** ··· 1429 1430 add_pending_object(&rev_info, &tree->object, ""); 1430 1431 diff_setup_done(&rev_info.diffopt); 1431 1432 run_diff_index(&rev_info, 1); 1433 + release_revisions(&rev_info); 1432 1434 } 1433 1435 1434 1436 /** ··· 1582 1584 add_pending_oid(&rev_info, "HEAD", &our_tree, 0); 1583 1585 diff_setup_done(&rev_info.diffopt); 1584 1586 run_diff_index(&rev_info, 1); 1587 + release_revisions(&rev_info); 1585 1588 } 1586 1589 1587 1590 if (run_apply(state, index_path))
+2
builtin/bisect--helper.c
··· 596 596 reset_revision_walk(); 597 597 598 598 strbuf_release(&commit_name); 599 + release_revisions(&revs); 599 600 fclose(fp); 600 601 return 0; 601 602 } ··· 1084 1085 oid_to_hex(&commit->object.oid)); 1085 1086 1086 1087 reset_revision_walk(); 1088 + release_revisions(&revs); 1087 1089 } else { 1088 1090 strvec_push(&argv_state, argv[i]); 1089 1091 }
+3 -1
builtin/blame.c
··· 1171 1171 if (!incremental) 1172 1172 setup_pager(); 1173 1173 else 1174 - return 0; 1174 + goto cleanup; 1175 1175 1176 1176 blame_sort_final(&sb); 1177 1177 ··· 1205 1205 printf("num commits: %d\n", sb.num_commits); 1206 1206 } 1207 1207 1208 + cleanup: 1208 1209 cleanup_scoreboard(&sb); 1210 + release_revisions(&revs); 1209 1211 return 0; 1210 1212 }
+2 -1
builtin/checkout.c
··· 629 629 diff_setup_done(&rev.diffopt); 630 630 add_pending_object(&rev, head, NULL); 631 631 run_diff_index(&rev, 0); 632 - object_array_clear(&rev.pending); 632 + release_revisions(&rev); 633 633 } 634 634 635 635 static void describe_detached_head(const char *msg, struct commit *commit) ··· 1082 1082 1083 1083 /* Clean up objects used, as they will be reused. */ 1084 1084 repo_clear_commit_marks(the_repository, ALL_REV_FLAGS); 1085 + release_revisions(&revs); 1085 1086 } 1086 1087 1087 1088 static int switch_branches(const struct checkout_opts *opts,
+3 -3
builtin/commit.c
··· 1100 1100 struct rev_info revs; 1101 1101 struct commit *commit; 1102 1102 struct strbuf buf = STRBUF_INIT; 1103 - struct string_list mailmap = STRING_LIST_INIT_NODUP; 1104 1103 const char *av[20]; 1105 1104 int ac = 0; 1106 1105 ··· 1111 1110 av[++ac] = buf.buf; 1112 1111 av[++ac] = NULL; 1113 1112 setup_revisions(ac, av, &revs, NULL); 1114 - revs.mailmap = &mailmap; 1113 + revs.mailmap = xmalloc(sizeof(struct string_list)); 1114 + string_list_init_nodup(revs.mailmap); 1115 1115 read_mailmap(revs.mailmap); 1116 1116 1117 1117 if (prepare_revision_walk(&revs)) ··· 1122 1122 ctx.date_mode.type = DATE_NORMAL; 1123 1123 strbuf_release(&buf); 1124 1124 format_commit_message(commit, "%aN <%aE>", &buf, &ctx); 1125 - clear_mailmap(&mailmap); 1125 + release_revisions(&revs); 1126 1126 return strbuf_detach(&buf, NULL); 1127 1127 } 1128 1128 die(_("--author '%s' is not 'Name <email>' and matches no existing author"), name);
+2
builtin/describe.c
··· 517 517 518 518 traverse_commit_list(&revs, process_commit, process_object, &pcd); 519 519 reset_revision_walk(); 520 + release_revisions(&revs); 520 521 } 521 522 522 523 static void describe(const char *arg, int last_one) ··· 667 668 suffix = NULL; 668 669 else 669 670 suffix = dirty; 671 + release_revisions(&revs); 670 672 } 671 673 describe("HEAD", 1); 672 674 } else if (dirty) {
+6 -2
builtin/diff-files.c
··· 77 77 78 78 if (read_cache_preload(&rev.diffopt.pathspec) < 0) { 79 79 perror("read_cache_preload"); 80 - return -1; 80 + result = -1; 81 + goto cleanup; 81 82 } 83 + cleanup: 82 84 result = run_diff_files(&rev, options); 83 - return diff_result_code(&rev.diffopt, result); 85 + result = diff_result_code(&rev.diffopt, result); 86 + release_revisions(&rev); 87 + return result; 84 88 }
+3 -2
builtin/diff-index.c
··· 70 70 return -1; 71 71 } 72 72 result = run_diff_index(&rev, option); 73 - UNLEAK(rev); 74 - return diff_result_code(&rev.diffopt, result); 73 + result = diff_result_code(&rev.diffopt, result); 74 + release_revisions(&rev); 75 + return result; 75 76 }
+1 -1
builtin/diff.c
··· 594 594 result = diff_result_code(&rev.diffopt, result); 595 595 if (1 < rev.diffopt.skip_stat_unmatch) 596 596 refresh_index_quietly(); 597 - UNLEAK(rev); 597 + release_revisions(&rev); 598 598 UNLEAK(ent); 599 599 UNLEAK(blob); 600 600 return result;
+1
builtin/fast-export.c
··· 1276 1276 printf("done\n"); 1277 1277 1278 1278 refspec_clear(&refspecs); 1279 + release_revisions(&revs); 1279 1280 1280 1281 return 0; 1281 1282 }
+24 -12
builtin/log.c
··· 231 231 } 232 232 233 233 if (mailmap) { 234 - rev->mailmap = xcalloc(1, sizeof(struct string_list)); 234 + rev->mailmap = xmalloc(sizeof(struct string_list)); 235 + string_list_init_nodup(rev->mailmap); 235 236 read_mailmap(rev->mailmap); 236 237 } 237 238 ··· 292 293 { 293 294 cmd_log_init_defaults(rev); 294 295 cmd_log_init_finish(argc, argv, prefix, rev, opt); 296 + } 297 + 298 + static int cmd_log_deinit(int ret, struct rev_info *rev) 299 + { 300 + release_revisions(rev); 301 + return ret; 295 302 } 296 303 297 304 /* ··· 565 572 cmd_log_init(argc, argv, prefix, &rev, &opt); 566 573 if (!rev.diffopt.output_format) 567 574 rev.diffopt.output_format = DIFF_FORMAT_RAW; 568 - return cmd_log_walk(&rev); 575 + return cmd_log_deinit(cmd_log_walk(&rev), &rev); 569 576 } 570 577 571 578 static void show_tagger(const char *buf, struct rev_info *rev) ··· 689 696 cmd_log_init(argc, argv, prefix, &rev, &opt); 690 697 691 698 if (!rev.no_walk) 692 - return cmd_log_walk(&rev); 699 + return cmd_log_deinit(cmd_log_walk(&rev), &rev); 693 700 694 701 count = rev.pending.nr; 695 702 objects = rev.pending.objects; ··· 749 756 rev.diffopt.no_free = 0; 750 757 diff_free(&rev.diffopt); 751 758 752 - free(objects); 753 - return ret; 759 + return cmd_log_deinit(ret, &rev); 754 760 } 755 761 756 762 /* ··· 778 784 rev.always_show_header = 1; 779 785 cmd_log_init_finish(argc, argv, prefix, &rev, &opt); 780 786 781 - return cmd_log_walk(&rev); 787 + return cmd_log_deinit(cmd_log_walk(&rev), &rev); 782 788 } 783 789 784 790 static void log_setup_revisions_tweak(struct rev_info *rev, ··· 809 815 opt.revarg_opt = REVARG_COMMITTISH; 810 816 opt.tweak = log_setup_revisions_tweak; 811 817 cmd_log_init(argc, argv, prefix, &rev, &opt); 812 - return cmd_log_walk(&rev); 818 + return cmd_log_deinit(cmd_log_walk(&rev), &rev); 813 819 } 814 820 815 821 /* format-patch */ ··· 1764 1770 struct commit *commit; 1765 1771 struct commit **list = NULL; 1766 1772 struct rev_info rev; 1773 + char *to_free = NULL; 1767 1774 struct setup_revision_opt s_r_opt; 1768 1775 int nr = 0, total, i; 1769 1776 int use_stdout = 0; ··· 1965 1972 strbuf_addch(&buf, '\n'); 1966 1973 } 1967 1974 1968 - rev.extra_headers = strbuf_detach(&buf, NULL); 1975 + rev.extra_headers = to_free = strbuf_detach(&buf, NULL); 1969 1976 1970 1977 if (from) { 1971 1978 if (split_ident_line(&rev.from_ident, from, strlen(from))) ··· 2186 2193 prepare_bases(&bases, base, list, nr); 2187 2194 } 2188 2195 2189 - if (in_reply_to || thread || cover_letter) 2190 - rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); 2196 + if (in_reply_to || thread || cover_letter) { 2197 + rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids)); 2198 + string_list_init_nodup(rev.ref_message_ids); 2199 + } 2191 2200 if (in_reply_to) { 2192 2201 const char *msgid = clean_message_id(in_reply_to); 2193 2202 string_list_append(rev.ref_message_ids, msgid); ··· 2294 2303 strbuf_release(&rdiff1); 2295 2304 strbuf_release(&rdiff2); 2296 2305 strbuf_release(&rdiff_title); 2297 - UNLEAK(rev); 2298 - return 0; 2306 + free(to_free); 2307 + if (rev.ref_message_ids) 2308 + string_list_clear(rev.ref_message_ids, 0); 2309 + free(rev.ref_message_ids); 2310 + return cmd_log_deinit(0, &rev); 2299 2311 } 2300 2312 2301 2313 static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
+2
builtin/merge.c
··· 443 443 } 444 444 write_file_buf(git_path_squash_msg(the_repository), out.buf, out.len); 445 445 strbuf_release(&out); 446 + release_revisions(&rev); 446 447 } 447 448 448 449 static void finish(struct commit *head_commit, ··· 998 999 */ 999 1000 cnt += count_unmerged_entries(); 1000 1001 1002 + release_revisions(&rev); 1001 1003 return cnt; 1002 1004 } 1003 1005
+2
builtin/pack-objects.c
··· 4464 4464 read_object_list_from_stdin(); 4465 4465 } else if (pfd.have_revs) { 4466 4466 get_object_list(&pfd.revs, rp.nr, rp.v); 4467 + release_revisions(&pfd.revs); 4467 4468 } else { 4468 4469 struct rev_info revs; 4469 4470 4470 4471 repo_init_revisions(the_repository, &revs, NULL); 4471 4472 get_object_list(&revs, rp.nr, rp.v); 4473 + release_revisions(&revs); 4472 4474 } 4473 4475 cleanup_preferred_base(); 4474 4476 if (include_tag && nr_result)
+1
builtin/prune.c
··· 196 196 prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0); 197 197 } 198 198 199 + release_revisions(&revs); 199 200 return 0; 200 201 }
+1
builtin/reflog.c
··· 293 293 if (verbose) 294 294 printf(_("Marking reachable objects...")); 295 295 mark_reachable_objects(&revs, 0, 0, NULL); 296 + release_revisions(&revs); 296 297 if (verbose) 297 298 putchar('\n'); 298 299 }
+14 -11
builtin/rev-list.c
··· 213 213 214 214 static void finish_commit(struct commit *commit) 215 215 { 216 - if (commit->parents) { 217 - free_commit_list(commit->parents); 218 - commit->parents = NULL; 219 - } 216 + free_commit_list(commit->parents); 217 + commit->parents = NULL; 220 218 free_commit_buffer(the_repository->parsed_objects, 221 219 commit); 222 220 } ··· 502 500 int use_bitmap_index = 0; 503 501 int filter_provided_objects = 0; 504 502 const char *show_progress = NULL; 503 + int ret = 0; 505 504 506 505 if (argc == 2 && !strcmp(argv[1], "-h")) 507 506 usage(rev_list_usage); ··· 585 584 } 586 585 if (!strcmp(arg, "--test-bitmap")) { 587 586 test_bitmap_walk(&revs); 588 - return 0; 587 + goto cleanup; 589 588 } 590 589 if (skip_prefix(arg, "--progress=", &arg)) { 591 590 show_progress = arg; ··· 674 673 675 674 if (use_bitmap_index) { 676 675 if (!try_bitmap_count(&revs, filter_provided_objects)) 677 - return 0; 676 + goto cleanup; 678 677 if (!try_bitmap_disk_usage(&revs, filter_provided_objects)) 679 - return 0; 678 + goto cleanup; 680 679 if (!try_bitmap_traversal(&revs, filter_provided_objects)) 681 - return 0; 680 + goto cleanup; 682 681 } 683 682 684 683 if (prepare_revision_walk(&revs)) ··· 698 697 699 698 find_bisection(&revs.commits, &reaches, &all, bisect_flags); 700 699 701 - if (bisect_show_vars) 702 - return show_bisect_vars(&info, reaches, all); 700 + if (bisect_show_vars) { 701 + ret = show_bisect_vars(&info, reaches, all); 702 + goto cleanup; 703 + } 703 704 } 704 705 705 706 if (filter_provided_objects) { ··· 754 755 if (show_disk_usage) 755 756 printf("%"PRIuMAX"\n", (uintmax_t)total_disk_usage); 756 757 757 - return 0; 758 + cleanup: 759 + release_revisions(&revs); 760 + return ret; 758 761 }
+6 -2
builtin/shortlog.c
··· 81 81 format_subject(&subject, oneline, " "); 82 82 buffer = strbuf_detach(&subject, NULL); 83 83 84 - if (!item->util) 85 - item->util = xcalloc(1, sizeof(struct string_list)); 84 + if (!item->util) { 85 + item->util = xmalloc(sizeof(struct string_list)); 86 + string_list_init_nodup(item->util); 87 + } 86 88 string_list_append(item->util, buffer); 87 89 } 88 90 } ··· 419 421 } 420 422 else 421 423 get_from_rev(&rev, &log); 424 + 425 + release_revisions(&rev); 422 426 423 427 shortlog_output(&log); 424 428 if (log.file != stdout)
+62 -53
builtin/stash.c
··· 117 117 int has_u; 118 118 }; 119 119 120 + #define STASH_INFO_INIT { \ 121 + .revision = STRBUF_INIT, \ 122 + } 123 + 120 124 static void free_stash_info(struct stash_info *info) 121 125 { 122 126 strbuf_release(&info->revision); ··· 158 162 if (argc == 1) 159 163 commit = argv[0]; 160 164 161 - strbuf_init(&info->revision, 0); 162 165 if (!commit) { 163 166 if (!ref_exists(ref_stash)) { 164 - free_stash_info(info); 165 167 fprintf_ln(stderr, _("No stash entries found.")); 166 168 return -1; 167 169 } ··· 175 177 176 178 revision = info->revision.buf; 177 179 178 - if (get_oid(revision, &info->w_commit)) { 179 - error(_("%s is not a valid reference"), revision); 180 - free_stash_info(info); 181 - return -1; 182 - } 180 + if (get_oid(revision, &info->w_commit)) 181 + return error(_("%s is not a valid reference"), revision); 183 182 184 183 assert_stash_like(info, revision); 185 184 ··· 198 197 info->is_stash_ref = !strcmp(expanded_ref, ref_stash); 199 198 break; 200 199 default: /* Invalid or ambiguous */ 201 - free_stash_info(info); 200 + break; 202 201 } 203 202 204 203 free(expanded_ref); ··· 616 615 617 616 static int apply_stash(int argc, const char **argv, const char *prefix) 618 617 { 619 - int ret; 618 + int ret = -1; 620 619 int quiet = 0; 621 620 int index = 0; 622 - struct stash_info info; 621 + struct stash_info info = STASH_INFO_INIT; 623 622 struct option options[] = { 624 623 OPT__QUIET(&quiet, N_("be quiet, only report errors")), 625 624 OPT_BOOL(0, "index", &index, ··· 631 630 git_stash_apply_usage, 0); 632 631 633 632 if (get_stash_info(&info, argc, argv)) 634 - return -1; 633 + goto cleanup; 635 634 636 635 ret = do_apply_stash(prefix, &info, index, quiet); 636 + cleanup: 637 637 free_stash_info(&info); 638 638 return ret; 639 639 } ··· 669 669 return 0; 670 670 } 671 671 672 - static void assert_stash_ref(struct stash_info *info) 672 + static int get_stash_info_assert(struct stash_info *info, int argc, 673 + const char **argv) 673 674 { 674 - if (!info->is_stash_ref) { 675 - error(_("'%s' is not a stash reference"), info->revision.buf); 676 - free_stash_info(info); 677 - exit(1); 678 - } 675 + int ret = get_stash_info(info, argc, argv); 676 + 677 + if (ret < 0) 678 + return ret; 679 + 680 + if (!info->is_stash_ref) 681 + return error(_("'%s' is not a stash reference"), info->revision.buf); 682 + 683 + return 0; 679 684 } 680 685 681 686 static int drop_stash(int argc, const char **argv, const char *prefix) 682 687 { 683 - int ret; 688 + int ret = -1; 684 689 int quiet = 0; 685 - struct stash_info info; 690 + struct stash_info info = STASH_INFO_INIT; 686 691 struct option options[] = { 687 692 OPT__QUIET(&quiet, N_("be quiet, only report errors")), 688 693 OPT_END() ··· 691 696 argc = parse_options(argc, argv, prefix, options, 692 697 git_stash_drop_usage, 0); 693 698 694 - if (get_stash_info(&info, argc, argv)) 695 - return -1; 696 - 697 - assert_stash_ref(&info); 699 + if (get_stash_info_assert(&info, argc, argv)) 700 + goto cleanup; 698 701 699 702 ret = do_drop_stash(&info, quiet); 703 + cleanup: 700 704 free_stash_info(&info); 701 705 return ret; 702 706 } 703 707 704 708 static int pop_stash(int argc, const char **argv, const char *prefix) 705 709 { 706 - int ret; 710 + int ret = -1; 707 711 int index = 0; 708 712 int quiet = 0; 709 - struct stash_info info; 713 + struct stash_info info = STASH_INFO_INIT; 710 714 struct option options[] = { 711 715 OPT__QUIET(&quiet, N_("be quiet, only report errors")), 712 716 OPT_BOOL(0, "index", &index, ··· 717 721 argc = parse_options(argc, argv, prefix, options, 718 722 git_stash_pop_usage, 0); 719 723 720 - if (get_stash_info(&info, argc, argv)) 721 - return -1; 724 + if (get_stash_info_assert(&info, argc, argv)) 725 + goto cleanup; 722 726 723 - assert_stash_ref(&info); 724 727 if ((ret = do_apply_stash(prefix, &info, index, quiet))) 725 728 printf_ln(_("The stash entry is kept in case " 726 729 "you need it again.")); 727 730 else 728 731 ret = do_drop_stash(&info, quiet); 729 732 733 + cleanup: 730 734 free_stash_info(&info); 731 735 return ret; 732 736 } 733 737 734 738 static int branch_stash(int argc, const char **argv, const char *prefix) 735 739 { 736 - int ret; 740 + int ret = -1; 737 741 const char *branch = NULL; 738 - struct stash_info info; 742 + struct stash_info info = STASH_INFO_INIT; 739 743 struct child_process cp = CHILD_PROCESS_INIT; 740 744 struct option options[] = { 741 745 OPT_END() ··· 752 756 branch = argv[0]; 753 757 754 758 if (get_stash_info(&info, argc - 1, argv + 1)) 755 - return -1; 759 + goto cleanup; 756 760 757 761 cp.git_cmd = 1; 758 762 strvec_pushl(&cp.args, "checkout", "-b", NULL); ··· 764 768 if (!ret && info.is_stash_ref) 765 769 ret = do_drop_stash(&info, 0); 766 770 771 + cleanup: 767 772 free_stash_info(&info); 768 - 769 773 return ret; 770 774 } 771 775 ··· 843 847 static int show_stash(int argc, const char **argv, const char *prefix) 844 848 { 845 849 int i; 846 - int ret = 0; 847 - struct stash_info info; 850 + int ret = -1; 851 + struct stash_info info = STASH_INFO_INIT; 848 852 struct rev_info rev; 849 853 struct strvec stash_args = STRVEC_INIT; 850 854 struct strvec revision_args = STRVEC_INIT; ··· 862 866 UNTRACKED_ONLY, PARSE_OPT_NONEG), 863 867 OPT_END() 864 868 }; 869 + int do_usage = 0; 865 870 866 871 init_diff_ui_defaults(); 867 872 git_config(git_diff_ui_config, NULL); ··· 879 884 strvec_push(&revision_args, argv[i]); 880 885 } 881 886 882 - ret = get_stash_info(&info, stash_args.nr, stash_args.v); 883 - strvec_clear(&stash_args); 884 - if (ret) 885 - return -1; 887 + if (get_stash_info(&info, stash_args.nr, stash_args.v)) 888 + goto cleanup; 886 889 887 890 /* 888 891 * The config settings are applied only if there are not passed ··· 896 899 rev.diffopt.output_format |= DIFF_FORMAT_PATCH; 897 900 898 901 if (!show_stat && !show_patch) { 899 - free_stash_info(&info); 900 - return 0; 902 + ret = 0; 903 + goto cleanup; 901 904 } 902 905 } 903 906 904 907 argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL); 905 - if (argc > 1) { 906 - free_stash_info(&info); 907 - usage_with_options(git_stash_show_usage, options); 908 - } 908 + if (argc > 1) 909 + goto usage; 909 910 if (!rev.diffopt.output_format) { 910 911 rev.diffopt.output_format = DIFF_FORMAT_PATCH; 911 912 diff_setup_done(&rev.diffopt); ··· 930 931 } 931 932 log_tree_diff_flush(&rev); 932 933 934 + ret = diff_result_code(&rev.diffopt, 0); 935 + cleanup: 936 + strvec_clear(&stash_args); 933 937 free_stash_info(&info); 934 - return diff_result_code(&rev.diffopt, 0); 938 + release_revisions(&rev); 939 + if (do_usage) 940 + usage_with_options(git_stash_show_usage, options); 941 + return ret; 942 + usage: 943 + do_usage = 1; 944 + goto cleanup; 935 945 } 936 946 937 947 static int do_store_stash(const struct object_id *w_commit, const char *stash_msg, ··· 1065 1075 goto done; 1066 1076 } 1067 1077 1068 - object_array_clear(&rev.pending); 1069 1078 result = run_diff_files(&rev, 0); 1070 1079 if (diff_result_code(&rev.diffopt, result)) { 1071 1080 ret = 1; ··· 1073 1082 } 1074 1083 1075 1084 done: 1076 - clear_pathspec(&rev.prune_data); 1085 + release_revisions(&rev); 1077 1086 return ret; 1078 1087 } 1079 1088 ··· 1284 1293 1285 1294 done: 1286 1295 discard_index(&istate); 1287 - UNLEAK(rev); 1288 - object_array_clear(&rev.pending); 1289 - clear_pathspec(&rev.prune_data); 1296 + release_revisions(&rev); 1290 1297 strbuf_release(&diff_output); 1291 1298 remove_path(stash_index_path.buf); 1292 1299 return ret; ··· 1428 1435 1429 1436 static int create_stash(int argc, const char **argv, const char *prefix) 1430 1437 { 1431 - int ret = 0; 1438 + int ret; 1432 1439 struct strbuf stash_msg_buf = STRBUF_INIT; 1433 - struct stash_info info; 1440 + struct stash_info info = STASH_INFO_INIT; 1434 1441 struct pathspec ps; 1435 1442 1436 1443 /* Starting with argv[1], since argv[0] is "create" */ ··· 1445 1452 if (!ret) 1446 1453 printf_ln("%s", oid_to_hex(&info.w_commit)); 1447 1454 1455 + free_stash_info(&info); 1448 1456 strbuf_release(&stash_msg_buf); 1449 1457 return ret; 1450 1458 } ··· 1453 1461 int keep_index, int patch_mode, int include_untracked, int only_staged) 1454 1462 { 1455 1463 int ret = 0; 1456 - struct stash_info info; 1464 + struct stash_info info = STASH_INFO_INIT; 1457 1465 struct strbuf patch = STRBUF_INIT; 1458 1466 struct strbuf stash_msg_buf = STRBUF_INIT; 1459 1467 struct strbuf untracked_files = STRBUF_INIT; ··· 1652 1660 } 1653 1661 1654 1662 done: 1663 + free_stash_info(&info); 1655 1664 strbuf_release(&stash_msg_buf); 1656 1665 return ret; 1657 1666 }
+10 -4
builtin/submodule--helper.c
··· 649 649 { 650 650 char *displaypath; 651 651 struct strvec diff_files_args = STRVEC_INIT; 652 - struct rev_info rev; 652 + struct rev_info rev = REV_INFO_INIT; 653 653 int diff_files_result; 654 654 struct strbuf buf = STRBUF_INIT; 655 655 const char *git_dir; ··· 736 736 cleanup: 737 737 strvec_clear(&diff_files_args); 738 738 free(displaypath); 739 + release_revisions(&rev); 739 740 } 740 741 741 742 static void status_submodule_cb(const struct cache_entry *list_item, ··· 1114 1115 struct strvec diff_args = STRVEC_INIT; 1115 1116 struct rev_info rev; 1116 1117 struct module_cb_list list = MODULE_CB_LIST_INIT; 1118 + int ret = 0; 1117 1119 1118 1120 strvec_push(&diff_args, get_diff_cmd(diff_cmd)); 1119 1121 if (info->cached) ··· 1139 1141 setup_work_tree(); 1140 1142 if (read_cache_preload(&rev.diffopt.pathspec) < 0) { 1141 1143 perror("read_cache_preload"); 1142 - return -1; 1144 + ret = -1; 1145 + goto cleanup; 1143 1146 } 1144 1147 } else if (read_cache() < 0) { 1145 1148 perror("read_cache"); 1146 - return -1; 1149 + ret = -1; 1150 + goto cleanup; 1147 1151 } 1148 1152 1149 1153 if (diff_cmd == DIFF_INDEX) ··· 1151 1155 else 1152 1156 run_diff_files(&rev, 0); 1153 1157 prepare_submodule_summary(info, &list); 1158 + cleanup: 1154 1159 strvec_clear(&diff_args); 1155 - return 0; 1160 + release_revisions(&rev); 1161 + return ret; 1156 1162 } 1157 1163 1158 1164 static int module_summary(int argc, const char **argv, const char *prefix)
+8 -4
bundle.c
··· 196 196 * to be verbose about the errors 197 197 */ 198 198 struct string_list *p = &header->prerequisites; 199 - struct rev_info revs; 199 + struct rev_info revs = REV_INFO_INIT; 200 200 const char *argv[] = {NULL, "--all", NULL}; 201 201 struct commit *commit; 202 202 int i, ret = 0, req_nr; 203 203 const char *message = _("Repository lacks these prerequisite commits:"); 204 204 205 - if (!r || !r->objects || !r->objects->odb) 206 - return error(_("need a repository to verify a bundle")); 205 + if (!r || !r->objects || !r->objects->odb) { 206 + ret = error(_("need a repository to verify a bundle")); 207 + goto cleanup; 208 + } 207 209 208 210 repo_init_revisions(r, &revs, NULL); 209 211 for (i = 0; i < p->nr; i++) { ··· 221 223 error("%s %s", oid_to_hex(oid), name); 222 224 } 223 225 if (revs.pending.nr != p->nr) 224 - return ret; 226 + goto cleanup; 225 227 req_nr = revs.pending.nr; 226 228 setup_revisions(2, argv, &revs, NULL); 227 229 ··· 284 286 printf_ln("The bundle uses this filter: %s", 285 287 list_objects_filter_spec(&header->filter)); 286 288 } 289 + cleanup: 290 + release_revisions(&revs); 287 291 return ret; 288 292 } 289 293
+8 -11
commit.c
··· 407 407 408 408 if (item->object.parsed) 409 409 return 0; 410 - 411 - if (item->parents) { 412 - /* 413 - * Presumably this is leftover from an earlier failed parse; 414 - * clear it out in preparation for us re-parsing (we'll hit the 415 - * same error, but that's good, since it lets our caller know 416 - * the result cannot be trusted. 417 - */ 418 - free_commit_list(item->parents); 419 - item->parents = NULL; 420 - } 410 + /* 411 + * Presumably this is leftover from an earlier failed parse; 412 + * clear it out in preparation for us re-parsing (we'll hit the 413 + * same error, but that's good, since it lets our caller know 414 + * the result cannot be trusted. 415 + */ 416 + free_commit_list(item->parents); 417 + item->parents = NULL; 421 418 422 419 tail += size; 423 420 if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) ||
+27
contrib/coccinelle/free.cocci
··· 2 2 expression E; 3 3 @@ 4 4 - if (E) 5 + ( 5 6 free(E); 7 + | 8 + free_commit_list(E); 9 + ) 6 10 7 11 @@ 8 12 expression E; 9 13 @@ 10 14 - if (!E) 15 + ( 11 16 free(E); 17 + | 18 + free_commit_list(E); 19 + ) 12 20 13 21 @@ 14 22 expression E; ··· 16 24 - free(E); 17 25 + FREE_AND_NULL(E); 18 26 - E = NULL; 27 + 28 + @@ 29 + expression E; 30 + @@ 31 + - if (E) 32 + - { 33 + free_commit_list(E); 34 + E = NULL; 35 + - } 36 + 37 + @@ 38 + expression E; 39 + statement S; 40 + @@ 41 + - if (E) { 42 + + if (E) 43 + S 44 + free_commit_list(E); 45 + - }
+5 -3
diff-lib.c
··· 641 641 642 642 if (diff_cache(&revs, tree_oid, NULL, 1)) 643 643 exit(128); 644 - clear_pathspec(&revs.prune_data); 644 + release_revisions(&revs); 645 645 return 0; 646 646 } 647 647 ··· 651 651 { 652 652 struct rev_info rev; 653 653 struct setup_revision_opt opt; 654 + unsigned has_changes; 654 655 655 656 repo_init_revisions(r, &rev, NULL); 656 657 memset(&opt, 0, sizeof(opt)); ··· 662 663 diff_flags_or(&rev.diffopt.flags, flags); 663 664 rev.diffopt.ita_invisible_in_index = ita_invisible_in_index; 664 665 run_diff_index(&rev, 1); 665 - object_array_clear(&rev.pending); 666 - return (rev.diffopt.flags.has_changes != 0); 666 + has_changes = rev.diffopt.flags.has_changes; 667 + release_revisions(&rev); 668 + return (has_changes != 0); 667 669 } 668 670 669 671 static struct strbuf *idiff_prefix_cb(struct diff_options *opt, void *data)
+1
fmt-merge-msg.c
··· 699 699 shortlog(origins.items[i].string, 700 700 origins.items[i].util, 701 701 head, &rev, opts, out); 702 + release_revisions(&rev); 702 703 } 703 704 704 705 strbuf_complete_line(out);
+2 -1
http-push.c
··· 1689 1689 struct refspec rs = REFSPEC_INIT_PUSH; 1690 1690 struct remote_lock *ref_lock = NULL; 1691 1691 struct remote_lock *info_ref_lock = NULL; 1692 - struct rev_info revs; 1693 1692 int delete_branch = 0; 1694 1693 int force_delete = 0; 1695 1694 int objects_to_send; ··· 1825 1824 1826 1825 new_refs = 0; 1827 1826 for (ref = remote_refs; ref; ref = ref->next) { 1827 + struct rev_info revs; 1828 1828 struct strvec commit_argv = STRVEC_INIT; 1829 1829 1830 1830 if (!ref->peer_ref) ··· 1941 1941 unlock_remote(ref_lock); 1942 1942 check_locks(); 1943 1943 strvec_clear(&commit_argv); 1944 + release_revisions(&revs); 1944 1945 } 1945 1946 1946 1947 /* Update remote server info if appropriate */
+1
merge-ort.c
··· 1594 1594 } 1595 1595 1596 1596 object_array_clear(&merges); 1597 + release_revisions(&revs); 1597 1598 return result->nr; 1598 1599 } 1599 1600
+3 -2
merge-recursive.c
··· 522 522 */ 523 523 static struct string_list *get_unmerged(struct index_state *istate) 524 524 { 525 - struct string_list *unmerged = xcalloc(1, sizeof(struct string_list)); 525 + struct string_list *unmerged = xmalloc(sizeof(struct string_list)); 526 526 int i; 527 527 528 - unmerged->strdup_strings = 1; 528 + string_list_init_dup(unmerged); 529 529 530 530 /* TODO: audit for interaction with sparse-index. */ 531 531 ensure_full_index(istate); ··· 1160 1160 } 1161 1161 1162 1162 object_array_clear(&merges); 1163 + release_revisions(&revs); 1163 1164 return result->nr; 1164 1165 } 1165 1166
+1
midx.c
··· 1049 1049 if (indexed_commits_nr_p) 1050 1050 *indexed_commits_nr_p = cb.commits_nr; 1051 1051 1052 + release_revisions(&revs); 1052 1053 return cb.commits; 1053 1054 } 1054 1055
+1
pack-bitmap-write.c
··· 326 326 trace2_data_intmax("pack-bitmap-write", the_repository, 327 327 "num_maximal_commits", num_maximal); 328 328 329 + release_revisions(&revs); 329 330 free_commit_list(reusable); 330 331 } 331 332
+1 -1
range-diff.c
··· 596 596 } 597 597 598 598 free(copy); 599 - object_array_clear(&revs.pending); 599 + release_revisions(&revs); 600 600 return negative > 0 && positive > 0; 601 601 }
+1
ref-filter.c
··· 2392 2392 clear_commit_marks(merge_commit, ALL_REV_FLAGS); 2393 2393 } 2394 2394 2395 + release_revisions(&revs); 2395 2396 free(to_clear); 2396 2397 } 2397 2398
+23 -1
reflog-walk.c
··· 8 8 9 9 struct complete_reflogs { 10 10 char *ref; 11 - const char *short_ref; 11 + char *short_ref; 12 12 struct reflog_info { 13 13 struct object_id ooid, noid; 14 14 char *email; ··· 51 51 } 52 52 free(array->items); 53 53 free(array->ref); 54 + free(array->short_ref); 54 55 free(array); 56 + } 57 + 58 + static void complete_reflogs_clear(void *util, const char *str) 59 + { 60 + struct complete_reflogs *array = util; 61 + free_complete_reflog(array); 55 62 } 56 63 57 64 static struct complete_reflogs *read_complete_reflog(const char *ref) ··· 114 121 { 115 122 CALLOC_ARRAY(*info, 1); 116 123 (*info)->complete_reflogs.strdup_strings = 1; 124 + } 125 + 126 + void reflog_walk_info_release(struct reflog_walk_info *info) 127 + { 128 + size_t i; 129 + 130 + if (!info) 131 + return; 132 + 133 + for (i = 0; i < info->nr; i++) 134 + free(info->logs[i]); 135 + string_list_clear_func(&info->complete_reflogs, 136 + complete_reflogs_clear); 137 + free(info->logs); 138 + free(info); 117 139 } 118 140 119 141 int add_reflog_for_walk(struct reflog_walk_info *info,
+1
reflog-walk.h
··· 8 8 struct date_mode; 9 9 10 10 void init_reflog_walk(struct reflog_walk_info **info); 11 + void reflog_walk_info_release(struct reflog_walk_info *info); 11 12 int add_reflog_for_walk(struct reflog_walk_info *info, 12 13 struct commit *commit, const char *name); 13 14 void show_reflog_message(struct reflog_walk_info *info, int,
+1
remote.c
··· 2175 2175 clear_commit_marks(theirs, ALL_REV_FLAGS); 2176 2176 2177 2177 strvec_clear(&argv); 2178 + release_revisions(&revs); 2178 2179 return 1; 2179 2180 } 2180 2181
+55 -15
revision.c
··· 606 606 * 607 607 * 2. We saw anything except REV_TREE_NEW. 608 608 */ 609 + #define REV_TREE_SAME 0 610 + #define REV_TREE_NEW 1 /* Only new files */ 611 + #define REV_TREE_OLD 2 /* Only files removed */ 612 + #define REV_TREE_DIFFERENT 3 /* Mixed changes */ 609 613 static int tree_difference = REV_TREE_SAME; 610 614 611 615 static void file_add_remove(struct diff_options *options, ··· 1459 1463 if (revs->left_only || revs->right_only) 1460 1464 limit_left_right(newlist, revs); 1461 1465 1462 - if (bottom) { 1466 + if (bottom) 1463 1467 limit_to_ancestry(bottom, newlist); 1464 - free_commit_list(bottom); 1465 - } 1468 + free_commit_list(bottom); 1466 1469 1467 1470 /* 1468 1471 * Check if any commits have become TREESAME by some of their parents ··· 2930 2933 return left; 2931 2934 } 2932 2935 2936 + static void release_revisions_cmdline(struct rev_cmdline_info *cmdline) 2937 + { 2938 + unsigned int i; 2939 + 2940 + for (i = 0; i < cmdline->nr; i++) 2941 + free((char *)cmdline->rev[i].name); 2942 + free(cmdline->rev); 2943 + } 2944 + 2945 + static void release_revisions_mailmap(struct string_list *mailmap) 2946 + { 2947 + if (!mailmap) 2948 + return; 2949 + clear_mailmap(mailmap); 2950 + free(mailmap); 2951 + } 2952 + 2953 + static void release_revisions_topo_walk_info(struct topo_walk_info *info); 2954 + 2955 + void release_revisions(struct rev_info *revs) 2956 + { 2957 + free_commit_list(revs->commits); 2958 + object_array_clear(&revs->pending); 2959 + object_array_clear(&revs->boundary_commits); 2960 + release_revisions_cmdline(&revs->cmdline); 2961 + list_objects_filter_release(&revs->filter); 2962 + clear_pathspec(&revs->prune_data); 2963 + date_mode_release(&revs->date_mode); 2964 + release_revisions_mailmap(revs->mailmap); 2965 + free_grep_patterns(&revs->grep_filter); 2966 + /* TODO (need to handle "no_free"): diff_free(&revs->diffopt) */ 2967 + diff_free(&revs->pruning); 2968 + reflog_walk_info_release(revs->reflog_info); 2969 + release_revisions_topo_walk_info(revs->topo_walk_info); 2970 + } 2971 + 2933 2972 static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child) 2934 2973 { 2935 2974 struct commit_list *l = xcalloc(1, sizeof(*l)); ··· 3440 3479 indegree_walk_step(revs); 3441 3480 } 3442 3481 3443 - static void reset_topo_walk(struct rev_info *revs) 3482 + static void release_revisions_topo_walk_info(struct topo_walk_info *info) 3444 3483 { 3445 - struct topo_walk_info *info = revs->topo_walk_info; 3446 - 3484 + if (!info) 3485 + return; 3447 3486 clear_prio_queue(&info->explore_queue); 3448 3487 clear_prio_queue(&info->indegree_queue); 3449 3488 clear_prio_queue(&info->topo_queue); 3450 3489 clear_indegree_slab(&info->indegree); 3451 3490 clear_author_date_slab(&info->author_date); 3491 + free(info); 3492 + } 3452 3493 3453 - FREE_AND_NULL(revs->topo_walk_info); 3494 + static void reset_topo_walk(struct rev_info *revs) 3495 + { 3496 + release_revisions_topo_walk_info(revs->topo_walk_info); 3497 + revs->topo_walk_info = NULL; 3454 3498 } 3455 3499 3456 3500 static void init_topo_walk(struct rev_info *revs) ··· 4090 4134 * boundary commits anyway. (This is what the code has always 4091 4135 * done.) 4092 4136 */ 4093 - if (revs->commits) { 4094 - free_commit_list(revs->commits); 4095 - revs->commits = NULL; 4096 - } 4137 + free_commit_list(revs->commits); 4138 + revs->commits = NULL; 4097 4139 4098 4140 /* 4099 4141 * Put all of the actual boundary commits from revs->boundary_commits ··· 4230 4272 graph_update(revs->graph, c); 4231 4273 if (!c) { 4232 4274 free_saved_parents(revs); 4233 - if (revs->previous_parents) { 4234 - free_commit_list(revs->previous_parents); 4235 - revs->previous_parents = NULL; 4236 - } 4275 + free_commit_list(revs->previous_parents); 4276 + revs->previous_parents = NULL; 4237 4277 } 4238 4278 return c; 4239 4279 }
+48 -25
revision.h
··· 330 330 struct tmp_objdir *remerge_objdir; 331 331 }; 332 332 333 - int ref_excluded(struct string_list *, const char *path); 334 - void clear_ref_exclusion(struct string_list **); 335 - void add_ref_exclusion(struct string_list **, const char *exclude); 336 - 337 - 338 - #define REV_TREE_SAME 0 339 - #define REV_TREE_NEW 1 /* Only new files */ 340 - #define REV_TREE_OLD 2 /* Only files removed */ 341 - #define REV_TREE_DIFFERENT 3 /* Mixed changes */ 342 - 343 - /* revision.c */ 344 - typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); 345 - extern volatile show_early_output_fn_t show_early_output; 346 - 347 - struct setup_revision_opt { 348 - const char *def; 349 - void (*tweak)(struct rev_info *, struct setup_revision_opt *); 350 - unsigned int assume_dashdash:1, 351 - allow_exclude_promisor_objects:1; 352 - unsigned revarg_opt; 353 - }; 354 - 355 - #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS 356 - #define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix) 357 - #endif 333 + /** 334 + * Initialize the "struct rev_info" structure with a macro. 335 + * 336 + * This will not fully initialize a "struct rev_info", the 337 + * repo_init_revisions() function needs to be called before 338 + * setup_revisions() and any revision walking takes place. 339 + * 340 + * Use REV_INFO_INIT to make the "struct rev_info" safe for passing to 341 + * release_revisions() when it's inconvenient (e.g. due to a "goto 342 + * cleanup" pattern) to arrange for repo_init_revisions() to be called 343 + * before release_revisions() is called. 344 + * 345 + * Initializing with this REV_INFO_INIT is redundant to invoking 346 + * repo_init_revisions(). If repo_init_revisions() is guaranteed to be 347 + * called before release_revisions() the "struct rev_info" can be left 348 + * uninitialized. 349 + */ 350 + #define REV_INFO_INIT { 0 } 358 351 359 352 /** 360 353 * Initialize a rev_info structure with default values. The third parameter may ··· 367 360 void repo_init_revisions(struct repository *r, 368 361 struct rev_info *revs, 369 362 const char *prefix); 363 + #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS 364 + #define init_revisions(revs, prefix) repo_init_revisions(the_repository, revs, prefix) 365 + #endif 370 366 371 367 /** 372 368 * Parse revision information, filling in the `rev_info` structure, and ··· 375 371 * head of the argument list. The last parameter is used in case no 376 372 * parameter given by the first two arguments. 377 373 */ 374 + struct setup_revision_opt { 375 + const char *def; 376 + void (*tweak)(struct rev_info *, struct setup_revision_opt *); 377 + unsigned int assume_dashdash:1, 378 + allow_exclude_promisor_objects:1; 379 + unsigned revarg_opt; 380 + }; 378 381 int setup_revisions(int argc, const char **argv, struct rev_info *revs, 379 382 struct setup_revision_opt *); 380 383 384 + /** 385 + * Free data allocated in a "struct rev_info" after it's been 386 + * initialized with repo_init_revisions() or REV_INFO_INIT. 387 + */ 388 + void release_revisions(struct rev_info *revs); 389 + 381 390 void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx, 382 391 const struct option *options, 383 392 const char * const usagestr[]); ··· 419 428 void show_object_with_name(FILE *, struct object *, const char *); 420 429 421 430 /** 431 + * Helpers to check if a "struct string_list" item matches with 432 + * wildmatch(). 433 + */ 434 + int ref_excluded(struct string_list *, const char *path); 435 + void clear_ref_exclusion(struct string_list **); 436 + void add_ref_exclusion(struct string_list **, const char *exclude); 437 + 438 + /** 422 439 * This function can be used if you want to add commit objects as revision 423 440 * information. You can use the `UNINTERESTING` object flag to indicate if 424 441 * you want to include or exclude the given commit (and commits reachable ··· 472 489 * history simplification is off. 473 490 */ 474 491 struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit); 492 + 493 + /** 494 + * Global for the (undocumented) "--early-output" flag for "git log". 495 + */ 496 + typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); 497 + extern volatile show_early_output_fn_t show_early_output; 475 498 476 499 #endif
+19 -7
sequencer.c
··· 1346 1346 log_tree_commit(&rev, commit); 1347 1347 } 1348 1348 1349 + release_revisions(&rev); 1349 1350 strbuf_release(&format); 1350 1351 } 1351 1352 ··· 3414 3415 unuse_commit_buffer(commit, commit_buffer); 3415 3416 } 3416 3417 strbuf_release(&buf); 3418 + release_revisions(&log_tree_opt); 3417 3419 3418 3420 return res; 3419 3421 } ··· 4524 4526 &log_tree_opt.diffopt); 4525 4527 log_tree_diff_flush(&log_tree_opt); 4526 4528 } 4529 + release_revisions(&log_tree_opt); 4527 4530 } 4528 4531 flush_rewritten_pending(); 4529 4532 if (!stat(rebase_path_rewritten_list(), &st) && ··· 5350 5353 int rebase_merges = flags & TODO_LIST_REBASE_MERGES; 5351 5354 int reapply_cherry_picks = flags & TODO_LIST_REAPPLY_CHERRY_PICKS; 5352 5355 int skipped_commit = 0; 5356 + int ret = 0; 5353 5357 5354 5358 repo_init_revisions(r, &revs, NULL); 5355 5359 revs.verbose_header = 1; ··· 5373 5377 pp.fmt = revs.commit_format; 5374 5378 pp.output_encoding = get_log_output_encoding(); 5375 5379 5376 - if (setup_revisions(argc, argv, &revs, NULL) > 1) 5377 - return error(_("make_script: unhandled options")); 5380 + if (setup_revisions(argc, argv, &revs, NULL) > 1) { 5381 + ret = error(_("make_script: unhandled options")); 5382 + goto cleanup; 5383 + } 5378 5384 5379 - if (prepare_revision_walk(&revs) < 0) 5380 - return error(_("make_script: error preparing revisions")); 5385 + if (prepare_revision_walk(&revs) < 0) { 5386 + ret = error(_("make_script: error preparing revisions")); 5387 + goto cleanup; 5388 + } 5381 5389 5382 - if (rebase_merges) 5383 - return make_script_with_merges(&pp, &revs, out, flags); 5390 + if (rebase_merges) { 5391 + ret = make_script_with_merges(&pp, &revs, out, flags); 5392 + goto cleanup; 5393 + } 5384 5394 5385 5395 while ((commit = get_revision(&revs))) { 5386 5396 int is_empty = is_original_commit_empty(commit); ··· 5404 5414 if (skipped_commit) 5405 5415 advise_if_enabled(ADVICE_SKIPPED_CHERRY_PICKS, 5406 5416 _("use --reapply-cherry-picks to include skipped commits")); 5407 - return 0; 5417 + cleanup: 5418 + release_revisions(&revs); 5419 + return ret; 5408 5420 } 5409 5421 5410 5422 /*
+1
shallow.c
··· 262 262 if ((o->flags & both_flags) == both_flags) 263 263 o->flags &= ~not_shallow_flag; 264 264 } 265 + release_revisions(&revs); 265 266 return result; 266 267 } 267 268
+6 -5
submodule.c
··· 619 619 struct object_id *one, struct object_id *two, 620 620 unsigned dirty_submodule) 621 621 { 622 - struct rev_info rev; 622 + struct rev_info rev = REV_INFO_INIT; 623 623 struct commit *left = NULL, *right = NULL; 624 624 struct commit_list *merge_bases = NULL; 625 625 struct repository *sub; ··· 645 645 print_submodule_diff_summary(sub, &rev, o); 646 646 647 647 out: 648 - if (merge_bases) 649 - free_commit_list(merge_bases); 648 + free_commit_list(merge_bases); 649 + release_revisions(&rev); 650 650 clear_commit_marks(left, ~0); 651 651 clear_commit_marks(right, ~0); 652 652 if (sub) { ··· 735 735 736 736 done: 737 737 strbuf_release(&sb); 738 - if (merge_bases) 739 - free_commit_list(merge_bases); 738 + free_commit_list(merge_bases); 740 739 if (left) 741 740 clear_commit_marks(left, ~0); 742 741 if (right) ··· 925 924 diff_rev.diffopt.format_callback_data = &data; 926 925 diff_rev.dense_combined_merges = 1; 927 926 diff_tree_combined_merge(commit, &diff_rev); 927 + release_revisions(&diff_rev); 928 928 } 929 929 930 930 reset_revision_walk(); 931 + release_revisions(&rev); 931 932 } 932 933 933 934 static void free_submodules_data(struct string_list *submodules)
+16 -7
t/helper/test-fast-rebase.c
··· 99 99 struct merge_result result; 100 100 struct strbuf reflog_msg = STRBUF_INIT; 101 101 struct strbuf branch_name = STRBUF_INIT; 102 + int ret = 0; 102 103 103 104 /* 104 105 * test-tool stuff doesn't set up the git directory by default; need to ··· 137 138 revs.topo_order = 1; 138 139 strvec_pushl(&rev_walk_args, "", argv[4], "--not", argv[3], NULL); 139 140 140 - if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) 141 - return error(_("unhandled options")); 141 + if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { 142 + ret = error(_("unhandled options")); 143 + goto cleanup; 144 + } 142 145 143 146 strvec_clear(&rev_walk_args); 144 147 145 - if (prepare_revision_walk(&revs) < 0) 146 - return error(_("error preparing revisions")); 148 + if (prepare_revision_walk(&revs) < 0) { 149 + ret = error(_("error preparing revisions")); 150 + goto cleanup; 151 + } 147 152 148 153 init_merge_options(&merge_opt, the_repository); 149 154 memset(&result, 0, sizeof(result)); ··· 201 206 } 202 207 if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) 203 208 die(_("unable to update HEAD")); 204 - strbuf_release(&reflog_msg); 205 - strbuf_release(&branch_name); 206 209 207 210 prime_cache_tree(the_repository, the_repository->index, 208 211 result.tree); ··· 221 224 if (write_locked_index(&the_index, &lock, 222 225 COMMIT_LOCK | SKIP_IF_UNCHANGED)) 223 226 die(_("unable to write %s"), get_index_file()); 224 - return (result.clean == 0); 227 + 228 + ret = (result.clean == 0); 229 + cleanup: 230 + strbuf_release(&reflog_msg); 231 + strbuf_release(&branch_name); 232 + release_revisions(&revs); 233 + return ret; 225 234 }
+1
t/helper/test-revision-walking.c
··· 43 43 } 44 44 45 45 reset_revision_walk(); 46 + release_revisions(&rev); 46 47 return got_revision; 47 48 } 48 49
+4
t/lib-git-svn.sh
··· 1 + if test -z "$TEST_FAILS_SANITIZE_LEAK" 2 + then 3 + TEST_PASSES_SANITIZE_LEAK=true 4 + fi 1 5 . ./test-lib.sh 2 6 3 7 if test -n "$NO_SVN_TESTS"
+1
t/t0056-git-C.sh
··· 2 2 3 3 test_description='"-C <path>" option and its effects on other path-related options' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success '"git -C <path>" runs git from the directory <path>' '
+1
t/t0062-revision-walking.sh
··· 5 5 6 6 test_description='Test revision walking api' 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 cat >run_twice_expected <<-EOF
+1
t/t0100-previous.sh
··· 5 5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6 6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 test_expect_success 'branch -d @{-1}' '
+2
t/t0101-at-syntax.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='various @{whatever} syntax tests' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 test_expect_success 'setup' '
+1
t/t1001-read-tree-m-2way.sh
··· 21 21 yomin - not in H or M 22 22 ' 23 23 24 + TEST_PASSES_SANITIZE_LEAK=true 24 25 . ./test-lib.sh 25 26 . "$TEST_DIRECTORY"/lib-read-tree.sh 26 27
+1
t/t1002-read-tree-m-u-2way.sh
··· 9 9 10 10 ' 11 11 12 + TEST_PASSES_SANITIZE_LEAK=true 12 13 . ./test-lib.sh 13 14 . "$TEST_DIRECTORY"/lib-read-tree.sh 14 15
+2
t/t1060-object-corruption.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='see how we handle various forms of corruption' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 # convert "1234abcd" to ".git/objects/12/34abcd"
+2
t/t1401-symbolic-ref.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='basic symbolic-ref tests' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 # If the tests munging HEAD fail, they can break detection of
+1
t/t1411-reflog-show.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 test_expect_success 'setup' '
+2
t/t1412-reflog-loop.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='reflog walk shows repeated commits again' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 test_expect_success 'setup commits' '
+1
t/t1415-worktree-refs.sh
··· 2 2 3 3 test_description='per-worktree refs' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success 'setup' '
+1
t/t2015-checkout-unborn.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 test_expect_success 'setup' '
+1
t/t2200-add-update.sh
··· 14 14 Also tested are "git add -u" without limiting, and "git add -u" 15 15 without contents changes, and other conditions' 16 16 17 + TEST_PASSES_SANITIZE_LEAK=true 17 18 . ./test-lib.sh 18 19 19 20 test_expect_success setup '
+1
t/t3302-notes-index-expensive.sh
··· 8 8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9 9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 10 11 + TEST_PASSES_SANITIZE_LEAK=true 11 12 . ./test-lib.sh 12 13 13 14 create_repo () {
+1
t/t3303-notes-subtrees.sh
··· 5 5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6 6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 number_of_commits=100
+1
t/t3305-notes-fanout.sh
··· 2 2 3 3 test_description='Test that adding/removing many notes triggers automatic fanout restructuring' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 path_has_fanout() {
+1
t/t3408-rebase-multi-line.sh
··· 5 5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6 6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 test_expect_success setup '
+1
t/t4021-format-patch-numbered.sh
··· 5 5 6 6 test_description='Format-patch numbering options' 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 test_expect_success setup '
+1
t/t4027-diff-submodule.sh
··· 2 2 3 3 test_description='difference in submodules' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 . "$TEST_DIRECTORY"/lib-diff.sh 7 8
+2
t/t4028-format-patch-mime-headers.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='format-patch mime headers and extra headers do not conflict' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 test_expect_success 'create commit with utf-8 body' '
+1
t/t4036-format-patch-signer-mime.sh
··· 2 2 3 3 test_description='format-patch -s should force MIME encoding as needed' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success setup '
+1
t/t4039-diff-assume-unchanged.sh
··· 2 2 3 3 test_description='diff with assume-unchanged entries' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 # external diff has been tested in t4020-diff-external.sh
+1
t/t4055-diff-context.sh
··· 5 5 6 6 test_description='diff.context configuration' 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 test_expect_success 'setup' '
+1
t/t4066-diff-emit-delay.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 # This test covers a weird 3-way interaction between "--cc -p", which will run
-1
t/t4126-apply-empty.sh
··· 2 2 3 3 test_description='apply empty' 4 4 5 - 6 5 TEST_PASSES_SANITIZE_LEAK=true 7 6 . ./test-lib.sh 8 7
+1
t/t4128-apply-root.sh
··· 2 2 3 3 test_description='apply same filename' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success 'setup' '
+2
t/t4206-log-follow-harder-copies.sh
··· 6 6 test_description='Test --follow should always find copies hard in git log. 7 7 8 8 ' 9 + 10 + TEST_PASSES_SANITIZE_LEAK=true 9 11 . ./test-lib.sh 10 12 . "$TEST_DIRECTORY"/lib-diff.sh 11 13
+1
t/t4207-log-decoration-colors.sh
··· 8 8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9 9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 10 11 + TEST_PASSES_SANITIZE_LEAK=true 11 12 . ./test-lib.sh 12 13 13 14 test_expect_success setup '
+1
t/t4212-log-corrupt.sh
··· 2 2 3 3 test_description='git log with invalid commit headers' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success 'setup' '
+2
t/t5301-sliding-window.sh
··· 4 4 # 5 5 6 6 test_description='mmap sliding window tests' 7 + 8 + TEST_PASSES_SANITIZE_LEAK=true 7 9 . ./test-lib.sh 8 10 9 11 test_expect_success \
+2
t/t5313-pack-bounds-checks.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='bounds-checking of access to mmapped on-disk file formats' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 clear_base () {
+2
t/t5316-pack-delta-depth.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='pack-objects breaks long cross-pack delta chains' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 # This mirrors a repeated push setup:
+2
t/t5320-delta-islands.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='exercise delta islands' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 # returns true iff $1 is a delta based on $2
+1
t/t5322-pack-objects-sparse.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 test_expect_success 'setup repo' '
+1
t/t5506-remote-groups.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 mark() {
+1
t/t5513-fetch-track.sh
··· 2 2 3 3 test_description='fetch follows remote-tracking branches correctly' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success setup '
+1
t/t5515-fetch-merge-logic.sh
··· 14 14 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 15 15 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 16 16 17 + TEST_PASSES_SANITIZE_LEAK=true 17 18 . ./test-lib.sh 18 19 19 20 build_script () {
+1
t/t5518-fetch-exit-status.sh
··· 8 8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9 9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 10 11 + TEST_PASSES_SANITIZE_LEAK=true 11 12 . ./test-lib.sh 12 13 13 14 test_expect_success setup '
+2
t/t5532-fetch-proxy.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='fetching via git:// using core.gitproxy' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 test_expect_success 'setup remote repo' '
+1
t/t5600-clone-fail-cleanup.sh
··· 13 13 wrote. 14 14 ' 15 15 16 + TEST_PASSES_SANITIZE_LEAK=true 16 17 . ./test-lib.sh 17 18 18 19 corrupt_repo () {
+2
t/t5900-repo-selection.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='selecting remote repo in ambiguous cases' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 reset() {
+1
t/t6002-rev-list-bisect.sh
··· 4 4 # 5 5 test_description='Tests git rev-list --bisect functionality' 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 . "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions 9 10
+1
t/t6003-rev-list-topo-order.sh
··· 5 5 6 6 test_description='Tests git rev-list --topo-order functionality' 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 . "$TEST_DIRECTORY"/lib-t6000.sh # t6xxx specific functions 10 11
+1
t/t6005-rev-list-count.sh
··· 2 2 3 3 test_description='git rev-list --max-count and --skip test' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success 'setup' '
+1
t/t6018-rev-list-glob.sh
··· 5 5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6 6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 7 8 + TEST_PASSES_SANITIZE_LEAK=true 8 9 . ./test-lib.sh 9 10 10 11 commit () {
+1
t/t6100-rev-list-in-order.sh
··· 2 2 3 3 test_description='rev-list testing in-commit-order' 4 4 5 + TEST_PASSES_SANITIZE_LEAK=true 5 6 . ./test-lib.sh 6 7 7 8 test_expect_success 'setup a commit history with trees, blobs' '
+1
t/t6101-rev-parse-parents.sh
··· 8 8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9 9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 10 11 + TEST_PASSES_SANITIZE_LEAK=true 11 12 . ./test-lib.sh 12 13 13 14 test_cmp_rev_output () {
+1
t/t6110-rev-list-sparse.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 test_expect_success setup '
+2
t/t6114-keep-packs.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='rev-list with .keep packs' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 test_expect_success 'setup' '
+2
t/t6131-pathspec-icase.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='test case insensitive pathspec limiting' 4 + 5 + TEST_PASSES_SANITIZE_LEAK=true 4 6 . ./test-lib.sh 5 7 6 8 if test_have_prereq CASE_INSENSITIVE_FS
+1
t/t7008-filter-branch-null-sha1.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='filter-branch removal of trees with null sha1' 4 + 4 5 . ./test-lib.sh 5 6 6 7 test_expect_success 'setup: base commits' '
+2
t/t7702-repack-cyclic-alternate.sh
··· 4 4 # 5 5 6 6 test_description='repack involving cyclic alternate' 7 + 8 + TEST_PASSES_SANITIZE_LEAK=true 7 9 . ./test-lib.sh 8 10 9 11 test_expect_success setup '
+1
t/t9001-send-email.sh
··· 4 4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 5 5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 6 6 7 + TEST_PASSES_SANITIZE_LEAK=true 7 8 . ./test-lib.sh 8 9 9 10 # May be altered later in the test
+1
t/t9100-git-svn-basic.sh
··· 8 8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 9 9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 10 10 11 + TEST_FAILS_SANITIZE_LEAK=true 11 12 . ./lib-git-svn.sh 12 13 13 14 prepare_utf8_locale
+2
t/t9101-git-svn-props.sh
··· 4 4 # 5 5 6 6 test_description='git svn property tests' 7 + 8 + TEST_FAILS_SANITIZE_LEAK=true 7 9 . ./lib-git-svn.sh 8 10 9 11 mkdir import
+2
t/t9104-git-svn-follow-parent.sh
··· 4 4 # 5 5 6 6 test_description='git svn fetching' 7 + 8 + TEST_FAILS_SANITIZE_LEAK=true 7 9 . ./lib-git-svn.sh 8 10 9 11 test_expect_success 'initialize repo' '
+2
t/t9106-git-svn-commit-diff-clobber.sh
··· 2 2 # 3 3 # Copyright (c) 2006 Eric Wong 4 4 test_description='git svn commit-diff clobber' 5 + 6 + TEST_FAILS_SANITIZE_LEAK=true 5 7 . ./lib-git-svn.sh 6 8 7 9 test_expect_success 'initialize repo' '
+1
t/t9115-git-svn-dcommit-funky-renames.sh
··· 5 5 6 6 test_description='git svn dcommit can commit renames of files with ugly names' 7 7 8 + TEST_FAILS_SANITIZE_LEAK=true 8 9 . ./lib-git-svn.sh 9 10 10 11 test_expect_success 'load repository with strange names' '
+1
t/t9116-git-svn-log.sh
··· 4 4 # 5 5 6 6 test_description='git svn log tests' 7 + 7 8 . ./lib-git-svn.sh 8 9 9 10 test_expect_success 'setup repository and import' '
+2
t/t9122-git-svn-author.sh
··· 1 1 #!/bin/sh 2 2 3 3 test_description='git svn authorship' 4 + 5 + TEST_FAILS_SANITIZE_LEAK=true 4 6 . ./lib-git-svn.sh 5 7 6 8 test_expect_success 'setup svn repository' '
+1
t/t9127-git-svn-partial-rebuild.sh
··· 4 4 # 5 5 6 6 test_description='git svn partial-rebuild tests' 7 + 7 8 . ./lib-git-svn.sh 8 9 9 10 test_expect_success 'initialize svnrepo' '
+1
t/t9129-git-svn-i18n-commitencoding.sh
··· 4 4 5 5 test_description='git svn honors i18n.commitEncoding in config' 6 6 7 + TEST_FAILS_SANITIZE_LEAK=true 7 8 . ./lib-git-svn.sh 8 9 9 10 compare_git_head_with () {
+1
t/t9132-git-svn-broken-symlink.sh
··· 2 2 3 3 test_description='test that git handles an svn repository with empty symlinks' 4 4 5 + TEST_FAILS_SANITIZE_LEAK=true 5 6 . ./lib-git-svn.sh 6 7 test_expect_success 'load svn dumpfile' ' 7 8 svnadmin load "$rawsvnrepo" <<EOF
+1
t/t9139-git-svn-non-utf8-commitencoding.sh
··· 4 4 5 5 test_description='git svn refuses to dcommit non-UTF8 messages' 6 6 7 + TEST_FAILS_SANITIZE_LEAK=true 7 8 . ./lib-git-svn.sh 8 9 9 10 # ISO-2022-JP can pass for valid UTF-8, so skipping that in this test
+2
t/t9146-git-svn-empty-dirs.sh
··· 3 3 # Copyright (c) 2009 Eric Wong 4 4 5 5 test_description='git svn creates empty directories' 6 + 7 + TEST_FAILS_SANITIZE_LEAK=true 6 8 . ./lib-git-svn.sh 7 9 8 10 test_expect_success 'initialize repo' '
+1
t/t9148-git-svn-propset.sh
··· 5 5 6 6 test_description='git svn propset tests' 7 7 8 + TEST_FAILS_SANITIZE_LEAK=true 8 9 . ./lib-git-svn.sh 9 10 10 11 test_expect_success 'setup propset via import' '
+1
t/t9160-git-svn-preserve-empty-dirs.sh
··· 9 9 directories, and checks that corresponding directories are created in the 10 10 local Git repository with placeholder files.' 11 11 12 + TEST_FAILS_SANITIZE_LEAK=true 12 13 . ./lib-git-svn.sh 13 14 14 15 GIT_REPO=git-svn-repo
+2
t/t9162-git-svn-dcommit-interactive.sh
··· 3 3 # Copyright (c) 2011 Frédéric Heitzmann 4 4 5 5 test_description='git svn dcommit --interactive series' 6 + 7 + TEST_FAILS_SANITIZE_LEAK=true 6 8 . ./lib-git-svn.sh 7 9 8 10 test_expect_success 'initialize repo' '
+2
t/t9164-git-svn-dcommit-concurrent.sh
··· 4 4 # 5 5 6 6 test_description='concurrent git svn dcommit' 7 + 8 + TEST_FAILS_SANITIZE_LEAK=true 7 9 . ./lib-git-svn.sh 8 10 9 11
+1
t/t9501-gitweb-standalone-http-status.sh
··· 13 13 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 14 14 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 15 15 16 + TEST_PASSES_SANITIZE_LEAK=true 16 17 . ./lib-gitweb.sh 17 18 18 19 #
+9 -6
wt-status.c
··· 616 616 rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score; 617 617 copy_pathspec(&rev.prune_data, &s->pathspec); 618 618 run_diff_files(&rev, 0); 619 - clear_pathspec(&rev.prune_data); 619 + release_revisions(&rev); 620 620 } 621 621 622 622 static void wt_status_collect_changes_index(struct wt_status *s) ··· 662 662 663 663 copy_pathspec(&rev.prune_data, &s->pathspec); 664 664 run_diff_index(&rev, 1); 665 - object_array_clear(&rev.pending); 666 - clear_pathspec(&rev.prune_data); 665 + release_revisions(&rev); 667 666 } 668 667 669 668 static int add_file_to_list(const struct object_id *oid, ··· 1152 1151 rev.diffopt.b_prefix = "w/"; 1153 1152 run_diff_files(&rev, 0); 1154 1153 } 1154 + release_revisions(&rev); 1155 1155 } 1156 1156 1157 1157 static void wt_longstatus_print_tracking(struct wt_status *s) ··· 2545 2545 rev_info.diffopt.flags.quick = 1; 2546 2546 diff_setup_done(&rev_info.diffopt); 2547 2547 result = run_diff_files(&rev_info, 0); 2548 - return diff_result_code(&rev_info.diffopt, result); 2548 + result = diff_result_code(&rev_info.diffopt, result); 2549 + release_revisions(&rev_info); 2550 + return result; 2549 2551 } 2550 2552 2551 2553 /** ··· 2577 2579 2578 2580 diff_setup_done(&rev_info.diffopt); 2579 2581 result = run_diff_index(&rev_info, 1); 2580 - object_array_clear(&rev_info.pending); 2581 - return diff_result_code(&rev_info.diffopt, result); 2582 + result = diff_result_code(&rev_info.diffopt, result); 2583 + release_revisions(&rev_info); 2584 + return result; 2582 2585 } 2583 2586 2584 2587 /**