diff options
Diffstat (limited to 'builtin')
124 files changed, 2113 insertions, 924 deletions
diff --git a/builtin/add.c b/builtin/add.c index 40b61ef90d..773b7224a4 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -3,7 +3,6 @@ * * Copyright (C) 2006 Linus Torvalds */ - #include "builtin.h" #include "advice.h" #include "config.h" @@ -18,7 +17,6 @@ #include "preload-index.h" #include "diff.h" #include "read-cache.h" -#include "repository.h" #include "revision.h" #include "bulk-checkin.h" #include "strvec.h" @@ -36,24 +34,27 @@ static int pathspec_file_nul; static int include_sparse; static const char *pathspec_from_file; -static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) +static int chmod_pathspec(struct repository *repo, + struct pathspec *pathspec, + char flip, + int show_only) { int i, ret = 0; - for (i = 0; i < the_repository->index->cache_nr; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < repo->index->cache_nr; i++) { + struct cache_entry *ce = repo->index->cache[i]; int err; if (!include_sparse && (ce_skip_worktree(ce) || - !path_in_sparse_checkout(ce->name, the_repository->index))) + !path_in_sparse_checkout(ce->name, repo->index))) continue; - if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL)) + if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL)) continue; if (!show_only) - err = chmod_index_entry(the_repository->index, ce, flip); + err = chmod_index_entry(repo->index, ce, flip); else err = S_ISREG(ce->ce_mode) ? 0 : -1; @@ -64,31 +65,36 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) return ret; } -static int renormalize_tracked_files(const struct pathspec *pathspec, int flags) +static int renormalize_tracked_files(struct repository *repo, + const struct pathspec *pathspec, + int flags) { int i, retval = 0; - for (i = 0; i < the_repository->index->cache_nr; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < repo->index->cache_nr; i++) { + struct cache_entry *ce = repo->index->cache[i]; if (!include_sparse && (ce_skip_worktree(ce) || - !path_in_sparse_checkout(ce->name, the_repository->index))) + !path_in_sparse_checkout(ce->name, repo->index))) continue; if (ce_stage(ce)) continue; /* do not touch unmerged paths */ if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode)) continue; /* do not touch non blobs */ - if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL)) + if (pathspec && !ce_path_match(repo->index, ce, pathspec, NULL)) continue; - retval |= add_file_to_index(the_repository->index, ce->name, + retval |= add_file_to_index(repo->index, ce->name, flags | ADD_CACHE_RENORMALIZE); } return retval; } -static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix) +static char *prune_directory(struct repository *repo, + struct dir_struct *dir, + struct pathspec *pathspec, + int prefix) { char *seen; int i; @@ -100,16 +106,16 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, i = dir->nr; while (--i >= 0) { struct dir_entry *entry = *src++; - if (dir_path_match(the_repository->index, entry, pathspec, prefix, seen)) + if (dir_path_match(repo->index, entry, pathspec, prefix, seen)) *dst++ = entry; } dir->nr = dst - dir->entries; - add_pathspec_matches_against_index(pathspec, the_repository->index, seen, + add_pathspec_matches_against_index(pathspec, repo->index, seen, PS_IGNORE_SKIP_WORKTREE); return seen; } -static int refresh(int verbose, const struct pathspec *pathspec) +static int refresh(struct repository *repo, int verbose, const struct pathspec *pathspec) { char *seen; int i, ret = 0; @@ -119,14 +125,14 @@ static int refresh(int verbose, const struct pathspec *pathspec) (verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET); seen = xcalloc(pathspec->nr, 1); - refresh_index(the_repository->index, flags, pathspec, seen, + refresh_index(repo->index, flags, pathspec, seen, _("Unstaged changes after refreshing the index:")); for (i = 0; i < pathspec->nr; i++) { if (!seen[i]) { const char *path = pathspec->items[i].original; if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) || - !path_in_sparse_checkout(path, the_repository->index)) { + !path_in_sparse_checkout(path, repo->index)) { string_list_append(&only_match_skip_worktree, pathspec->items[i].original); } else { @@ -147,7 +153,10 @@ static int refresh(int verbose, const struct pathspec *pathspec) return ret; } -int interactive_add(const char **argv, const char *prefix, int patch) +int interactive_add(struct repository *repo, + const char **argv, + const char *prefix, + int patch) { struct pathspec pathspec; int ret; @@ -159,28 +168,31 @@ int interactive_add(const char **argv, const char *prefix, int patch) prefix, argv); if (patch) - ret = !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec); + ret = !!run_add_p(repo, ADD_P_ADD, NULL, &pathspec); else - ret = !!run_add_i(the_repository, &pathspec); + ret = !!run_add_i(repo, &pathspec); clear_pathspec(&pathspec); return ret; } -static int edit_patch(int argc, const char **argv, const char *prefix) +static int edit_patch(struct repository *repo, + int argc, + const char **argv, + const char *prefix) { - char *file = git_pathdup("ADD_EDIT.patch"); + char *file = repo_git_path(repo, "ADD_EDIT.patch"); struct child_process child = CHILD_PROCESS_INIT; struct rev_info rev; int out; struct stat st; - git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ + repo_config(repo, git_diff_basic_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die(_("could not read the index")); - repo_init_revisions(the_repository, &rev, prefix); + repo_init_revisions(repo, &rev, prefix); rev.diffopt.context = 7; argc = setup_revisions(argc, argv, &rev, NULL); @@ -318,7 +330,7 @@ static void check_embedded_repo(const char *path) strbuf_release(&name); } -static int add_files(struct dir_struct *dir, int flags) +static int add_files(struct repository *repo, struct dir_struct *dir, int flags) { int i, exit_status = 0; struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP; @@ -334,12 +346,12 @@ static int add_files(struct dir_struct *dir, int flags) for (i = 0; i < dir->nr; i++) { if (!include_sparse && - !path_in_sparse_checkout(dir->entries[i]->name, the_repository->index)) { + !path_in_sparse_checkout(dir->entries[i]->name, repo->index)) { string_list_append(&matched_sparse_paths, dir->entries[i]->name); continue; } - if (add_file_to_index(the_repository->index, dir->entries[i]->name, flags)) { + if (add_file_to_index(repo->index, dir->entries[i]->name, flags)) { if (!ignore_add_errors) die(_("adding files failed")); exit_status = 1; @@ -358,7 +370,10 @@ static int add_files(struct dir_struct *dir, int flags) return exit_status; } -int cmd_add(int argc, const char **argv, const char *prefix) +int cmd_add(int argc, + const char **argv, + const char *prefix, + struct repository *repo) { int exit_status = 0; struct pathspec pathspec; @@ -370,7 +385,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) char *ps_matched = NULL; struct lock_file lock_file = LOCK_INIT; - git_config(add_config, NULL); + repo_config(repo, add_config, NULL); argc = parse_options(argc, argv, prefix, builtin_add_options, builtin_add_usage, PARSE_OPT_KEEP_ARGV0); @@ -381,13 +396,13 @@ int cmd_add(int argc, const char **argv, const char *prefix) die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch"); if (pathspec_from_file) die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch"); - exit(interactive_add(argv + 1, prefix, patch_interactive)); + exit(interactive_add(repo, argv + 1, prefix, patch_interactive)); } if (edit_interactive) { if (pathspec_from_file) die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--edit"); - return(edit_patch(argc, argv, prefix)); + return(edit_patch(repo, argc, argv, prefix)); } argc--; argv++; @@ -410,10 +425,10 @@ int cmd_add(int argc, const char **argv, const char *prefix) add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize; require_pathspec = !(take_worktree_changes || (0 < addremove_explicit)); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); /* * Check the "pathspec '%s' did not match any files" block @@ -454,11 +469,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) (!(addremove || take_worktree_changes) ? ADD_CACHE_IGNORE_REMOVAL : 0)); - if (repo_read_index_preload(the_repository, &pathspec, 0) < 0) + if (repo_read_index_preload(repo, &pathspec, 0) < 0) die(_("index file corrupt")); - die_in_unpopulated_submodule(the_repository->index, prefix); - die_path_inside_submodule(the_repository->index, &pathspec); + die_in_unpopulated_submodule(repo->index, prefix); + die_path_inside_submodule(repo->index, &pathspec); if (add_new_files) { int baselen; @@ -470,13 +485,13 @@ int cmd_add(int argc, const char **argv, const char *prefix) } /* This picks up the paths that are not tracked */ - baselen = fill_directory(&dir, the_repository->index, &pathspec); + baselen = fill_directory(&dir, repo->index, &pathspec); if (pathspec.nr) - seen = prune_directory(&dir, &pathspec, baselen); + seen = prune_directory(repo, &dir, &pathspec, baselen); } if (refresh_only) { - exit_status |= refresh(verbose, &pathspec); + exit_status |= refresh(repo, verbose, &pathspec); goto finish; } @@ -487,7 +502,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (!seen) seen = find_pathspecs_matching_against_index(&pathspec, - the_repository->index, PS_IGNORE_SKIP_WORKTREE); + repo->index, PS_IGNORE_SKIP_WORKTREE); /* * file_exists() assumes exact match @@ -523,8 +538,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) !file_exists(path)) { if (ignore_missing) { int dtype = DT_UNKNOWN; - if (is_excluded(&dir, the_repository->index, path, &dtype)) - dir_add_ignored(&dir, the_repository->index, + if (is_excluded(&dir, repo->index, path, &dtype)) + dir_add_ignored(&dir, repo->index, path, pathspec.items[i].len); } else die(_("pathspec '%s' did not match any files"), @@ -547,9 +562,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) ps_matched = xcalloc(pathspec.nr, 1); if (add_renormalize) - exit_status |= renormalize_tracked_files(&pathspec, flags); + exit_status |= renormalize_tracked_files(repo, &pathspec, flags); else - exit_status |= add_files_to_cache(the_repository, prefix, + exit_status |= add_files_to_cache(repo, prefix, &pathspec, ps_matched, include_sparse, flags); @@ -558,14 +573,14 @@ int cmd_add(int argc, const char **argv, const char *prefix) exit(128); if (add_new_files) - exit_status |= add_files(&dir, flags); + exit_status |= add_files(repo, &dir, flags); if (chmod_arg && pathspec.nr) - exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only); + exit_status |= chmod_pathspec(repo, &pathspec, chmod_arg[0], show_only); end_odb_transaction(); finish: - if (write_locked_index(the_repository->index, &lock_file, + if (write_locked_index(repo->index, &lock_file, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write new index file")); diff --git a/builtin/am.c b/builtin/am.c index 370f5593f2..bfa95147cf 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -4,6 +4,7 @@ * Based on git-am.sh by Junio C Hamano. */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "advice.h" @@ -38,7 +39,6 @@ #include "string-list.h" #include "pager.h" #include "path.h" -#include "repository.h" #include "pretty.h" /** @@ -490,7 +490,8 @@ static int run_applypatch_msg_hook(struct am_state *state) assert(state->msg); if (!state->no_verify) - ret = run_hooks_l("applypatch-msg", am_path(state, "final-commit"), NULL); + ret = run_hooks_l(the_repository, "applypatch-msg", + am_path(state, "final-commit"), NULL); if (!ret) { FREE_AND_NULL(state->msg); @@ -512,7 +513,7 @@ static int run_post_rewrite_hook(const struct am_state *state) strvec_push(&opt.args, "rebase"); opt.path_to_stdin = am_path(state, "rewritten"); - return run_hooks_opt("post-rewrite", &opt); + return run_hooks_opt(the_repository, "post-rewrite", &opt); } /** @@ -1543,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file) if (index_file) { /* Reload index as apply_all_patches() will have modified it. */ discard_index(the_repository->index); - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, + repo_get_git_dir(the_repository)); } return 0; @@ -1586,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa return error("could not build fake ancestor"); discard_index(the_repository->index); - read_index_from(the_repository->index, index_path, get_git_dir()); + read_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository)); if (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL)) return error(_("Repository lacks necessary blobs to fall back on 3-way merge.")); @@ -1630,7 +1632,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa * changes. */ - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); @@ -1663,10 +1665,12 @@ static void do_commit(const struct am_state *state) const char *reflog_msg, *author, *committer = NULL; struct strbuf sb = STRBUF_INIT; - if (!state->no_verify && run_hooks("pre-applypatch")) + if (!state->no_verify && run_hooks(the_repository, "pre-applypatch")) exit(1); - if (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(&tree, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) die(_("git write-tree failed to write a tree")); if (!repo_get_oid_commit(the_repository, "HEAD", &parent)) { @@ -1716,7 +1720,7 @@ static void do_commit(const struct am_state *state) fclose(fp); } - run_hooks("post-applypatch"); + run_hooks(the_repository, "post-applypatch"); free_commit_list(parents); strbuf_release(&sb); @@ -2076,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem if (fast_forward_to(head_tree, head_tree, 1)) return -1; - if (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(&index, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) return -1; index_tree = parse_tree_indirect(&index); @@ -2297,7 +2303,10 @@ static int parse_opt_show_current_patch(const struct option *opt, const char *ar return 0; } -int cmd_am(int argc, const char **argv, const char *prefix) +int cmd_am(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct am_state state; int binary = -1; diff --git a/builtin/annotate.c b/builtin/annotate.c index 58ff977a23..03413c7df8 100644 --- a/builtin/annotate.c +++ b/builtin/annotate.c @@ -3,20 +3,35 @@ * * Copyright (C) 2006 Ryan Anderson */ + +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "builtin.h" #include "strvec.h" -int cmd_annotate(int argc, const char **argv, const char *prefix) +int cmd_annotate(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strvec args = STRVEC_INIT; - int i; + const char **args_copy; + int ret; strvec_pushl(&args, "annotate", "-c", NULL); - - for (i = 1; i < argc; i++) { + for (int i = 1; i < argc; i++) strvec_push(&args, argv[i]); - } - return cmd_blame(args.nr, args.v, prefix); + /* + * `cmd_blame()` ends up modifying the array, which causes memory leaks + * if we didn't copy the array here. + */ + CALLOC_ARRAY(args_copy, args.nr + 1); + COPY_ARRAY(args_copy, args.v, args.nr); + + ret = cmd_blame(args.nr, args_copy, prefix, the_repository); + + strvec_clear(&args); + free(args_copy); + return ret; } diff --git a/builtin/apply.c b/builtin/apply.c index d623c52f78..84f1863d3a 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1,6 +1,6 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" -#include "repository.h" #include "hash.h" #include "apply.h" @@ -9,7 +9,10 @@ static const char * const apply_usage[] = { NULL }; -int cmd_apply(int argc, const char **argv, const char *prefix) +int cmd_apply(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force_apply = 0; int options = 0; diff --git a/builtin/archive.c b/builtin/archive.c index b50981504f..dc926d1a3d 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -2,13 +2,13 @@ * Copyright (c) 2006 Franck Bui-Huu * Copyright (c) 2006 Rene Scharfe */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "archive.h" #include "gettext.h" #include "transport.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" static void create_output_file(const char *output_file) { @@ -76,7 +76,10 @@ static int run_remote_archiver(int argc, const char **argv, PARSE_OPT_KEEP_UNKNOWN_OPT | \ PARSE_OPT_NO_INTERNAL_HELP ) -int cmd_archive(int argc, const char **argv, const char *prefix) +int cmd_archive(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *exec = "git-upload-archive"; char *output = NULL; @@ -100,13 +103,16 @@ int cmd_archive(int argc, const char **argv, const char *prefix) if (output) create_output_file(output); - if (remote) - return run_remote_archiver(argc, argv, remote, exec, output); + if (remote) { + ret = run_remote_archiver(argc, argv, remote, exec, output); + goto out; + } setvbuf(stderr, NULL, _IOLBF, BUFSIZ); ret = write_archive(argc, argv, prefix, the_repository, output, 0); +out: free(output); return ret; } diff --git a/builtin/bisect.c b/builtin/bisect.c index dabce9b542..21d17a6c1a 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "copy.h" #include "environment.h" @@ -356,6 +357,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) } static int inc_nr(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cb_data) { @@ -545,7 +547,7 @@ finish: return res; } -static int add_bisect_ref(const char *refname, const struct object_id *oid, +static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb) { struct add_bisect_ref_data *data = cb; @@ -582,7 +584,7 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs) refs_for_each_glob_ref_in(get_main_ref_store(the_repository), add_bisect_ref, good, "refs/bisect/", &cb); if (prepare_revision_walk(revs)) - res = error(_("revision walk setup failed\n")); + res = error(_("revision walk setup failed")); free(good); free(bad); @@ -1107,7 +1109,7 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, int argc, setup_revisions(2, argv + i - 1, &revs, NULL); if (prepare_revision_walk(&revs)) - die(_("revision walk setup failed\n")); + die(_("revision walk setup failed")); while ((commit = get_revision(&revs)) != NULL) strvec_push(&argv_state, oid_to_hex(&commit->object.oid)); @@ -1162,6 +1164,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc, } static int get_first_good(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -1409,7 +1412,10 @@ static int cmd_bisect__run(int argc, const char **argv, const char *prefix UNUSE return res; } -int cmd_bisect(int argc, const char **argv, const char *prefix) +int cmd_bisect(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int res = 0; parse_opt_subcommand_fn *fn = NULL; diff --git a/builtin/blame.c b/builtin/blame.c index 35e975fb13..e407a22da3 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -4,7 +4,7 @@ * Copyright (c) 2006, 2014 by its authors * See COPYING for licensing conditions */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "color.h" @@ -12,7 +12,6 @@ #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "commit.h" #include "diff.h" #include "revision.h" @@ -864,7 +863,10 @@ static void build_ignorelist(struct blame_scoreboard *sb, } } -int cmd_blame(int argc, const char **argv, const char *prefix) +int cmd_blame(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; char *path = NULL; @@ -1081,7 +1083,7 @@ parse_done: path = add_prefix(prefix, argv[1]); argv[1] = argv[2]; } else { /* (2a) */ - if (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree()) + if (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository)) die("missing <path> to blame"); path = add_prefix(prefix, argv[argc - 1]); } diff --git a/builtin/branch.c b/builtin/branch.c index 48cac74f97..fd1611ebf5 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -4,7 +4,7 @@ * Copyright (c) 2006 Kristian Høgsberg <krh@redhat.com> * Based on git-branch.sh by Junio C Hamano. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "color.h" @@ -210,7 +210,7 @@ static void delete_branch_config(const char *branchname) { struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "branch.%s", branchname); - if (git_config_rename_section(buf.buf, NULL) < 0) + if (repo_config_rename_section(the_repository, buf.buf, NULL) < 0) warning(_("update of config-file failed")); strbuf_release(&buf); } @@ -659,9 +659,10 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int strbuf_addf(&oldsection, "branch.%s", interpreted_oldname); strbuf_addf(&newsection, "branch.%s", interpreted_newname); - if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0) + if (!copy && repo_config_rename_section(the_repository, oldsection.buf, newsection.buf) < 0) die(_("branch is renamed, but update of config-file failed")); - if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0) + if (copy && strcmp(interpreted_oldname, interpreted_newname) && + repo_config_copy_section(the_repository, oldsection.buf, newsection.buf) < 0) die(_("branch is copied, but update of config-file failed")); strbuf_release(&oldref); strbuf_release(&newref); @@ -703,7 +704,10 @@ static int edit_branch_description(const char *branch_name) return 0; } -int cmd_branch(int argc, const char **argv, const char *prefix) +int cmd_branch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { /* possible actions */ int delete = 0, rename = 0, copy = 0, list = 0, @@ -877,6 +881,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) string_list_clear(&output, 0); ref_sorting_release(sorting); ref_filter_clear(&filter); + ref_format_clear(&format); return 0; } else if (edit_description) { const char *branch_name; diff --git a/builtin/bugreport.c b/builtin/bugreport.c index b3cc77af53..7c2df035c9 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "editor.h" @@ -58,7 +59,7 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit) for (p = hook_name_list; *p; p++) { const char *hook = *p; - if (hook_exists(hook)) + if (hook_exists(the_repository, hook)) strbuf_addf(hook_info, "%s\n", hook); } } @@ -98,7 +99,10 @@ static void get_header(struct strbuf *buf, const char *title) strbuf_addf(buf, "\n\n[%s]\n", title); } -int cmd_bugreport(int argc, const char **argv, const char *prefix) +int cmd_bugreport(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buffer = STRBUF_INIT; struct strbuf report_path = STRBUF_INIT; diff --git a/builtin/bundle.c b/builtin/bundle.c index 86d0ed7049..127518c2a8 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" @@ -5,7 +6,6 @@ #include "strvec.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" #include "bundle.h" /* @@ -221,12 +221,17 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) &extra_index_pack_args, 0) || list_bundle_refs(&header, argc, argv); bundle_header_release(&header); + cleanup: + strvec_clear(&extra_index_pack_args); free(bundle_file); return ret; } -int cmd_bundle(int argc, const char **argv, const char *prefix) +int cmd_bundle(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 18fe58d6b8..bfdfb51c7c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "convert.h" @@ -191,7 +191,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, const char *ls_args[3] = { NULL }; ls_args[0] = "ls-tree"; ls_args[1] = obj_name; - ret = cmd_ls_tree(2, ls_args, NULL); + ret = cmd_ls_tree(2, ls_args, NULL, the_repository); goto cleanup; } @@ -923,7 +923,10 @@ static int batch_option_callback(const struct option *opt, return 0; } -int cmd_cat_file(int argc, const char **argv, const char *prefix) +int cmd_cat_file(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int opt = 0; int opt_cw = 0; @@ -1047,6 +1050,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) if (batch.buffer_output < 0) batch.buffer_output = batch.all_objects; + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + /* Return early if we're in batch mode? */ if (batch.enabled) { if (opt_cw) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 9376810710..7cf275b893 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "attr.h" @@ -5,7 +6,6 @@ #include "gettext.h" #include "object-name.h" #include "quote.h" -#include "repository.h" #include "setup.h" #include "parse-options.h" #include "write-or-die.h" @@ -107,7 +107,10 @@ static NORETURN void error_with_usage(const char *msg) usage_with_options(check_attr_usage, check_attr_options); } -int cmd_check_attr(int argc, const char **argv, const char *prefix) +int cmd_check_attr(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct attr_check *check; struct object_id initialized_oid; diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 2bda6a1d46..7b7831d13a 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -5,7 +6,6 @@ #include "quote.h" #include "pathspec.h" #include "parse-options.h" -#include "repository.h" #include "submodule.h" #include "write-or-die.h" @@ -151,7 +151,10 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix) return num_ignored; } -int cmd_check_ignore(int argc, const char **argv, const char *prefix) +int cmd_check_ignore(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int num_ignored; struct dir_struct dir = DIR_INIT; diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index b8a05b8e07..df00b5ee13 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -9,6 +10,7 @@ #include "write-or-die.h" static int use_stdin; +static const char *mailmap_file, *mailmap_blob; static const char * const check_mailmap_usage[] = { N_("git check-mailmap [<options>] <contact>..."), NULL @@ -16,6 +18,8 @@ NULL static const struct option check_mailmap_options[] = { OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")), + OPT_FILENAME(0, "mailmap-file", &mailmap_file, N_("read additional mailmap entries from file")), + OPT_STRING(0, "mailmap-blob", &mailmap_blob, N_("blob"), N_("read additional mailmap entries from blob")), OPT_END() }; @@ -25,13 +29,17 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) size_t namelen, maillen; struct ident_split ident; - if (split_ident_line(&ident, contact, strlen(contact))) - die(_("unable to parse contact: %s"), contact); - - name = ident.name_begin; - namelen = ident.name_end - ident.name_begin; - mail = ident.mail_begin; - maillen = ident.mail_end - ident.mail_begin; + if (!split_ident_line(&ident, contact, strlen(contact))) { + name = ident.name_begin; + namelen = ident.name_end - ident.name_begin; + mail = ident.mail_begin; + maillen = ident.mail_end - ident.mail_begin; + } else { + name = NULL; + namelen = 0; + mail = contact; + maillen = strlen(contact); + } map_user(mailmap, &mail, &maillen, &name, &namelen); @@ -40,7 +48,10 @@ static void check_mailmap(struct string_list *mailmap, const char *contact) printf("<%.*s>\n", (int)maillen, mail); } -int cmd_check_mailmap(int argc, const char **argv, const char *prefix) +int cmd_check_mailmap(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct string_list mailmap = STRING_LIST_INIT_NODUP; @@ -52,6 +63,10 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix) die(_("no contacts specified")); read_mailmap(&mailmap); + if (mailmap_blob) + read_mailmap_blob(&mailmap, mailmap_blob); + if (mailmap_file) + read_mailmap_file(&mailmap, mailmap_file, 0); for (i = 0; i < argc; ++i) check_mailmap(&mailmap, argv[i]); diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index 5eb6bdc3f6..e86d8ef980 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -1,7 +1,6 @@ /* * GIT - The information manager from hell */ - #include "builtin.h" #include "refs.h" #include "setup.h" @@ -51,7 +50,10 @@ static int check_ref_format_branch(const char *arg) return 0; } -int cmd_check_ref_format(int argc, const char **argv, const char *prefix) +int cmd_check_ref_format(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; int normalize = 0; diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c index 6b62b5375b..ff6cdccc21 100644 --- a/builtin/checkout--worker.c +++ b/builtin/checkout--worker.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "entry.h" @@ -113,7 +114,10 @@ static const char * const checkout_worker_usage[] = { NULL }; -int cmd_checkout__worker(int argc, const char **argv, const char *prefix) +int cmd_checkout__worker(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout state = CHECKOUT_INIT; struct option checkout_worker_options[] = { diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 29e744d11b..6dd38eb05d 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -4,13 +4,12 @@ * Copyright (C) 2005 Linus Torvalds * */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "lockfile.h" #include "quote.h" -#include "repository.h" #include "cache-tree.h" #include "parse-options.h" #include "entry.h" @@ -208,7 +207,10 @@ static int option_parse_stage(const struct option *opt, return 0; } -int cmd_checkout_index(int argc, const char **argv, const char *prefix) +int cmd_checkout_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct lock_file lock_file = LOCK_INIT; diff --git a/builtin/checkout.c b/builtin/checkout.c index 1748d68c96..9c30000d3a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "branch.h" @@ -23,6 +24,7 @@ #include "read-cache.h" #include "refs.h" #include "remote.h" +#include "repo-settings.h" #include "resolve-undo.h" #include "revision.h" #include "setup.h" @@ -125,7 +127,7 @@ static void branch_info_release(struct branch_info *info) static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit, int changed) { - return run_hooks_l("post-checkout", + return run_hooks_l(the_repository, "post-checkout", oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()), oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()), changed ? "1" : "0", NULL); @@ -884,7 +886,7 @@ static int merge_working_tree(const struct checkout_opts *opts, add_files_to_cache(the_repository, NULL, NULL, NULL, 0, 0); - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.verbosity = 0; work = write_in_core_index_as_tree(the_repository); @@ -950,11 +952,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts, const char *old_desc, *reflog_msg; if (opts->new_branch) { if (opts->new_orphan_branch) { + enum log_refs_config log_all_ref_updates = + repo_settings_get_log_all_ref_updates(the_repository); char *refname; refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); if (opts->new_branch_log && - !should_autocreate_reflog(refname)) { + !should_autocreate_reflog(log_all_ref_updates, refname)) { int ret; struct strbuf err = STRBUF_INIT; @@ -1045,7 +1049,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, report_tracking(new_branch_info); } -static int add_pending_uninteresting_ref(const char *refname, +static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -1953,7 +1957,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix, return ret; } -int cmd_checkout(int argc, const char **argv, const char *prefix) +int cmd_checkout(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; @@ -2000,7 +2007,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) checkout_usage); } -int cmd_switch(int argc, const char **argv, const char *prefix) +int cmd_switch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options = NULL; @@ -2036,7 +2046,10 @@ int cmd_switch(int argc, const char **argv, const char *prefix) switch_branch_usage); } -int cmd_restore(int argc, const char **argv, const char *prefix) +int cmd_restore(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; diff --git a/builtin/clean.c b/builtin/clean.c index ded5a91534..9c48dd0271 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -5,7 +5,7 @@ * * Based on git-clean.sh by Pavel Roskin */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -14,7 +14,6 @@ #include "parse-options.h" #include "path.h" #include "read-cache-ll.h" -#include "repository.h" #include "setup.h" #include "string-list.h" #include "quote.h" @@ -915,7 +914,10 @@ static void correct_untracked_entries(struct dir_struct *dir) dir->nr = dst; } -int cmd_clean(int argc, const char **argv, const char *prefix) +int cmd_clean(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, res; int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0; diff --git a/builtin/clone.c b/builtin/clone.c index af6017d41a..59fcb317a6 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -7,8 +7,9 @@ * * Clone a repository into a different directory that does not yet exist. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "advice.h" #include "config.h" @@ -729,7 +730,8 @@ static int git_sparse_checkout_init(const char *repo) return result; } -static int checkout(int submodule_progress, int filter_submodules) +static int checkout(int submodule_progress, int filter_submodules, + enum ref_storage_format ref_storage_format) { struct object_id oid; char *head; @@ -788,7 +790,7 @@ static int checkout(int submodule_progress, int filter_submodules) if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); - err |= run_hooks_l("post-checkout", oid_to_hex(null_oid()), + err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid()), oid_to_hex(&oid), "1", NULL); if (!err && (option_recurse_submodules.nr > 0)) { @@ -813,6 +815,10 @@ static int checkout(int submodule_progress, int filter_submodules) strvec_push(&cmd.args, "--no-fetch"); } + if (ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&cmd.args, "--ref-format=%s", + ref_storage_format_to_name(ref_storage_format)); + if (filter_submodules && filter_options.choice) strvec_pushf(&cmd.args, "--filter=%s", expand_list_objects_filter_spec(&filter_options)); @@ -951,7 +957,10 @@ static int path_exists(const char *path) return !stat(path, &sb); } -int cmd_clone(int argc, const char **argv, const char *prefix) +int cmd_clone(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { int is_bundle = 0, is_local; int reject_shallow = 0; @@ -1394,8 +1403,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix) * data from the --bundle-uri option. */ if (bundle_uri) { + struct remote_state *state; int has_heuristic = 0; + /* + * We need to save the remote state as our remote's lifetime is + * tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); @@ -1404,6 +1422,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) bundle_uri); else if (has_heuristic) git_config_set_gently("fetch.bundleuri", bundle_uri); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { /* * Populate transport->got_remote_bundle_uri and @@ -1413,12 +1435,26 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (transport->bundles && hashmap_get_size(&transport->bundles->bundles)) { + struct remote_state *state; + + /* + * We need to save the remote state as our remote's + * lifetime is tied to it. + */ + state = the_repository->remote_state; + the_repository->remote_state = NULL; + repo_clear(the_repository); + /* At this point, we need the_repository to match the cloned repo. */ if (repo_init(the_repository, git_dir, work_tree)) warning(_("failed to initialize the repo, skipping bundle URI")); else if (fetch_bundle_list(the_repository, transport->bundles)) warning(_("failed to fetch advertised bundles")); + + remote_state_clear(the_repository->remote_state); + free(the_repository->remote_state); + the_repository->remote_state = state; } else { clear_bundle_list(transport->bundles); FREE_AND_NULL(transport->bundles); @@ -1536,7 +1572,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) return 1; junk_mode = JUNK_LEAVE_REPO; - err = checkout(submodule_progress, filter_submodules); + err = checkout(submodule_progress, filter_submodules, + ref_storage_format); free(remote_name); strbuf_release(&reflog_msg); diff --git a/builtin/column.c b/builtin/column.c index 10ff7e0166..50314cc255 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -18,7 +19,10 @@ static int column_config(const char *var, const char *value, return git_column_config(var, value, cb, &colopts); } -int cmd_column(int argc, const char **argv, const char *prefix) +int cmd_column(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct string_list list = STRING_LIST_INIT_DUP; struct strbuf sb = STRBUF_INIT; diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 7102ee90a0..7c991db6eb 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -1,11 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "parse-options.h" -#include "repository.h" #include "commit-graph.h" #include "object-store-ll.h" #include "progress.h" @@ -95,7 +94,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix) usage_with_options(builtin_commit_graph_verify_usage, options); if (!opts.obj_dir) - opts.obj_dir = get_object_directory(); + opts.obj_dir = repo_get_object_directory(the_repository); if (opts.shallow) flags |= COMMIT_GRAPH_VERIFY_SHALLOW; if (opts.progress) @@ -275,7 +274,7 @@ static int graph_write(int argc, const char **argv, const char *prefix) if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1) die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs")); if (!opts.obj_dir) - opts.obj_dir = get_object_directory(); + opts.obj_dir = repo_get_object_directory(the_repository); if (opts.append) flags |= COMMIT_GRAPH_WRITE_APPEND; if (opts.split) @@ -331,7 +330,10 @@ cleanup: return result; } -int cmd_commit_graph(int argc, const char **argv, const char *prefix) +int cmd_commit_graph(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_commit_graph_options[] = { diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 84bb450222..2ca1a57ebb 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -3,13 +3,14 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "hex.h" #include "object-name.h" #include "object-store-ll.h" -#include "repository.h" + #include "commit.h" #include "parse-options.h" @@ -90,7 +91,10 @@ static int parse_file_arg_callback(const struct option *opt, return 0; } -int cmd_commit_tree(int argc, const char **argv, const char *prefix) +int cmd_commit_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct strbuf buffer = STRBUF_INIT; struct commit_list *parents = NULL; diff --git a/builtin/commit.c b/builtin/commit.c index 66427ba82d..8db4e9df0c 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -4,7 +4,7 @@ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com> * Based on git-commit.sh by Junio C Hamano and Linus Torvalds */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -26,6 +26,7 @@ #include "path.h" #include "preload-index.h" #include "read-cache.h" +#include "repository.h" #include "string-list.h" #include "rerere.h" #include "unpack-trees.h" @@ -395,7 +396,7 @@ static const char *prepare_index(const char **argv, const char *prefix, old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT)); setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1); - if (interactive_add(argv, prefix, patch_interactive) != 0) + if (interactive_add(the_repository, argv, prefix, patch_interactive) != 0) die(_("interactive add failed")); the_repository->index_file = old_repo_index_file; @@ -407,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix, discard_index(the_repository->index); read_index_from(the_repository->index, get_lock_file_path(&index_lock), - get_git_dir()); + repo_get_git_dir(the_repository)); if (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) { if (reopen_lock_file(&index_lock) < 0) die(_("unable to write index file")); @@ -472,7 +473,7 @@ static const char *prepare_index(const char **argv, const char *prefix, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write new index file")); commit_style = COMMIT_AS_IS; - ret = get_index_file(); + ret = repo_get_index_file(the_repository); goto out; } @@ -534,7 +535,7 @@ static const char *prepare_index(const char **argv, const char *prefix, discard_index(the_repository->index); ret = get_lock_file_path(&false_lock); - read_index_from(the_repository->index, ret, get_git_dir()); + read_index_from(the_repository->index, ret, repo_get_git_dir(the_repository)); out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); @@ -684,7 +685,9 @@ static void adjust_comment_line_char(const struct strbuf *sb) const char *p; if (!memchr(sb->buf, candidates[0], sb->len)) { - comment_line_str = xstrfmt("%c", candidates[0]); + free(comment_line_str_to_free); + comment_line_str = comment_line_str_to_free = + xstrfmt("%c", candidates[0]); return; } @@ -705,7 +708,8 @@ static void adjust_comment_line_char(const struct strbuf *sb) if (!*p) die(_("unable to select a comment character that is not used\n" "in the current commit message")); - comment_line_str = xstrfmt("%c", *p); + free(comment_line_str_to_free); + comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p); } static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, @@ -1069,7 +1073,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, */ discard_index(the_repository->index); } - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository)); if (cache_tree_update(the_repository->index, 0)) { error(_("Error building trees")); @@ -1499,7 +1503,10 @@ static int git_status_config(const char *k, const char *v, return git_diff_ui_config(k, v, ctx, NULL); } -int cmd_status(int argc, const char **argv, const char *prefix) +int cmd_status(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { static int no_renames = -1; static const char *rename_score_arg = (const char *)-1; @@ -1638,7 +1645,10 @@ static int git_commit_config(const char *k, const char *v, return git_status_config(k, v, ctx, s); } -int cmd_commit(int argc, const char **argv, const char *prefix) +int cmd_commit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct wt_status s; static struct option builtin_commit_options[] = { @@ -1870,8 +1880,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), NULL, "post-commit", - NULL); + run_commit_hook(use_editor, repo_get_index_file(the_repository), + NULL, "post-commit", NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } diff --git a/builtin/config.c b/builtin/config.c index 97e4d5f57c..cba7022108 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" #include "color.h" #include "editor.h" #include "environment.h" -#include "repository.h" #include "gettext.h" #include "ident.h" #include "parse-options.h" @@ -19,7 +19,7 @@ static const char *const builtin_config_usage[] = { N_("git config list [<file-option>] [<display-option>] [--includes]"), N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"), N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), N_("git config rename-section [<file-option>] <old-name> <new-name>"), N_("git config remove-section [<file-option>] <name>"), N_("git config edit [<file-option>]"), @@ -43,7 +43,7 @@ static const char *const builtin_config_set_usage[] = { }; static const char *const builtin_config_unset_usage[] = { - N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"), + N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name>"), NULL }; @@ -807,8 +807,8 @@ static void location_options_init(struct config_location_options *opts, else opts->options.respect_includes = opts->respect_includes_opt; if (startup_info->have_repository) { - opts->options.commondir = get_git_common_dir(); - opts->options.git_dir = get_git_dir(); + opts->options.commondir = repo_get_common_dir(the_repository); + opts->options.git_dir = repo_get_git_dir(the_repository); } } @@ -1026,8 +1026,8 @@ static int cmd_config_rename_section(int argc, const char **argv, const char *pr location_options_init(&location_opts, prefix); check_write(&location_opts.source); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], argv[1]); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], argv[1]); if (ret < 0) goto out; else if (!ret) @@ -1055,8 +1055,8 @@ static int cmd_config_remove_section(int argc, const char **argv, const char *pr location_options_init(&location_opts, prefix); check_write(&location_opts.source); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], NULL); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], NULL); if (ret < 0) goto out; else if (!ret) @@ -1353,8 +1353,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix) else if (actions == ACTION_RENAME_SECTION) { check_write(&location_opts.source); check_argc(argc, 2, 2); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], argv[1]); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], argv[1]); if (ret < 0) goto out; else if (!ret) @@ -1365,8 +1365,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix) else if (actions == ACTION_REMOVE_SECTION) { check_write(&location_opts.source); check_argc(argc, 1, 1); - ret = git_config_rename_section_in_file(location_opts.source.file, - argv[0], NULL); + ret = repo_config_rename_section_in_file(the_repository, location_opts.source.file, + argv[0], NULL); if (ret < 0) goto out; else if (!ret) @@ -1392,7 +1392,10 @@ out: return ret; } -int cmd_config(int argc, const char **argv, const char *prefix) +int cmd_config(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *subcommand = NULL; struct option subcommand_opts[] = { diff --git a/builtin/count-objects.c b/builtin/count-objects.c index 2d4bb5e8d0..04d80887e0 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -3,14 +3,12 @@ * * Copyright (c) 2006 Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" -#include "environment.h" #include "gettext.h" #include "path.h" -#include "repository.h" #include "parse-options.h" #include "quote.h" #include "packfile.h" @@ -95,7 +93,10 @@ static char const * const count_objects_usage[] = { NULL }; -int cmd_count_objects(int argc, const char **argv, const char *prefix) +int cmd_count_objects(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int human_readable = 0; struct option opts[] = { @@ -113,10 +114,10 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix) usage_with_options(count_objects_usage, opts); if (verbose) { report_garbage = real_report_garbage; - report_linked_checkout_garbage(); + report_linked_checkout_garbage(the_repository); } - for_each_loose_file_in_objdir(get_object_directory(), + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), count_loose, count_cruft, NULL, NULL); if (verbose) { diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index 4952b22547..bc22f5c6d2 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" @@ -287,7 +288,10 @@ static void init_socket_directory(const char *path) free(path_copy); } -int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) +int cmd_credential_cache_daemon(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct tempfile *socket_file; const char *socket_path; @@ -330,7 +334,10 @@ int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) #else -int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) +int cmd_credential_cache_daemon(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { const char * const usage[] = { "git credential-cache--daemon [--debug] <socket-path>", diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c index 3db8df70a9..5de8b9123b 100644 --- a/builtin/credential-cache.c +++ b/builtin/credential-cache.c @@ -88,6 +88,8 @@ static void spawn_daemon(const char *socket) die_errno("unable to read result code from cache daemon"); if (r != 3 || memcmp(buf, "ok\n", 3)) die("cache daemon did not start: %.*s", r, buf); + + child_process_clear(&daemon); close(daemon.out); } @@ -135,9 +137,13 @@ static void announce_capabilities(void) credential_announce_capabilities(&c, stdout); } -int cmd_credential_cache(int argc, const char **argv, const char *prefix) +int cmd_credential_cache(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { - char *socket_path = NULL; + const char *socket_path_arg = NULL; + char *socket_path; int timeout = 900; const char *op; const char * const usage[] = { @@ -147,7 +153,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_INTEGER(0, "timeout", &timeout, "number of seconds to cache credentials"), - OPT_STRING(0, "socket", &socket_path, "path", + OPT_STRING(0, "socket", &socket_path_arg, "path", "path of cache-daemon socket"), OPT_END() }; @@ -160,6 +166,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix) if (!have_unix_sockets()) die(_("credential-cache unavailable; no unix socket support")); + socket_path = xstrdup_or_null(socket_path_arg); if (!socket_path) socket_path = get_socket_path(); if (!socket_path) @@ -176,6 +183,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix) else ; /* ignore unknown operation */ + free(socket_path); return 0; } diff --git a/builtin/credential-store.c b/builtin/credential-store.c index 494c809332..e669e99dbf 100644 --- a/builtin/credential-store.c +++ b/builtin/credential-store.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -170,7 +171,10 @@ static void lookup_credential(const struct string_list *fns, struct credential * return; /* Found credential */ } -int cmd_credential_store(int argc, const char **argv, const char *prefix) +int cmd_credential_store(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char * const usage[] = { "git credential-store [<options>] <action>", @@ -218,5 +222,6 @@ int cmd_credential_store(int argc, const char **argv, const char *prefix) ; /* Ignore unknown operation. */ string_list_clear(&fns, 0); + credential_clear(&c); return 0; } diff --git a/builtin/credential.c b/builtin/credential.c index b72e76dd9a..14c8c6608b 100644 --- a/builtin/credential.c +++ b/builtin/credential.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "credential.h" #include "builtin.h" @@ -6,7 +8,10 @@ static const char usage_msg[] = "git credential (fill|approve|reject)"; -int cmd_credential(int argc, const char **argv, const char *prefix UNUSED) +int cmd_credential(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { const char *op; struct credential c = CREDENTIAL_INIT; diff --git a/builtin/describe.c b/builtin/describe.c index cf8edc4222..7330a77b38 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -149,7 +150,7 @@ static void add_to_known_names(const char *path, } } -static int get_name(const char *path, const struct object_id *oid, +static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { int is_tag = 0; @@ -529,6 +530,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst) traverse_commit_list(&revs, process_commit, process_object, &pcd); reset_revision_walk(); release_revisions(&revs); + strvec_clear(&args); } static void describe(const char *arg, int last_one) @@ -570,7 +572,10 @@ static int option_parse_exact_match(const struct option *opt, const char *arg, return 0; } -int cmd_describe(int argc, const char **argv, const char *prefix) +int cmd_describe(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED ) { int contains = 0; struct option options[] = { @@ -619,6 +624,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix) if (contains) { struct string_list_item *item; struct strvec args; + const char **argv_copy; + int ret; strvec_init(&args); strvec_pushl(&args, "name-rev", @@ -637,7 +644,21 @@ int cmd_describe(int argc, const char **argv, const char *prefix) strvec_pushv(&args, argv); else strvec_push(&args, "HEAD"); - return cmd_name_rev(args.nr, args.v, prefix); + + /* + * `cmd_name_rev()` modifies the array, so we'd leak its + * contained strings if we didn't do a copy here. + */ + ALLOC_ARRAY(argv_copy, args.nr + 1); + for (size_t i = 0; i < args.nr; i++) + argv_copy[i] = args.v[i]; + argv_copy[args.nr] = NULL; + + ret = cmd_name_rev(args.nr, argv_copy, prefix, the_repository); + + strvec_clear(&args); + free(argv_copy); + return ret; } hashmap_init(&names, commit_name_neq, NULL, 0); @@ -679,7 +700,6 @@ int cmd_describe(int argc, const char **argv, const char *prefix) } else if (dirty) { struct lock_file index_lock = LOCK_INIT; struct rev_info revs; - struct strvec args = STRVEC_INIT; int fd; setup_work_tree(); @@ -694,12 +714,13 @@ int cmd_describe(int argc, const char **argv, const char *prefix) repo_update_index_if_able(the_repository, &index_lock); repo_init_revisions(the_repository, &revs, prefix); - strvec_pushv(&args, diff_index_args); - if (setup_revisions(args.nr, args.v, &revs, NULL) != 1) + + if (setup_revisions(ARRAY_SIZE(diff_index_args) - 1, + diff_index_args, &revs, NULL) != 1) BUG("malformed internal diff-index command line"); run_diff_index(&revs, 0); - if (!diff_result_code(&revs.diffopt)) + if (!diff_result_code(&revs)) suffix = NULL; else suffix = dirty; diff --git a/builtin/diagnose.c b/builtin/diagnose.c index 4857a4395b..66a22d918e 100644 --- a/builtin/diagnose.c +++ b/builtin/diagnose.c @@ -11,7 +11,10 @@ static const char * const diagnose_usage[] = { NULL }; -int cmd_diagnose(int argc, const char **argv, const char *prefix) +int cmd_diagnose(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf zip_path = STRBUF_INIT; time_t now = time(NULL); diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 018011f29e..e0e0ccec23 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -3,13 +3,13 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" #include "preload-index.h" -#include "repository.h" #include "revision.h" static const char diff_files_usage[] = @@ -17,7 +17,10 @@ static const char diff_files_usage[] = "\n" COMMON_DIFF_OPTIONS_HELP; -int cmd_diff_files(int argc, const char **argv, const char *prefix) +int cmd_diff_files(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info rev; int result; @@ -82,7 +85,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) die_errno("repo_read_index_preload"); run_diff_files(&rev, options); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); release_revisions(&rev); return result; } diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 3e05260ac0..ad503624c0 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" #include "diff-merges.h" #include "commit.h" #include "preload-index.h" -#include "repository.h" #include "revision.h" #include "setup.h" @@ -14,7 +14,10 @@ static const char diff_cache_usage[] = "\n" COMMON_DIFF_OPTIONS_HELP; -int cmd_diff_index(int argc, const char **argv, const char *prefix) +int cmd_diff_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info rev; unsigned int option = 0; @@ -25,6 +28,10 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) usage(diff_cache_usage); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ + + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + repo_init_revisions(the_repository, &rev, prefix); rev.abbrev = 0; prefix = precompose_argv_prefix(argc, argv, prefix); @@ -71,7 +78,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) return -1; } run_diff_index(&rev, option); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); release_revisions(&rev); return result; } diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index b8df1d4b79..4b6656bb9f 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" @@ -6,7 +7,6 @@ #include "hex.h" #include "log-tree.h" #include "read-cache-ll.h" -#include "repository.h" #include "revision.h" #include "tmp-objdir.h" #include "tree.h" @@ -108,7 +108,10 @@ static void diff_tree_tweak_rev(struct rev_info *rev) } } -int cmd_diff_tree(int argc, const char **argv, const char *prefix) +int cmd_diff_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { char line[1000]; struct object *tree1, *tree2; @@ -167,13 +170,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) opt->diffopt.rotate_to_strict = 1; - if (opt->remerge_diff) { - opt->remerge_objdir = tmp_objdir_create("remerge-diff"); - if (!opt->remerge_objdir) - die(_("unable to create temporary object directory")); - tmp_objdir_replace_primary_odb(opt->remerge_objdir, 1); - } - /* * NOTE! We expect "a..b" to expand to "^a b" but it is * perfectly valid for revision range parser to yield "b ^a", @@ -238,10 +234,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) diff_free(&opt->diffopt); } - if (opt->remerge_diff) { - tmp_objdir_destroy(opt->remerge_objdir); - opt->remerge_objdir = NULL; - } - - return diff_result_code(&opt->diffopt); + return diff_result_code(opt); } diff --git a/builtin/diff.c b/builtin/diff.c index 9b6cdabe15..dca52d4221 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -3,7 +3,7 @@ * * Copyright (c) 2006 Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "ewah/ewok.h" @@ -388,7 +388,15 @@ static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym) sym->skip = map; } -int cmd_diff(int argc, const char **argv, const char *prefix) +static void symdiff_release(struct symdiff *sdiff) +{ + bitmap_free(sdiff->skip); +} + +int cmd_diff(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct rev_info rev; @@ -614,11 +622,12 @@ int cmd_diff(int argc, const char **argv, const char *prefix) builtin_diff_combined(&rev, argc, argv, ent.objects, ent.nr, first_non_parent); - result = diff_result_code(&rev.diffopt); + result = diff_result_code(&rev); if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); release_revisions(&rev); object_array_clear(&ent); + symdiff_release(&sdiff); UNLEAK(blob); return result; } diff --git a/builtin/difftool.c b/builtin/difftool.c index dcc68e190c..5772e82106 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -11,8 +11,9 @@ * * Copyright (C) 2016 Johannes Schindelin */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "config.h" #include "copy.h" @@ -22,6 +23,7 @@ #include "hex.h" #include "parse-options.h" #include "read-cache-ll.h" +#include "repository.h" #include "sparse-index.h" #include "strvec.h" #include "strbuf.h" @@ -214,7 +216,7 @@ static void changed_files(struct hashmap *result, const char *index_path, struct child_process update_index = CHILD_PROCESS_INIT; struct child_process diff_files = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; - const char *git_dir = absolute_path(get_git_dir()); + const char *git_dir = absolute_path(repo_get_git_dir(the_repository)); FILE *fp; strvec_pushl(&update_index.args, @@ -377,7 +379,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct hashmap wt_modified, tmp_modified; int indices_loaded = 0; - workdir = get_git_work_tree(); + workdir = repo_get_work_tree(the_repository); /* Setup temp directories */ tmp = getenv("TMPDIR"); @@ -660,6 +662,12 @@ finish: if (fp) fclose(fp); + hashmap_clear_and_free(&working_tree_dups, struct working_tree_entry, entry); + hashmap_clear_and_free(&wt_modified, struct path_entry, entry); + hashmap_clear_and_free(&tmp_modified, struct path_entry, entry); + hashmap_clear_and_free(&submodules, struct pair_entry, entry); + hashmap_clear_and_free(&symlinks2, struct pair_entry, entry); + release_index(&wtindex); free(lbase_dir); free(rbase_dir); strbuf_release(&info); @@ -690,7 +698,10 @@ static int run_file_diff(int prompt, const char *prefix, return run_command(child); } -int cmd_difftool(int argc, const char **argv, const char *prefix) +int cmd_difftool(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0, tool_help = 0, no_index = 0; @@ -737,8 +748,8 @@ int cmd_difftool(int argc, const char **argv, const char *prefix) if (!no_index){ setup_work_tree(); - setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1); - setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1); + setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1); + setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1); } else if (dir_diff) die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index"); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 4b6e8c6832..e17f262e8e 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -3,6 +3,7 @@ * * Copyright (C) 2007 Johannes E. Schindelin */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -42,8 +43,8 @@ static int full_tree; static int reference_excluded_commits; static int show_original_ids; static int mark_tags; -static struct string_list extra_refs = STRING_LIST_INIT_NODUP; -static struct string_list tag_refs = STRING_LIST_INIT_NODUP; +static struct string_list extra_refs = STRING_LIST_INIT_DUP; +static struct string_list tag_refs = STRING_LIST_INIT_DUP; static struct refspec refspecs = REFSPEC_INIT_FETCH; static int anonymize; static struct hashmap anonymized_seeds; @@ -901,7 +902,7 @@ static void handle_tag(const char *name, struct tag *tag) free(buf); } -static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name) +static struct commit *get_commit(struct rev_cmdline_entry *e, const char *full_name) { switch (e->item->type) { case OBJ_COMMIT: @@ -932,14 +933,16 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) struct rev_cmdline_entry *e = info->rev + i; struct object_id oid; struct commit *commit; - char *full_name; + char *full_name = NULL; if (e->flags & UNINTERESTING) continue; if (repo_dwim_ref(the_repository, e->name, strlen(e->name), - &oid, &full_name, 0) != 1) + &oid, &full_name, 0) != 1) { + free(full_name); continue; + } if (refspecs.nr) { char *private; @@ -955,6 +958,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) warning("%s: Unexpected object of type %s, skipping.", e->name, type_name(e->item->type)); + free(full_name); continue; } @@ -963,10 +967,12 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) break; case OBJ_BLOB: export_blob(&commit->object.oid); + free(full_name); continue; default: /* OBJ_TAG (nested tags) is already handled */ warning("Tag points to object of unexpected type %s, skipping.", type_name(commit->object.type)); + free(full_name); continue; } @@ -979,6 +985,8 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) if (!*revision_sources_at(&revision_sources, commit)) *revision_sources_at(&revision_sources, commit) = full_name; + else + free(full_name); } string_list_sort(&extra_refs); @@ -1173,7 +1181,10 @@ static int parse_opt_anonymize_map(const struct option *opt, return 0; } -int cmd_fast_export(int argc, const char **argv, const char *prefix) +int cmd_fast_export(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct commit *commit; @@ -1278,9 +1289,11 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) revs.diffopt.format_callback = show_filemodify; revs.diffopt.format_callback_data = &paths_of_changed_objects; revs.diffopt.flags.recursive = 1; + revs.diffopt.no_free = 1; while ((commit = get_revision(&revs))) handle_commit(commit, &revs, &paths_of_changed_objects); + revs.diffopt.no_free = 0; handle_tags_and_duplicates(&extra_refs); handle_tags_and_duplicates(&tag_refs); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index d21c4053a7..1e7ab67f6e 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "lockfile.h" #include "object.h" @@ -206,8 +206,8 @@ static unsigned int object_entry_alloc = 5000; static struct object_entry_pool *blocks; static struct hashmap object_table; static struct mark_set *marks; -static const char *export_marks_file; -static const char *import_marks_file; +static char *export_marks_file; +static char *import_marks_file; static int import_marks_file_from_stream; static int import_marks_file_ignore_missing; static int import_marks_file_done; @@ -3274,6 +3274,7 @@ static void option_import_marks(const char *marks, read_marks(); } + free(import_marks_file); import_marks_file = make_fast_import_path(marks); import_marks_file_from_stream = from_stream; import_marks_file_ignore_missing = ignore_missing; @@ -3316,6 +3317,7 @@ static void option_active_branches(const char *branches) static void option_export_marks(const char *marks) { + free(export_marks_file); export_marks_file = make_fast_import_path(marks); } @@ -3357,6 +3359,8 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list) free(f); string_list_insert(list, s)->util = ms; + + free(s); } static int parse_one_option(const char *option) @@ -3481,8 +3485,8 @@ static void git_pack_config(void) if (!git_config_get_int("pack.indexversion", &indexversion_value)) { pack_idx_opts.version = indexversion_value; if (pack_idx_opts.version > 2) - git_die_config("pack.indexversion", - "bad pack.indexVersion=%"PRIu32, pack_idx_opts.version); + git_die_config(the_repository, "pack.indexversion", + "bad pack.indexVersion=%"PRIu32, pack_idx_opts.version); } if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value)) max_packsize = packsizelimit_value; @@ -3533,7 +3537,10 @@ static void parse_argv(void) build_mark_map(&sub_marks_from, &sub_marks_to); } -int cmd_fast_import(int argc, const char **argv, const char *prefix) +int cmd_fast_import(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { unsigned int i; diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index af329e8d5c..62e8c3aa6b 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -43,12 +44,16 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, (*sought)[*nr - 1] = ref; } -int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) +int cmd_fetch_pack(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i, ret; - struct ref *ref = NULL; + struct ref *fetched_refs = NULL, *remote_refs = NULL; const char *dest = NULL; struct ref **sought = NULL; + struct ref **sought_to_free = NULL; int nr_sought = 0, alloc_sought = 0; int fd[2]; struct string_list pack_lockfiles = STRING_LIST_INIT_DUP; @@ -228,19 +233,27 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) version = discover_version(&reader); switch (version) { case protocol_v2: - get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL, + get_remote_refs(fd[1], &reader, &remote_refs, 0, NULL, NULL, args.stateless_rpc); break; case protocol_v1: case protocol_v0: - get_remote_heads(&reader, &ref, 0, NULL, &shallow); + get_remote_heads(&reader, &remote_refs, 0, NULL, &shallow); break; case protocol_unknown_version: BUG("unknown protocol version"); } - ref = fetch_pack(&args, fd, ref, sought, nr_sought, + /* + * Create a shallow copy of `sought` so that we can free all of its entries. + * This is because `fetch_pack()` will modify the array to evict some + * entries, but won't free those. + */ + DUP_ARRAY(sought_to_free, sought, nr_sought); + + fetched_refs = fetch_pack(&args, fd, remote_refs, sought, nr_sought, &shallow, pack_lockfiles_ptr, version); + if (pack_lockfiles.nr) { int i; @@ -260,7 +273,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) if (finish_connect(conn)) return 1; - ret = !ref; + ret = !fetched_refs; /* * If the heads to pull were given, we should have consumed @@ -270,11 +283,18 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED) */ ret |= report_unmatched_refs(sought, nr_sought); - while (ref) { + for (struct ref *ref = fetched_refs; ref; ref = ref->next) printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); - ref = ref->next; - } + for (size_t i = 0; i < nr_sought; i++) + free_one_ref(sought_to_free[i]); + free(sought_to_free); + free(sought); + free_refs(fetched_refs); + free_refs(remote_refs); + list_objects_filter_release(&args.filter_options); + oid_array_clear(&shallow); + string_list_clear(&pack_lockfiles, 0); return ret; } diff --git a/builtin/fetch.c b/builtin/fetch.c index 693f02b958..d9027e4dc9 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1,13 +1,13 @@ /* * "git fetch" */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" #include "gettext.h" #include "environment.h" #include "hex.h" -#include "repository.h" #include "refs.h" #include "refspec.h" #include "object-name.h" @@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map, return ent; } -static int add_one_refname(const char *refname, +static int add_one_refname(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cbdata) { @@ -456,6 +456,7 @@ static void filter_prefetch_refspec(struct refspec *rs) free(rs->items[i].src); free(rs->items[i].dst); + free(rs->raw[i]); for (j = i + 1; j < rs->nr; j++) { rs->items[j - 1] = rs->items[j]; @@ -1161,7 +1162,7 @@ static int store_updated_refs(struct display_state *display_state, opt.exclude_hidden_refs_section = "fetch"; rm = ref_map; if (check_connected(iterate_ref_map, &rm, &opt)) { - rc = error(_("%s did not send all necessary objects\n"), + rc = error(_("%s did not send all necessary objects"), display_state->url); goto abort; } @@ -1458,12 +1459,13 @@ static void set_option(struct transport *transport, const char *name, const char die(_("option \"%s\" value \"%s\" is not valid for %s"), name, value, transport->url); if (r > 0) - warning(_("option \"%s\" is ignored for %s\n"), + warning(_("option \"%s\" is ignored for %s"), name, transport->url); } static int add_oid(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { @@ -1730,11 +1732,8 @@ static int do_fetch(struct transport *transport, goto cleanup; retcode = ref_transaction_commit(transaction, &err); - if (retcode) { - ref_transaction_free(transaction); - transaction = NULL; + if (retcode) goto cleanup; - } } commit_fetch_head(&fetch_head); @@ -1802,8 +1801,11 @@ cleanup: if (transaction && ref_transaction_abort(transaction, &err) && err.len) error("%s", err.buf); + transaction = NULL; } + if (transaction) + ref_transaction_free(transaction); display_state_release(&display_state); close_fetch_head(&fetch_head); strbuf_release(&err); @@ -1979,6 +1981,8 @@ static int fetch_multiple(struct string_list *list, int max_children, strvec_pushl(&argv, "-c", "fetch.bundleURI=", "fetch", "--append", "--no-auto-gc", "--no-write-commit-graph", NULL); + for (i = 0; i < server_options.nr; i++) + strvec_pushf(&argv, "--server-option=%s", server_options.items[i].string); add_options_to_argv(&argv, config); if (max_children != 1 && list->nr != 1) { @@ -2137,7 +2141,10 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, return exit_code; } -int cmd_fetch(int argc, const char **argv, const char *prefix) +int cmd_fetch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct fetch_config config = { .display_format = DISPLAY_FORMAT_FULL, @@ -2407,6 +2414,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) struct oidset_iter iter; const struct object_id *oid; + trace2_region_enter("fetch", "negotiate-only", the_repository); if (!remote) die(_("must supply remote when using --negotiate-only")); gtransport = prepare_transport(remote, 1); @@ -2415,6 +2423,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } else { warning(_("protocol does not support --negotiate-only, exiting")); result = 1; + trace2_region_leave("fetch", "negotiate-only", the_repository); goto cleanup; } if (server_options.nr) @@ -2425,11 +2434,17 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) while ((oid = oidset_iter_next(&iter))) printf("%s\n", oid_to_hex(oid)); oidset_clear(&acked_commits); + trace2_region_leave("fetch", "negotiate-only", the_repository); } else if (remote) { - if (filter_options.choice || repo_has_promisor_remote(the_repository)) + if (filter_options.choice || repo_has_promisor_remote(the_repository)) { + trace2_region_enter("fetch", "setup-partial", the_repository); fetch_one_setup_partial(remote); + trace2_region_leave("fetch", "setup-partial", the_repository); + } + trace2_region_enter("fetch", "fetch-one", the_repository); result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs, &config); + trace2_region_leave("fetch", "fetch-one", the_repository); } else { int max_children = max_jobs; @@ -2449,7 +2464,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) max_children = config.parallel; /* TODO should this also die if we have a previous partial-clone? */ + trace2_region_enter("fetch", "fetch-multiple", the_repository); result = fetch_multiple(&list, max_children, &config); + trace2_region_leave("fetch", "fetch-multiple", the_repository); } /* @@ -2471,6 +2488,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) max_children = config.parallel; add_options_to_argv(&options, &config); + trace2_region_enter_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix); result = fetch_submodules(the_repository, &options, submodule_prefix, @@ -2478,6 +2496,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) recurse_submodules_default, verbosity < 0, max_children); + trace2_region_leave_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix); strvec_clear(&options); } @@ -2501,9 +2520,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (progress) commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS; + trace2_region_enter("fetch", "write-commit-graph", the_repository); write_commit_graph_reachable(the_repository->objects->odb, commit_graph_flags, NULL); + trace2_region_leave("fetch", "write-commit-graph", the_repository); } if (enable_auto_gc) { diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 957786d1b3..189cd1096a 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "fmt-merge-msg.h" @@ -9,7 +10,10 @@ static const char * const fmt_merge_msg_usage[] = { NULL }; -int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) +int cmd_fmt_merge_msg(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { char *inpath = NULL; const char *message = NULL; @@ -67,6 +71,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) return ret; write_in_full(STDOUT_FILENO, output.buf, output.len); + strbuf_release(&input); + strbuf_release(&output); free(inpath); return 0; } diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 5517a4a1c0..715745a262 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -16,7 +17,10 @@ static char const * const for_each_ref_usage[] = { NULL }; -int cmd_for_each_ref(int argc, const char **argv, const char *prefix) +int cmd_for_each_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -104,6 +108,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) filter_and_format_refs(&filter, flags, sorting, &format); ref_filter_clear(&filter); + ref_format_clear(&format); ref_sorting_release(sorting); strvec_clear(&vec); return 0; diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c index c4fa41fda9..fae7f91cf1 100644 --- a/builtin/for-each-repo.c +++ b/builtin/for-each-repo.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" #include "path.h" -#include "repository.h" #include "run-command.h" #include "string-list.h" @@ -29,7 +29,10 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv) return run_command(&child); } -int cmd_for_each_repo(int argc, const char **argv, const char *prefix) +int cmd_for_each_repo(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static const char *config_key = NULL; int keep_going = 0; diff --git a/builtin/fsck.c b/builtin/fsck.c index d13a226c2e..7f4e2f0414 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "commit.h" #include "tree.h" @@ -89,13 +89,16 @@ static int objerror(struct object *obj, const char *err) return -1; } -static int fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid, - enum object_type object_type, - enum fsck_msg_type msg_type, - enum fsck_msg_id msg_id UNUSED, - const char *message) +static int fsck_objects_error_func(struct fsck_options *o UNUSED, + void *fsck_report, + enum fsck_msg_type msg_type, + enum fsck_msg_id msg_id UNUSED, + const char *message) { + struct fsck_object_report *report = fsck_report; + const struct object_id *oid = report->oid; + enum object_type object_type = report->object_type; + switch (msg_type) { case FSCK_WARN: /* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */ @@ -521,7 +524,7 @@ static int fsck_handle_reflog(const char *logname, void *cb_data) return 0; } -static int fsck_handle_ref(const char *refname, const struct object_id *oid, +static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object *obj; @@ -576,7 +579,7 @@ static void get_default_heads(void) strbuf_worktree_ref(wt, &ref, "HEAD"); fsck_head_link(ref.buf, &head_points_at, &head_oid); if (head_points_at && !is_null_oid(&head_oid)) - fsck_handle_ref(ref.buf, &head_oid, 0, NULL); + fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL); strbuf_release(&ref); if (include_reflogs) @@ -922,7 +925,10 @@ static struct option fsck_opts[] = { OPT_END(), }; -int cmd_fsck(int argc, const char **argv, const char *prefix) +int cmd_fsck(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; struct object_directory *odb; @@ -938,7 +944,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) fsck_walk_options.walk = mark_object; fsck_obj_options.walk = mark_used; - fsck_obj_options.error_func = fsck_error_func; + fsck_obj_options.error_func = fsck_objects_error_func; if (check_strict) fsck_obj_options.strict = 1; @@ -1050,7 +1056,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) * and may get overwritten by other calls * while we're examining the index. */ - path = xstrdup(worktree_git_path(wt, "index")); + path = xstrdup(worktree_git_path(the_repository, wt, "index")); read_index_from(&istate, path, get_worktree_git_dir(wt)); fsck_index(&istate, path, wt->is_current); discard_index(&istate); diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 97421d73a2..f3f6bd330b 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" #include "dir.h" -#include "environment.h" #include "gettext.h" #include "parse-options.h" #include "fsmonitor-ll.h" @@ -11,7 +11,7 @@ #include "compat/fsmonitor/fsm-health.h" #include "compat/fsmonitor/fsm-listen.h" #include "fsmonitor--daemon.h" -#include "repository.h" + #include "simple-ipc.h" #include "khash.h" #include "run-command.h" @@ -1291,7 +1291,8 @@ static int fsmonitor_run_daemon(void) /* Prepare to (recursively) watch the <worktree-root> directory. */ strbuf_init(&state.path_worktree_watch, 0); - strbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree())); + strbuf_addstr(&state.path_worktree_watch, + absolute_path(repo_get_work_tree(the_repository))); state.nr_paths_watching = 1; strbuf_init(&state.alias.alias, 0); @@ -1311,7 +1312,9 @@ static int fsmonitor_run_daemon(void) strbuf_addstr(&state.path_gitdir_watch, "/.git"); if (!is_directory(state.path_gitdir_watch.buf)) { strbuf_reset(&state.path_gitdir_watch); - strbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir())); + strbuf_addstr(&state.path_gitdir_watch, + absolute_path(repo_get_git_dir(the_repository))); + strbuf_strip_suffix(&state.path_gitdir_watch, "/."); state.nr_paths_watching = 2; } @@ -1521,7 +1524,10 @@ static int try_to_start_background_daemon(void) } } -int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) +int cmd_fsmonitor__daemon(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *subcmd; enum fsmonitor_reason reason; @@ -1584,7 +1590,7 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) } #else -int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED) +int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { struct option options[] = { OPT_END() diff --git a/builtin/gc.c b/builtin/gc.c index 72bac2554f..6a7a2da006 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -9,13 +9,12 @@ * * Copyright (c) 2006 Shawn O. Pearce */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "date.h" #include "environment.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "tempfile.h" #include "lockfile.h" @@ -49,23 +48,7 @@ static const char * const builtin_gc_usage[] = { NULL }; -static int pack_refs = 1; -static int prune_reflogs = 1; -static int cruft_packs = 1; -static unsigned long max_cruft_size; -static int aggressive_depth = 50; -static int aggressive_window = 250; -static int gc_auto_threshold = 6700; -static int gc_auto_pack_limit = 50; -static int detach_auto = 1; static timestamp_t gc_log_expire_time; -static const char *gc_log_expire = "1.day.ago"; -static const char *prune_expire = "2.weeks.ago"; -static const char *prune_worktrees_expire = "3.months.ago"; -static char *repack_filter; -static char *repack_filter_to; -static unsigned long big_pack_threshold; -static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE; static struct strvec reflog = STRVEC_INIT; static struct strvec repack = STRVEC_INIT; @@ -125,13 +108,6 @@ static void process_log_file_at_exit(void) process_log_file(); } -static void process_log_file_on_signal(int signo) -{ - process_log_file(); - sigchain_pop(signo); - raise(signo); -} - static int gc_config_is_timestamp_never(const char *var) { const char *value; @@ -145,37 +121,100 @@ static int gc_config_is_timestamp_never(const char *var) return 0; } -static void gc_config(void) +struct gc_config { + int pack_refs; + int prune_reflogs; + int cruft_packs; + unsigned long max_cruft_size; + int aggressive_depth; + int aggressive_window; + int gc_auto_threshold; + int gc_auto_pack_limit; + int detach_auto; + char *gc_log_expire; + char *prune_expire; + char *prune_worktrees_expire; + char *repack_filter; + char *repack_filter_to; + unsigned long big_pack_threshold; + unsigned long max_delta_cache_size; +}; + +#define GC_CONFIG_INIT { \ + .pack_refs = 1, \ + .prune_reflogs = 1, \ + .cruft_packs = 1, \ + .aggressive_depth = 50, \ + .aggressive_window = 250, \ + .gc_auto_threshold = 6700, \ + .gc_auto_pack_limit = 50, \ + .detach_auto = 1, \ + .gc_log_expire = xstrdup("1.day.ago"), \ + .prune_expire = xstrdup("2.weeks.ago"), \ + .prune_worktrees_expire = xstrdup("3.months.ago"), \ + .max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE, \ +} + +static void gc_config_release(struct gc_config *cfg) +{ + free(cfg->gc_log_expire); + free(cfg->prune_expire); + free(cfg->prune_worktrees_expire); + free(cfg->repack_filter); + free(cfg->repack_filter_to); +} + +static void gc_config(struct gc_config *cfg) { const char *value; + char *owned = NULL; if (!git_config_get_value("gc.packrefs", &value)) { if (value && !strcmp(value, "notbare")) - pack_refs = -1; + cfg->pack_refs = -1; else - pack_refs = git_config_bool("gc.packrefs", value); + cfg->pack_refs = git_config_bool("gc.packrefs", value); } if (gc_config_is_timestamp_never("gc.reflogexpire") && gc_config_is_timestamp_never("gc.reflogexpireunreachable")) - prune_reflogs = 0; + cfg->prune_reflogs = 0; + + git_config_get_int("gc.aggressivewindow", &cfg->aggressive_window); + git_config_get_int("gc.aggressivedepth", &cfg->aggressive_depth); + git_config_get_int("gc.auto", &cfg->gc_auto_threshold); + git_config_get_int("gc.autopacklimit", &cfg->gc_auto_pack_limit); + git_config_get_bool("gc.autodetach", &cfg->detach_auto); + git_config_get_bool("gc.cruftpacks", &cfg->cruft_packs); + git_config_get_ulong("gc.maxcruftsize", &cfg->max_cruft_size); + + if (!repo_config_get_expiry(the_repository, "gc.pruneexpire", &owned)) { + free(cfg->prune_expire); + cfg->prune_expire = owned; + } + + if (!repo_config_get_expiry(the_repository, "gc.worktreepruneexpire", &owned)) { + free(cfg->prune_worktrees_expire); + cfg->prune_worktrees_expire = owned; + } - git_config_get_int("gc.aggressivewindow", &aggressive_window); - git_config_get_int("gc.aggressivedepth", &aggressive_depth); - git_config_get_int("gc.auto", &gc_auto_threshold); - git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); - git_config_get_bool("gc.autodetach", &detach_auto); - git_config_get_bool("gc.cruftpacks", &cruft_packs); - git_config_get_ulong("gc.maxcruftsize", &max_cruft_size); - git_config_get_expiry("gc.pruneexpire", &prune_expire); - git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire); - git_config_get_expiry("gc.logexpiry", &gc_log_expire); + if (!repo_config_get_expiry(the_repository, "gc.logexpiry", &owned)) { + free(cfg->gc_log_expire); + cfg->gc_log_expire = owned; + } + + git_config_get_ulong("gc.bigpackthreshold", &cfg->big_pack_threshold); + git_config_get_ulong("pack.deltacachesize", &cfg->max_delta_cache_size); - git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold); - git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size); + if (!git_config_get_string("gc.repackfilter", &owned)) { + free(cfg->repack_filter); + cfg->repack_filter = owned; + } - git_config_get_string("gc.repackfilter", &repack_filter); - git_config_get_string("gc.repackfilterto", &repack_filter_to); + if (!git_config_get_string("gc.repackfilterto", &owned)) { + free(cfg->repack_filter_to); + cfg->repack_filter_to = owned; + } git_config(git_default_config, NULL); } @@ -202,11 +241,15 @@ static enum schedule_priority parse_schedule(const char *value) struct maintenance_run_opts { int auto_flag; + int detach; int quiet; enum schedule_priority schedule; }; +#define MAINTENANCE_RUN_OPTS_INIT { \ + .detach = -1, \ +} -static int pack_refs_condition(void) +static int pack_refs_condition(UNUSED struct gc_config *cfg) { /* * The auto-repacking logic for refs is handled by the ref backends and @@ -216,7 +259,8 @@ static int pack_refs_condition(void) return 1; } -static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts) +static int maintenance_task_pack_refs(struct maintenance_run_opts *opts, + UNUSED struct gc_config *cfg) { struct child_process cmd = CHILD_PROCESS_INIT; @@ -228,7 +272,7 @@ static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts * return run_command(&cmd); } -static int too_many_loose_objects(void) +static int too_many_loose_objects(struct gc_config *cfg) { /* * Quickly check if a "gc" is needed, by estimating how @@ -247,7 +291,7 @@ static int too_many_loose_objects(void) if (!dir) return 0; - auto_threshold = DIV_ROUND_UP(gc_auto_threshold, 256); + auto_threshold = DIV_ROUND_UP(cfg->gc_auto_threshold, 256); while ((ent = readdir(dir)) != NULL) { if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose || ent->d_name[hexsz_loose] != '\0') @@ -283,12 +327,12 @@ static struct packed_git *find_base_packs(struct string_list *packs, return base; } -static int too_many_packs(void) +static int too_many_packs(struct gc_config *cfg) { struct packed_git *p; int cnt; - if (gc_auto_pack_limit <= 0) + if (cfg->gc_auto_pack_limit <= 0) return 0; for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) { @@ -302,7 +346,7 @@ static int too_many_packs(void) */ cnt++; } - return gc_auto_pack_limit < cnt; + return cfg->gc_auto_pack_limit < cnt; } static uint64_t total_ram(void) @@ -336,7 +380,8 @@ static uint64_t total_ram(void) return 0; } -static uint64_t estimate_repack_memory(struct packed_git *pack) +static uint64_t estimate_repack_memory(struct gc_config *cfg, + struct packed_git *pack) { unsigned long nr_objects = repo_approximate_object_count(the_repository); size_t os_cache, heap; @@ -373,7 +418,7 @@ static uint64_t estimate_repack_memory(struct packed_git *pack) */ heap += delta_base_cache_limit; /* and of course pack-objects has its own delta cache */ - heap += max_delta_cache_size; + heap += cfg->max_delta_cache_size; return os_cache + heap; } @@ -384,30 +429,31 @@ static int keep_one_pack(struct string_list_item *item, void *data UNUSED) return 0; } -static void add_repack_all_option(struct string_list *keep_pack) +static void add_repack_all_option(struct gc_config *cfg, + struct string_list *keep_pack) { - if (prune_expire && !strcmp(prune_expire, "now")) + if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")) strvec_push(&repack, "-a"); - else if (cruft_packs) { + else if (cfg->cruft_packs) { strvec_push(&repack, "--cruft"); - if (prune_expire) - strvec_pushf(&repack, "--cruft-expiration=%s", prune_expire); - if (max_cruft_size) + if (cfg->prune_expire) + strvec_pushf(&repack, "--cruft-expiration=%s", cfg->prune_expire); + if (cfg->max_cruft_size) strvec_pushf(&repack, "--max-cruft-size=%lu", - max_cruft_size); + cfg->max_cruft_size); } else { strvec_push(&repack, "-A"); - if (prune_expire) - strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire); + if (cfg->prune_expire) + strvec_pushf(&repack, "--unpack-unreachable=%s", cfg->prune_expire); } if (keep_pack) for_each_string_list(keep_pack, keep_one_pack, NULL); - if (repack_filter && *repack_filter) - strvec_pushf(&repack, "--filter=%s", repack_filter); - if (repack_filter_to && *repack_filter_to) - strvec_pushf(&repack, "--filter-to=%s", repack_filter_to); + if (cfg->repack_filter && *cfg->repack_filter) + strvec_pushf(&repack, "--filter=%s", cfg->repack_filter); + if (cfg->repack_filter_to && *cfg->repack_filter_to) + strvec_pushf(&repack, "--filter-to=%s", cfg->repack_filter_to); } static void add_repack_incremental_option(void) @@ -415,13 +461,13 @@ static void add_repack_incremental_option(void) strvec_push(&repack, "--no-write-bitmap-index"); } -static int need_to_gc(void) +static int need_to_gc(struct gc_config *cfg) { /* * Setting gc.auto to 0 or negative can disable the * automatic gc. */ - if (gc_auto_threshold <= 0) + if (cfg->gc_auto_threshold <= 0) return 0; /* @@ -430,13 +476,13 @@ static int need_to_gc(void) * we run "repack -A -d -l". Otherwise we tell the caller * there is no need. */ - if (too_many_packs()) { + if (too_many_packs(cfg)) { struct string_list keep_pack = STRING_LIST_INIT_NODUP; - if (big_pack_threshold) { - find_base_packs(&keep_pack, big_pack_threshold); - if (keep_pack.nr >= gc_auto_pack_limit) { - big_pack_threshold = 0; + if (cfg->big_pack_threshold) { + find_base_packs(&keep_pack, cfg->big_pack_threshold); + if (keep_pack.nr >= cfg->gc_auto_pack_limit) { + cfg->big_pack_threshold = 0; string_list_clear(&keep_pack, 0); find_base_packs(&keep_pack, 0); } @@ -445,7 +491,7 @@ static int need_to_gc(void) uint64_t mem_have, mem_want; mem_have = total_ram(); - mem_want = estimate_repack_memory(p); + mem_want = estimate_repack_memory(cfg, p); /* * Only allow 1/2 of memory for pack-objects, leave @@ -456,14 +502,14 @@ static int need_to_gc(void) string_list_clear(&keep_pack, 0); } - add_repack_all_option(&keep_pack); + add_repack_all_option(cfg, &keep_pack); string_list_clear(&keep_pack, 0); - } else if (too_many_loose_objects()) + } else if (too_many_loose_objects(cfg)) add_repack_incremental_option(); else return 0; - if (run_hooks("pre-auto-gc")) + if (run_hooks(the_repository, "pre-auto-gc")) return 0; return 1; } @@ -585,7 +631,8 @@ done: return ret; } -static void gc_before_repack(struct maintenance_run_opts *opts) +static void gc_before_repack(struct maintenance_run_opts *opts, + struct gc_config *cfg) { /* * We may be called twice, as both the pre- and @@ -596,10 +643,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts) if (done++) return; - if (pack_refs && maintenance_task_pack_refs(opts)) + if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg)) die(FAILED_RUN, "pack-refs"); - if (prune_reflogs) { + if (cfg->prune_reflogs) { struct child_process cmd = CHILD_PROCESS_INIT; cmd.git_cmd = 1; @@ -609,7 +656,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts) } } -int cmd_gc(int argc, const char **argv, const char *prefix) +int cmd_gc(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { int aggressive = 0; int quiet = 0; @@ -620,19 +670,25 @@ int cmd_gc(int argc, const char **argv, const char *prefix) int keep_largest_pack = -1; timestamp_t dummy; struct child_process rerere_cmd = CHILD_PROCESS_INIT; - struct maintenance_run_opts opts = {0}; + struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; + struct gc_config cfg = GC_CONFIG_INIT; + const char *prune_expire_sentinel = "sentinel"; + const char *prune_expire_arg = prune_expire_sentinel; + int ret; struct option builtin_gc_options[] = { OPT__QUIET(&quiet, N_("suppress progress reporting")), - { OPTION_STRING, 0, "prune", &prune_expire, N_("date"), + { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"), N_("prune unreferenced objects"), - PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire }, - OPT_BOOL(0, "cruft", &cruft_packs, N_("pack unreferenced objects separately")), - OPT_MAGNITUDE(0, "max-cruft-size", &max_cruft_size, + PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg }, + OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")), + OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size, N_("with --cruft, limit the size of new cruft packs")), OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")), OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"), PARSE_OPT_NOCOMPLETE), + OPT_BOOL(0, "detach", &opts.detach, + N_("perform garbage collection in the background")), OPT_BOOL_F(0, "force", &force, N_("force running gc even if there may be another gc running"), PARSE_OPT_NOCOMPLETE), @@ -650,84 +706,103 @@ int cmd_gc(int argc, const char **argv, const char *prefix) strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL); strvec_pushl(&rerere, "rerere", "gc", NULL); - /* default expiry time, overwritten in gc_config */ - gc_config(); - if (parse_expiry_date(gc_log_expire, &gc_log_expire_time)) - die(_("failed to parse gc.logExpiry value %s"), gc_log_expire); + gc_config(&cfg); + + if (parse_expiry_date(cfg.gc_log_expire, &gc_log_expire_time)) + die(_("failed to parse gc.logExpiry value %s"), cfg.gc_log_expire); - if (pack_refs < 0) - pack_refs = !is_bare_repository(); + if (cfg.pack_refs < 0) + cfg.pack_refs = !is_bare_repository(); argc = parse_options(argc, argv, prefix, builtin_gc_options, builtin_gc_usage, 0); if (argc > 0) usage_with_options(builtin_gc_usage, builtin_gc_options); - if (prune_expire && parse_expiry_date(prune_expire, &dummy)) - die(_("failed to parse prune expiry value %s"), prune_expire); + if (prune_expire_arg != prune_expire_sentinel) { + free(cfg.prune_expire); + cfg.prune_expire = xstrdup_or_null(prune_expire_arg); + } + if (cfg.prune_expire && parse_expiry_date(cfg.prune_expire, &dummy)) + die(_("failed to parse prune expiry value %s"), cfg.prune_expire); if (aggressive) { strvec_push(&repack, "-f"); - if (aggressive_depth > 0) - strvec_pushf(&repack, "--depth=%d", aggressive_depth); - if (aggressive_window > 0) - strvec_pushf(&repack, "--window=%d", aggressive_window); + if (cfg.aggressive_depth > 0) + strvec_pushf(&repack, "--depth=%d", cfg.aggressive_depth); + if (cfg.aggressive_window > 0) + strvec_pushf(&repack, "--window=%d", cfg.aggressive_window); } if (quiet) strvec_push(&repack, "-q"); if (opts.auto_flag) { + if (cfg.detach_auto && opts.detach < 0) + opts.detach = 1; + /* * Auto-gc should be least intrusive as possible. */ - if (!need_to_gc()) - return 0; + if (!need_to_gc(&cfg)) { + ret = 0; + goto out; + } + if (!quiet) { - if (detach_auto) + if (opts.detach > 0) fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n")); else fprintf(stderr, _("Auto packing the repository for optimum performance.\n")); fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n")); } - if (detach_auto) { - int ret = report_last_gc_error(); - - if (ret == 1) - /* Last gc --auto failed. Skip this one. */ - return 0; - else if (ret) - /* an I/O error occurred, already reported */ - return ret; - - if (lock_repo_for_gc(force, &pid)) - return 0; - gc_before_repack(&opts); /* dies on failure */ - delete_tempfile(&pidfile); - - /* - * failure to daemonize is ok, we'll continue - * in foreground - */ - daemonized = !daemonize(); - } } else { struct string_list keep_pack = STRING_LIST_INIT_NODUP; if (keep_largest_pack != -1) { if (keep_largest_pack) find_base_packs(&keep_pack, 0); - } else if (big_pack_threshold) { - find_base_packs(&keep_pack, big_pack_threshold); + } else if (cfg.big_pack_threshold) { + find_base_packs(&keep_pack, cfg.big_pack_threshold); } - add_repack_all_option(&keep_pack); + add_repack_all_option(&cfg, &keep_pack); string_list_clear(&keep_pack, 0); } + if (opts.detach > 0) { + ret = report_last_gc_error(); + if (ret == 1) { + /* Last gc --auto failed. Skip this one. */ + ret = 0; + goto out; + + } else if (ret) { + /* an I/O error occurred, already reported */ + goto out; + } + + if (lock_repo_for_gc(force, &pid)) { + ret = 0; + goto out; + } + + gc_before_repack(&opts, &cfg); /* dies on failure */ + delete_tempfile(&pidfile); + + /* + * failure to daemonize is ok, we'll continue + * in foreground + */ + daemonized = !daemonize(); + } + name = lock_repo_for_gc(force, &pid); if (name) { - if (opts.auto_flag) - return 0; /* be quiet on --auto */ + if (opts.auto_flag) { + ret = 0; + goto out; /* be quiet on --auto */ + } + die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"), name, (uintmax_t)pid); } @@ -737,11 +812,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) git_path("gc.log"), LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); - sigchain_push_common(process_log_file_on_signal); atexit(process_log_file_at_exit); } - gc_before_repack(&opts); + gc_before_repack(&opts, &cfg); if (!repository_format_precious_objects) { struct child_process repack_cmd = CHILD_PROCESS_INIT; @@ -752,11 +826,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (run_command(&repack_cmd)) die(FAILED_RUN, repack.v[0]); - if (prune_expire) { + if (cfg.prune_expire) { struct child_process prune_cmd = CHILD_PROCESS_INIT; /* run `git prune` even if using cruft packs */ - strvec_push(&prune, prune_expire); + strvec_push(&prune, cfg.prune_expire); if (quiet) strvec_push(&prune, "--no-progress"); if (repo_has_promisor_remote(the_repository)) @@ -769,10 +843,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) } } - if (prune_worktrees_expire) { + if (cfg.prune_worktrees_expire) { struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT; - strvec_push(&prune_worktrees, prune_worktrees_expire); + strvec_push(&prune_worktrees, cfg.prune_worktrees_expire); prune_worktrees_cmd.git_cmd = 1; strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v); if (run_command(&prune_worktrees_cmd)) @@ -796,13 +870,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix) !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0, NULL); - if (opts.auto_flag && too_many_loose_objects()) + if (opts.auto_flag && too_many_loose_objects(&cfg)) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); if (!daemonized) unlink(git_path("gc.log")); +out: + gc_config_release(&cfg); return 0; } @@ -836,6 +912,7 @@ struct cg_auto_data { }; static int dfs_on_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) @@ -892,7 +969,7 @@ static int dfs_on_ref(const char *refname UNUSED, return result; } -static int should_write_commit_graph(void) +static int should_write_commit_graph(struct gc_config *cfg UNUSED) { int result; struct cg_auto_data data; @@ -929,7 +1006,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts) return !!run_command(&child); } -static int maintenance_task_commit_graph(struct maintenance_run_opts *opts) +static int maintenance_task_commit_graph(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { prepare_repo_settings(the_repository); if (!the_repository->settings.core_commit_graph) @@ -963,7 +1041,8 @@ static int fetch_remote(struct remote *remote, void *cbdata) return !!run_command(&child); } -static int maintenance_task_prefetch(struct maintenance_run_opts *opts) +static int maintenance_task_prefetch(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { if (for_each_remote(fetch_remote, opts)) { error(_("failed to prefetch remotes")); @@ -973,7 +1052,8 @@ static int maintenance_task_prefetch(struct maintenance_run_opts *opts) return 0; } -static int maintenance_task_gc(struct maintenance_run_opts *opts) +static int maintenance_task_gc(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { struct child_process child = CHILD_PROCESS_INIT; @@ -986,6 +1066,7 @@ static int maintenance_task_gc(struct maintenance_run_opts *opts) strvec_push(&child.args, "--quiet"); else strvec_push(&child.args, "--no-quiet"); + strvec_push(&child.args, "--no-detach"); return run_command(&child); } @@ -1021,7 +1102,7 @@ static int loose_object_count(const struct object_id *oid UNUSED, return 0; } -static int loose_object_auto_condition(void) +static int loose_object_auto_condition(struct gc_config *cfg UNUSED) { int count = 0; @@ -1081,6 +1162,12 @@ static int pack_loose(struct maintenance_run_opts *opts) pack_proc.in = -1; + /* + * git-pack-objects(1) ends up writing the pack hash to stdout, which + * we do not care for. + */ + pack_proc.out = -1; + if (start_command(&pack_proc)) { error(_("failed to start 'git pack-objects' process")); return 1; @@ -1106,12 +1193,13 @@ static int pack_loose(struct maintenance_run_opts *opts) return result; } -static int maintenance_task_loose_objects(struct maintenance_run_opts *opts) +static int maintenance_task_loose_objects(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { return prune_packed(opts) || pack_loose(opts); } -static int incremental_repack_auto_condition(void) +static int incremental_repack_auto_condition(struct gc_config *cfg UNUSED) { struct packed_git *p; int incremental_repack_auto_limit = 10; @@ -1230,7 +1318,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts) return 0; } -static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts) +static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts, + struct gc_config *cfg UNUSED) { prepare_repo_settings(the_repository); if (!the_repository->settings.core_multi_pack_index) { @@ -1247,14 +1336,15 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts return 0; } -typedef int maintenance_task_fn(struct maintenance_run_opts *opts); +typedef int maintenance_task_fn(struct maintenance_run_opts *opts, + struct gc_config *cfg); /* * An auto condition function returns 1 if the task should run * and 0 if the task should NOT run. See needs_to_gc() for an * example. */ -typedef int maintenance_auto_fn(void); +typedef int maintenance_auto_fn(struct gc_config *cfg); struct maintenance_task { const char *name; @@ -1321,7 +1411,8 @@ static int compare_tasks_by_selection(const void *a_, const void *b_) return b->selected_order - a->selected_order; } -static int maintenance_run_tasks(struct maintenance_run_opts *opts) +static int maintenance_run_tasks(struct maintenance_run_opts *opts, + struct gc_config *cfg) { int i, found_selected = 0; int result = 0; @@ -1345,6 +1436,13 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) } free(lock_path); + /* Failure to daemonize is ok, we'll continue in foreground. */ + if (opts->detach > 0) { + trace2_region_enter("maintenance", "detach", the_repository); + daemonize(); + trace2_region_leave("maintenance", "detach", the_repository); + } + for (i = 0; !found_selected && i < TASK__COUNT; i++) found_selected = tasks[i].selected_order >= 0; @@ -1360,14 +1458,14 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) if (opts->auto_flag && (!tasks[i].auto_condition || - !tasks[i].auto_condition())) + !tasks[i].auto_condition(cfg))) continue; if (opts->schedule && tasks[i].schedule < opts->schedule) continue; trace2_region_enter("maintenance", tasks[i].name, r); - if (tasks[i].fn(opts)) { + if (tasks[i].fn(opts, cfg)) { error(_("task '%s' failed"), tasks[i].name); result = 1; } @@ -1380,9 +1478,9 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts) static void initialize_maintenance_strategy(void) { - char *config_str; + const char *config_str; - if (git_config_get_string("maintenance.strategy", &config_str)) + if (git_config_get_string_tmp("maintenance.strategy", &config_str)) return; if (!strcasecmp(config_str, "incremental")) { @@ -1404,7 +1502,6 @@ static void initialize_task_config(int schedule) { int i; struct strbuf config_name = STRBUF_INIT; - gc_config(); if (schedule) initialize_maintenance_strategy(); @@ -1467,10 +1564,13 @@ static int task_option_parse(const struct option *opt UNUSED, static int maintenance_run(int argc, const char **argv, const char *prefix) { int i; - struct maintenance_run_opts opts; + struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; + struct gc_config cfg = GC_CONFIG_INIT; struct option builtin_maintenance_run_options[] = { OPT_BOOL(0, "auto", &opts.auto_flag, N_("run tasks based on the state of the repository")), + OPT_BOOL(0, "detach", &opts.detach, + N_("perform maintenance in the background")), OPT_CALLBACK(0, "schedule", &opts.schedule, N_("frequency"), N_("run tasks based on frequency"), maintenance_opt_schedule), @@ -1481,7 +1581,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix) PARSE_OPT_NONEG, task_option_parse), OPT_END() }; - memset(&opts, 0, sizeof(opts)); + int ret; opts.quiet = !isatty(2); @@ -1496,12 +1596,16 @@ static int maintenance_run(int argc, const char **argv, const char *prefix) if (opts.auto_flag && opts.schedule) die(_("use at most one of --auto and --schedule=<frequency>")); + gc_config(&cfg); initialize_task_config(opts.schedule); if (argc != 0) usage_with_options(builtin_maintenance_run_usage, builtin_maintenance_run_options); - return maintenance_run_tasks(&opts); + + ret = maintenance_run_tasks(&opts, &cfg); + gc_config_release(&cfg); + return ret; } static char *get_maintpath(void) @@ -1664,6 +1768,42 @@ static const char *get_frequency(enum schedule_priority schedule) } } +static const char *extraconfig[] = { + "credential.interactive=false", + "core.askPass=true", /* 'true' returns success, but no output. */ + NULL +}; + +static const char *get_extra_config_parameters(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) + strbuf_addf(&builder, "-c %s ", *s); + + result = strbuf_detach(&builder, NULL); + return result; +} + +static const char *get_extra_launchctl_strings(void) { + static const char *result = NULL; + struct strbuf builder = STRBUF_INIT; + + if (result) + return result; + + for (const char **s = extraconfig; s && *s; s++) { + strbuf_addstr(&builder, "<string>-c</string>\n"); + strbuf_addf(&builder, "<string>%s</string>\n", *s); + } + + result = strbuf_detach(&builder, NULL); + return result; +} + /* * get_schedule_cmd` reads the GIT_TEST_MAINT_SCHEDULER environment variable * to mock the schedulers that `git maintenance start` rely on. @@ -1678,32 +1818,33 @@ static const char *get_frequency(enum schedule_priority schedule) * * If $GIT_TEST_MAINT_SCHEDULER is set, return true. * In this case, the *cmd value is read as input. * - * * if the input value *cmd is the key of one of the comma-separated list - * item, then *is_available is set to true and *cmd is modified and becomes + * * if the input value cmd is the key of one of the comma-separated list + * item, then *is_available is set to true and *out is set to * the mock command. * * * if the input value *cmd isn’t the key of any of the comma-separated list - * item, then *is_available is set to false. + * item, then *is_available is set to false and *out is set to the original + * command. * * Ex.: * GIT_TEST_MAINT_SCHEDULER not set * +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ - * | "foo" | false | "foo" (unchanged) | (unchanged) | + * | "foo" | false | NULL | (unchanged) | * +-------+-------------+-------------------+---------------+ * * GIT_TEST_MAINT_SCHEDULER set to “foo:./mock_foo.sh,bar:./mock_bar.sh” * +-------+-------------------------------------------------+ * | Input | Output | - * | *cmd | return code | *cmd | *is_available | + * | *cmd | return code | *out | *is_available | * +-------+-------------+-------------------+---------------+ * | "foo" | true | "./mock.foo.sh" | true | - * | "qux" | true | "qux" (unchanged) | false | + * | "qux" | true | "qux" (allocated) | false | * +-------+-------------+-------------------+---------------+ */ -static int get_schedule_cmd(const char **cmd, int *is_available) +static int get_schedule_cmd(const char *cmd, int *is_available, char **out) { char *testing = xstrdup_or_null(getenv("GIT_TEST_MAINT_SCHEDULER")); struct string_list_item *item; @@ -1722,16 +1863,22 @@ static int get_schedule_cmd(const char **cmd, int *is_available) if (string_list_split_in_place(&pair, item->string, ":", 2) != 2) continue; - if (!strcmp(*cmd, pair.items[0].string)) { - *cmd = pair.items[1].string; + if (!strcmp(cmd, pair.items[0].string)) { + if (out) + *out = xstrdup(pair.items[1].string); if (is_available) *is_available = 1; - string_list_clear(&list, 0); - UNLEAK(testing); - return 1; + string_list_clear(&pair, 0); + goto out; } + + string_list_clear(&pair, 0); } + if (out) + *out = xstrdup(cmd); + +out: string_list_clear(&list, 0); free(testing); return 1; @@ -1748,9 +1895,8 @@ static int get_random_minute(void) static int is_launchctl_available(void) { - const char *cmd = "launchctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("launchctl", &is_available, NULL)) return is_available; #ifdef __APPLE__ @@ -1788,12 +1934,12 @@ static char *launchctl_get_uid(void) static int launchctl_boot_plist(int enable, const char *filename) { - const char *cmd = "launchctl"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; char *uid = launchctl_get_uid(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, enable ? "bootstrap" : "bootout", uid, filename, NULL); @@ -1806,6 +1952,7 @@ static int launchctl_boot_plist(int enable, const char *filename) result = finish_command(&child); + free(cmd); free(uid); return result; } @@ -1857,10 +2004,10 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit static unsigned long lock_file_timeout_ms = ULONG_MAX; struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT; struct stat st; - const char *cmd = "launchctl"; + char *cmd; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("launchctl", NULL, &cmd); preamble = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">" @@ -1870,6 +2017,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "<array>\n" "<string>%s/git</string>\n" "<string>--exec-path=%s</string>\n" + "%s" /* For extra config parameters. */ "<string>for-each-repo</string>\n" "<string>--keep-going</string>\n" "<string>--config=maintenance.repo</string>\n" @@ -1879,7 +2027,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit "</array>\n" "<key>StartCalendarInterval</key>\n" "<array>\n"; - strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency); + strbuf_addf(&plist, preamble, name, exec_path, exec_path, + get_extra_launchctl_strings(), frequency); switch (schedule) { case SCHEDULE_HOURLY: @@ -1950,6 +2099,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit free(filename); free(name); + free(cmd); strbuf_release(&plist); strbuf_release(&plist2); return 0; @@ -1974,9 +2124,8 @@ static int launchctl_update_schedule(int run_maintenance, int fd UNUSED) static int is_schtasks_available(void) { - const char *cmd = "schtasks"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("schtasks", &is_available, NULL)) return is_available; #ifdef GIT_WINDOWS_NATIVE @@ -1995,15 +2144,16 @@ static char *schtasks_task_name(const char *frequency) static int schtasks_remove_task(enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); char *name = schtasks_task_name(frequency); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/delete", "/tn", name, "/f", NULL); free(name); + free(cmd); return run_command(&child); } @@ -2017,7 +2167,7 @@ static int schtasks_remove_tasks(void) static int schtasks_schedule_task(const char *exec_path, enum schedule_priority schedule) { - const char *cmd = "schtasks"; + char *cmd; int result; struct child_process child = CHILD_PROCESS_INIT; const char *xml; @@ -2027,10 +2177,10 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority struct strbuf tfilename = STRBUF_INIT; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("schtasks", NULL, &cmd); strbuf_addf(&tfilename, "%s/schedule_%s_XXXXXX", - get_git_common_dir(), frequency); + repo_get_common_dir(the_repository), frequency); tfile = xmks_tempfile(tfilename.buf); strbuf_release(&tfilename); @@ -2114,11 +2264,12 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "<Actions Context=\"Author\">\n" "<Exec>\n" "<Command>\"%s\\headless-git.exe\"</Command>\n" - "<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" + "<Arguments>--exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n" "</Exec>\n" "</Actions>\n" "</Task>\n"; - fprintf(tfile->fp, xml, exec_path, exec_path, frequency); + fprintf(tfile->fp, xml, exec_path, exec_path, + get_extra_config_parameters(), frequency); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml", get_tempfile_path(tfile), NULL); @@ -2133,6 +2284,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority delete_tempfile(&tfile); free(name); + free(cmd); return result; } @@ -2174,21 +2326,28 @@ static int check_crontab_process(const char *cmd) static int is_crontab_available(void) { - const char *cmd = "crontab"; + char *cmd; int is_available; + int ret; - if (get_schedule_cmd(&cmd, &is_available)) - return is_available; + if (get_schedule_cmd("crontab", &is_available, &cmd)) { + ret = is_available; + goto out; + } #ifdef __APPLE__ /* * macOS has cron, but it requires special permissions and will * create a UI alert when attempting to run this command. */ - return 0; + ret = 0; #else - return check_crontab_process(cmd); + ret = check_crontab_process(cmd); #endif + +out: + free(cmd); + return ret; } #define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE" @@ -2196,7 +2355,7 @@ static int is_crontab_available(void) static int crontab_update_schedule(int run_maintenance, int fd) { - const char *cmd = "crontab"; + char *cmd; int result = 0; int in_old_region = 0; struct child_process crontab_list = CHILD_PROCESS_INIT; @@ -2206,15 +2365,17 @@ static int crontab_update_schedule(int run_maintenance, int fd) struct tempfile *tmpedit = NULL; int minute = get_random_minute(); - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("crontab", NULL, &cmd); strvec_split(&crontab_list.args, cmd); strvec_push(&crontab_list.args, "-l"); crontab_list.in = -1; crontab_list.out = dup(fd); crontab_list.git_cmd = 0; - if (start_command(&crontab_list)) - return error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + if (start_command(&crontab_list)) { + result = error(_("failed to run 'crontab -l'; your system might not support 'cron'")); + goto out; + } /* Ignore exit code, as an empty crontab will return error. */ finish_command(&crontab_list); @@ -2259,8 +2420,8 @@ static int crontab_update_schedule(int run_maintenance, int fd) "# replaced in the future by a Git command.\n\n"); strbuf_addf(&line_format, - "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", - exec_path, exec_path); + "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n", + exec_path, exec_path, get_extra_config_parameters()); fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly"); fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily"); fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly"); @@ -2284,8 +2445,10 @@ static int crontab_update_schedule(int run_maintenance, int fd) result = error(_("'crontab' died")); else fclose(cron_list); + out: delete_tempfile(&tmpedit); + free(cmd); return result; } @@ -2308,10 +2471,9 @@ static int real_is_systemd_timer_available(void) static int is_systemd_timer_available(void) { - const char *cmd = "systemctl"; int is_available; - if (get_schedule_cmd(&cmd, &is_available)) + if (get_schedule_cmd("systemctl", &is_available, NULL)) return is_available; return real_is_systemd_timer_available(); @@ -2460,7 +2622,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "\n" "[Service]\n" "Type=oneshot\n" - "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" + "ExecStart=\"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n" "LockPersonality=yes\n" "MemoryDenyWriteExecute=yes\n" "NoNewPrivileges=yes\n" @@ -2470,7 +2632,7 @@ static int systemd_timer_write_service_template(const char *exec_path) "RestrictSUIDSGID=yes\n" "SystemCallArchitectures=native\n" "SystemCallFilter=@system-service\n"; - if (fprintf(file, unit, exec_path, exec_path) < 0) { + if (fprintf(file, unit, exec_path, exec_path, get_extra_config_parameters()) < 0) { error(_("failed to write to '%s'"), filename); fclose(file); goto error; @@ -2492,9 +2654,10 @@ static int systemd_timer_enable_unit(int enable, enum schedule_priority schedule, int minute) { - const char *cmd = "systemctl"; + char *cmd = NULL; struct child_process child = CHILD_PROCESS_INIT; const char *frequency = get_frequency(schedule); + int ret; /* * Disabling the systemd unit while it is already disabled makes @@ -2505,20 +2668,25 @@ static int systemd_timer_enable_unit(int enable, * On the other hand, enabling a systemd unit which is already enabled * produces no error. */ - if (!enable) + if (!enable) { child.no_stderr = 1; - else if (systemd_timer_write_timer_file(schedule, minute)) - return -1; + } else if (systemd_timer_write_timer_file(schedule, minute)) { + ret = -1; + goto out; + } - get_schedule_cmd(&cmd, NULL); + get_schedule_cmd("systemctl", NULL, &cmd); strvec_split(&child.args, cmd); strvec_pushl(&child.args, "--user", enable ? "enable" : "disable", "--now", NULL); strvec_pushf(&child.args, SYSTEMD_UNIT_FORMAT, frequency, "timer"); - if (start_command(&child)) - return error(_("failed to start systemctl")); - if (finish_command(&child)) + if (start_command(&child)) { + ret = error(_("failed to start systemctl")); + goto out; + } + + if (finish_command(&child)) { /* * Disabling an already disabled systemd unit makes * systemctl fail. @@ -2526,9 +2694,17 @@ static int systemd_timer_enable_unit(int enable, * * Enabling an enabled systemd unit doesn't fail. */ - if (enable) - return error(_("failed to run systemctl")); - return 0; + if (enable) { + ret = error(_("failed to run systemctl")); + goto out; + } + } + + ret = 0; + +out: + free(cmd); + return ret; } /* @@ -2788,7 +2964,10 @@ static const char * const builtin_maintenance_usage[] = { NULL, }; -int cmd_maintenance(int argc, const char **argv, const char *prefix) +int cmd_maintenance(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_maintenance_options[] = { diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index 7195a072ed..6bec0d1854 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -12,7 +12,10 @@ static const char builtin_get_tar_commit_id_usage[] = #define RECORDSIZE (512) #define HEADERSIZE (2 * RECORDSIZE) -int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix) +int cmd_get_tar_commit_id(int argc, + const char **argv UNUSED, + const char *prefix, + struct repository *repo UNUSED) { char buffer[HEADERSIZE]; struct ustar_header *header = (struct ustar_header *)buffer; diff --git a/builtin/grep.c b/builtin/grep.c index dfc3c3e8bd..f17d46a06e 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -3,11 +3,11 @@ * * Copyright (c) 2006 Junio C Hamano */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "tag.h" #include "tree-walk.h" @@ -888,7 +888,10 @@ static int pattern_callback(const struct option *opt, const char *arg, return 0; } -int cmd_grep(int argc, const char **argv, const char *prefix) +int cmd_grep(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int hit = 0; int cached = 0, untracked = 0, opt_exclude = -1; @@ -1133,6 +1136,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) &oid, &oc)) { if (seen_dashdash) die(_("unable to resolve revision: %s"), arg); + object_context_release(&oc); break; } diff --git a/builtin/hash-object.c b/builtin/hash-object.c index c767414a0c..a25f0403f4 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -4,6 +4,7 @@ * Copyright (C) Linus Torvalds, 2005 * Copyright (C) Junio C Hamano, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -84,7 +85,10 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, strbuf_release(&unquoted); } -int cmd_hash_object(int argc, const char **argv, const char *prefix) +int cmd_hash_object(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static const char * const hash_object_usage[] = { N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" diff --git a/builtin/help.c b/builtin/help.c index dc1fbe2b98..4a5a079070 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -1,6 +1,8 @@ + /* * Builtin help command */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "exec-cmd.h" @@ -52,7 +54,7 @@ static enum help_action { HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION, } cmd_mode; -static const char *html_path; +static char *html_path; static int verbose = 1; static enum help_format help_format = HELP_FORMAT_NONE; static int exclude_guides; @@ -409,6 +411,7 @@ static int git_help_config(const char *var, const char *value, if (!strcmp(var, "help.htmlpath")) { if (!value) return config_error_nonbool(var); + free(html_path); html_path = xstrdup(value); return 0; } @@ -513,23 +516,24 @@ static void show_info_page(const char *page) static void get_html_page_path(struct strbuf *page_path, const char *page) { struct stat st; + const char *path = html_path; char *to_free = NULL; - if (!html_path) - html_path = to_free = system_path(GIT_HTML_PATH); + if (!path) + path = to_free = system_path(GIT_HTML_PATH); /* * Check that the page we're looking for exists. */ - if (!strstr(html_path, "://")) { - if (stat(mkpath("%s/%s.html", html_path, page), &st) + if (!strstr(path, "://")) { + if (stat(mkpath("%s/%s.html", path, page), &st) || !S_ISREG(st.st_mode)) die("'%s/%s.html': documentation file not found.", - html_path, page); + path, page); } strbuf_init(page_path, 0); - strbuf_addf(page_path, "%s/%s.html", html_path, page); + strbuf_addf(page_path, "%s/%s.html", path, page); free(to_free); } @@ -540,7 +544,7 @@ static void open_html(const char *path) static void show_html_page(const char *page) { - struct strbuf page_path; /* it leaks but we exec bellow */ + struct strbuf page_path; /* it leaks but we exec below */ get_html_page_path(&page_path, page); @@ -631,7 +635,10 @@ static void opt_mode_usage(int argc, const char *opt_mode, no_help_format(opt_mode, fmt); } -int cmd_help(int argc, const char **argv, const char *prefix) +int cmd_help(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int nongit; enum help_format parsed_help_format; diff --git a/builtin/hook.c b/builtin/hook.c index 5234693a94..367ef3e0b8 100644 --- a/builtin/hook.c +++ b/builtin/hook.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -58,7 +59,7 @@ static int run(int argc, const char **argv, const char *prefix) hook_name = argv[0]; if (!ignore_missing) opt.error_if_missing = 1; - ret = run_hooks_opt(hook_name, &opt); + ret = run_hooks_opt(the_repository, hook_name, &opt); if (ret < 0) /* error() return */ ret = 1; return ret; @@ -66,7 +67,10 @@ usage: usage_with_options(builtin_hook_run_usage, run_options); } -int cmd_hook(int argc, const char **argv, const char *prefix) +int cmd_hook(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_hook_options[] = { diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 763b01372a..9d23b41b3a 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "delta.h" @@ -1504,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name, struct strbuf *name, unsigned char *hash, const char *ext, int make_read_only_if_same) { - if (*final_name != curr_name) { + if (!*final_name || strcmp(*final_name, curr_name)) { if (!*final_name) *final_name = odb_pack_name(name, hash, ext); if (finalize_object_file(curr_name, *final_name)) @@ -1718,11 +1719,14 @@ static void show_pack_info(int stat_only) free(chain_histogram); } -int cmd_index_pack(int argc, const char **argv, const char *prefix) +int cmd_index_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; const char *curr_index; - const char *curr_rev_index = NULL; + char *curr_rev_index = NULL; const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; const char *keep_msg = NULL; const char *promisor_msg = NULL; @@ -1964,8 +1968,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) free((void *) curr_pack); if (!index_name) free((void *) curr_index); - if (!rev_index_name) - free((void *) curr_rev_index); + free(curr_rev_index); /* * Let the caller know this pack is not self contained diff --git a/builtin/init-db.c b/builtin/init-db.c index 582dcf20f8..7e00d57d65 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -3,6 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" @@ -11,7 +12,6 @@ #include "parse-options.h" #include "path.h" #include "refs.h" -#include "repository.h" #include "setup.h" #include "strbuf.h" @@ -70,7 +70,10 @@ static const char *const init_db_usage[] = { * On the other hand, it might just make lookup slower and messier. You * be the judge. The default case is to have one DB per managed directory. */ -int cmd_init_db(int argc, const char **argv, const char *prefix) +int cmd_init_db(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *git_dir; const char *real_git_dir = NULL; @@ -231,9 +234,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) set_git_work_tree(work_tree); else set_git_work_tree(git_work_tree_cfg); - if (access(get_git_work_tree(), X_OK)) + if (access(repo_get_work_tree(the_repository), X_OK)) die_errno (_("Cannot access work tree '%s'"), - get_git_work_tree()); + repo_get_work_tree(the_repository)); } else { if (real_git_dir) diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index e6f22459f1..c5e56e2cd3 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -4,7 +4,7 @@ * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org> * */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "parse-options.h" @@ -189,7 +189,10 @@ static void interpret_trailers(const struct process_trailer_options *opts, strbuf_release(&sb); } -int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) +int cmd_interpret_trailers(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; LIST_HEAD(trailers); diff --git a/builtin/log.c b/builtin/log.c index 4d4b60caa7..368f6580a6 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -4,6 +4,7 @@ * (C) Copyright 2006 Linus Torvalds * 2006 Junio Hamano */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -37,7 +38,7 @@ #include "mailmap.h" #include "progress.h" #include "commit-slab.h" -#include "repository.h" + #include "commit-reach.h" #include "range-diff.h" #include "tmp-objdir.h" @@ -504,13 +505,7 @@ static int cmd_log_walk_no_free(struct rev_info *rev) struct commit *commit; int saved_nrl = 0; int saved_dcctc = 0; - - if (rev->remerge_diff) { - rev->remerge_objdir = tmp_objdir_create("remerge-diff"); - if (!rev->remerge_objdir) - die(_("unable to create temporary object directory")); - tmp_objdir_replace_primary_odb(rev->remerge_objdir, 1); - } + int result; if (rev->early_output) setup_early_output(); @@ -551,16 +546,12 @@ static int cmd_log_walk_no_free(struct rev_info *rev) rev->diffopt.degraded_cc_to_c = saved_dcctc; rev->diffopt.needed_rename_limit = saved_nrl; - if (rev->remerge_diff) { - tmp_objdir_destroy(rev->remerge_objdir); - rev->remerge_objdir = NULL; - } - + result = diff_result_code(rev); if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && rev->diffopt.flags.check_failed) { - return 02; + result = 02; } - return diff_result_code(&rev->diffopt); + return result; } static int cmd_log_walk(struct rev_info *rev) @@ -637,7 +628,10 @@ static int git_log_config(const char *var, const char *value, return git_diff_ui_config(var, value, ctx, cb); } -int cmd_whatchanged(int argc, const char **argv, const char *prefix) +int cmd_whatchanged(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -707,6 +701,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c write_or_die(1, buf, size); object_context_release(&obj_context); + free(buf); return 0; } @@ -757,7 +752,10 @@ static void show_setup_revisions_tweak(struct rev_info *rev) rev->diffopt.output_format = DIFF_FORMAT_PATCH; } -int cmd_show(int argc, const char **argv, const char *prefix) +int cmd_show(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -873,7 +871,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) /* * This is equivalent to "git log -g --abbrev-commit --pretty=oneline" */ -int cmd_log_reflog(int argc, const char **argv, const char *prefix) +int cmd_log_reflog(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -915,7 +916,10 @@ static void log_setup_revisions_tweak(struct rev_info *rev) diff_merges_default_to_first_parent(rev); } -int cmd_log(int argc, const char **argv, const char *prefix) +int cmd_log(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct log_config cfg; struct rev_info rev; @@ -1434,6 +1438,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, int need_8bit_cte = 0; struct pretty_print_context pp = {0}; struct commit *head = list[0]; + char *to_free = NULL; if (!cmit_fmt_is_mail(rev->commit_format)) die(_("cover letter needs email format")); @@ -1455,7 +1460,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, } if (!branch_name) - branch_name = find_branch_name(rev); + branch_name = to_free = find_branch_name(rev); pp.fmt = CMIT_FMT_EMAIL; pp.date_mode.type = DATE_RFC2822; @@ -1466,6 +1471,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, encoding, need_8bit_cte, cfg); fprintf(rev->diffopt.file, "%s\n", sb.buf); + free(to_free); free(pp.after_subject); strbuf_release(&sb); @@ -1825,12 +1831,14 @@ static struct commit *get_base_commit(const struct format_config *cfg, if (die_on_failure) { die(_("failed to find exact merge base")); } else { + free_commit_list(merge_base); free(rev); return NULL; } } rev[i] = merge_base->item; + free_commit_list(merge_base); } if (rev_nr % 2) @@ -1981,7 +1989,10 @@ static void infer_range_diff_ranges(struct strbuf *r1, } } -int cmd_format_patch(int argc, const char **argv, const char *prefix) +int cmd_format_patch(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct format_config cfg; struct commit *commit; @@ -2021,6 +2032,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *rfc = NULL; int creation_factor = -1; const char *signature = git_version_string; + char *signature_to_free = NULL; char *signature_file_arg = NULL; struct keep_callback_data keep_callback_data = { .cfg = &cfg, @@ -2441,7 +2453,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (strbuf_read_file(&buf, signature_file, 128) < 0) die_errno(_("unable to read signature file '%s'"), signature_file); - signature = strbuf_detach(&buf, NULL); + signature = signature_to_free = strbuf_detach(&buf, NULL); } else if (cfg.signature) { signature = cfg.signature; } @@ -2546,12 +2558,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) else print_signature(signature, rev.diffopt.file); } - if (output_directory) + if (output_directory) { fclose(rev.diffopt.file); + rev.diffopt.file = NULL; + } } stop_progress(&progress); free(list); - free(branch_name); if (ignore_if_in_upstream) free_patch_ids(&ids); @@ -2563,11 +2576,14 @@ done: strbuf_release(&rdiff_title); free(description_file); free(signature_file_arg); + free(signature_to_free); + free(branch_name); free(to_free); free(rev.message_id); if (rev.ref_message_ids) string_list_clear(rev.ref_message_ids, 0); free(rev.ref_message_ids); + rev.diffopt.no_free = 0; release_revisions(&rev); format_config_release(&cfg); return 0; @@ -2609,7 +2625,10 @@ static void print_commit(char sign, struct commit *commit, int verbose, } } -int cmd_cherry(int argc, const char **argv, const char *prefix) +int cmd_cherry(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct patch_ids ids; diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 6eeb5cba78..e016b0415d 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -5,8 +5,8 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" -#include "repository.h" #include "config.h" #include "convert.h" #include "quote.h" @@ -507,7 +507,7 @@ static int get_common_prefix_len(const char *common_prefix) common_prefix_len = strlen(common_prefix); /* - * If the prefix has a trailing slash, strip it so that submodules wont + * If the prefix has a trailing slash, strip it so that submodules won't * be pruned from the index. */ if (common_prefix[common_prefix_len - 1] == '/') @@ -561,7 +561,10 @@ static int option_parse_exclude_standard(const struct option *opt, return 0; } -int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) +int cmd_ls_files(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 6da63a67f5..423318f87e 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -19,17 +20,16 @@ static const char * const ls_remote_usage[] = { * Is there one among the list of patterns that match the tail part * of the path? */ -static int tail_match(const char **pattern, const char *path) +static int tail_match(const struct strvec *pattern, const char *path) { - const char *p; char *pathbuf; - if (!pattern) + if (!pattern->nr) return 1; /* no restriction */ pathbuf = xstrfmt("/%s", path); - while ((p = *(pattern++)) != NULL) { - if (!wildmatch(p, pathbuf, 0)) { + for (size_t i = 0; i < pattern->nr; i++) { + if (!wildmatch(pattern->v[i], pathbuf, 0)) { free(pathbuf); return 1; } @@ -38,7 +38,10 @@ static int tail_match(const char **pattern, const char *path) return 0; } -int cmd_ls_remote(int argc, const char **argv, const char *prefix) +int cmd_ls_remote(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *dest = NULL; unsigned flags = 0; @@ -47,7 +50,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) int status = 0; int show_symref_target = 0; const char *uploadpack = NULL; - const char **pattern = NULL; + struct strvec pattern = STRVEC_INIT; struct transport_ls_refs_options transport_options = TRANSPORT_LS_REFS_OPTIONS_INIT; int i; @@ -108,13 +111,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) packet_trace_identity("ls-remote"); - if (argc > 1) { - int i; - CALLOC_ARRAY(pattern, argc); - for (i = 1; i < argc; i++) { - pattern[i - 1] = xstrfmt("*/%s", argv[i]); - } - } + for (int i = 1; i < argc; i++) + strvec_pushf(&pattern, "*/%s", argv[i]); if (flags & REF_TAGS) strvec_push(&transport_options.ref_prefixes, "refs/tags/"); @@ -151,7 +149,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) struct ref_array_item *item; if (!check_ref_type(ref, flags)) continue; - if (!tail_match(pattern, ref->name)) + if (!tail_match(&pattern, ref->name)) continue; item = ref_array_push(&ref_array, ref->name, &ref->old_oid); item->symref = xstrdup_or_null(ref->symref); @@ -173,5 +171,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) if (transport_disconnect(transport)) status = 1; transport_ls_refs_options_release(&transport_options); + + strvec_clear(&pattern); + string_list_clear(&server_options, 0); return status; } diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index bf372c67d7..8542b5d53e 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -3,7 +3,9 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "config.h" #include "gettext.h" #include "hex.h" @@ -329,7 +331,10 @@ static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = { }, }; -int cmd_ls_tree(int argc, const char **argv, const char *prefix) +int cmd_ls_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct object_id oid; struct tree *tree; diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 53a22645da..e17dec27b1 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -2,6 +2,7 @@ * Another stupid program, this one parsing the headers of an * email to figure out authorship and subject */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" @@ -48,7 +49,10 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un return 0; } -int cmd_mailinfo(int argc, const char **argv, const char *prefix) +int cmd_mailinfo(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct metainfo_charset meta_charset; struct mailinfo mi; diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index fe6dbc5d05..b8f7150ce9 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -269,7 +269,10 @@ out: return ret; } -int cmd_mailsplit(int argc, const char **argv, const char *prefix) +int cmd_mailsplit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int nr = 0, nr_prec = 4, num = 0; int allow_bare = 0; diff --git a/builtin/merge-base.c b/builtin/merge-base.c index 5a8e729502..a20c93b11a 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -5,7 +6,6 @@ #include "hex.h" #include "object-name.h" #include "parse-options.h" -#include "repository.h" #include "commit-reach.h" static int show_merge_base(struct commit **rev, int rev_nr, int show_all) @@ -143,7 +143,10 @@ static int handle_fork_point(int argc, const char **argv) return 0; } -int cmd_merge_base(int argc, const char **argv, const char *prefix) +int cmd_merge_base(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct commit **rev; int rev_nr = 0; diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 1f987334a3..cb42865eb5 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "diff.h" @@ -53,7 +54,10 @@ static int diff_algorithm_cb(const struct option *opt, return 0; } -int cmd_merge_file(int argc, const char **argv, const char *prefix) +int cmd_merge_file(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *names[3] = { 0 }; mmfile_t mmfs[3] = { 0 }; diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 0fabe3f6bb..a5b87ee3c5 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "hex.h" #include "read-cache-ll.h" -#include "repository.h" #include "run-command.h" #include "sparse-index.h" @@ -73,7 +73,10 @@ static void merge_all(void) } } -int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_index(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i, force_file = 0; diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c index 932924e5d0..1fcf53f005 100644 --- a/builtin/merge-ours.c +++ b/builtin/merge-ours.c @@ -7,15 +7,19 @@ * * Pretend we resolved the heads, but declare our tree trumps everybody else. */ +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "builtin.h" #include "diff.h" -#include "repository.h" + static const char builtin_merge_ours_usage[] = "git merge-ours <base>... -- HEAD <remote>..."; -int cmd_merge_ours(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_ours(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { if (argc == 2 && !strcmp(argv[1], "-h")) usage(builtin_merge_ours_usage); diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 82bebea15b..1dd295558b 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -1,10 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "gettext.h" #include "hash.h" #include "merge-recursive.h" #include "object-name.h" -#include "repository.h" static const char builtin_merge_recursive_usage[] = "git %s <base>... -- <head> <remote> ..."; @@ -21,7 +21,10 @@ static char *better_branch_name(const char *branch) return xstrdup(name ? name : branch); } -int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED) +int cmd_merge_recursive(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { struct object_id bases[21]; unsigned bases_count = 0; @@ -31,7 +34,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED) char *better1, *better2; struct commit *result; - init_merge_options(&o, the_repository); + init_basic_merge_options(&o, the_repository); if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index dab2fdc2a6..c5ed472967 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "tree-walk.h" #include "xdiff-interface.h" @@ -10,7 +11,6 @@ #include "object-name.h" #include "object-store-ll.h" #include "parse-options.h" -#include "repository.h" #include "blob.h" #include "merge-blobs.h" #include "quote.h" @@ -526,13 +526,17 @@ static int real_merge(struct merge_tree_options *o, return !result.clean; /* result.clean < 0 handled above */ } -int cmd_merge_tree(int argc, const char **argv, const char *prefix) +int cmd_merge_tree(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct merge_tree_options o = { .show_messages = -1 }; struct strvec xopts = STRVEC_INIT; int expected_remaining_argc; int original_argc; const char *merge_base = NULL; + int ret; const char * const merge_tree_usage[] = { N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), @@ -571,7 +575,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) }; /* Init merge options */ - init_merge_options(&o.merge_options, the_repository); + init_ui_merge_options(&o.merge_options, the_repository); /* Parse arguments */ original_argc = argc - 1; /* ignoring argv[0] */ @@ -625,7 +629,9 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) strbuf_list_free(split); } strbuf_release(&buf); - return 0; + + ret = 0; + goto out; } /* Figure out which mode to use */ @@ -664,7 +670,11 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) /* Do the relevant type of merge */ if (o.mode == MODE_REAL) - return real_merge(&o, merge_base, argv[0], argv[1], prefix); + ret = real_merge(&o, merge_base, argv[0], argv[1], prefix); else - return trivial_merge(argv[0], argv[1], argv[2]); + ret = trivial_merge(argv[0], argv[1], argv[2]); + +out: + strvec_clear(&xopts); + return ret; } diff --git a/builtin/merge.c b/builtin/merge.c index 9fba27d85d..84d0f3604b 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -5,8 +5,9 @@ * * Based on git-merge.sh by Junio C Hamano. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "advice.h" #include "config.h" @@ -17,6 +18,7 @@ #include "object-name.h" #include "parse-options.h" #include "lockfile.h" +#include "repository.h" #include "run-command.h" #include "hook.h" #include "diff.h" @@ -478,7 +480,7 @@ static void finish(struct commit *head_commit, } /* Run a post-merge hook */ - run_hooks_l("post-merge", squash ? "1" : "0", NULL); + run_hooks_l(the_repository, "post-merge", squash ? "1" : "0", NULL); if (new_head) apply_autostash_ref(the_repository, "MERGE_AUTOSTASH"); @@ -695,7 +697,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head, static void write_tree_trivial(struct object_id *oid) { - if (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL)) + if (write_index_as_tree(oid, the_repository->index, + repo_get_index_file(the_repository), + 0, NULL)) die(_("git write-tree failed to write a tree")); } @@ -724,7 +728,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, return 2; } - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); if (!strcmp(strategy, "subtree")) o.subtree_shift = ""; @@ -757,7 +761,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, } if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write %s"), get_index_file()); + die(_("unable to write %s"), repo_get_index_file(the_repository)); return clean ? 0 : 1; } else { return try_merge_command(the_repository, @@ -839,7 +843,7 @@ static void write_merge_heads(struct commit_list *); static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; - const char *index_file = get_index_file(); + const char *index_file = repo_get_index_file(the_repository); if (!no_verify) { int invoked_hook; @@ -855,7 +859,8 @@ static void prepare_to_commit(struct commit_list *remoteheads) if (invoked_hook) discard_index(the_repository->index); } - read_index_from(the_repository->index, index_file, get_git_dir()); + read_index_from(the_repository->index, index_file, + repo_get_git_dir(the_repository)); strbuf_addbuf(&msg, &merge_msg); if (squash) BUG("the control must not reach here under --squash"); @@ -878,8 +883,8 @@ static void prepare_to_commit(struct commit_list *remoteheads) append_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0); write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); - if (run_commit_hook(0 < option_edit, get_index_file(), NULL, - "prepare-commit-msg", + if (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository), + NULL, "prepare-commit-msg", git_path_merge_msg(the_repository), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { @@ -887,7 +892,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) abort_commit(remoteheads, NULL); } - if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), + if (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository), NULL, "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); @@ -1275,7 +1280,10 @@ static int merging_a_throwaway_tag(struct commit *commit) return is_throwaway_tag; } -int cmd_merge(int argc, const char **argv, const char *prefix) +int cmd_merge(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct object_id result_tree, stash, head_oid; struct commit *head_commit; @@ -1347,7 +1355,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) REF_NO_DEREF); /* Invoke 'git reset --merge' */ - ret = cmd_reset(nargc, nargv, prefix); + ret = cmd_reset(nargc, nargv, prefix, the_repository); if (!is_null_oid(&stash_oid)) { oid_to_hex_r(stash_oid_hex, &stash_oid); @@ -1379,7 +1387,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) die(_("There is no merge in progress (MERGE_HEAD missing).")); /* Invoke 'git commit' */ - ret = cmd_commit(nargc, nargv, prefix); + ret = cmd_commit(nargc, nargv, prefix, the_repository); goto done; } diff --git a/builtin/mktag.c b/builtin/mktag.c index 4767f1a97e..6e188dce50 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -18,8 +19,7 @@ static int option_strict = 1; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static int mktag_fsck_error_func(struct fsck_options *o UNUSED, - const struct object_id *oid UNUSED, - enum object_type object_type UNUSED, + void *fsck_report UNUSED, enum fsck_msg_type msg_type, enum fsck_msg_id msg_id UNUSED, const char *message) @@ -72,7 +72,10 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) return ret; } -int cmd_mktag(int argc, const char **argv, const char *prefix) +int cmd_mktag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { static struct option builtin_mktag_options[] = { OPT_BOOL(0, "strict", &option_strict, diff --git a/builtin/mktree.c b/builtin/mktree.c index 9a22d4e277..3c16faa40e 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -3,6 +3,7 @@ * * Copyright (c) Junio C Hamano, 2006, 2009 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" @@ -150,7 +151,10 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing) free(to_free); } -int cmd_mktree(int ac, const char **av, const char *prefix) +int cmd_mktree(int ac, + const char **av, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf sb = STRBUF_INIT; struct object_id oid; @@ -199,5 +203,6 @@ int cmd_mktree(int ac, const char **av, const char *prefix) used=0; /* reset tree entry buffer for re-use in batch mode */ } strbuf_release(&sb); + return 0; } diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c index 9cf1a32d65..d159ed1314 100644 --- a/builtin/multi-pack-index.c +++ b/builtin/multi-pack-index.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "parse-options.h" #include "midx.h" @@ -9,6 +9,7 @@ #include "trace2.h" #include "object-store-ll.h" #include "replace-object.h" +#include "repository.h" #define BUILTIN_MIDX_WRITE_USAGE \ N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \ @@ -63,7 +64,7 @@ static int parse_object_dir(const struct option *opt, const char *arg, char **value = opt->value; free(*value); if (unset) - *value = xstrdup(get_object_directory()); + *value = xstrdup(repo_get_object_directory(the_repository)); else *value = real_pathdup(arg, 1); return 0; @@ -129,6 +130,8 @@ static int cmd_multi_pack_index_write(int argc, const char **argv, MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX), OPT_BIT(0, "progress", &opts.flags, N_("force progress reporting"), MIDX_PROGRESS), + OPT_BIT(0, "incremental", &opts.flags, + N_("write a new incremental MIDX"), MIDX_WRITE_INCREMENTAL), OPT_BOOL(0, "stdin-packs", &opts.stdin_packs, N_("write multi-pack index containing only given indexes")), OPT_FILENAME(0, "refs-snapshot", &opts.refs_snapshot, @@ -265,8 +268,10 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv, (size_t)opts.batch_size, opts.flags); } -int cmd_multi_pack_index(int argc, const char **argv, - const char *prefix) +int cmd_multi_pack_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int res; parse_opt_subcommand_fn *fn = NULL; diff --git a/builtin/mv.c b/builtin/mv.c index 6c69033c5f..472a278737 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -3,6 +3,7 @@ * * Copyright (C) 2006 Johannes Schindelin */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" @@ -18,7 +19,7 @@ #include "string-list.h" #include "parse-options.h" #include "read-cache-ll.h" -#include "repository.h" + #include "setup.h" #include "strvec.h" #include "submodule.h" @@ -178,7 +179,10 @@ static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr) strbuf_release(&a_src_dir); } -int cmd_mv(int argc, const char **argv, const char *prefix) +int cmd_mv(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, flags, gitmodules_modified = 0; int verbose = 0, show_only = 0, force = 0, ignore_errors = 0, ignore_sparse = 0; diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 70e9ec4e47..765eb20a93 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "commit.h" #include "tag.h" @@ -65,7 +65,7 @@ static void set_commit_cutoff(struct commit *commit) static void adjust_cutoff_timestamp_for_slop(void) { if (cutoff) { - /* check for undeflow */ + /* check for underflow */ if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP) cutoff = cutoff - CUTOFF_DATE_SLOP; else @@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_) return a->taggerdate != b->taggerdate; } -static int name_ref(const char *path, const struct object_id *oid, +static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) { struct object *o = parse_object(the_repository, oid); @@ -558,7 +558,10 @@ static void name_rev_line(char *p, struct name_ref_data *data) strbuf_release(&buf); } -int cmd_name_rev(int argc, const char **argv, const char *prefix) +int cmd_name_rev(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct mem_pool string_pool; struct object_array revs = OBJECT_ARRAY_INIT; @@ -677,7 +680,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) always, allow_undefined, data.name_only); } - UNLEAK(string_pool); - UNLEAK(revs); + string_list_clear(&data.ref_filters, 0); + string_list_clear(&data.exclude_filters, 0); + mem_pool_discard(&string_pool, 0); + object_array_clear(&revs); return 0; } diff --git a/builtin/notes.c b/builtin/notes.c index 4cc5bfedc3..8c26e45526 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -6,7 +6,7 @@ * Based on git-notes.sh by Johannes Schindelin, * and builtin/tag.c by Kristian Høgsberg and Carlos Rica. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "editor.h" @@ -17,7 +17,7 @@ #include "object-name.h" #include "object-store-ll.h" #include "path.h" -#include "repository.h" + #include "pretty.h" #include "refs.h" #include "exec-cmd.h" @@ -805,7 +805,7 @@ static int merge_commit(struct notes_merge_options *o) { struct strbuf msg = STRBUF_INIT; struct object_id oid, parent_oid; - struct notes_tree *t; + struct notes_tree t = {0}; struct commit *partial; struct pretty_print_context pretty_ctx; void *local_ref_to_free; @@ -828,8 +828,7 @@ static int merge_commit(struct notes_merge_options *o) else oidclr(&parent_oid, the_repository->hash_algo); - CALLOC_ARRAY(t, 1); - init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); + init_notes(&t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); o->local_ref = local_ref_to_free = refs_resolve_refdup(get_main_ref_store(the_repository), @@ -837,7 +836,7 @@ static int merge_commit(struct notes_merge_options *o) if (!o->local_ref) die(_("failed to resolve NOTES_MERGE_REF")); - if (notes_merge_commit(o, t, partial, &oid)) + if (notes_merge_commit(o, &t, partial, &oid)) die(_("failed to finalize notes merge")); /* Reuse existing commit message in reflog message */ @@ -851,7 +850,7 @@ static int merge_commit(struct notes_merge_options *o) is_null_oid(&parent_oid) ? NULL : &parent_oid, 0, UPDATE_REFS_DIE_ON_ERR); - free_notes(t); + free_notes(&t); strbuf_release(&msg); ret = merge_abort(o); free(local_ref_to_free); @@ -866,7 +865,7 @@ static int git_config_get_notes_strategy(const char *key, if (git_config_get_string(key, &value)) return 1; if (parse_notes_merge_strategy(value, strategy)) - git_die_config(key, _("unknown notes merge strategy %s"), value); + git_die_config(the_repository, key, _("unknown notes merge strategy %s"), value); free(value); return 0; @@ -898,6 +897,7 @@ static int merge(int argc, const char **argv, const char *prefix) 1, PARSE_OPT_NONEG), OPT_END() }; + char *notes_ref; argc = parse_options(argc, argv, prefix, options, git_notes_merge_usage, 0); @@ -925,7 +925,8 @@ static int merge(int argc, const char **argv, const char *prefix) if (do_commit) return merge_commit(&o); - o.local_ref = default_notes_ref(); + notes_ref = default_notes_ref(the_repository); + o.local_ref = notes_ref; strbuf_addstr(&remote_ref, argv[0]); expand_loose_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; @@ -954,7 +955,7 @@ static int merge(int argc, const char **argv, const char *prefix) } strbuf_addf(&msg, "notes: Merged notes from %s into %s", - remote_ref.buf, default_notes_ref()); + remote_ref.buf, notes_ref); strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ result = notes_merge(&o, t, &result_oid); @@ -962,7 +963,7 @@ static int merge(int argc, const char **argv, const char *prefix) if (result >= 0) /* Merge resulted (trivially) in result_oid */ /* Update default notes ref with new commit */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, - default_notes_ref(), &result_oid, NULL, 0, + notes_ref, &result_oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ struct worktree **worktrees; @@ -974,14 +975,14 @@ static int merge(int argc, const char **argv, const char *prefix) /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ worktrees = get_worktrees(); wt = find_shared_symref(worktrees, "NOTES_MERGE_REF", - default_notes_ref()); + notes_ref); if (wt) die(_("a notes merge into %s is already in-progress at %s"), - default_notes_ref(), wt->path); + notes_ref, wt->path); free_worktrees(worktrees); - if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL)) + if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL)) die(_("failed to store link to current notes ref (%s)"), - default_notes_ref()); + notes_ref); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " "and commit the result with 'git notes merge --commit', " "or abort the merge with 'git notes merge --abort'.\n"), @@ -989,6 +990,7 @@ static int merge(int argc, const char **argv, const char *prefix) } free_notes(t); + free(notes_ref); strbuf_release(&remote_ref); strbuf_release(&msg); return result < 0; /* return non-zero on conflicts */ @@ -1085,6 +1087,7 @@ static int prune(int argc, const char **argv, const char *prefix) static int get_ref(int argc, const char **argv, const char *prefix) { struct option options[] = { OPT_END() }; + char *notes_ref; argc = parse_options(argc, argv, prefix, options, git_notes_get_ref_usage, 0); @@ -1093,11 +1096,16 @@ static int get_ref(int argc, const char **argv, const char *prefix) usage_with_options(git_notes_get_ref_usage, options); } - puts(default_notes_ref()); + notes_ref = default_notes_ref(the_repository); + puts(notes_ref); + free(notes_ref); return 0; } -int cmd_notes(int argc, const char **argv, const char *prefix) +int cmd_notes(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *override_notes_ref = NULL; parse_opt_subcommand_fn *fn = NULL; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index f395488971..0fc0680b40 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1,8 +1,8 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" #include "config.h" #include "attr.h" #include "object.h" @@ -771,7 +771,7 @@ static enum write_one_status write_one(struct hashfile *f, return WRITE_ONE_WRITTEN; } -static int mark_tagged(const char *path UNUSED, const struct object_id *oid, +static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id peeled; @@ -1072,7 +1072,7 @@ static void write_reused_pack_one(struct packed_git *reuse_packfile, fixup = find_reused_offset(offset) - find_reused_offset(base_offset); if (fixup) { - unsigned char ofs_header[10]; + unsigned char ofs_header[MAX_PACK_OBJECT_HEADER]; unsigned i, ofs_len; off_t ofs = offset - base_offset - fixup; @@ -1191,6 +1191,7 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile, size_t pos = (i * BITS_IN_EWORD); for (offset = 0; offset < BITS_IN_EWORD; ++offset) { + uint32_t pack_pos; if ((word >> offset) == 0) break; @@ -1199,14 +1200,41 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile, continue; if (pos + offset >= reuse_packfile->bitmap_pos + reuse_packfile->bitmap_nr) goto done; - /* - * Can use bit positions directly, even for MIDX - * bitmaps. See comment in try_partial_reuse() - * for why. - */ - write_reused_pack_one(reuse_packfile->p, - pos + offset - reuse_packfile->bitmap_pos, - f, pack_start, &w_curs); + + if (reuse_packfile->bitmap_pos) { + /* + * When doing multi-pack reuse on a + * non-preferred pack, translate bit positions + * from the MIDX pseudo-pack order back to their + * pack-relative positions before attempting + * reuse. + */ + struct multi_pack_index *m = reuse_packfile->from_midx; + uint32_t midx_pos; + off_t pack_ofs; + + if (!m) + BUG("non-zero bitmap position without MIDX"); + + midx_pos = pack_pos_to_midx(m, pos + offset); + pack_ofs = nth_midxed_offset(m, midx_pos); + + if (offset_to_pack_pos(reuse_packfile->p, + pack_ofs, &pack_pos) < 0) + BUG("could not find expected object at offset %"PRIuMAX" in pack %s", + (uintmax_t)pack_ofs, + pack_basename(reuse_packfile->p)); + } else { + /* + * Can use bit positions directly, even for MIDX + * bitmaps. See comment in try_partial_reuse() + * for why. + */ + pack_pos = pos + offset; + } + + write_reused_pack_one(reuse_packfile->p, pack_pos, f, + pack_start, &w_curs); display_progress(progress_state, ++written); } } @@ -1342,10 +1370,10 @@ static void write_pack_file(void) if (write_bitmap_index) { bitmap_writer_init(&bitmap_writer, - the_repository); + the_repository, &to_pack); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, - &to_pack, written_list, nr_written); + written_list); } if (cruft) @@ -1367,10 +1395,10 @@ static void write_pack_file(void) bitmap_writer_select_commits(&bitmap_writer, indexed_commits, indexed_commits_nr); - if (bitmap_writer_build(&bitmap_writer, &to_pack) < 0) + if (bitmap_writer_build(&bitmap_writer) < 0) die(_("failed to write bitmap index")); bitmap_writer_finish(&bitmap_writer, - written_list, nr_written, + written_list, tmpname.buf, write_bitmap_options); bitmap_writer_free(&bitmap_writer); write_bitmap_index = 0; @@ -3129,7 +3157,7 @@ static void add_tag_chain(const struct object_id *oid) } } -static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid, +static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id peeled; @@ -3940,7 +3968,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, */ static void add_unreachable_loose_objects(void) { - for_each_loose_file_in_objdir(get_object_directory(), + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), add_loose_object, NULL, NULL, NULL); } @@ -4076,6 +4104,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED) } static int mark_bitmap_preferred_tip(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *data UNUSED) @@ -4283,7 +4312,10 @@ static int option_parse_cruft_expiration(const struct option *opt UNUSED, return 0; } -int cmd_pack_objects(int argc, const char **argv, const char *prefix) +int cmd_pack_objects(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int use_internal_rev_list = 0; int shallow = 0; @@ -4640,6 +4672,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) cleanup: clear_packing_data(&to_pack); list_objects_filter_release(&filter_options); + string_list_clear(&keep_pack_list, 0); strvec_clear(&rp); return 0; diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index dd9bf35f5b..5809613002 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -5,11 +5,12 @@ * This file is licensed under the GPL v2. * */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hex.h" -#include "repository.h" + #include "packfile.h" #include "object-store-ll.h" @@ -68,6 +69,15 @@ static inline void llist_init(struct llist **list) (*list)->size = 0; } +static void llist_free(struct llist *list) +{ + for (struct llist_item *i = list->front, *next; i; i = next) { + next = i->next; + llist_item_put(i); + } + free(list); +} + static struct llist * llist_copy(struct llist *list) { struct llist *ret; @@ -205,6 +215,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl, return p; } +static void pack_list_free(struct pack_list *pl) +{ + for (struct pack_list *next; pl; pl = next) { + next = pl->next; + free(pl); + } +} + static inline size_t pack_list_size(struct pack_list *pl) { size_t ret = 0; @@ -418,7 +436,8 @@ static void minimize(struct pack_list **min) /* return if there are no objects missing from the unique set */ if (missing->size == 0) { - free(missing); + llist_free(missing); + pack_list_free(non_unique); return; } @@ -433,6 +452,8 @@ static void minimize(struct pack_list **min) } while (non_unique) { + struct pack_list *next; + /* sort the non_unique packs, greater size of remaining_objects first */ sort_pack_list(&non_unique); if (non_unique->remaining_objects->size == 0) @@ -443,8 +464,14 @@ static void minimize(struct pack_list **min) for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next) llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects); - non_unique = non_unique->next; + next = non_unique->next; + free(non_unique); + non_unique = next; } + + pack_list_free(non_unique); + llist_free(unique_pack_objects); + llist_free(missing); } static void load_all_objects(void) @@ -561,13 +588,9 @@ static void load_all(void) } } -int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) -{ - int i; - int i_still_use_this = 0; - struct pack_list *min = NULL, *red, *pl; +int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { + int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl; struct llist *ignore; - struct object_id *oid; char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ if (argc == 2 && !strcmp(argv[1], "-h")) @@ -627,11 +650,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) /* ignore objects given on stdin */ llist_init(&ignore); if (!isatty(0)) { + struct object_id oid; while (fgets(buf, sizeof(buf), stdin)) { - oid = xmalloc(sizeof(*oid)); - if (get_oid_hex(buf, oid)) + if (get_oid_hex(buf, &oid)) die("Bad object ID on stdin: %s", buf); - llist_insert_sorted_unique(ignore, oid, NULL); + llist_insert_sorted_unique(ignore, &oid, NULL); } } llist_sorted_difference_inplace(all_objects, ignore); @@ -673,5 +696,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED) fprintf(stderr, "%luMB of redundant packs in total.\n", (unsigned long)pack_set_bytecount(red)/(1024*1024)); + pack_list_free(red); + pack_list_free(min); + llist_free(ignore); return 0; } diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index db40825666..2d83c1ed2a 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" #include "refs.h" -#include "repository.h" #include "revision.h" static char const * const pack_refs_usage[] = { @@ -11,7 +11,10 @@ static char const * const pack_refs_usage[] = { NULL }; -int cmd_pack_refs(int argc, const char **argv, const char *prefix) +int cmd_pack_refs(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; diff --git a/builtin/patch-id.c b/builtin/patch-id.c index d790ae6354..93b398e391 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "diff.h" @@ -214,7 +215,10 @@ static int git_patch_id_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_patch_id(int argc, const char **argv, const char *prefix) +int cmd_patch_id(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { /* if nothing is set, default to unstable */ struct patch_id_opts config = {0, 0}; diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c index ca3578e158..4d63f26b0a 100644 --- a/builtin/prune-packed.c +++ b/builtin/prune-packed.c @@ -8,7 +8,10 @@ static const char * const prune_packed_usage[] = { NULL }; -int cmd_prune_packed(int argc, const char **argv, const char *prefix) +int cmd_prune_packed(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int opts = isatty(2) ? PRUNE_PACKED_VERBOSE : 0; const struct option prune_packed_options[] = { diff --git a/builtin/prune.c b/builtin/prune.c index 57fe31467f..2b1de01339 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "diff.h" @@ -147,7 +148,10 @@ static void remove_temporary_files(const char *path) closedir(dir); } -int cmd_prune(int argc, const char **argv, const char *prefix) +int cmd_prune(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; int exclude_promisor_objects = 0; @@ -193,12 +197,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix) revs.exclude_promisor_objects = 1; } - for_each_loose_file_in_objdir(get_object_directory(), prune_object, - prune_cruft, prune_subdir, &revs); + for_each_loose_file_in_objdir(repo_get_object_directory(the_repository), + prune_object, prune_cruft, prune_subdir, &revs); prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0); - remove_temporary_files(get_object_directory()); - s = mkpathdup("%s/pack", get_object_directory()); + remove_temporary_files(repo_get_object_directory(the_repository)); + s = mkpathdup("%s/pack", repo_get_object_directory(the_repository)); remove_temporary_files(s); free(s); diff --git a/builtin/pull.c b/builtin/pull.c index 4c54d8196f..388ef3d130 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -6,6 +6,7 @@ * Fetch one or more remote refs and merge it/them into the current HEAD. */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -84,7 +85,7 @@ static const char *opt_squash; static const char *opt_commit; static const char *opt_edit; static const char *cleanup_arg; -static const char *opt_ff; +static char *opt_ff; static const char *opt_verify_signatures; static const char *opt_verify; static int opt_autostash = -1; @@ -977,7 +978,10 @@ static void show_advice_pull_non_ff(void) "invocation.\n")); } -int cmd_pull(int argc, const char **argv, const char *prefix) +int cmd_pull(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { const char *repo, **refspecs; struct oid_array merge_heads = OID_ARRAY_INIT; @@ -1024,8 +1028,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix) * "--rebase" can override a config setting of * pull.ff=only. */ - if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) - opt_ff = "--ff"; + if (opt_rebase >= 0 && opt_ff && !strcmp(opt_ff, "--ff-only")) { + free(opt_ff); + opt_ff = xstrdup("--ff"); + } } if (opt_rebase < 0) @@ -1135,7 +1141,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (can_ff) { /* we can fast-forward this without invoking rebase */ - opt_ff = "--ff-only"; + free(opt_ff); + opt_ff = xstrdup("--ff-only"); ret = run_merge(); } else { ret = run_rebase(&newbase, &upstream); diff --git a/builtin/push.c b/builtin/push.c index 7a67398124..51c609f208 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -1,6 +1,7 @@ /* * "git push" */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "branch.h" @@ -13,7 +14,6 @@ #include "transport.h" #include "parse-options.h" #include "pkt-line.h" -#include "repository.h" #include "submodule.h" #include "submodule-config.h" #include "send-pack.h" @@ -72,13 +72,15 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref, const char *branch_name; if (remote->push.nr) { - struct refspec_item query; - memset(&query, 0, sizeof(struct refspec_item)); - query.src = matched->name; + struct refspec_item query = { + .src = matched->name, + }; + if (!query_refspecs(&remote->push, &query) && query.dst) { refspec_appendf(refspec, "%s%s:%s", query.force ? "+" : "", query.src, query.dst); + free(query.dst); return; } } @@ -517,14 +519,7 @@ static int git_push_config(const char *k, const char *v, RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF; recurse_submodules = val; } else if (!strcmp(k, "push.pushoption")) { - if (!v) - return config_error_nonbool(k); - else - if (!*v) - string_list_clear(&push_options_config, 0); - else - string_list_append(&push_options_config, v); - return 0; + return parse_transport_option(k, v, &push_options_config); } else if (!strcmp(k, "color.push")) { push_use_color = git_config_colorbool(k, v); return 0; @@ -546,7 +541,10 @@ static int git_push_config(const char *k, const char *v, return git_default_config(k, v, ctx, NULL); } -int cmd_push(int argc, const char **argv, const char *prefix) +int cmd_push(int argc, + const char **argv, + const char *prefix, + struct repository *repository UNUSED) { int flags = 0; int tags = 0; @@ -664,6 +662,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) rc = do_push(flags, push_options, remote); string_list_clear(&push_options_cmdline, 0); string_list_clear(&push_options_config, 0); + clear_cas_option(&cas); if (rc == -1) usage_with_options(push_usage, options); else diff --git a/builtin/range-diff.c b/builtin/range-diff.c index f02cbac087..1b33ab66a7 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -1,10 +1,11 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "object-name.h" #include "parse-options.h" #include "range-diff.h" #include "config.h" -#include "repository.h" + static const char * const builtin_range_diff_usage[] = { N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"), @@ -13,7 +14,10 @@ N_("git range-diff [<options>] <base> <old-tip> <new-tip>"), NULL }; -int cmd_range_diff(int argc, const char **argv, const char *prefix) +int cmd_range_diff(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct diff_options diffopt = { NULL }; struct strvec other_arg = STRVEC_INIT; diff --git a/builtin/read-tree.c b/builtin/read-tree.c index a8cf8504b8..d2a807a828 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -16,7 +16,6 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "parse-options.h" -#include "repository.h" #include "resolve-undo.h" #include "setup.h" #include "sparse-index.h" @@ -108,7 +107,10 @@ static int git_read_tree_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) +int cmd_read_tree(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int i, stage = 0; struct object_id oid; diff --git a/builtin/rebase.c b/builtin/rebase.c index e3a8e74cfc..bbaca3c5d5 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -3,8 +3,9 @@ * * Copyright (c) 2018 Pratik Karki */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "environment.h" #include "gettext.h" @@ -186,6 +187,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) replay.committer_date_is_author_date = opts->committer_date_is_author_date; replay.ignore_date = opts->ignore_date; + free(replay.gpg_sign); replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt); replay.reflog_action = xstrdup(opts->reflog_action); if (opts->strategy) @@ -526,6 +528,23 @@ static int rebase_write_basic_state(struct rebase_options *opts) return 0; } +static int cleanup_autostash(struct rebase_options *opts) +{ + int ret; + struct strbuf dir = STRBUF_INIT; + const char *path = state_dir_path("autostash", opts); + + if (!file_exists(path)) + return 0; + ret = apply_autostash(path); + strbuf_addstr(&dir, opts->state_dir); + if (remove_dir_recursively(&dir, 0)) + ret = error_errno(_("could not remove '%s'"), opts->state_dir); + strbuf_release(&dir); + + return ret; +} + static int finish_rebase(struct rebase_options *opts) { struct strbuf dir = STRBUF_INIT; @@ -1062,7 +1081,10 @@ static int check_exec_cmd(const char *cmd) return 0; } -int cmd_rebase(int argc, const char **argv, const char *prefix) +int cmd_rebase(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rebase_options options = REBASE_OPTIONS_INIT; const char *branch_name; @@ -1726,7 +1748,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (require_clean_work_tree(the_repository, "rebase", _("Please commit or stash them."), 1, 1)) { ret = -1; - goto cleanup; + goto cleanup_autostash; } /* @@ -1749,7 +1771,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (options.switch_to) { ret = checkout_up_to_date(&options); if (ret) - goto cleanup; + goto cleanup_autostash; } if (!(options.flags & REBASE_NO_QUIET)) @@ -1774,9 +1796,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) /* If a hook exists, give it a chance to interrupt*/ if (!ok_to_skip_pre_rebase && - run_hooks_l("pre-rebase", options.upstream_arg, - argc ? argv[0] : NULL, NULL)) - die(_("The pre-rebase hook refused to rebase.")); + run_hooks_l(the_repository, "pre-rebase", options.upstream_arg, + argc ? argv[0] : NULL, NULL)) { + ret = error(_("The pre-rebase hook refused to rebase.")); + goto cleanup_autostash; + } if (options.flags & REBASE_DIFFSTAT) { struct diff_options opts; @@ -1821,9 +1845,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) RESET_HEAD_RUN_POST_CHECKOUT_HOOK; ropts.head_msg = msg.buf; ropts.default_reflog_action = options.reflog_action; - if (reset_head(the_repository, &ropts)) - die(_("Could not detach HEAD")); - strbuf_release(&msg); + if (reset_head(the_repository, &ropts)) { + ret = error(_("Could not detach HEAD")); + goto cleanup_autostash; + } /* * If the onto is a proper descendant of the tip of the branch, then @@ -1851,9 +1876,14 @@ run_rebase: cleanup: strbuf_release(&buf); + strbuf_release(&msg); strbuf_release(&revisions); rebase_options_release(&options); free(squash_onto_name); free(keep_base_onto_name); return !!ret; + +cleanup_autostash: + ret |= !!cleanup_autostash(&options); + goto cleanup; } diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 339524ae2a..ab5b20e39c 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1,6 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" -#include "repository.h" + #include "config.h" #include "environment.h" #include "gettext.h" @@ -300,7 +301,7 @@ static void show_ref(const char *path, const struct object_id *oid) } } -static int show_ref_cb(const char *path_full, const struct object_id *oid, +static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *data) { struct oidset *seen = data; @@ -339,12 +340,26 @@ static void show_one_alternate_ref(const struct object_id *oid, static void write_head_info(void) { static struct oidset seen = OIDSET_INIT; + struct strvec excludes_vector = STRVEC_INIT; + const char **exclude_patterns; + + /* + * We need access to the reference names both with and without their + * namespace and thus cannot use `refs_for_each_namespaced_ref()`. We + * thus have to adapt exclude patterns to carry the namespace prefix + * ourselves. + */ + exclude_patterns = get_namespaced_exclude_patterns( + hidden_refs_to_excludes(&hidden_refs), + get_git_namespace(), &excludes_vector); refs_for_each_fullref_in(get_main_ref_store(the_repository), "", - hidden_refs_to_excludes(&hidden_refs), - show_ref_cb, &seen); + exclude_patterns, show_ref_cb, &seen); for_each_alternate_ref(show_one_alternate_ref, &seen); + oidset_clear(&seen); + strvec_clear(&excludes_vector); + if (!sent_capabilities) show_ref("capabilities^{}", null_oid()); @@ -359,6 +374,7 @@ static void write_head_info(void) struct command { struct command *next; const char *error_string; + char *error_string_owned; struct ref_push_report *report; unsigned int skip_update:1, did_not_exist:1, @@ -792,7 +808,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, struct child_process proc = CHILD_PROCESS_INIT; struct async muxer; int code; - const char *hook_path = find_hook(hook_name); + const char *hook_path = find_hook(the_repository, hook_name); if (!hook_path) return 0; @@ -922,7 +938,7 @@ static int run_update_hook(struct command *cmd) { struct child_process proc = CHILD_PROCESS_INIT; int code; - const char *hook_path = find_hook("update"); + const char *hook_path = find_hook(the_repository, "update"); if (!hook_path) return 0; @@ -1068,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader, hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED; if (!strcmp(head, "ng")) { if (p) - hint->error_string = xstrdup(p); + hint->error_string = hint->error_string_owned = xstrdup(p); else hint->error_string = "failed"; code = -1; @@ -1098,7 +1114,7 @@ static int run_proc_receive_hook(struct command *commands, int hook_use_push_options = 0; int version = 0; int code; - const char *hook_path = find_hook("proc-receive"); + const char *hook_path = find_hook(the_repository, "proc-receive"); if (!hook_path) { rp_error("cannot find hook 'proc-receive'"); @@ -1324,7 +1340,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) } /* - * NEEDSWORK: we should consolidate various implementions of "are we + * NEEDSWORK: we should consolidate various implementations of "are we * on an unborn branch?" test into one, and make the unified one more * robust. !get_sha1() based check used here and elsewhere would not * allow us to tell an unborn branch from corrupt ref, for example. @@ -1409,7 +1425,7 @@ static const char *push_to_checkout(unsigned char *hash, strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree)); strvec_pushv(&opt.env, env->v); strvec_push(&opt.args, hash_to_hex(hash)); - if (run_hooks_opt(push_to_checkout_hook, &opt)) + if (run_hooks_opt(the_repository, push_to_checkout_hook, &opt)) return "push-to-checkout hook declined"; else return NULL; @@ -1618,7 +1634,7 @@ static void run_update_post_hook(struct command *commands) struct child_process proc = CHILD_PROCESS_INIT; const char *hook; - hook = find_hook("post-update"); + hook = find_hook(the_repository, "post-update"); if (!hook) return; @@ -2039,6 +2055,8 @@ static void free_commands(struct command *commands) while (commands) { struct command *next = commands->next; + ref_push_report_free(commands->report); + free(commands->error_string_owned); free(commands); commands = next; } @@ -2480,7 +2498,10 @@ static int delete_only(struct command *commands) return 1; } -int cmd_receive_pack(int argc, const char **argv, const char *prefix) +int cmd_receive_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int advertise_refs = 0; struct command *commands; diff --git a/builtin/reflog.c b/builtin/reflog.c index 0d2ff95c6e..22df6834f7 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -1,7 +1,7 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" -#include "repository.h" #include "revision.h" #include "reachable.h" #include "wildmatch.h" @@ -244,7 +244,7 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); - return cmd_log_reflog(argc, argv, prefix); + return cmd_log_reflog(argc, argv, prefix, the_repository); } static int show_reflog(const char *refname, void *cb_data UNUSED) @@ -447,7 +447,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) * main "reflog" */ -int cmd_reflog(int argc, const char **argv, const char *prefix) +int cmd_reflog(int argc, + const char **argv, + const char *prefix, + struct repository *repository) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { @@ -466,5 +469,5 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) if (fn) return fn(argc - 1, argv + 1, prefix); else - return cmd_log_reflog(argc, argv, prefix); + return cmd_log_reflog(argc, argv, prefix, repository); } diff --git a/builtin/refs.c b/builtin/refs.c index 46dcd150d4..24978a7b7b 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -1,12 +1,17 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" +#include "config.h" +#include "fsck.h" #include "parse-options.h" #include "refs.h" -#include "repository.h" #include "strbuf.h" #define REFS_MIGRATE_USAGE \ N_("git refs migrate --ref-format=<format> [--dry-run]") +#define REFS_VERIFY_USAGE \ + N_("git refs verify [--strict] [--verbose]") + static int cmd_refs_migrate(int argc, const char **argv, const char *prefix) { const char * const migrate_usage[] = { @@ -58,15 +63,47 @@ out: return err; } -int cmd_refs(int argc, const char **argv, const char *prefix) +static int cmd_refs_verify(int argc, const char **argv, const char *prefix) +{ + struct fsck_options fsck_refs_options = FSCK_REFS_OPTIONS_DEFAULT; + const char * const verify_usage[] = { + REFS_VERIFY_USAGE, + NULL, + }; + struct option options[] = { + OPT_BOOL(0, "verbose", &fsck_refs_options.verbose, N_("be verbose")), + OPT_BOOL(0, "strict", &fsck_refs_options.strict, N_("enable strict checking")), + OPT_END(), + }; + int ret; + + argc = parse_options(argc, argv, prefix, options, verify_usage, 0); + if (argc) + usage(_("'git refs verify' takes no arguments")); + + git_config(git_fsck_config, &fsck_refs_options); + prepare_repo_settings(the_repository); + + ret = refs_fsck(get_main_ref_store(the_repository), &fsck_refs_options); + + fsck_options_clear(&fsck_refs_options); + return ret; +} + +int cmd_refs(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char * const refs_usage[] = { REFS_MIGRATE_USAGE, + REFS_VERIFY_USAGE, NULL, }; parse_opt_subcommand_fn *fn = NULL; struct option opts[] = { OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), + OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify), OPT_END(), }; diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index 282782eccd..33c8ae0fc7 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -195,7 +195,10 @@ static int command_loop(const char *child) } } -int cmd_remote_ext(int argc, const char **argv, const char *prefix) +int cmd_remote_ext(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { BUG_ON_NON_EMPTY_PREFIX(prefix); diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c index 9020fab9c5..ae896eda57 100644 --- a/builtin/remote-fd.c +++ b/builtin/remote-fd.c @@ -53,7 +53,10 @@ static void command_loop(int input_fd, int output_fd) } } -int cmd_remote_fd(int argc, const char **argv, const char *prefix) +int cmd_remote_fd(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int input_fd = -1; int output_fd = -1; diff --git a/builtin/remote.c b/builtin/remote.c index 08292498bd..76670ddd8b 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -164,6 +165,7 @@ static int add(int argc, const char **argv, const char *prefix) struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; const char *name, *url; int i; + int result = 0; struct option options[] = { OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")), @@ -230,8 +232,10 @@ static int add(int argc, const char **argv, const char *prefix) fetch_tags == TAGS_SET ? "--tags" : "--no-tags"); } - if (fetch && fetch_remote(name)) - return 1; + if (fetch && fetch_remote(name)) { + result = 1; + goto out; + } if (master) { strbuf_reset(&buf); @@ -241,14 +245,15 @@ static int add(int argc, const char **argv, const char *prefix) strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master); if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add")) - return error(_("Could not setup master '%s'"), master); + result = error(_("Could not setup master '%s'"), master); } +out: strbuf_release(&buf); strbuf_release(&buf2); string_list_clear(&track, 0); - return 0; + return result; } struct branch_info { @@ -258,7 +263,7 @@ struct branch_info { char *push_remote_name; }; -static struct string_list branch_list = STRING_LIST_INIT_NODUP; +static struct string_list branch_list = STRING_LIST_INIT_DUP; static const char *abbrev_ref(const char *name, const char *prefix) { @@ -292,8 +297,8 @@ static int config_read_branches(const char *key, const char *value, type = PUSH_REMOTE; else return 0; - name = xmemdupz(key, key_len); + name = xmemdupz(key, key_len); item = string_list_insert(&branch_list, name); if (!item->util) @@ -337,6 +342,7 @@ static int config_read_branches(const char *key, const char *value, BUG("unexpected type=%d", type); } + free(name); return 0; } @@ -543,6 +549,7 @@ struct branches_for_remote { }; static int add_branch_for_removal(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data) { @@ -554,13 +561,16 @@ static int add_branch_for_removal(const char *refname, refspec.dst = (char *)refname; if (remote_find_tracking(branches->remote, &refspec)) return 0; + free(refspec.src); /* don't delete a branch if another remote also uses it */ for (kr = branches->keep->list; kr; kr = kr->next) { memset(&refspec, 0, sizeof(refspec)); refspec.dst = (char *)refname; - if (!remote_find_tracking(kr->remote, &refspec)) + if (!remote_find_tracking(kr->remote, &refspec)) { + free(refspec.src); return 0; + } } /* don't delete non-remote-tracking refs */ @@ -585,7 +595,7 @@ struct rename_info { uint32_t symrefs_nr; }; -static int read_remote_branches(const char *refname, +static int read_remote_branches(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data) { @@ -667,7 +677,11 @@ static int config_read_push_default(const char *key, const char *value, static void handle_push_default(const char* old_name, const char* new_name) { struct push_default_info push_default = { - old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 }; + .old_name = old_name, + .scope = CONFIG_SCOPE_UNKNOWN, + .origin = STRBUF_INIT, + .linenr = -1, + }; git_config(config_read_push_default, &push_default); if (push_default.scope >= CONFIG_SCOPE_COMMAND) ; /* pass */ @@ -687,6 +701,8 @@ static void handle_push_default(const char* old_name, const char* new_name) push_default.origin.buf, push_default.linenr, old_name); } + + strbuf_release(&push_default.origin); } @@ -704,6 +720,7 @@ static int mv(int argc, const char **argv, const char *prefix) struct rename_info rename; int i, refs_renamed_nr = 0, refspec_updated = 0; struct progress *progress = NULL; + int result = 0; argc = parse_options(argc, argv, prefix, options, builtin_remote_rename_usage, 0); @@ -736,9 +753,11 @@ static int mv(int argc, const char **argv, const char *prefix) strbuf_addf(&buf, "remote.%s", rename.old_name); strbuf_addf(&buf2, "remote.%s", rename.new_name); - if (git_config_rename_section(buf.buf, buf2.buf) < 1) - return error(_("Could not rename config section '%s' to '%s'"), - buf.buf, buf2.buf); + if (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1) { + result = error(_("Could not rename config section '%s' to '%s'"), + buf.buf, buf2.buf); + goto out; + } if (oldremote->fetch.raw_nr) { strbuf_reset(&buf); @@ -784,7 +803,7 @@ static int mv(int argc, const char **argv, const char *prefix) } if (!refspec_updated) - return 0; + goto out; /* * First remove symrefs, then rename the rest, finally create @@ -850,11 +869,16 @@ static int mv(int argc, const char **argv, const char *prefix) display_progress(progress, ++refs_renamed_nr); } stop_progress(&progress); - string_list_clear(&remote_branches, 1); handle_push_default(rename.old_name, rename.new_name); - return 0; +out: + string_list_clear(&remote_branches, 1); + strbuf_release(&old_remote_context); + strbuf_release(&buf); + strbuf_release(&buf2); + strbuf_release(&buf3); + return result; } static int rm(int argc, const char **argv, const char *prefix) @@ -944,12 +968,21 @@ static int rm(int argc, const char **argv, const char *prefix) if (!result) { strbuf_addf(&buf, "remote.%s", remote->name); - if (git_config_rename_section(buf.buf, NULL) < 1) - return error(_("Could not remove config section '%s'"), buf.buf); + if (repo_config_rename_section(the_repository, buf.buf, NULL) < 1) { + result = error(_("Could not remove config section '%s'"), buf.buf); + goto out; + } handle_push_default(remote->name, NULL); } +out: + for (struct known_remote *r = known_remotes.list; r;) { + struct known_remote *next = r->next; + free(r); + r = next; + } + strbuf_release(&buf); return result; } @@ -971,6 +1004,7 @@ static void free_remote_ref_states(struct ref_states *states) } static int append_ref_to_tracked_list(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags, void *cb_data) { @@ -982,8 +1016,10 @@ static int append_ref_to_tracked_list(const char *refname, memset(&refspec, 0, sizeof(refspec)); refspec.dst = (char *)refname; - if (!remote_find_tracking(states->remote, &refspec)) + if (!remote_find_tracking(states->remote, &refspec)) { string_list_append(&states->tracked, abbrev_branch(refspec.src)); + free(refspec.src); + } return 0; } @@ -1726,7 +1762,10 @@ out: return 0; } -int cmd_remote(int argc, const char **argv, const char *prefix) +int cmd_remote(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { diff --git a/builtin/repack.c b/builtin/repack.c index f0317fa94a..d6bb37e84a 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -85,17 +86,34 @@ static int repack_config(const char *var, const char *value, run_update_server_info = git_config_bool(var, value); return 0; } - if (!strcmp(var, "repack.cruftwindow")) + if (!strcmp(var, "repack.cruftwindow")) { + free(cruft_po_args->window); return git_config_string(&cruft_po_args->window, var, value); - if (!strcmp(var, "repack.cruftwindowmemory")) + } + if (!strcmp(var, "repack.cruftwindowmemory")) { + free(cruft_po_args->window_memory); return git_config_string(&cruft_po_args->window_memory, var, value); - if (!strcmp(var, "repack.cruftdepth")) + } + if (!strcmp(var, "repack.cruftdepth")) { + free(cruft_po_args->depth); return git_config_string(&cruft_po_args->depth, var, value); - if (!strcmp(var, "repack.cruftthreads")) + } + if (!strcmp(var, "repack.cruftthreads")) { + free(cruft_po_args->threads); return git_config_string(&cruft_po_args->threads, var, value); + } return git_default_config(var, value, ctx, cb); } +static void pack_objects_args_release(struct pack_objects_args *args) +{ + free(args->window); + free(args->window_memory); + free(args->depth); + free(args->threads); + list_objects_filter_release(&args->filter_options); +} + struct existing_packs { struct string_list kept_packs; struct string_list non_kept_packs; @@ -425,9 +443,11 @@ static void repack_promisor_objects(const struct pack_objects_args *args, free(promisor_name); } + fclose(out); if (finish_command(&cmd)) die(_("could not finish pack-objects to repack promisor objects")); + strbuf_release(&line); } struct pack_geometry { @@ -667,6 +687,7 @@ struct midx_snapshot_ref_data { }; static int midx_snapshot_ref_one(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *_data) { @@ -731,14 +752,23 @@ static void midx_included_packs(struct string_list *include, struct pack_geometry *geometry) { struct string_list_item *item; + struct strbuf buf = STRBUF_INIT; + + for_each_string_list_item(item, &existing->kept_packs) { + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); + } + + for_each_string_list_item(item, names) { + strbuf_reset(&buf); + strbuf_addf(&buf, "pack-%s.idx", item->string); + string_list_insert(include, buf.buf); + } - for_each_string_list_item(item, &existing->kept_packs) - string_list_insert(include, xstrfmt("%s.idx", item->string)); - for_each_string_list_item(item, names) - string_list_insert(include, xstrfmt("pack-%s.idx", item->string)); if (geometry->split_factor) { - struct strbuf buf = STRBUF_INIT; uint32_t i; + for (i = geometry->split; i < geometry->pack_nr; i++) { struct packed_git *p = geometry->pack[i]; @@ -753,17 +783,21 @@ static void midx_included_packs(struct string_list *include, if (!p->pack_local) continue; + strbuf_reset(&buf); strbuf_addstr(&buf, pack_basename(p)); strbuf_strip_suffix(&buf, ".pack"); strbuf_addstr(&buf, ".idx"); - string_list_insert(include, strbuf_detach(&buf, NULL)); + string_list_insert(include, buf.buf); } } else { for_each_string_list_item(item, &existing->non_kept_packs) { if (pack_is_marked_for_deletion(item)) continue; - string_list_insert(include, xstrfmt("%s.idx", item->string)); + + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); } } @@ -783,8 +817,13 @@ static void midx_included_packs(struct string_list *include, */ if (pack_is_marked_for_deletion(item)) continue; - string_list_insert(include, xstrfmt("%s.idx", item->string)); + + strbuf_reset(&buf); + strbuf_addf(&buf, "%s.idx", item->string); + string_list_insert(include, buf.buf); } + + strbuf_release(&buf); } static int write_midx_included_packs(struct string_list *include, @@ -1115,7 +1154,10 @@ static const char *find_pack_prefix(const char *packdir, const char *packtmp) return pack_prefix; } -int cmd_repack(int argc, const char **argv, const char *prefix) +int cmd_repack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct child_process cmd = CHILD_PROCESS_INIT; struct string_list_item *item; @@ -1131,12 +1173,16 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *unpack_unreachable = NULL; int keep_unreachable = 0; struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; - struct pack_objects_args po_args = {NULL}; - struct pack_objects_args cruft_po_args = {NULL}; + struct pack_objects_args po_args = { 0 }; + struct pack_objects_args cruft_po_args = { 0 }; int write_midx = 0; const char *cruft_expiration = NULL; const char *expire_to = NULL; const char *filter_to = NULL; + const char *opt_window = NULL; + const char *opt_window_memory = NULL; + const char *opt_depth = NULL; + const char *opt_threads = NULL; struct option builtin_repack_options[] = { OPT_BIT('a', NULL, &pack_everything, @@ -1170,13 +1216,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("with -A, do not loosen objects older than this")), OPT_BOOL('k', "keep-unreachable", &keep_unreachable, N_("with -a, repack unreachable objects")), - OPT_STRING(0, "window", &po_args.window, N_("n"), + OPT_STRING(0, "window", &opt_window, N_("n"), N_("size of the window used for delta compression")), - OPT_STRING(0, "window-memory", &po_args.window_memory, N_("bytes"), + OPT_STRING(0, "window-memory", &opt_window_memory, N_("bytes"), N_("same as the above, but limit memory size instead of entries count")), - OPT_STRING(0, "depth", &po_args.depth, N_("n"), + OPT_STRING(0, "depth", &opt_depth, N_("n"), N_("limits the maximum delta depth")), - OPT_STRING(0, "threads", &po_args.threads, N_("n"), + OPT_STRING(0, "threads", &opt_threads, N_("n"), N_("limits the maximum number of threads")), OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size, N_("maximum size of each packfile")), @@ -1203,6 +1249,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_repack_options, git_repack_usage, 0); + po_args.window = xstrdup_or_null(opt_window); + po_args.window_memory = xstrdup_or_null(opt_window_memory); + po_args.depth = xstrdup_or_null(opt_depth); + po_args.threads = xstrdup_or_null(opt_threads); + if (delete_redundant && repository_format_precious_objects) die(_("cannot delete packs in a precious-objects repo")); @@ -1217,10 +1268,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (!write_midx && (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository())) write_bitmaps = 0; - } else if (write_bitmaps && - git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0) && - git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP, 0)) { - write_bitmaps = 0; } if (pack_kept_objects < 0) pack_kept_objects = write_bitmaps > 0 && !write_midx; @@ -1243,7 +1290,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (write_midx && write_bitmaps) { struct strbuf path = STRBUF_INIT; - strbuf_addf(&path, "%s/%s_XXXXXX", get_object_directory(), + strbuf_addf(&path, "%s/%s_XXXXXX", repo_get_object_directory(the_repository), "bitmap-ref-tips"); refs_snapshot = xmks_tempfile(path.buf); @@ -1252,7 +1299,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) strbuf_release(&path); } - packdir = mkpathdup("%s/pack", get_object_directory()); + packdir = mkpathdup("%s/pack", repo_get_object_directory(the_repository)); packtmp_name = xstrfmt(".tmp-%d-pack", (int)getpid()); packtmp = mkpathdup("%s/%s", packdir, packtmp_name); @@ -1372,13 +1419,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *pack_prefix = find_pack_prefix(packdir, packtmp); if (!cruft_po_args.window) - cruft_po_args.window = po_args.window; + cruft_po_args.window = xstrdup_or_null(po_args.window); if (!cruft_po_args.window_memory) - cruft_po_args.window_memory = po_args.window_memory; + cruft_po_args.window_memory = xstrdup_or_null(po_args.window_memory); if (!cruft_po_args.depth) - cruft_po_args.depth = po_args.depth; + cruft_po_args.depth = xstrdup_or_null(po_args.depth); if (!cruft_po_args.threads) - cruft_po_args.threads = po_args.threads; + cruft_po_args.threads = xstrdup_or_null(po_args.threads); if (!cruft_po_args.max_pack_size) cruft_po_args.max_pack_size = po_args.max_pack_size; @@ -1479,7 +1526,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) mark_packs_for_deletion(&existing, &names); if (write_midx) { - struct string_list include = STRING_LIST_INIT_NODUP; + struct string_list include = STRING_LIST_INIT_DUP; midx_included_packs(&include, &existing, &names, &geometry); ret = write_midx_included_packs(&include, &geometry, &names, @@ -1520,16 +1567,19 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) { unsigned flags = 0; - if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP, 0)) - flags |= MIDX_WRITE_BITMAP | MIDX_WRITE_REV_INDEX; - write_midx_file(get_object_directory(), NULL, NULL, flags); + if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0)) + flags |= MIDX_WRITE_INCREMENTAL; + write_midx_file(repo_get_object_directory(the_repository), + NULL, NULL, flags); } cleanup: + string_list_clear(&keep_pack_list, 0); string_list_clear(&names, 1); existing_packs_release(&existing); free_pack_geometry(&geometry); - list_objects_filter_release(&po_args.filter_options); + pack_objects_args_release(&po_args); + pack_objects_args_release(&cruft_po_args); return ret; } diff --git a/builtin/replace.c b/builtin/replace.c index 1ef833c07f..a44f4e7ea9 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -7,11 +7,10 @@ * and Carlos Rica <jasampler@gmail.com> that was itself based on * git-tag.sh and mktag.c by Linus Torvalds. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "editor.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" @@ -22,7 +21,6 @@ #include "object-name.h" #include "object-store-ll.h" #include "replace-object.h" -#include "repository.h" #include "tag.h" #include "wildmatch.h" @@ -49,6 +47,7 @@ struct show_data { }; static int show_reference(const char *refname, + const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data) { @@ -513,7 +512,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle) static int convert_graft_file(int force) { - const char *graft_file = get_graft_file(the_repository); + const char *graft_file = repo_get_graft_file(the_repository); FILE *fp = fopen_or_warn(graft_file, "r"); struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT; struct strvec args = STRVEC_INIT; @@ -544,7 +543,10 @@ static int convert_graft_file(int force) return -1; } -int cmd_replace(int argc, const char **argv, const char *prefix) +int cmd_replace(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force = 0; int raw = 0; diff --git a/builtin/replay.c b/builtin/replay.c index 0448326636..2d12a4e403 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -4,6 +4,7 @@ #include "git-compat-util.h" +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "environment.h" #include "hex.h" @@ -151,7 +152,7 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info, static void determine_replay_mode(struct rev_cmdline_info *cmd_info, const char *onto_name, - const char **advance_name, + char **advance_name, struct commit **onto, struct strset **update_refs) { @@ -174,6 +175,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, *onto = peel_committish(*advance_name); if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name), &oid, &fullname, 0) == 1) { + free(*advance_name); *advance_name = fullname; } else { die(_("argument to --advance must be a reference")); @@ -197,6 +199,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, if (negative_refs_complete) { struct hashmap_iter iter; struct strmap_entry *entry; + const char *last_key = NULL; if (rinfo.negative_refexprs == 0) die(_("all positive revisions given must be references")); @@ -208,8 +211,11 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, /* Only one entry, but we have to loop to get it */ strset_for_each_entry(&rinfo.negative_refs, &iter, entry) { - *advance_name = entry->key; + last_key = entry->key; } + + free(*advance_name); + *advance_name = xstrdup_or_null(last_key); } else { /* positive_refs_complete */ if (rinfo.negative_refexprs > 1) die(_("cannot implicitly determine correct base for --onto")); @@ -269,9 +275,13 @@ static struct commit *pick_regular_commit(struct commit *pickme, return create_commit(result->tree, pickme, replayed_base); } -int cmd_replay(int argc, const char **argv, const char *prefix) +int cmd_replay(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { - const char *advance_name = NULL; + const char *advance_name_opt = NULL; + char *advance_name = NULL; struct commit *onto = NULL; const char *onto_name = NULL; int contained = 0; @@ -292,7 +302,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) NULL }; struct option replay_options[] = { - OPT_STRING(0, "advance", &advance_name, + OPT_STRING(0, "advance", &advance_name_opt, N_("branch"), N_("make replay advance given branch")), OPT_STRING(0, "onto", &onto_name, @@ -306,14 +316,15 @@ int cmd_replay(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, replay_options, replay_usage, PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT); - if (!onto_name && !advance_name) { + if (!onto_name && !advance_name_opt) { error(_("option --onto or --advance is mandatory")); usage_with_options(replay_usage, replay_options); } - if (advance_name && contained) + if (advance_name_opt && contained) die(_("options '%s' and '%s' cannot be used together"), "--advance", "--contained"); + advance_name = xstrdup_or_null(advance_name_opt); repo_init_revisions(the_repository, &revs, prefix); @@ -377,7 +388,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) goto cleanup; } - init_merge_options(&merge_opt, the_repository); + init_basic_merge_options(&merge_opt, the_repository); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; last_commit = onto; @@ -441,6 +452,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix) cleanup: release_revisions(&revs); + free(advance_name); /* Return */ if (ret < 0) diff --git a/builtin/rerere.c b/builtin/rerere.c index b2efc6f640..f7143c3f5d 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -1,8 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "parse-options.h" -#include "repository.h" + #include "string-list.h" #include "rerere.h" #include "xdiff/xdiff.h" @@ -48,7 +49,10 @@ static int diff_two(const char *file1, const char *label1, return ret; } -int cmd_rerere(int argc, const char **argv, const char *prefix) +int cmd_rerere(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct string_list merge_rr = STRING_LIST_INIT_DUP; int i, autoupdate = -1, flags = 0; @@ -73,11 +77,17 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) if (!strcmp(argv[0], "forget")) { struct pathspec pathspec; + int ret; + if (argc < 2) warning(_("'git rerere forget' without paths is deprecated")); parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, prefix, argv + 1); - return rerere_forget(the_repository, &pathspec); + + ret = rerere_forget(the_repository, &pathspec); + + clear_pathspec(&pathspec); + return ret; } if (!strcmp(argv[0], "clear")) { diff --git a/builtin/reset.c b/builtin/reset.c index 5f941fb3a2..7154f88826 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -7,7 +7,7 @@ * * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -26,6 +26,7 @@ #include "object-name.h" #include "parse-options.h" #include "path.h" +#include "repository.h" #include "unpack-trees.h" #include "cache-tree.h" #include "setup.h" @@ -330,7 +331,10 @@ static int git_reset_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_reset(int argc, const char **argv, const char *prefix) +int cmd_reset(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int reset_type = NONE, update_ref_status = 0, quiet = 0; int no_refresh = 0; @@ -441,7 +445,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) else trace2_cmd_mode(reset_type_names[reset_type]); - if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree())) + if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository))) setup_work_tree(); if (reset_type == MIXED && is_bare_repository()) @@ -474,7 +478,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) goto cleanup; } the_repository->index->updated_skipworktree = 1; - if (!no_refresh && get_git_work_tree()) { + if (!no_refresh && repo_get_work_tree(the_repository)) { uint64_t t_begin, t_delta_in_ms; t_begin = getnanotime(); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 97d077a994..f62bcbf2b1 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -513,7 +514,10 @@ static int try_bitmap_disk_usage(struct rev_info *revs, return 0; } -int cmd_rev_list(int argc, const char **argv, const char *prefix) +int cmd_rev_list(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct rev_info revs; struct rev_list_info info; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 2e64f5bda7..8401b4d7ab 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -3,8 +3,9 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "abspath.h" #include "config.h" #include "commit.h" @@ -19,6 +20,8 @@ #include "path.h" #include "diff.h" #include "read-cache-ll.h" +#include "repo-settings.h" +#include "repository.h" #include "revision.h" #include "setup.h" #include "split-index.h" @@ -211,7 +214,7 @@ static int show_default(void) return 0; } -static int show_reference(const char *refname, const struct object_id *oid, +static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { if (ref_excluded(&ref_excludes, refname)) @@ -220,7 +223,7 @@ static int show_reference(const char *refname, const struct object_id *oid, return 0; } -static int anti_reference(const char *refname, const struct object_id *oid, +static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { show_rev(REVERSED, oid, refname); @@ -553,7 +556,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) strbuf_release(&sb); strvec_clear(&longnames); strvec_clear(&usage); - free((char *) opts->help); + for (size_t i = 0; i < opts_nr; i++) { + free((char *) opts[i].help); + free((char *) opts[i].argh); + } free(opts); return 0; } @@ -685,7 +691,10 @@ static void print_path(const char *path, const char *prefix, enum format_type fo free(cwd); } -int cmd_rev_parse(int argc, const char **argv, const char *prefix) +int cmd_rev_parse(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; const struct git_hash_algo *output_algo = NULL; @@ -895,7 +904,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } if (opt_with_value(arg, "--abbrev-ref", &arg)) { abbrev_ref = 1; - abbrev_ref_strict = warn_ambiguous_refs; + abbrev_ref_strict = + repo_settings_get_warn_ambiguous_refs(the_repository); if (arg) { if (!strcmp(arg, "strict")) abbrev_ref_strict = 1; @@ -963,7 +973,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--show-toplevel")) { - const char *work_tree = get_git_work_tree(); + const char *work_tree = repo_get_work_tree(the_repository); if (work_tree) print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED); else @@ -988,7 +998,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) const char *pfx = prefix; if (!is_inside_work_tree()) { const char *work_tree = - get_git_work_tree(); + repo_get_work_tree(the_repository); if (work_tree) printf("%s\n", work_tree); continue; @@ -1039,7 +1049,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--git-common-dir")) { - print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED); + print_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED); continue; } if (!strcmp(arg, "--is-inside-git-dir")) { diff --git a/builtin/revert.c b/builtin/revert.c index 7bf2b4e11d..b7917dddd3 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -1,9 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "builtin.h" #include "parse-options.h" #include "diff.h" #include "gettext.h" -#include "repository.h" #include "revision.h" #include "rerere.h" #include "sequencer.h" @@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char *me = action_name(opts); const char *cleanup_arg = NULL; + const char sentinel_value; + const char *strategy = &sentinel_value; + const char *gpg_sign = &sentinel_value; enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; int cmd = 0; struct option base_options[] = { @@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, OPT_CALLBACK('m', "mainline", opts, N_("parent-number"), N_("select mainline parent"), option_parse_m), OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto), - OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")), + OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"), N_("option for merge strategy")), - { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), + { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_END() }; @@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, usage_with_options(usage_str, options); /* These option values will be free()d */ - opts->gpg_sign = xstrdup_or_null(opts->gpg_sign); - opts->strategy = xstrdup_or_null(opts->strategy); + if (gpg_sign != &sentinel_value) { + free(opts->gpg_sign); + opts->gpg_sign = xstrdup_or_null(gpg_sign); + } + if (strategy != &sentinel_value) { + free(opts->strategy); + opts->strategy = xstrdup_or_null(strategy); + } if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); free(options); @@ -261,7 +270,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, return sequencer_pick_revisions(the_repository, opts); } -int cmd_revert(int argc, const char **argv, const char *prefix) +int cmd_revert(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct replay_opts opts = REPLAY_OPTS_INIT; int res; @@ -275,7 +287,10 @@ int cmd_revert(int argc, const char **argv, const char *prefix) return res; } -int cmd_cherry_pick(int argc, const char **argv, const char *prefix) +int cmd_cherry_pick(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct replay_opts opts = REPLAY_OPTS_INIT; int res; diff --git a/builtin/rm.c b/builtin/rm.c index 0e79cbab62..eaff027258 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds 2006 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -15,7 +15,7 @@ #include "object-name.h" #include "parse-options.h" #include "read-cache.h" -#include "repository.h" + #include "string-list.h" #include "setup.h" #include "sparse-index.h" @@ -261,7 +261,10 @@ static struct option builtin_rm_options[] = { OPT_END(), }; -int cmd_rm(int argc, const char **argv, const char *prefix) +int cmd_rm(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct lock_file lock_file = LOCK_INIT; int i, ret = 0; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 17cae6bbbd..59b626aae8 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -147,7 +148,10 @@ static int send_pack_config(const char *k, const char *v, return git_default_config(k, v, ctx, cb); } -int cmd_send_pack(int argc, const char **argv, const char *prefix) +int cmd_send_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -336,7 +340,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) /* stable plumbing output; do not modify or localize */ fprintf(stderr, "Everything up-to-date\n"); + string_list_clear(&push_options, 0); free_refs(remote_refs); free_refs(local_refs); + refspec_clear(&rs); + oid_array_clear(&shallow); + clear_cas_option(&cas); return ret; } diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 5bde7c68c2..3ed5c46078 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "commit.h" @@ -5,7 +6,6 @@ #include "environment.h" #include "gettext.h" #include "string-list.h" -#include "repository.h" #include "revision.h" #include "utf8.h" #include "mailmap.h" @@ -378,7 +378,10 @@ void shortlog_finish_setup(struct shortlog *log) string_list_sort(&log->trailers); } -int cmd_shortlog(int argc, const char **argv, const char *prefix) +int cmd_shortlog(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct shortlog log = { STRING_LIST_INIT_NODUP }; struct rev_info rev; @@ -514,4 +517,5 @@ void shortlog_output(struct shortlog *log) string_list_clear(&log->list, 1); clear_mailmap(&log->mailmap); string_list_clear(&log->format, 0); + string_list_clear(&log->trailers, 0); } diff --git a/builtin/show-branch.c b/builtin/show-branch.c index d72f4cb98d..cd6bdf63bc 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -10,7 +11,7 @@ #include "strvec.h" #include "object-name.h" #include "parse-options.h" -#include "repository.h" + #include "dir.h" #include "commit-slab.h" #include "date.h" @@ -410,7 +411,7 @@ static int append_ref(const char *refname, const struct object_id *oid, return 0; } -static int append_head_ref(const char *refname, const struct object_id *oid, +static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id tmp; @@ -425,7 +426,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid, return append_ref(refname + ofs, oid, 0); } -static int append_remote_ref(const char *refname, const struct object_id *oid, +static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cb_data UNUSED) { struct object_id tmp; @@ -451,7 +452,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid, static const char *match_ref_pattern = NULL; static int match_ref_slash = 0; -static int append_matching_ref(const char *refname, const struct object_id *oid, +static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data) { /* we want to allow pattern hold/<asterisk> to show all @@ -468,7 +469,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid, if (wildmatch(match_ref_pattern, tail, 0)) return 0; if (starts_with(refname, "refs/heads/")) - return append_head_ref(refname, oid, flag, cb_data); + return append_head_ref(refname, NULL, oid, flag, cb_data); if (starts_with(refname, "refs/tags/")) return append_tag_ref(refname, oid, flag, cb_data); return append_ref(refname, oid, 0); @@ -502,14 +503,14 @@ static int rev_is_head(const char *head, const char *name) return !strcmp(head, name); } -static int show_merge_base(struct commit_list *seen, int num_rev) +static int show_merge_base(const struct commit_list *seen, int num_rev) { int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); int all_revs = all_mask & ~((1u << REV_SHIFT) - 1); int exit_status = 1; - while (seen) { - struct commit *commit = pop_commit(&seen); + for (const struct commit_list *s = seen; s; s = s->next) { + struct commit *commit = s->item; int flags = commit->object.flags & all_mask; if (!(flags & UNINTERESTING) && ((flags & all_revs) == all_revs)) { @@ -632,10 +633,13 @@ static int parse_reflog_param(const struct option *opt, const char *arg, return 0; } -int cmd_show_branch(int ac, const char **av, const char *prefix) +int cmd_show_branch(int ac, + const char **av, + const char *prefix, + struct repository *repo UNUSED) { struct commit *rev[MAX_REVS], *commit; - char *reflog_msg[MAX_REVS]; + char *reflog_msg[MAX_REVS] = {0}; struct commit_list *list = NULL, *seen = NULL; unsigned int rev_mask[MAX_REVS]; int num_rev, i, extra = 0; @@ -692,6 +696,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) parse_reflog_param), OPT_END() }; + const char **args_copy = NULL; + int ret; init_commit_name_slab(&name_slab); @@ -699,8 +705,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) /* If nothing is specified, try the default first */ if (ac == 1 && default_args.nr) { + DUP_ARRAY(args_copy, default_args.v, default_args.nr); ac = default_args.nr; - av = default_args.v; + av = args_copy; } ac = parse_options(ac, av, prefix, builtin_show_branch_options, @@ -780,7 +787,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) } for (i = 0; i < reflog; i++) { - char *logmsg; + char *logmsg = NULL; char *nth_desc; const char *msg; char *end; @@ -790,6 +797,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) if (read_ref_at(get_main_ref_store(the_repository), ref, flags, 0, base + i, &oid, &logmsg, ×tamp, &tz, NULL)) { + free(logmsg); reflog = i; break; } @@ -842,7 +850,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) if (!ref_name_cnt) { fprintf(stderr, "No revs to be shown.\n"); - exit(0); + ret = 0; + goto out; } for (num_rev = 0; ref_name[num_rev]; num_rev++) { @@ -879,11 +888,15 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) commit_list_sort_by_date(&seen); - if (merge_base) - return show_merge_base(seen, num_rev); + if (merge_base) { + ret = show_merge_base(seen, num_rev); + goto out; + } - if (independent) - return show_independent(rev, num_rev, rev_mask); + if (independent) { + ret = show_independent(rev, num_rev, rev_mask); + goto out; + } /* Show list; --more=-1 means list-only */ if (1 < num_rev || extra < 0) { @@ -919,8 +932,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) putchar('\n'); } } - if (extra < 0) - exit(0); + if (extra < 0) { + ret = 0; + goto out; + } /* Sort topologically */ sort_in_topological_order(&seen, sort_order); @@ -932,8 +947,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); - while (seen) { - struct commit *commit = pop_commit(&seen); + for (struct commit_list *l = seen; l; l = l->next) { + struct commit *commit = l->item; int this_flag = commit->object.flags; int is_merge_point = ((this_flag & all_revs) == all_revs); @@ -973,6 +988,15 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) if (shown_merge_point && --extra < 0) break; } + + ret = 0; + +out: + for (size_t i = 0; i < ARRAY_SIZE(reflog_msg); i++) + free(reflog_msg[i]); + free_commit_list(seen); + free_commit_list(list); + free(args_copy); free(head); - return 0; + return ret; } diff --git a/builtin/show-index.c b/builtin/show-index.c index 540dc3dad1..f164c01bbe 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -1,17 +1,20 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "gettext.h" #include "hash.h" #include "hex.h" #include "pack.h" #include "parse-options.h" -#include "repository.h" static const char *const show_index_usage[] = { "git show-index [--object-format=<hash-algorithm>]", NULL }; -int cmd_show_index(int argc, const char **argv, const char *prefix) +int cmd_show_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i; unsigned nr; diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 839a5c29f3..285cd3e433 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -63,7 +64,7 @@ struct show_ref_data { int show_head; }; -static int show_ref(const char *refname, const struct object_id *oid, +static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag UNUSED, void *cbdata) { struct show_ref_data *data = cbdata; @@ -97,6 +98,7 @@ match: } static int add_existing(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flag UNUSED, void *cbdata) { @@ -286,15 +288,18 @@ static int exclude_existing_callback(const struct option *opt, const char *arg, return 0; } -int cmd_show_ref(int argc, const char **argv, const char *prefix) +int cmd_show_ref(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct exclude_existing_options exclude_existing_opts = {0}; struct patterns_options patterns_opts = {0}; struct show_one_options show_one_opts = {0}; int verify = 0, exists = 0; const struct option show_ref_options[] = { - OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with branches)")), - OPT_BOOL(0, "branches", &patterns_opts.branches_only, N_("only show branches (can be combined with tags)")), + OPT_BOOL(0, "tags", &patterns_opts.tags_only, N_("only show tags (can be combined with --branches)")), + OPT_BOOL(0, "branches", &patterns_opts.branches_only, N_("only show branches (can be combined with --tags)")), OPT_HIDDEN_BOOL(0, "heads", &patterns_opts.branches_only, N_("deprecated synonym for --branches")), OPT_BOOL(0, "exists", &exists, N_("check for reference existence without resolving")), diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 2604ab04df..49aedc1de8 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "dir.h" @@ -7,7 +8,6 @@ #include "object-name.h" #include "parse-options.h" #include "pathspec.h" -#include "repository.h" #include "strbuf.h" #include "string-list.h" #include "lockfile.h" @@ -327,7 +327,6 @@ static int write_patterns_and_update(struct pattern_list *pl) { char *sparse_filename; FILE *fp; - int fd; struct lock_file lk = LOCK_INIT; int result; @@ -336,31 +335,31 @@ static int write_patterns_and_update(struct pattern_list *pl) if (safe_create_leading_directories(sparse_filename)) die(_("failed to create directory for sparse-checkout file")); - fd = hold_lock_file_for_update(&lk, sparse_filename, - LOCK_DIE_ON_ERROR); - free(sparse_filename); + hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR); result = update_working_directory(pl); if (result) { rollback_lock_file(&lk); - clear_pattern_list(pl); update_working_directory(NULL); - return result; + goto out; } - fp = xfdopen(fd, "w"); + fp = fdopen_lock_file(&lk, "w"); + if (!fp) + die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk)); if (core_sparse_checkout_cone) write_cone_to_file(fp, pl); else write_patterns_to_file(fp, pl); - fflush(fp); - commit_lock_file(&lk); + if (commit_lock_file(&lk)) + die_errno(_("unable to write %s"), sparse_filename); +out: clear_pattern_list(pl); - - return 0; + free(sparse_filename); + return result; } enum sparse_checkout_mode { @@ -925,6 +924,11 @@ static int sparse_checkout_disable(int argc, const char **argv, builtin_sparse_checkout_disable_options, builtin_sparse_checkout_disable_usage, 0); + /* + * Disable the advice message for expanding a sparse index, as we + * are expecting to do that when disabling sparse-checkout. + */ + give_advice_on_expansion = 0; repo_read_index(the_repository); memset(&pl, 0, sizeof(pl)); @@ -1030,7 +1034,10 @@ static int sparse_checkout_check_rules(int argc, const char **argv, const char * return ret; } -int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) +int cmd_sparse_checkout(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option builtin_sparse_checkout_options[] = { diff --git a/builtin/stash.c b/builtin/stash.c index 80ccfc7a08..1399a1bbe2 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "config.h" @@ -19,6 +20,7 @@ #include "entry.h" #include "preload-index.h" #include "read-cache.h" +#include "repository.h" #include "rerere.h" #include "revision.h" #include "setup.h" @@ -484,7 +486,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree) " to make room.\n"), ce->name, new_path.buf); if (rename(ce->name, new_path.buf)) - die("Failed to move %s to %s\n", + die("Failed to move %s to %s", ce->name, new_path.buf); strbuf_release(&new_path); } @@ -539,8 +541,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, NULL, NULL, NULL)) return error(_("could not write index")); - if (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0, - NULL)) + if (write_index_as_tree(&c_tree, the_repository->index, + repo_get_index_file(the_repository), 0, NULL)) return error(_("cannot apply a stash in the middle of a merge")); if (index) { @@ -565,7 +567,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, discard_index(the_repository->index); repo_read_index(the_repository); if (write_index_as_tree(&index_tree, the_repository->index, - get_index_file(), 0, NULL)) + repo_get_index_file(the_repository), 0, NULL)) return error(_("could not save index tree")); reset_head(); @@ -574,7 +576,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, } } - init_merge_options(&o, the_repository); + init_ui_merge_options(&o, the_repository); o.branch1 = "Updated upstream"; o.branch2 = "Stashed changes"; @@ -640,9 +642,9 @@ restore_untracked: cp.git_cmd = 1; cp.dir = prefix; strvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT"=%s", - absolute_path(get_git_work_tree())); + absolute_path(repo_get_work_tree(the_repository))); strvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT"=%s", - absolute_path(get_git_dir())); + absolute_path(repo_get_git_dir(the_repository))); strvec_push(&cp.args, "status"); run_command(&cp); } @@ -974,7 +976,7 @@ static int show_stash(int argc, const char **argv, const char *prefix) } log_tree_diff_flush(&rev); - ret = diff_result_code(&rev.diffopt); + ret = diff_result_code(&rev); cleanup: strvec_clear(&revision_args); @@ -1126,13 +1128,13 @@ static int check_changes_tracked_files(const struct pathspec *ps) diff_setup_done(&rev.diffopt); run_diff_index(&rev, DIFF_INDEX_CACHED); - if (diff_result_code(&rev.diffopt)) { + if (diff_result_code(&rev)) { ret = 1; goto done; } run_diff_files(&rev, 0); - if (diff_result_code(&rev.diffopt)) { + if (diff_result_code(&rev)) { ret = 1; goto done; } @@ -1405,8 +1407,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf); commit_list_insert(head_commit, &parents); - if (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0, - NULL) || + if (write_index_as_tree(&info->i_tree, the_repository->index, + repo_get_index_file(the_repository), 0, NULL) || commit_tree(commit_tree_label.buf, commit_tree_label.len, &info->i_tree, parents, &info->i_commit, NULL, NULL)) { if (!quiet) @@ -1521,6 +1523,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q struct strbuf patch = STRBUF_INIT; struct strbuf stash_msg_buf = STRBUF_INIT; struct strbuf untracked_files = STRBUF_INIT; + struct strbuf out = STRBUF_INIT; if (patch_mode && keep_index == -1) keep_index = 1; @@ -1626,7 +1629,6 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q struct child_process cp_add = CHILD_PROCESS_INIT; struct child_process cp_diff = CHILD_PROCESS_INIT; struct child_process cp_apply = CHILD_PROCESS_INIT; - struct strbuf out = STRBUF_INIT; cp_add.git_cmd = 1; strvec_push(&cp_add.args, "add"); @@ -1739,6 +1741,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q done: strbuf_release(&patch); + strbuf_release(&out); free_stash_info(&info); strbuf_release(&stash_msg_buf); strbuf_release(&untracked_files); @@ -1756,7 +1759,7 @@ static int push_stash(int argc, const char **argv, const char *prefix, int quiet = 0; int pathspec_file_nul = 0; const char *stash_msg = NULL; - const char *pathspec_from_file = NULL; + char *pathspec_from_file = NULL; struct pathspec ps; struct option options[] = { OPT_BOOL('k', "keep-index", &keep_index, @@ -1818,7 +1821,9 @@ static int push_stash(int argc, const char **argv, const char *prefix, ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, include_untracked, only_staged); + clear_pathspec(&ps); + free(pathspec_from_file); return ret; } @@ -1870,7 +1875,10 @@ static int save_stash(int argc, const char **argv, const char *prefix) return ret; } -int cmd_stash(int argc, const char **argv, const char *prefix) +int cmd_stash(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { pid_t pid = getpid(); const char *index_file; @@ -1890,6 +1898,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix) OPT_SUBCOMMAND_F("save", &fn, save_stash, PARSE_OPT_NOCOMPLETE), OPT_END() }; + const char **args_copy; + int ret; git_config(git_stash_config, NULL); @@ -1901,7 +1911,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - index_file = get_index_file(); + index_file = repo_get_index_file(the_repository); strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file, (uintmax_t)pid); @@ -1913,5 +1923,16 @@ int cmd_stash(int argc, const char **argv, const char *prefix) /* Assume 'stash push' */ strvec_push(&args, "push"); strvec_pushv(&args, argv); - return !!push_stash(args.nr, args.v, prefix, 1); + + /* + * `push_stash()` ends up modifying the array, which causes memory + * leaks if we didn't copy the array here. + */ + DUP_ARRAY(args_copy, args.v, args.nr); + + ret = !!push_stash(args.nr, args_copy, prefix, 1); + + strvec_clear(&args); + free(args_copy); + return ret; } diff --git a/builtin/stripspace.c b/builtin/stripspace.c index e5626e5126..e147f3ff92 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "environment.h" @@ -29,7 +30,10 @@ enum stripspace_mode { COMMENT_LINES }; -int cmd_stripspace(int argc, const char **argv, const char *prefix) +int cmd_stripspace(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buf = STRBUF_INIT; enum stripspace_mode mode = STRIP_DEFAULT; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f1218a1995..dc89488a7d 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1,9 +1,10 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "repository.h" + #include "config.h" #include "parse-options.h" #include "quote.h" @@ -363,9 +364,13 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, if (!info->quiet) printf(_("Entering '%s'\n"), displaypath); - if (info->argv[0] && run_command(&cp)) - die(_("run_command returned non-zero status for %s\n."), - displaypath); + if (info->argv[0]) { + if (run_command(&cp)) + die(_("run_command returned non-zero status for %s\n."), + displaypath); + } else { + child_process_clear(&cp); + } if (info->recursive) { struct child_process cpr = CHILD_PROCESS_INIT; @@ -608,6 +613,7 @@ static void print_status(unsigned int flags, char state, const char *path, } static int handle_submodule_head_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid, int flags UNUSED, void *cb_data) @@ -671,7 +677,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, setup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt); run_diff_files(&rev, 0); - if (!diff_result_code(&rev.diffopt)) { + if (!diff_result_code(&rev)) { print_status(flags, ' ', path, ce_oid, displaypath); } else if (!(flags & OPT_CACHED)) { @@ -694,6 +700,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_RECURSIVE) { struct child_process cpr = CHILD_PROCESS_INIT; + int res; cpr.git_cmd = 1; cpr.dir = path; @@ -709,7 +716,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (flags & OPT_QUIET) strvec_push(&cpr.args, "--quiet"); - if (run_command(&cpr)) + res = run_command(&cpr); + if (res == SIGPIPE + 128) + raise(SIGPIPE); + else if (res) die(_("failed to recurse into submodule '%s'"), path); } @@ -916,7 +926,7 @@ static void generate_submodule_summary(struct summary_cb *info, } else { /* for a submodule removal (mode:0000000), don't warn */ if (p->mod_dst) - warning(_("unexpected mode %o\n"), p->mod_dst); + warning(_("unexpected mode %o"), p->mod_dst); } } @@ -1455,7 +1465,7 @@ static void deinit_submodule(const char *path, const char *prefix, * remove the whole section so we have a clean state when * the user later decides to init this submodule again */ - git_config_rename_section_in_file(NULL, sub_key, NULL); + repo_config_rename_section_in_file(the_repository, NULL, sub_key, NULL); if (!(flags & OPT_QUIET)) printf(_("Submodule '%s' (%s) unregistered for path '%s'\n"), sub->name, sub->url, displaypath); @@ -1530,8 +1540,9 @@ struct module_clone_data { const char *path; const char *name; const char *url; - const char *depth; + int depth; struct list_objects_filter_options *filter_options; + enum ref_storage_format ref_storage_format; unsigned int quiet: 1; unsigned int progress: 1; unsigned int dissociate: 1; @@ -1540,6 +1551,7 @@ struct module_clone_data { }; #define MODULE_CLONE_DATA_INIT { \ .single_branch = -1, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ } struct submodule_alternate_setup { @@ -1614,6 +1626,8 @@ static int add_possible_reference_from_superproject( ; /* nothing */ } } + + strbuf_release(&err); strbuf_release(&sb); } @@ -1706,7 +1720,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, exit(128); if (!is_absolute_path(clone_data->path)) - clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(), + clone_data_path = to_free = xstrfmt("%s/%s", repo_get_work_tree(the_repository), clone_data->path); if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0) @@ -1729,8 +1743,8 @@ static int clone_submodule(const struct module_clone_data *clone_data, strvec_push(&cp.args, "--quiet"); if (clone_data->progress) strvec_push(&cp.args, "--progress"); - if (clone_data->depth && *(clone_data->depth)) - strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL); + if (clone_data->depth > 0) + strvec_pushf(&cp.args, "--depth=%d", clone_data->depth); if (reference->nr) { struct string_list_item *item; @@ -1738,6 +1752,9 @@ static int clone_submodule(const struct module_clone_data *clone_data, strvec_pushl(&cp.args, "--reference", item->string, NULL); } + if (clone_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&cp.args, "--ref-format=%s", + ref_storage_format_to_name(clone_data->ref_storage_format)); if (clone_data->dissociate) strvec_push(&cp.args, "--dissociate"); if (sm_gitdir && *sm_gitdir) @@ -1832,6 +1849,7 @@ static int module_clone(int argc, const char **argv, const char *prefix) struct string_list reference = STRING_LIST_INIT_NODUP; struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; + const char *ref_storage_format = NULL; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &clone_data.prefix, @@ -1849,10 +1867,11 @@ static int module_clone(int argc, const char **argv, const char *prefix) OPT_STRING_LIST(0, "reference", &reference, N_("repo"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &dissociate, N_("use --reference only while cloning")), - OPT_STRING(0, "depth", &clone_data.depth, - N_("string"), + OPT_INTEGER(0, "depth", &clone_data.depth, N_("depth for shallow clones")), OPT__QUIET(&quiet, "suppress output for cloning a submodule"), OPT_BOOL(0, "progress", &progress, @@ -1875,6 +1894,11 @@ static int module_clone(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, module_clone_options, git_submodule_helper_usage, 0); + if (ref_storage_format) { + clone_data.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (clone_data.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } clone_data.dissociate = !!dissociate; clone_data.quiet = !!quiet; clone_data.progress = !!progress; @@ -1974,6 +1998,7 @@ struct update_data { struct submodule_update_strategy update_strategy; struct list_objects_filter_options *filter_options; struct module_list list; + enum ref_storage_format ref_storage_format; int depth; int max_jobs; int single_branch; @@ -1997,6 +2022,7 @@ struct update_data { #define UPDATE_DATA_INIT { \ .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT, \ .list = MODULE_LIST_INIT, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ .recommend_shallow = -1, \ .references = STRING_LIST_INIT_DUP, \ .single_branch = -1, \ @@ -2006,6 +2032,7 @@ struct update_data { static void update_data_release(struct update_data *ud) { free(ud->displaypath); + submodule_update_strategy_release(&ud->update_strategy); module_list_release(&ud->list); } @@ -2132,6 +2159,9 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, expand_list_objects_filter_spec(suc->update_data->filter_options)); if (suc->update_data->require_init) strvec_push(&child->args, "--require-init"); + if (suc->update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(&child->args, "--ref-format=%s", + ref_storage_format_to_name(suc->update_data->ref_storage_format)); strvec_pushl(&child->args, "--path", sub->path, NULL); strvec_pushl(&child->args, "--name", sub->name, NULL); strvec_pushl(&child->args, "--url", url, NULL); @@ -2269,6 +2299,7 @@ static int is_tip_reachable(const char *path, const struct object_id *oid) struct child_process cp = CHILD_PROCESS_INIT; struct strbuf rev = STRBUF_INIT; char *hex = oid_to_hex(oid); + int reachable; cp.git_cmd = 1; cp.dir = path; @@ -2278,9 +2309,12 @@ static int is_tip_reachable(const char *path, const struct object_id *oid) prepare_submodule_repo_env(&cp.env); if (capture_command(&cp, &rev, GIT_MAX_HEXSZ + 1) || rev.len) - return 0; + reachable = 0; + else + reachable = 1; - return 1; + strbuf_release(&rev); + return reachable; } static int fetch_in_submodule(const char *module_path, int depth, int quiet, @@ -2562,6 +2596,9 @@ static void update_data_to_args(const struct update_data *update_data, for_each_string_list_item(item, &update_data->references) strvec_pushl(args, "--reference", item->string, NULL); } + if (update_data->ref_storage_format != REF_STORAGE_FORMAT_UNKNOWN) + strvec_pushf(args, "--ref-format=%s", + ref_storage_format_to_name(update_data->ref_storage_format)); if (update_data->filter_options && update_data->filter_options->choice) strvec_pushf(args, "--filter=%s", expand_list_objects_filter_spec( @@ -2616,15 +2653,20 @@ static int update_submodule(struct update_data *update_data) if (!update_data->nofetch) { if (fetch_in_submodule(update_data->sm_path, update_data->depth, - 0, NULL)) + 0, NULL)) { + free(remote_ref); return die_message(_("Unable to fetch in submodule path '%s'"), update_data->sm_path); + } } if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, - remote_ref, &update_data->oid)) - return die_message(_("Unable to find %s revision in submodule path '%s'"), - remote_ref, update_data->sm_path); + remote_ref, &update_data->oid)) { + ret = die_message(_("Unable to find %s revision in submodule path '%s'"), + remote_ref, update_data->sm_path); + free(remote_ref); + return ret; + } free(remote_ref); } @@ -2737,6 +2779,7 @@ static int module_update(int argc, const char **argv, const char *prefix) struct update_data opt = UPDATE_DATA_INIT; struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; + const char *ref_storage_format = NULL; int ret; struct option module_update_options[] = { OPT__SUPER_PREFIX(&opt.super_prefix), @@ -2760,6 +2803,8 @@ static int module_update(int argc, const char **argv, const char *prefix) SM_UPDATE_REBASE), OPT_STRING_LIST(0, "reference", &opt.references, N_("repo"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &opt.dissociate, N_("use --reference only while cloning")), OPT_INTEGER(0, "depth", &opt.depth, @@ -2803,6 +2848,12 @@ static int module_update(int argc, const char **argv, const char *prefix) module_update_options); } + if (ref_storage_format) { + opt.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (opt.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } + opt.filter_options = &filter_options; opt.prefix = prefix; @@ -2924,7 +2975,9 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED) rs->src); } } + refspec_clear(&refspec); + free_refs(local_refs); } free(head); @@ -3098,13 +3151,17 @@ struct add_data { const char *sm_name; const char *repo; const char *realrepo; + enum ref_storage_format ref_storage_format; int depth; unsigned int force: 1; unsigned int quiet: 1; unsigned int progress: 1; unsigned int dissociate: 1; }; -#define ADD_DATA_INIT { .depth = -1 } +#define ADD_DATA_INIT { \ + .depth = -1, \ + .ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN, \ +} static void append_fetch_remotes(struct strbuf *msg, const char *git_dir_path) { @@ -3198,9 +3255,10 @@ static int add_submodule(const struct add_data *add_data) string_list_append(&reference, p)->util = p; } + clone_data.ref_storage_format = add_data->ref_storage_format; clone_data.dissociate = add_data->dissociate; if (add_data->depth >= 0) - clone_data.depth = xstrfmt("%d", add_data->depth); + clone_data.depth = add_data->depth; if (clone_submodule(&clone_data, &reference)) goto cleanup; @@ -3223,6 +3281,7 @@ static int add_submodule(const struct add_data *add_data) die(_("unable to checkout submodule '%s'"), add_data->sm_path); } ret = 0; + cleanup: string_list_clear(&reference, 1); return ret; @@ -3362,6 +3421,7 @@ static int module_add(int argc, const char **argv, const char *prefix) { int force = 0, quiet = 0, progress = 0, dissociate = 0; struct add_data add_data = ADD_DATA_INIT; + const char *ref_storage_format = NULL; char *to_free = NULL; struct option options[] = { OPT_STRING('b', "branch", &add_data.branch, N_("branch"), @@ -3372,6 +3432,8 @@ static int module_add(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "progress", &progress, N_("force cloning progress")), OPT_STRING(0, "reference", &add_data.reference_path, N_("repository"), N_("reference repository")), + OPT_STRING(0, "ref-format", &ref_storage_format, N_("format"), + N_("specify the reference format to use")), OPT_BOOL(0, "dissociate", &dissociate, N_("borrow the objects from reference repositories")), OPT_STRING(0, "name", &add_data.sm_name, N_("name"), N_("sets the submodule's name to the given string " @@ -3398,6 +3460,12 @@ static int module_add(int argc, const char **argv, const char *prefix) if (argc == 0 || argc > 2) usage_with_options(usage, options); + if (ref_storage_format) { + add_data.ref_storage_format = ref_storage_format_by_name(ref_storage_format); + if (add_data.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), ref_storage_format); + } + add_data.repo = argv[0]; if (argc == 1) add_data.sm_path = git_url_basename(add_data.repo, 0, 0); @@ -3479,7 +3547,10 @@ cleanup: return ret; } -int cmd_submodule__helper(int argc, const char **argv, const char *prefix) +int cmd_submodule__helper(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; const char *const usage[] = { diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index 81abdd170f..299d23d76a 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -41,7 +42,10 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i return 0; } -int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) +int cmd_symbolic_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int quiet = 0, delete = 0, shorten = 0, recurse = 1, ret = 0; const char *msg = NULL; diff --git a/builtin/tag.c b/builtin/tag.c index a1fb218512..93d10d5915 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -5,7 +5,7 @@ * Carlos Rica <jasampler@gmail.com> * Based on git-tag.sh and mktag.c by Linus Torvalds. */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "advice.h" #include "config.h" @@ -160,7 +160,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid, const struct git_hash_algo *compat = the_repository->compat_hash_algo; struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT; struct strbuf compat_buf = STRBUF_INIT; - const char *keyid = get_signing_key(); + char *keyid = get_signing_key(); int ret = -1; if (sign_buffer(buffer, &sig, keyid)) @@ -190,6 +190,7 @@ out: strbuf_release(&sig); strbuf_release(&compat_sig); strbuf_release(&compat_buf); + free(keyid); return ret; } @@ -457,7 +458,10 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name) return check_refname_format(sb->buf, 0); } -int cmd_tag(int argc, const char **argv, const char *prefix) +int cmd_tag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strbuf buf = STRBUF_INIT; struct strbuf ref = STRBUF_INIT; @@ -702,6 +706,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) cleanup: ref_sorting_release(sorting); ref_filter_clear(&filter); + ref_format_clear(&format); strbuf_release(&buf); strbuf_release(&ref); strbuf_release(&reflog_msg); diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index c129e2bb6c..6da2825753 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -25,7 +26,10 @@ static char *create_temp_file(struct object_id *oid) return path; } -int cmd_unpack_file(int argc, const char **argv, const char *prefix UNUSED) +int cmd_unpack_file(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { struct object_id oid; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 08fa2a7a74..02b8d02f63 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "bulk-checkin.h" #include "config.h" @@ -601,7 +602,10 @@ static void unpack_all(void) die("unresolved deltas left after unpacking"); } -int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED) +int cmd_unpack_objects(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { int i; struct object_id oid; diff --git a/builtin/update-index.c b/builtin/update-index.c index d343416ae2..45b4a8b555 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "bulk-checkin.h" #include "config.h" @@ -22,7 +22,6 @@ #include "pathspec.h" #include "dir.h" #include "read-cache.h" -#include "repository.h" #include "setup.h" #include "sparse-index.h" #include "split-index.h" @@ -917,7 +916,10 @@ static enum parse_opt_result reupdate_callback( return 0; } -int cmd_update_index(int argc, const char **argv, const char *prefix) +int cmd_update_index(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int newfd, entries, has_errors = 0, nul_term_line = 0; enum uc_mode untracked_cache = UC_UNSPECIFIED; @@ -1156,7 +1158,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) end_odb_transaction(); if (split_index > 0) { - if (git_config_get_split_index() == 0) + if (repo_config_get_split_index(the_repository) == 0) warning(_("core.splitIndex is set to false; " "remove or change it, if you really want to " "enable split index")); @@ -1165,7 +1167,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) else add_split_index(the_repository->index); } else if (!split_index) { - if (git_config_get_split_index() == 1) + if (repo_config_get_split_index(the_repository) == 1) warning(_("core.splitIndex is set to true; " "remove or change it, if you really want to " "disable split index")); @@ -1194,7 +1196,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) "remove or change it, if you really want to " "enable the untracked cache")); add_untracked_cache(the_repository->index); - report(_("Untracked cache enabled for '%s'"), get_git_work_tree()); + report(_("Untracked cache enabled for '%s'"), repo_get_work_tree(the_repository)); break; default: BUG("bad untracked_cache value: %d", untracked_cache); @@ -1239,7 +1241,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) if (newfd < 0) { if (refresh_args.flags & REFRESH_QUIET) exit(128); - unable_to_lock_die(get_index_file(), lock_error); + unable_to_lock_die(repo_get_index_file(the_repository), lock_error); } if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 6a6a2ff55d..8a98615dc8 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -6,7 +7,6 @@ #include "object-name.h" #include "parse-options.h" #include "quote.h" -#include "repository.h" static const char * const git_update_ref_usage[] = { N_("git update-ref [<options>] -d <refname> [<old-oid>]"), @@ -274,7 +274,7 @@ static void parse_cmd_update(struct ref_transaction *transaction, } static void parse_cmd_symref_update(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { char *refname, *new_target, *old_arg; char *old_target = NULL; @@ -360,7 +360,7 @@ static void parse_cmd_create(struct ref_transaction *transaction, static void parse_cmd_symref_create(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; char *refname, *new_target; @@ -423,7 +423,7 @@ static void parse_cmd_delete(struct ref_transaction *transaction, static void parse_cmd_symref_delete(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; char *refname, *old_target; @@ -479,7 +479,7 @@ static void parse_cmd_verify(struct ref_transaction *transaction, } static void parse_cmd_symref_verify(struct ref_transaction *transaction, - const char *next, const char *end) + const char *next, const char *end UNUSED) { struct strbuf err = STRBUF_INIT; struct object_id old_oid; @@ -713,7 +713,10 @@ static void update_refs_stdin(void) strbuf_release(&input); } -int cmd_update_ref(int argc, const char **argv, const char *prefix) +int cmd_update_ref(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *refname, *oldval; struct object_id oid, oldoid; diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index 1dc3971ede..6769611a02 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -9,7 +10,10 @@ static const char * const update_server_info_usage[] = { NULL }; -int cmd_update_server_info(int argc, const char **argv, const char *prefix) +int cmd_update_server_info(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int force = 0; struct option options[] = { diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 1b09e5e1aa..9e9343f121 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -1,12 +1,12 @@ /* * Copyright (c) 2006 Franck Bui-Huu */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "archive.h" #include "path.h" #include "pkt-line.h" #include "sideband.h" -#include "repository.h" #include "run-command.h" #include "strvec.h" @@ -18,10 +18,14 @@ static const char deadchild[] = #define MAX_ARGS (64) -int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) +int cmd_upload_archive_writer(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { struct strvec sent_argv = STRVEC_INIT; const char *arg_cmd = "argument "; + int ret; if (argc != 2 || !strcmp(argv[1], "-h")) usage(upload_archive_usage); @@ -46,8 +50,11 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) } /* parse all options sent by the client */ - return write_archive(sent_argv.nr, sent_argv.v, prefix, - the_repository, NULL, 1); + ret = write_archive(sent_argv.nr, sent_argv.v, prefix, + the_repository, NULL, 1); + + strvec_clear(&sent_argv); + return ret; } __attribute__((format (printf, 1, 2))) @@ -76,7 +83,10 @@ static ssize_t process_input(int child_fd, int band) return sz; } -int cmd_upload_archive(int argc, const char **argv, const char *prefix) +int cmd_upload_archive(int argc, +const char **argv, +const char *prefix, +struct repository *repo UNUSED) { struct child_process writer = CHILD_PROCESS_INIT; diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index 46d93278d9..3b6c83fbce 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -17,7 +17,10 @@ static const char * const upload_pack_usage[] = { NULL }; -int cmd_upload_pack(int argc, const char **argv, const char *prefix) +int cmd_upload_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { const char *dir; int strict = 0; diff --git a/builtin/var.c b/builtin/var.c index e30ff45be1..2ecaed51b4 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -3,7 +3,9 @@ * * Copyright (C) Eric Biederman, 2005 */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" + #include "attr.h" #include "config.h" #include "editor.h" @@ -210,7 +212,10 @@ static int show_config(const char *var, const char *value, return git_default_config(var, value, ctx, cb); } -int cmd_var(int argc, const char **argv, const char *prefix UNUSED) +int cmd_var(int argc, + const char **argv, + const char *prefix UNUSED, + struct repository *repo UNUSED) { const struct git_var *git_var; char *val; diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 0d2b9aea2a..779b7988ca 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,11 +5,11 @@ * * Based on git-verify-tag */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" #include "object-name.h" -#include "repository.h" #include "commit.h" #include "parse-options.h" #include "gpg-interface.h" @@ -51,7 +51,10 @@ static int verify_commit(const char *name, unsigned flags) return run_gpg_verify((struct commit *)obj, flags); } -int cmd_verify_commit(int argc, const char **argv, const char *prefix) +int cmd_verify_commit(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c index 011dddd2dc..34e4ed715f 100644 --- a/builtin/verify-pack.c +++ b/builtin/verify-pack.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -61,7 +62,10 @@ static const char * const verify_pack_usage[] = { NULL }; -int cmd_verify_pack(int argc, const char **argv, const char *prefix) +int cmd_verify_pack(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int err = 0; unsigned int flags = 0; diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index c731e2f87b..a7f20618ff 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,6 +5,7 @@ * * Based on git-verify-tag.sh */ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -19,7 +20,10 @@ static const char * const verify_tag_usage[] = { NULL }; -int cmd_verify_tag(int argc, const char **argv, const char *prefix) +int cmd_verify_tag(int argc, + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -65,5 +69,6 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) if (format.format) pretty_print_ref(name, &oid, &format); } + ref_format_clear(&format); return had_error; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 1d51e54fcd..fc31d072a6 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -1,3 +1,4 @@ +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "abspath.h" #include "advice.h" @@ -17,7 +18,6 @@ #include "read-cache-ll.h" #include "refs.h" #include "remote.h" -#include "repository.h" #include "run-command.h" #include "hook.h" #include "sigchain.h" @@ -219,7 +219,7 @@ static void prune_worktrees(void) } closedir(dir); - strbuf_add_absolute_path(&main_path, get_git_common_dir()); + strbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository)); /* massage main worktree absolute path to match 'gitdir' content */ strbuf_strip_suffix(&main_path, "/."); string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL)); @@ -492,7 +492,7 @@ static int add_worktree(const char *path, const char *refname, strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); strbuf_realpath(&realpath, sb_git.buf, 1); write_file(sb.buf, "%s", realpath.buf); - strbuf_realpath(&realpath, get_git_common_dir(), 1); + strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1); write_file(sb_git.buf, "gitdir: %s/worktrees/%s", realpath.buf, name); strbuf_reset(&sb); @@ -573,7 +573,7 @@ done: NULL); opt.dir = path; - ret = run_hooks_opt("post-checkout", &opt); + ret = run_hooks_opt(the_repository, "post-checkout", &opt); } strvec_clear(&child_env); @@ -626,6 +626,7 @@ static void print_preparing_worktree_line(int detach, * Returns 0 on failure and non-zero on success. */ static int first_valid_ref(const char *refname UNUSED, + const char *referent UNUSED, const struct object_id *oid UNUSED, int flags UNUSED, void *cb_data UNUSED) @@ -769,7 +770,7 @@ static int add(int ac, const char **av, const char *prefix) char *branch_to_free = NULL; char *new_branch_to_free = NULL; const char *new_branch = NULL; - const char *opt_track = NULL; + char *opt_track = NULL; const char *lock_reason = NULL; int keep_locked = 0; int used_new_branch_options; @@ -846,7 +847,7 @@ static int add(int ac, const char **av, const char *prefix) if (opts.orphan && !new_branch) { int n; const char *s = worktree_basename(path, &n); - new_branch = xstrndup(s, n); + new_branch = new_branch_to_free = xstrndup(s, n); } else if (opts.orphan) { ; /* no-op */ } else if (opts.detach) { @@ -875,7 +876,7 @@ static int add(int ac, const char **av, const char *prefix) remote = unique_tracking_name(branch, &oid, NULL); if (remote) { new_branch = branch; - branch = remote; + branch = new_branch_to_free = remote; } } @@ -923,6 +924,7 @@ static int add(int ac, const char **av, const char *prefix) ret = add_worktree(path, branch, &opts); free(path); + free(opt_track); free(branch_to_free); free(new_branch_to_free); return ret; @@ -1146,14 +1148,14 @@ static void validate_no_submodules(const struct worktree *wt) struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; - if (is_directory(worktree_git_path(wt, "modules"))) { + if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* * There could be false positives, e.g. the "modules" * directory exists but is empty. But it's a rare case and * this simpler check is probably good enough for now. */ found_submodules = 1; - } else if (read_index_from(&istate, worktree_git_path(wt, "index"), + } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), get_worktree_git_dir(wt)) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; @@ -1390,7 +1392,10 @@ static int repair(int ac, const char **av, const char *prefix) return rc; } -int cmd_worktree(int ac, const char **av, const char *prefix) +int cmd_worktree(int ac, + const char **av, + const char *prefix, + struct repository *repo UNUSED) { parse_opt_subcommand_fn *fn = NULL; struct option options[] = { diff --git a/builtin/write-tree.c b/builtin/write-tree.c index 8c75b4609b..43f233e69b 100644 --- a/builtin/write-tree.c +++ b/builtin/write-tree.c @@ -3,23 +3,24 @@ * * Copyright (C) Linus Torvalds, 2005 */ - +#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" -#include "environment.h" #include "gettext.h" #include "hex.h" #include "tree.h" #include "cache-tree.h" #include "parse-options.h" -#include "repository.h" static const char * const write_tree_usage[] = { N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"), NULL }; -int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix) +int cmd_write_tree(int argc, + const char **argv, + const char *cmd_prefix, + struct repository *repo UNUSED) { int flags = 0, ret; const char *tree_prefix = NULL; @@ -44,7 +45,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; - ret = write_index_as_tree(&oid, the_repository->index, get_index_file(), + ret = write_index_as_tree(&oid, the_repository->index, + repo_get_index_file(the_repository), flags, tree_prefix); switch (ret) { case 0: |
