diff options
Diffstat (limited to 'builtin')
92 files changed, 903 insertions, 408 deletions
diff --git a/builtin/add.c b/builtin/add.c index f12054d9be..76cc026a68 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -5,9 +5,11 @@ */ #define USE_THE_INDEX_VARIABLE #include "cache.h" +#include "advice.h" #include "config.h" #include "builtin.h" #include "lockfile.h" +#include "editor.h" #include "dir.h" #include "gettext.h" #include "pathspec.h" diff --git a/builtin/am.c b/builtin/am.c index cd1e20f24e..5c83f2e003 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -6,8 +6,10 @@ #define USE_THE_INDEX_VARIABLE #include "cache.h" #include "abspath.h" +#include "advice.h" #include "config.h" #include "builtin.h" +#include "editor.h" #include "environment.h" #include "exec-cmd.h" #include "gettext.h" @@ -26,6 +28,7 @@ #include "diffcore.h" #include "unpack-trees.h" #include "branch.h" +#include "object-name.h" #include "sequencer.h" #include "revision.h" #include "merge-recursive.h" @@ -37,6 +40,7 @@ #include "apply.h" #include "string-list.h" #include "packfile.h" +#include "pager.h" #include "repository.h" #include "pretty.h" #include "wrapper.h" diff --git a/builtin/apply.c b/builtin/apply.c index fe72c0ec3e..e3ff02a09e 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2,6 +2,7 @@ #include "builtin.h" #include "gettext.h" #include "parse-options.h" +#include "repository.h" #include "apply.h" static const char * const apply_usage[] = { diff --git a/builtin/archive.c b/builtin/archive.c index d13934f1a8..b0eaa3c14a 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -9,6 +9,7 @@ #include "transport.h" #include "parse-options.h" #include "pkt-line.h" +#include "repository.h" #include "sideband.h" static void create_output_file(const char *output_file) diff --git a/builtin/bisect.c b/builtin/bisect.c index 26f07357a0..4812450c39 100644 --- a/builtin/bisect.c +++ b/builtin/bisect.c @@ -1,14 +1,17 @@ #include "builtin.h" #include "cache.h" +#include "copy.h" #include "environment.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "parse-options.h" #include "bisect.h" #include "refs.h" #include "dir.h" #include "strvec.h" #include "run-command.h" +#include "oid-array.h" #include "prompt.h" #include "quote.h" #include "revision.h" diff --git a/builtin/blame.c b/builtin/blame.c index a8d2114adc..2df6039a6e 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -28,7 +28,9 @@ #include "line-log.h" #include "dir.h" #include "progress.h" +#include "object-name.h" #include "object-store.h" +#include "pager.h" #include "blame.h" #include "refs.h" #include "setup.h" diff --git a/builtin/branch.c b/builtin/branch.c index 6413a016c5..e6c2655af6 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -8,11 +8,13 @@ #include "cache.h" #include "config.h" #include "color.h" +#include "editor.h" #include "environment.h" #include "refs.h" #include "commit.h" #include "builtin.h" #include "gettext.h" +#include "object-name.h" #include "remote.h" #include "parse-options.h" #include "branch.h" @@ -44,6 +46,7 @@ static const char *head; static struct object_id head_oid; static int recurse_submodules = 0; static int submodule_propagate_branches = 0; +static int omit_empty = 0; static int branch_use_color = -1; static char branch_colors[][COLOR_MAXLEN] = { @@ -220,10 +223,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, struct string_list refs_to_delete = STRING_LIST_INIT_DUP; struct string_list_item *item; int branch_name_pos; + const char *fmt_remotes = "refs/remotes/%s"; switch (kinds) { case FILTER_REFS_REMOTES: - fmt = "refs/remotes/%s"; + fmt = fmt_remotes; /* For subsequent UI messages */ remote_branch = 1; allowed_interpret = INTERPRET_BRANCH_REMOTE; @@ -267,9 +271,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, | RESOLVE_REF_ALLOW_BAD_NAME, &oid, &flags); if (!target) { - error(remote_branch - ? _("remote-tracking branch '%s' not found.") - : _("branch '%s' not found."), bname.buf); + if (remote_branch) { + error(_("remote-tracking branch '%s' not found."), bname.buf); + } else { + char *virtual_name = mkpathdup(fmt_remotes, bname.buf); + char *virtual_target = resolve_refdup(virtual_name, + RESOLVE_REF_READING + | RESOLVE_REF_NO_RECURSE + | RESOLVE_REF_ALLOW_BAD_NAME, + &oid, &flags); + FREE_AND_NULL(virtual_name); + + if (virtual_target) + error(_("branch '%s' not found.\n" + "Did you forget --remote?"), + bname.buf); + else + error(_("branch '%s' not found."), bname.buf); + FREE_AND_NULL(virtual_target); + } ret = 1; continue; } @@ -466,7 +486,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin string_list_append(output, out.buf); } else { fwrite(out.buf, 1, out.len, stdout); - putchar('\n'); + if (out.len || !omit_empty) + putchar('\n'); } } @@ -491,9 +512,9 @@ static void print_current_branch_name(void) die(_("HEAD (%s) points outside of refs/heads/"), refname); } -static void reject_rebase_or_bisect_branch(const char *target) +static void reject_rebase_or_bisect_branch(struct worktree **worktrees, + const char *target) { - struct worktree **worktrees = get_worktrees(); int i; for (i = 0; worktrees[i]; i++) { @@ -510,17 +531,50 @@ static void reject_rebase_or_bisect_branch(const char *target) die(_("Branch %s is being bisected at %s"), target, wt->path); } +} - free_worktrees(worktrees); +/* + * Update all per-worktree HEADs pointing at the old ref to point the new ref. + * This will be used when renaming a branch. Returns 0 if successful, non-zero + * otherwise. + */ +static int replace_each_worktree_head_symref(struct worktree **worktrees, + const char *oldref, const char *newref, + const char *logmsg) +{ + int ret = 0; + int i; + + for (i = 0; worktrees[i]; i++) { + struct ref_store *refs; + + if (worktrees[i]->is_detached) + continue; + if (!worktrees[i]->head_ref) + continue; + if (strcmp(oldref, worktrees[i]->head_ref)) + continue; + + refs = get_worktree_ref_store(worktrees[i]); + if (refs_create_symref(refs, "HEAD", newref, logmsg)) + ret = error(_("HEAD of working tree %s is not updated"), + worktrees[i]->path); + } + + return ret; } +#define IS_HEAD 1 +#define IS_ORPHAN 2 + static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force) { struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT; struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT; const char *interpreted_oldname = NULL; const char *interpreted_newname = NULL; - int recovery = 0; + int recovery = 0, oldref_usage = 0; + struct worktree **worktrees = get_worktrees(); if (strbuf_check_branch_ref(&oldref, oldname)) { /* @@ -533,8 +587,19 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int die(_("Invalid branch name: '%s'"), oldname); } - if ((copy || strcmp(head, oldname)) && !ref_exists(oldref.buf)) { - if (copy && !strcmp(head, oldname)) + for (int i = 0; worktrees[i]; i++) { + struct worktree *wt = worktrees[i]; + + if (wt->head_ref && !strcmp(oldref.buf, wt->head_ref)) { + oldref_usage |= IS_HEAD; + if (is_null_oid(&wt->head_oid)) + oldref_usage |= IS_ORPHAN; + break; + } + } + + if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) { + if (oldref_usage & IS_HEAD) die(_("No commit on branch '%s' yet."), oldname); else die(_("No branch named '%s'."), oldname); @@ -549,7 +614,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int else validate_new_branchname(newname, &newref, force); - reject_rebase_or_bisect_branch(oldref.buf); + reject_rebase_or_bisect_branch(worktrees, oldref.buf); if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) || !skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) { @@ -563,8 +628,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int strbuf_addf(&logmsg, "Branch: renamed %s to %s", oldref.buf, newref.buf); - if (!copy && - (!head || strcmp(oldname, head) || !is_null_oid(&head_oid)) && + if (!copy && !(oldref_usage & IS_ORPHAN) && rename_ref(oldref.buf, newref.buf, logmsg.buf)) die(_("Branch rename failed")); if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf)) @@ -579,8 +643,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int interpreted_oldname); } - if (!copy && - replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) + if (!copy && (oldref_usage & IS_HEAD) && + replace_each_worktree_head_symref(worktrees, oldref.buf, newref.buf, + logmsg.buf)) die(_("Branch renamed to %s, but HEAD is not updated!"), newname); strbuf_release(&logmsg); @@ -595,6 +660,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int strbuf_release(&newref); strbuf_release(&oldsection); strbuf_release(&newsection); + free_worktrees(worktrees); } static GIT_PATH_FUNC(edit_description, "EDIT_DESCRIPTION") @@ -675,6 +741,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2), OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1), OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2), + OPT_BOOL(0, "omit-empty", &omit_empty, + N_("do not output a newline after empty formatted refs")), OPT_BIT('c', "copy", ©, N_("copy a branch and its reflog"), 1), OPT_BIT('C', NULL, ©, N_("copy a branch, even if target exists"), 2), OPT_BOOL('l', "list", &list, N_("list branch names")), @@ -811,7 +879,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) strbuf_addf(&branch_ref, "refs/heads/%s", branch_name); if (!ref_exists(branch_ref.buf)) - error((!argc || !strcmp(head, branch_name)) + error((!argc || branch_checked_out(branch_ref.buf)) ? _("No commit on branch '%s' yet.") : _("No branch named '%s'."), branch_name); @@ -856,7 +924,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) } if (!ref_exists(branch->refname)) { - if (!argc || !strcmp(head, branch->name)) + if (!argc || branch_checked_out(branch->refname)) die(_("No commit on branch '%s' yet."), branch->name); die(_("branch '%s' does not exist"), branch->name); } diff --git a/builtin/bugreport.c b/builtin/bugreport.c index 52955e1d38..daf6c23657 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -1,5 +1,6 @@ #include "builtin.h" #include "abspath.h" +#include "editor.h" #include "gettext.h" #include "parse-options.h" #include "strbuf.h" @@ -8,6 +9,7 @@ #include "hook.h" #include "hook-list.h" #include "diagnose.h" +#include "object-file.h" #include "setup.h" #include "wrapper.h" diff --git a/builtin/bundle.c b/builtin/bundle.c index e68fc83d94..44113389d7 100644 --- a/builtin/bundle.c +++ b/builtin/bundle.c @@ -4,6 +4,8 @@ #include "setup.h" #include "strvec.h" #include "parse-options.h" +#include "pkt-line.h" +#include "repository.h" #include "cache.h" #include "bundle.h" diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 04d4bb6c77..0bafc14e6c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -7,6 +7,7 @@ #include "cache.h" #include "alloc.h" #include "config.h" +#include "convert.h" #include "builtin.h" #include "diff.h" #include "environment.h" @@ -19,6 +20,8 @@ #include "tree-walk.h" #include "oid-array.h" #include "packfile.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "replace-object.h" #include "promisor-remote.h" diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 1dbe9d6ca8..e27b86d150 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -5,7 +5,9 @@ #include "attr.h" #include "environment.h" #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" @@ -62,7 +64,7 @@ static void output_attr(struct attr_check *check, const char *file) } static void check_attr(const char *prefix, struct attr_check *check, - const struct object_id *tree_oid, int collect_all, + int collect_all, const char *file) { @@ -70,9 +72,9 @@ static void check_attr(const char *prefix, struct attr_check *check, prefix_path(prefix, prefix ? strlen(prefix) : 0, file); if (collect_all) { - git_all_attrs(&the_index, tree_oid, full_path, check); + git_all_attrs(&the_index, full_path, check); } else { - git_check_attr(&the_index, tree_oid, full_path, check); + git_check_attr(&the_index, full_path, check); } output_attr(check, file); @@ -80,7 +82,7 @@ static void check_attr(const char *prefix, struct attr_check *check, } static void check_attr_stdin_paths(const char *prefix, struct attr_check *check, - const struct object_id *tree_oid, int collect_all) + int collect_all) { struct strbuf buf = STRBUF_INIT; struct strbuf unquoted = STRBUF_INIT; @@ -94,7 +96,7 @@ static void check_attr_stdin_paths(const char *prefix, struct attr_check *check, die("line is badly quoted"); strbuf_swap(&buf, &unquoted); } - check_attr(prefix, check, tree_oid, collect_all, buf.buf); + check_attr(prefix, check, collect_all, buf.buf); maybe_flush_or_die(stdout, "attribute to stdout"); } strbuf_release(&buf); @@ -110,7 +112,6 @@ static NORETURN void error_with_usage(const char *msg) int cmd_check_attr(int argc, const char **argv, const char *prefix) { struct attr_check *check; - struct object_id *tree_oid = NULL; struct object_id initialized_oid; int cnt, i, doubledash, filei; @@ -186,14 +187,14 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) if (source) { if (repo_get_oid_tree(the_repository, source, &initialized_oid)) die("%s: not a valid tree-ish source", source); - tree_oid = &initialized_oid; + set_git_attr_source(source); } if (stdin_paths) - check_attr_stdin_paths(prefix, check, tree_oid, all_attrs); + check_attr_stdin_paths(prefix, check, all_attrs); else { for (i = filei; i < argc; i++) - check_attr(prefix, check, tree_oid, all_attrs, argv[i]); + check_attr(prefix, check, all_attrs, argv[i]); maybe_flush_or_die(stdout, "attribute to stdout"); } diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index 9401dad007..e4b78782a3 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -7,6 +7,7 @@ #include "quote.h" #include "pathspec.h" #include "parse-options.h" +#include "repository.h" #include "submodule.h" #include "write-or-die.h" diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 7df673e3e7..9375a05539 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -11,6 +11,7 @@ #include "gettext.h" #include "lockfile.h" #include "quote.h" +#include "repository.h" #include "cache-tree.h" #include "parse-options.h" #include "entry.h" diff --git a/builtin/checkout.c b/builtin/checkout.c index 38a8cd6a96..715eeb5048 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -15,7 +15,9 @@ #include "hook.h" #include "ll-merge.h" #include "lockfile.h" +#include "mem-pool.h" #include "merge-recursive.h" +#include "object-name.h" #include "object-store.h" #include "parse-options.h" #include "refs.h" @@ -26,6 +28,8 @@ #include "setup.h" #include "submodule.h" #include "submodule-config.h" +#include "symlinks.h" +#include "trace2.h" #include "tree.h" #include "tree-walk.h" #include "unpack-trees.h" diff --git a/builtin/clean.c b/builtin/clean.c index 14c0d555ea..78852d28ce 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -14,6 +14,7 @@ #include "dir.h" #include "gettext.h" #include "parse-options.h" +#include "repository.h" #include "setup.h" #include "string-list.h" #include "quote.h" diff --git a/builtin/clone.c b/builtin/clone.c index 6dc89f1058..15f9912b4c 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -11,7 +11,9 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" #include "abspath.h" +#include "advice.h" #include "config.h" +#include "copy.h" #include "environment.h" #include "gettext.h" #include "hex.h" @@ -20,6 +22,7 @@ #include "fetch-pack.h" #include "refs.h" #include "refspec.h" +#include "object-file.h" #include "object-store.h" #include "tree.h" #include "tree-walk.h" @@ -36,10 +39,12 @@ #include "setup.h" #include "connected.h" #include "packfile.h" +#include "pkt-line.h" #include "list-objects-filter-options.h" #include "hook.h" #include "bundle.h" #include "bundle-uri.h" +#include "wrapper.h" /* * Overall FIXMEs: @@ -331,8 +336,18 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC); - if (!iter) + if (!iter) { + if (errno == ENOTDIR) { + int saved_errno = errno; + struct stat st; + + if (!lstat(src->buf, &st) && S_ISLNK(st.st_mode)) + die(_("'%s' is a symlink, refusing to clone with --local"), + src->buf); + errno = saved_errno; + } die_errno(_("failed to start iterator over '%s'"), src->buf); + } strbuf_addch(src, '/'); src_len = src->len; diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 9011426976..a3d00fa232 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -12,6 +12,7 @@ #include "progress.h" #include "replace-object.h" #include "tag.h" +#include "trace2.h" #define BUILTIN_COMMIT_GRAPH_VERIFY_USAGE \ N_("git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]") diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 15be167f87..d1d251c3de 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -7,6 +7,7 @@ #include "config.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "object-store.h" #include "repository.h" #include "commit.h" diff --git a/builtin/commit.c b/builtin/commit.c index 9d8e1ea91a..9ab57ea1aa 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -7,11 +7,13 @@ #define USE_THE_INDEX_VARIABLE #include "cache.h" +#include "advice.h" #include "config.h" #include "lockfile.h" #include "cache-tree.h" #include "color.h" #include "dir.h" +#include "editor.h" #include "environment.h" #include "builtin.h" #include "diff.h" @@ -26,6 +28,7 @@ #include "log-tree.h" #include "strbuf.h" #include "utf8.h" +#include "object-name.h" #include "parse-options.h" #include "string-list.h" #include "rerere.h" @@ -760,7 +763,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *c; c = lookup_commit_reference_by_name(squash_message); if (!c) - die(_("could not lookup commit %s"), squash_message); + die(_("could not lookup commit '%s'"), squash_message); ctx.output_encoding = get_commit_output_encoding(); repo_format_commit_message(the_repository, c, "squash! %s\n\n", &sb, @@ -795,7 +798,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, char *fmt; commit = lookup_commit_reference_by_name(fixup_commit); if (!commit) - die(_("could not lookup commit %s"), fixup_commit); + die(_("could not lookup commit '%s'"), fixup_commit); ctx.output_encoding = get_commit_output_encoding(); fmt = xstrfmt("%s! %%s\n\n", fixup_prefix); repo_format_commit_message(the_repository, commit, fmt, &sb, @@ -1186,7 +1189,7 @@ static const char *read_commit_message(const char *name) commit = lookup_commit_reference_by_name(name); if (!commit) - die(_("could not lookup commit %s"), name); + die(_("could not lookup commit '%s'"), name); out_enc = get_commit_output_encoding(); return repo_logmsg_reencode(the_repository, commit, NULL, out_enc); } diff --git a/builtin/config.c b/builtin/config.c index fe79fb60c4..d40fddb042 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -3,11 +3,14 @@ #include "alloc.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" #include "urlmatch.h" +#include "path.h" #include "quote.h" #include "setup.h" #include "worktree.h" @@ -373,7 +376,8 @@ static int get_value(const char *key_, const char *regex_, unsigned flags) } config_with_options(collect_config, &values, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (!values.nr && default_value) { struct strbuf *item; @@ -484,7 +488,8 @@ static void get_color(const char *var, const char *def_color) get_color_found = 0; parsed_color[0] = '\0'; config_with_options(git_get_color_config, NULL, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (!get_color_found && def_color) { if (color_parse(def_color, parsed_color) < 0) @@ -516,7 +521,8 @@ static int get_colorbool(const char *var, int print) get_diff_color_found = -1; get_color_ui_found = -1; config_with_options(git_get_colorbool_config, NULL, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); if (get_colorbool_found < 0) { if (!strcmp(get_colorbool_slot, "color.diff")) @@ -605,7 +611,8 @@ static int get_urlmatch(const char *var, const char *url) } config_with_options(urlmatch_config_entry, &config, - &given_config_source, &config_options); + &given_config_source, the_repository, + &config_options); ret = !values.nr; @@ -711,7 +718,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) given_config_source.scope = CONFIG_SCOPE_LOCAL; } else if (use_worktree_config) { struct worktree **worktrees = get_worktrees(); - if (repository_format_worktree_config) + if (the_repository->repository_format_worktree_config) given_config_source.file = git_pathdup("config.worktree"); else if (worktrees[0] && worktrees[1]) die(_("--worktree cannot be used with multiple " @@ -825,7 +832,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (actions == ACTION_LIST) { check_argc(argc, 0, 0); if (config_with_options(show_all_config, NULL, - &given_config_source, + &given_config_source, the_repository, &config_options) < 0) { if (given_config_source.file) die_errno(_("unable to read config file '%s'"), diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index 62c09a271d..756c5f02ae 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -2,6 +2,7 @@ #include "abspath.h" #include "alloc.h" #include "gettext.h" +#include "object-file.h" #include "parse-options.h" #ifndef NO_UNIX_SOCKETS @@ -133,6 +134,9 @@ static void serve_one_client(FILE *in, FILE *out) if (e->item.password_expiry_utc != TIME_MAX) fprintf(out, "password_expiry_utc=%"PRItime"\n", e->item.password_expiry_utc); + if (e->item.oauth_refresh_token) + fprintf(out, "oauth_refresh_token=%s\n", + e->item.oauth_refresh_token); } } else if (!strcmp(action.buf, "exit")) { diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c index 508da4c6e4..0ffacfdd83 100644 --- a/builtin/credential-cache.c +++ b/builtin/credential-cache.c @@ -1,6 +1,7 @@ #include "builtin.h" #include "gettext.h" #include "parse-options.h" +#include "path.h" #include "wrapper.h" #include "write-or-die.h" diff --git a/builtin/credential-store.c b/builtin/credential-store.c index 8977604eb9..30c6ccf56c 100644 --- a/builtin/credential-store.c +++ b/builtin/credential-store.c @@ -3,6 +3,7 @@ #include "gettext.h" #include "lockfile.h" #include "credential.h" +#include "path.h" #include "string-list.h" #include "parse-options.h" #include "write-or-die.h" diff --git a/builtin/describe.c b/builtin/describe.c index 0125d4ddba..55b4baaa22 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -11,6 +11,7 @@ #include "refs.h" #include "builtin.h" #include "exec-cmd.h" +#include "object-name.h" #include "parse-options.h" #include "revision.h" #include "diff.h" @@ -658,6 +659,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix) int fd, result; setup_work_tree(); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; repo_read_index(the_repository); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL); diff --git a/builtin/diagnose.c b/builtin/diagnose.c index 0f8b64994c..4f22eb2b55 100644 --- a/builtin/diagnose.c +++ b/builtin/diagnose.c @@ -1,6 +1,7 @@ #include "builtin.h" #include "abspath.h" #include "gettext.h" +#include "object-file.h" #include "parse-options.h" #include "diagnose.h" diff --git a/builtin/diff-files.c b/builtin/diff-files.c index dc991f753b..360464e6ef 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -27,6 +27,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) usage(diff_files_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; diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 385c2d0230..c0540317fb 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -9,6 +9,7 @@ #include "builtin.h" #include "submodule.h" #include "repository.h" +#include "tree.h" static struct rev_info log_tree_opt; @@ -121,6 +122,10 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) usage(diff_tree_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, opt, prefix); if (repo_read_index(the_repository) < 0) die(_("index file corrupt")); diff --git a/builtin/diff.c b/builtin/diff.c index 5a6a5d7f4b..7b64659fe7 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -22,6 +22,7 @@ #include "setup.h" #include "submodule.h" #include "oid-array.h" +#include "tree.h" #define DIFF_NO_INDEX_EXPLICIT 1 #define DIFF_NO_INDEX_IMPLICIT 2 diff --git a/builtin/difftool.c b/builtin/difftool.c index e010a21bfb..0049342f5c 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -15,6 +15,7 @@ #include "cache.h" #include "abspath.h" #include "config.h" +#include "copy.h" #include "builtin.h" #include "run-command.h" #include "environment.h" @@ -25,6 +26,7 @@ #include "strvec.h" #include "strbuf.h" #include "lockfile.h" +#include "object-file.h" #include "object-store.h" #include "dir.h" #include "entry.h" @@ -691,7 +693,7 @@ static int run_file_diff(int prompt, const char *prefix, int cmd_difftool(int argc, const char **argv, const char *prefix) { - int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0, + int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0, tool_help = 0, no_index = 0; static char *difftool_cmd = NULL, *extcmd = NULL; struct option builtin_difftool_options[] = { @@ -741,13 +743,21 @@ int cmd_difftool(int argc, const char **argv, const char *prefix) } else if (dir_diff) die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index"); - die_for_incompatible_opt3(use_gui_tool, "--gui", + die_for_incompatible_opt3(use_gui_tool == 1, "--gui", !!difftool_cmd, "--tool", !!extcmd, "--extcmd"); - if (use_gui_tool) + /* + * Explicitly specified GUI option is forwarded to git-mergetool--lib.sh; + * empty or unset means "use the difftool.guiDefault config or default to + * false". + */ + if (use_gui_tool == 1) setenv("GIT_MERGETOOL_GUI", "true", 1); - else if (difftool_cmd) { + else if (use_gui_tool == 0) + setenv("GIT_MERGETOOL_GUI", "false", 1); + + if (difftool_cmd) { if (*difftool_cmd) setenv("GIT_DIFF_TOOL", difftool_cmd, 1); else diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 8224bf4bc1..9a95f6a1a8 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -10,6 +10,7 @@ #include "hex.h" #include "refs.h" #include "refspec.h" +#include "object-file.h" #include "object-store.h" #include "commit.h" #include "object.h" diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 1fb95275d7..bbd9b2b3e7 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -19,6 +19,8 @@ #include "dir.h" #include "run-command.h" #include "packfile.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "mem-pool.h" #include "commit-reach.h" diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 5f341b794d..3ba0fe5a39 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -2,6 +2,7 @@ #include "alloc.h" #include "gettext.h" #include "hex.h" +#include "object-file.h" #include "pkt-line.h" #include "fetch-pack.h" #include "remote.h" diff --git a/builtin/fetch.c b/builtin/fetch.c index 85bd280103..e3871048cf 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -2,6 +2,7 @@ * "git fetch" */ #include "cache.h" +#include "advice.h" #include "config.h" #include "gettext.h" #include "environment.h" @@ -9,8 +10,10 @@ #include "repository.h" #include "refs.h" #include "refspec.h" +#include "object-name.h" #include "object-store.h" #include "oidset.h" +#include "oid-array.h" #include "commit.h" #include "builtin.h" #include "string-list.h" @@ -25,12 +28,16 @@ #include "strvec.h" #include "utf8.h" #include "packfile.h" +#include "pager.h" +#include "pkt-line.h" #include "list-objects-filter-options.h" #include "commit-reach.h" #include "branch.h" #include "promisor-remote.h" #include "commit-graph.h" #include "shallow.h" +#include "trace.h" +#include "trace2.h" #include "worktree.h" #include "bundle-uri.h" @@ -50,35 +57,35 @@ enum { TAGS_SET = 2 }; +enum display_format { + DISPLAY_FORMAT_FULL, + DISPLAY_FORMAT_COMPACT, + DISPLAY_FORMAT_PORCELAIN, +}; + struct display_state { struct strbuf buf; int refcol_width; - int compact_format; + enum display_format format; char *url; int url_len, shown_url; }; -static int fetch_prune_config = -1; /* unspecified */ -static int fetch_show_forced_updates = 1; static uint64_t forced_updates_ms = 0; static int prefetch = 0; static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ -static int fetch_prune_tags_config = -1; /* unspecified */ static int prune_tags = -1; /* unspecified */ #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */ -static int all, append, dry_run, force, keep, multiple, update_head_ok; +static int append, dry_run, force, keep, update_head_ok; static int write_fetch_head = 1; static int verbosity, deepen_relative, set_upstream, refetch; static int progress = -1; -static int enable_auto_gc = 1; -static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; -static int max_jobs = -1, submodule_fetch_jobs_config = -1; -static int fetch_parallel_config = 1; +static int tags = TAGS_DEFAULT, update_shallow, deepen; static int atomic_fetch; static enum transport_family family; static const char *depth; @@ -88,58 +95,75 @@ static struct string_list deepen_not = STRING_LIST_INIT_NODUP; static struct strbuf default_rla = STRBUF_INIT; static struct transport *gtransport; static struct transport *gsecondary; -static const char *submodule_prefix = ""; -static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT; -static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND; static struct refspec refmap = REFSPEC_INIT_FETCH; static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT; static struct string_list server_options = STRING_LIST_INIT_DUP; static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP; -static int fetch_write_commit_graph = -1; -static int stdin_refspecs = 0; -static int negotiate_only; + +struct fetch_config { + enum display_format display_format; + int prune; + int prune_tags; + int show_forced_updates; + int recurse_submodules; + int parallel; + int submodule_fetch_jobs; +}; static int git_fetch_config(const char *k, const char *v, void *cb) { + struct fetch_config *fetch_config = cb; + if (!strcmp(k, "fetch.prune")) { - fetch_prune_config = git_config_bool(k, v); + fetch_config->prune = git_config_bool(k, v); return 0; } if (!strcmp(k, "fetch.prunetags")) { - fetch_prune_tags_config = git_config_bool(k, v); + fetch_config->prune_tags = git_config_bool(k, v); return 0; } if (!strcmp(k, "fetch.showforcedupdates")) { - fetch_show_forced_updates = git_config_bool(k, v); + fetch_config->show_forced_updates = git_config_bool(k, v); return 0; } if (!strcmp(k, "submodule.recurse")) { int r = git_config_bool(k, v) ? RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; - recurse_submodules = r; + fetch_config->recurse_submodules = r; } if (!strcmp(k, "submodule.fetchjobs")) { - submodule_fetch_jobs_config = parse_submodule_fetchjobs(k, v); + fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v); return 0; } else if (!strcmp(k, "fetch.recursesubmodules")) { - recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); + fetch_config->recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); return 0; } if (!strcmp(k, "fetch.parallel")) { - fetch_parallel_config = git_config_int(k, v); - if (fetch_parallel_config < 0) + fetch_config->parallel = git_config_int(k, v); + if (fetch_config->parallel < 0) die(_("fetch.parallel cannot be negative")); - if (!fetch_parallel_config) - fetch_parallel_config = online_cpus(); + if (!fetch_config->parallel) + fetch_config->parallel = online_cpus(); return 0; } + if (!strcmp(k, "fetch.output")) { + if (!v) + return config_error_nonbool(k); + else if (!strcasecmp(v, "full")) + fetch_config->display_format = DISPLAY_FORMAT_FULL; + else if (!strcasecmp(v, "compact")) + fetch_config->display_format = DISPLAY_FORMAT_COMPACT; + else + die(_("invalid value for '%s': '%s'"), + "fetch.output", v); + } + return git_default_config(k, v, cb); } @@ -156,92 +180,6 @@ static int parse_refmap_arg(const struct option *opt, const char *arg, int unset return 0; } -static struct option builtin_fetch_options[] = { - OPT__VERBOSITY(&verbosity), - OPT_BOOL(0, "all", &all, - N_("fetch from all remotes")), - OPT_BOOL(0, "set-upstream", &set_upstream, - N_("set upstream for git pull/fetch")), - OPT_BOOL('a', "append", &append, - N_("append to .git/FETCH_HEAD instead of overwriting")), - OPT_BOOL(0, "atomic", &atomic_fetch, - N_("use atomic transaction to update references")), - OPT_STRING(0, "upload-pack", &upload_pack, N_("path"), - N_("path to upload pack on remote end")), - OPT__FORCE(&force, N_("force overwrite of local reference"), 0), - OPT_BOOL('m', "multiple", &multiple, - N_("fetch from multiple remotes")), - OPT_SET_INT('t', "tags", &tags, - N_("fetch all tags and associated objects"), TAGS_SET), - OPT_SET_INT('n', NULL, &tags, - N_("do not fetch all tags (--no-tags)"), TAGS_UNSET), - OPT_INTEGER('j', "jobs", &max_jobs, - N_("number of submodules fetched in parallel")), - OPT_BOOL(0, "prefetch", &prefetch, - N_("modify the refspec to place all refs within refs/prefetch/")), - OPT_BOOL('p', "prune", &prune, - N_("prune remote-tracking branches no longer on remote")), - OPT_BOOL('P', "prune-tags", &prune_tags, - N_("prune local tags no longer on remote and clobber changed tags")), - OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"), - N_("control recursive fetching of submodules"), - PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules), - OPT_BOOL(0, "dry-run", &dry_run, - N_("dry run")), - OPT_BOOL(0, "write-fetch-head", &write_fetch_head, - N_("write fetched references to the FETCH_HEAD file")), - OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")), - OPT_BOOL('u', "update-head-ok", &update_head_ok, - N_("allow updating of HEAD ref")), - OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), - OPT_STRING(0, "depth", &depth, N_("depth"), - N_("deepen history of shallow clone")), - OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), - N_("deepen history of shallow repository based on time")), - OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"), - N_("deepen history of shallow clone, excluding rev")), - OPT_INTEGER(0, "deepen", &deepen_relative, - N_("deepen history of shallow clone")), - OPT_SET_INT_F(0, "unshallow", &unshallow, - N_("convert to a complete repository"), - 1, PARSE_OPT_NONEG), - OPT_SET_INT_F(0, "refetch", &refetch, - N_("re-fetch without negotiating common commits"), - 1, PARSE_OPT_NONEG), - { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"), - N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN }, - OPT_CALLBACK_F(0, "recurse-submodules-default", - &recurse_submodules_default, N_("on-demand"), - N_("default for recursive fetching of submodules " - "(lower priority than config files)"), - PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules), - OPT_BOOL(0, "update-shallow", &update_shallow, - N_("accept refs that update .git/shallow")), - OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"), - N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg), - OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")), - OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), - TRANSPORT_FAMILY_IPV4), - OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), - TRANSPORT_FAMILY_IPV6), - OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"), - N_("report that we have only objects reachable from this object")), - OPT_BOOL(0, "negotiate-only", &negotiate_only, - N_("do not fetch a packfile; instead, print ancestors of negotiation tips")), - OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), - OPT_BOOL(0, "auto-maintenance", &enable_auto_gc, - N_("run 'maintenance --auto' after fetching")), - OPT_BOOL(0, "auto-gc", &enable_auto_gc, - N_("run 'maintenance --auto' after fetching")), - OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates, - N_("check for forced-updates on all updated branches")), - OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph, - N_("write the commit-graph after fetching")), - OPT_BOOL(0, "stdin", &stdin_refspecs, - N_("accept refspecs from stdin")), - OPT_END() -}; - static void unlock_pack(unsigned int flags) { if (gtransport) @@ -753,46 +691,56 @@ out: return ret; } -static int refcol_width(const struct ref *ref, int compact_format) +static int refcol_width(const struct ref *ref_map, int compact_format) { - int max, rlen, llen, len; + const struct ref *ref; + int max, width = 10; - /* uptodate lines are only shown on high verbosity level */ - if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid)) - return 0; + max = term_columns(); + if (compact_format) + max = max * 2 / 3; - max = term_columns(); - rlen = utf8_strwidth(prettify_refname(ref->name)); + for (ref = ref_map; ref; ref = ref->next) { + int rlen, llen = 0, len; - llen = utf8_strwidth(prettify_refname(ref->peer_ref->name)); + if (ref->status == REF_STATUS_REJECT_SHALLOW || + !ref->peer_ref || + !strcmp(ref->name, "HEAD")) + continue; - /* - * rough estimation to see if the output line is too long and - * should not be counted (we can't do precise calculation - * anyway because we don't know if the error explanation part - * will be printed in update_local_ref) - */ - if (compact_format) { - llen = 0; - max = max * 2 / 3; + /* uptodate lines are only shown on high verbosity level */ + if (verbosity <= 0 && oideq(&ref->peer_ref->old_oid, &ref->old_oid)) + continue; + + rlen = utf8_strwidth(prettify_refname(ref->name)); + if (!compact_format) + llen = utf8_strwidth(prettify_refname(ref->peer_ref->name)); + + /* + * rough estimation to see if the output line is too long and + * should not be counted (we can't do precise calculation + * anyway because we don't know if the error explanation part + * will be printed in update_local_ref) + */ + len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen; + if (len >= max) + continue; + + if (width < rlen) + width = rlen; } - len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen; - if (len >= max) - return 0; - return rlen; + return width; } static void display_state_init(struct display_state *display_state, struct ref *ref_map, - const char *raw_url) + const char *raw_url, enum display_format format) { - struct ref *rm; - const char *format = "full"; int i; memset(display_state, 0, sizeof(*display_state)); - strbuf_init(&display_state->buf, 0); + display_state->format = format; if (raw_url) display_state->url = transport_anonymize_url(raw_url); @@ -809,33 +757,17 @@ static void display_state_init(struct display_state *display_state, struct ref * if (verbosity < 0) return; - git_config_get_string_tmp("fetch.output", &format); - if (!strcasecmp(format, "full")) - display_state->compact_format = 0; - else if (!strcasecmp(format, "compact")) - display_state->compact_format = 1; - else - die(_("invalid value for '%s': '%s'"), - "fetch.output", format); - - display_state->refcol_width = 10; - for (rm = ref_map; rm; rm = rm->next) { - int width; - - if (rm->status == REF_STATUS_REJECT_SHALLOW || - !rm->peer_ref || - !strcmp(rm->name, "HEAD")) - continue; - - width = refcol_width(rm, display_state->compact_format); - - /* - * Not precise calculation for compact mode because '*' can - * appear on the left hand side of '->' and shrink the column - * back. - */ - if (display_state->refcol_width < width) - display_state->refcol_width = width; + switch (display_state->format) { + case DISPLAY_FORMAT_FULL: + case DISPLAY_FORMAT_COMPACT: + display_state->refcol_width = refcol_width(ref_map, + display_state->format == DISPLAY_FORMAT_COMPACT); + break; + case DISPLAY_FORMAT_PORCELAIN: + /* We don't need to precompute anything here. */ + break; + default: + BUG("unexpected display format %d", display_state->format); } } @@ -904,40 +836,63 @@ static void print_compact(struct display_state *display_state, static void display_ref_update(struct display_state *display_state, char code, const char *summary, const char *error, const char *remote, const char *local, + const struct object_id *old_oid, + const struct object_id *new_oid, int summary_width) { - int width; + FILE *f = stderr; if (verbosity < 0) return; strbuf_reset(&display_state->buf); - if (!display_state->shown_url) { - strbuf_addf(&display_state->buf, _("From %.*s\n"), - display_state->url_len, display_state->url); - display_state->shown_url = 1; - } + switch (display_state->format) { + case DISPLAY_FORMAT_FULL: + case DISPLAY_FORMAT_COMPACT: { + int width; - width = (summary_width + strlen(summary) - gettext_width(summary)); + if (!display_state->shown_url) { + strbuf_addf(&display_state->buf, _("From %.*s\n"), + display_state->url_len, display_state->url); + display_state->shown_url = 1; + } - strbuf_addf(&display_state->buf, " %c %-*s ", code, width, summary); - if (!display_state->compact_format) - print_remote_to_local(display_state, remote, prettify_refname(local)); - else - print_compact(display_state, remote, prettify_refname(local)); - if (error) - strbuf_addf(&display_state->buf, " (%s)", error); + width = (summary_width + strlen(summary) - gettext_width(summary)); + remote = prettify_refname(remote); + local = prettify_refname(local); + + strbuf_addf(&display_state->buf, " %c %-*s ", code, width, summary); + + if (display_state->format != DISPLAY_FORMAT_COMPACT) + print_remote_to_local(display_state, remote, local); + else + print_compact(display_state, remote, local); + + if (error) + strbuf_addf(&display_state->buf, " (%s)", error); + + break; + } + case DISPLAY_FORMAT_PORCELAIN: + strbuf_addf(&display_state->buf, "%c %s %s %s", code, + oid_to_hex(old_oid), oid_to_hex(new_oid), local); + f = stdout; + break; + default: + BUG("unexpected display format %d", display_state->format); + }; strbuf_addch(&display_state->buf, '\n'); - fputs(display_state->buf.buf, stderr); + fputs(display_state->buf.buf, f); } static int update_local_ref(struct ref *ref, struct ref_transaction *transaction, struct display_state *display_state, - const char *remote, const struct ref *remote_ref, - int summary_width) + const struct ref *remote_ref, + int summary_width, + const struct fetch_config *config) { struct commit *current = NULL, *updated; int fast_forward = 0; @@ -948,7 +903,8 @@ static int update_local_ref(struct ref *ref, if (oideq(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) display_ref_update(display_state, '=', _("[up to date]"), NULL, - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return 0; } @@ -961,7 +917,8 @@ static int update_local_ref(struct ref *ref, */ display_ref_update(display_state, '!', _("[rejected]"), _("can't fetch into checked-out branch"), - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return 1; } @@ -972,12 +929,14 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("updating tag", ref, transaction, 0); display_ref_update(display_state, r ? '!' : 't', _("[tag update]"), r ? _("unable to update local ref") : NULL, - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return r; } else { display_ref_update(display_state, '!', _("[rejected]"), _("would clobber existing tag"), - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return 1; } } @@ -995,11 +954,10 @@ static int update_local_ref(struct ref *ref, * Base this on the remote's ref name, as it's * more likely to follow a standard layout. */ - const char *name = remote_ref ? remote_ref->name : ""; - if (starts_with(name, "refs/tags/")) { + if (starts_with(remote_ref->name, "refs/tags/")) { msg = "storing tag"; what = _("[new tag]"); - } else if (starts_with(name, "refs/heads/")) { + } else if (starts_with(remote_ref->name, "refs/heads/")) { msg = "storing head"; what = _("[new branch]"); } else { @@ -1010,11 +968,12 @@ static int update_local_ref(struct ref *ref, r = s_update_ref(msg, ref, transaction, 0); display_ref_update(display_state, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return r; } - if (fetch_show_forced_updates) { + if (config->show_forced_updates) { uint64_t t_before = getnanotime(); fast_forward = repo_in_merge_bases(the_repository, current, updated); @@ -1033,7 +992,8 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("fast-forward", ref, transaction, 1); display_ref_update(display_state, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); strbuf_release(&quickref); return r; } else if (force || ref->force) { @@ -1045,12 +1005,14 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("forced-update", ref, transaction, 1); display_ref_update(display_state, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); strbuf_release(&quickref); return r; } else { display_ref_update(display_state, '!', _("[rejected]"), _("non-fast-forward"), - remote, ref->name, summary_width); + remote_ref->name, ref->name, + &ref->old_oid, &ref->new_oid, summary_width); return 1; } } @@ -1164,7 +1126,8 @@ static int store_updated_refs(struct display_state *display_state, const char *remote_name, int connectivity_checked, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int rc = 0; struct strbuf note = STRBUF_INIT; @@ -1247,7 +1210,7 @@ static int store_updated_refs(struct display_state *display_state, ref->force = rm->peer_ref->force; } - if (recurse_submodules != RECURSE_SUBMODULES_OFF && + if (config->recurse_submodules != RECURSE_SUBMODULES_OFF && (!rm->peer_ref || !oideq(&ref->old_oid, &ref->new_oid))) { check_for_new_submodule_commits(&rm->old_oid); } @@ -1255,14 +1218,13 @@ static int store_updated_refs(struct display_state *display_state, if (!strcmp(rm->name, "HEAD")) { kind = ""; what = ""; - } - else if (skip_prefix(rm->name, "refs/heads/", &what)) + } else if (skip_prefix(rm->name, "refs/heads/", &what)) { kind = "branch"; - else if (skip_prefix(rm->name, "refs/tags/", &what)) + } else if (skip_prefix(rm->name, "refs/tags/", &what)) { kind = "tag"; - else if (skip_prefix(rm->name, "refs/remotes/", &what)) + } else if (skip_prefix(rm->name, "refs/remotes/", &what)) { kind = "remote-tracking branch"; - else { + } else { kind = ""; what = rm->name; } @@ -1280,8 +1242,8 @@ static int store_updated_refs(struct display_state *display_state, display_state->url_len); if (ref) { - rc |= update_local_ref(ref, transaction, display_state, what, - rm, summary_width); + rc |= update_local_ref(ref, transaction, display_state, + rm, summary_width, config); free(ref); } else if (write_fetch_head || dry_run) { /* @@ -1291,8 +1253,10 @@ static int store_updated_refs(struct display_state *display_state, */ display_ref_update(display_state, '*', *kind ? kind : "branch", NULL, - *what ? what : "HEAD", - "FETCH_HEAD", summary_width); + rm->name, + "FETCH_HEAD", + &rm->new_oid, &rm->old_oid, + summary_width); } } } @@ -1303,7 +1267,7 @@ static int store_updated_refs(struct display_state *display_state, "branches"), remote_name); if (advice_enabled(ADVICE_FETCH_SHOW_FORCED_UPDATES)) { - if (!fetch_show_forced_updates) { + if (!config->show_forced_updates) { warning(_(warn_show_forced_updates)); } else if (forced_updates_ms > FORCED_UPDATES_DELAY_WARNING_IN_MS) { warning(_(warn_time_show_forced_updates), @@ -1364,7 +1328,8 @@ static int fetch_and_consume_refs(struct display_state *display_state, struct transport *transport, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int connectivity_checked = 1; int ret; @@ -1387,7 +1352,7 @@ static int fetch_and_consume_refs(struct display_state *display_state, trace2_region_enter("fetch", "consume_refs", the_repository); ret = store_updated_refs(display_state, transport->remote->name, connectivity_checked, transaction, ref_map, - fetch_head); + fetch_head, config); trace2_region_leave("fetch", "consume_refs", the_repository); out: @@ -1432,6 +1397,7 @@ static int prune_refs(struct display_state *display_state, for (ref = stale_refs; ref; ref = ref->next) { display_ref_update(display_state, '-', _("[deleted]"), NULL, _("(none)"), ref->name, + &ref->new_oid, &ref->old_oid, summary_width); warn_dangling_symref(stderr, dangling_msg, ref->name); } @@ -1557,7 +1523,8 @@ static int backfill_tags(struct display_state *display_state, struct transport *transport, struct ref_transaction *transaction, struct ref *ref_map, - struct fetch_head *fetch_head) + struct fetch_head *fetch_head, + const struct fetch_config *config) { int retcode, cannot_reuse; @@ -1578,7 +1545,8 @@ static int backfill_tags(struct display_state *display_state, transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL); - retcode = fetch_and_consume_refs(display_state, transport, transaction, ref_map, fetch_head); + retcode = fetch_and_consume_refs(display_state, transport, transaction, ref_map, + fetch_head, config); if (gsecondary) { transport_disconnect(gsecondary); @@ -1589,7 +1557,8 @@ static int backfill_tags(struct display_state *display_state, } static int do_fetch(struct transport *transport, - struct refspec *rs) + struct refspec *rs, + const struct fetch_config *config) { struct ref_transaction *transaction = NULL; struct ref *ref_map = NULL; @@ -1675,7 +1644,8 @@ static int do_fetch(struct transport *transport, if (retcode) goto cleanup; - display_state_init(&display_state, ref_map, transport->url); + display_state_init(&display_state, ref_map, transport->url, + config->display_format); if (atomic_fetch) { transaction = ref_transaction_begin(&err); @@ -1703,7 +1673,8 @@ static int do_fetch(struct transport *transport, retcode = 1; } - if (fetch_and_consume_refs(&display_state, transport, transaction, ref_map, &fetch_head)) { + if (fetch_and_consume_refs(&display_state, transport, transaction, ref_map, + &fetch_head, config)) { retcode = 1; goto cleanup; } @@ -1726,7 +1697,7 @@ static int do_fetch(struct transport *transport, * the transaction and don't commit anything. */ if (backfill_tags(&display_state, transport, transaction, tags_ref_map, - &fetch_head)) + &fetch_head, config)) retcode = 1; } @@ -1863,7 +1834,8 @@ static int add_remote_or_group(const char *name, struct string_list *list) return 1; } -static void add_options_to_argv(struct strvec *argv) +static void add_options_to_argv(struct strvec *argv, + const struct fetch_config *config) { if (dry_run) strvec_push(argv, "--dry-run"); @@ -1877,9 +1849,11 @@ static void add_options_to_argv(struct strvec *argv) strvec_push(argv, "--force"); if (keep) strvec_push(argv, "--keep"); - if (recurse_submodules == RECURSE_SUBMODULES_ON) + if (config->recurse_submodules == RECURSE_SUBMODULES_ON) strvec_push(argv, "--recurse-submodules"); - else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) + else if (config->recurse_submodules == RECURSE_SUBMODULES_OFF) + strvec_push(argv, "--no-recurse-submodules"); + else if (config->recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) strvec_push(argv, "--recurse-submodules=on-demand"); if (tags == TAGS_SET) strvec_push(argv, "--tags"); @@ -1897,6 +1871,8 @@ static void add_options_to_argv(struct strvec *argv) strvec_push(argv, "--ipv6"); if (!write_fetch_head) strvec_push(argv, "--no-write-fetch-head"); + if (config->display_format == DISPLAY_FORMAT_PORCELAIN) + strvec_pushf(argv, "--porcelain"); } /* Fetch multiple remotes in parallel */ @@ -1905,6 +1881,7 @@ struct parallel_fetch_state { const char **argv; struct string_list *remotes; int next, result; + const struct fetch_config *config; }; static int fetch_next_remote(struct child_process *cp, @@ -1924,7 +1901,7 @@ static int fetch_next_remote(struct child_process *cp, strvec_push(&cp->args, remote); cp->git_cmd = 1; - if (verbosity >= 0) + if (verbosity >= 0 && state->config->display_format != DISPLAY_FORMAT_PORCELAIN) printf(_("Fetching %s\n"), remote); return 1; @@ -1956,7 +1933,8 @@ static int fetch_finished(int result, struct strbuf *out, return 0; } -static int fetch_multiple(struct string_list *list, int max_children) +static int fetch_multiple(struct string_list *list, int max_children, + const struct fetch_config *config) { int i, result = 0; struct strvec argv = STRVEC_INIT; @@ -1974,10 +1952,10 @@ 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); - add_options_to_argv(&argv); + add_options_to_argv(&argv, config); if (max_children != 1 && list->nr != 1) { - struct parallel_fetch_state state = { argv.v, list, 0, 0 }; + struct parallel_fetch_state state = { argv.v, list, 0, 0, config }; const struct run_process_parallel_opts opts = { .tr2_category = "fetch", .tr2_label = "parallel/fetch", @@ -2001,7 +1979,7 @@ static int fetch_multiple(struct string_list *list, int max_children) strvec_pushv(&cmd.args, argv.v); strvec_push(&cmd.args, name); - if (verbosity >= 0) + if (verbosity >= 0 && config->display_format != DISPLAY_FORMAT_PORCELAIN) printf(_("Fetching %s\n"), name); cmd.git_cmd = 1; if (run_command(&cmd)) { @@ -2056,7 +2034,8 @@ static inline void fetch_one_setup_partial(struct remote *remote) } static int fetch_one(struct remote *remote, int argc, const char **argv, - int prune_tags_ok, int use_stdin_refspecs) + int prune_tags_ok, int use_stdin_refspecs, + const struct fetch_config *config) { struct refspec rs = REFSPEC_INIT_FETCH; int i; @@ -2074,8 +2053,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, /* no command line request */ if (0 <= remote->prune) prune = remote->prune; - else if (0 <= fetch_prune_config) - prune = fetch_prune_config; + else if (0 <= config->prune) + prune = config->prune; else prune = PRUNE_BY_DEFAULT; } @@ -2084,8 +2063,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, /* no command line request */ if (0 <= remote->prune_tags) prune_tags = remote->prune_tags; - else if (0 <= fetch_prune_tags_config) - prune_tags = fetch_prune_tags_config; + else if (0 <= config->prune_tags) + prune_tags = config->prune_tags; else prune_tags = PRUNE_TAGS_BY_DEFAULT; } @@ -2123,7 +2102,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, sigchain_push_common(unlock_pack_on_signal); atexit(unlock_pack_atexit); sigchain_push(SIGPIPE, SIG_IGN); - exit_code = do_fetch(gtransport, &rs); + exit_code = do_fetch(gtransport, &rs, config); sigchain_pop(SIGPIPE); refspec_clear(&rs); transport_disconnect(gtransport); @@ -2133,12 +2112,119 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int cmd_fetch(int argc, const char **argv, const char *prefix) { - int i; + struct fetch_config config = { + .display_format = DISPLAY_FORMAT_FULL, + .prune = -1, + .prune_tags = -1, + .show_forced_updates = 1, + .recurse_submodules = RECURSE_SUBMODULES_DEFAULT, + .parallel = 1, + .submodule_fetch_jobs = -1, + }; + const char *submodule_prefix = ""; const char *bundle_uri; struct string_list list = STRING_LIST_INIT_DUP; struct remote *remote = NULL; + int all = 0, multiple = 0; int result = 0; int prune_tags_ok = 1; + int enable_auto_gc = 1; + int unshallow = 0; + int max_jobs = -1; + int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT; + int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND; + int fetch_write_commit_graph = -1; + int stdin_refspecs = 0; + int negotiate_only = 0; + int porcelain = 0; + int i; + + struct option builtin_fetch_options[] = { + OPT__VERBOSITY(&verbosity), + OPT_BOOL(0, "all", &all, + N_("fetch from all remotes")), + OPT_BOOL(0, "set-upstream", &set_upstream, + N_("set upstream for git pull/fetch")), + OPT_BOOL('a', "append", &append, + N_("append to .git/FETCH_HEAD instead of overwriting")), + OPT_BOOL(0, "atomic", &atomic_fetch, + N_("use atomic transaction to update references")), + OPT_STRING(0, "upload-pack", &upload_pack, N_("path"), + N_("path to upload pack on remote end")), + OPT__FORCE(&force, N_("force overwrite of local reference"), 0), + OPT_BOOL('m', "multiple", &multiple, + N_("fetch from multiple remotes")), + OPT_SET_INT('t', "tags", &tags, + N_("fetch all tags and associated objects"), TAGS_SET), + OPT_SET_INT('n', NULL, &tags, + N_("do not fetch all tags (--no-tags)"), TAGS_UNSET), + OPT_INTEGER('j', "jobs", &max_jobs, + N_("number of submodules fetched in parallel")), + OPT_BOOL(0, "prefetch", &prefetch, + N_("modify the refspec to place all refs within refs/prefetch/")), + OPT_BOOL('p', "prune", &prune, + N_("prune remote-tracking branches no longer on remote")), + OPT_BOOL('P', "prune-tags", &prune_tags, + N_("prune local tags no longer on remote and clobber changed tags")), + OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"), + N_("control recursive fetching of submodules"), + PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules), + OPT_BOOL(0, "dry-run", &dry_run, + N_("dry run")), + OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")), + OPT_BOOL(0, "write-fetch-head", &write_fetch_head, + N_("write fetched references to the FETCH_HEAD file")), + OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")), + OPT_BOOL('u', "update-head-ok", &update_head_ok, + N_("allow updating of HEAD ref")), + OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), + OPT_STRING(0, "depth", &depth, N_("depth"), + N_("deepen history of shallow clone")), + OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), + N_("deepen history of shallow repository based on time")), + OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"), + N_("deepen history of shallow clone, excluding rev")), + OPT_INTEGER(0, "deepen", &deepen_relative, + N_("deepen history of shallow clone")), + OPT_SET_INT_F(0, "unshallow", &unshallow, + N_("convert to a complete repository"), + 1, PARSE_OPT_NONEG), + OPT_SET_INT_F(0, "refetch", &refetch, + N_("re-fetch without negotiating common commits"), + 1, PARSE_OPT_NONEG), + { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"), + N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN }, + OPT_CALLBACK_F(0, "recurse-submodules-default", + &recurse_submodules_default, N_("on-demand"), + N_("default for recursive fetching of submodules " + "(lower priority than config files)"), + PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules), + OPT_BOOL(0, "update-shallow", &update_shallow, + N_("accept refs that update .git/shallow")), + OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"), + N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg), + OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")), + OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"), + TRANSPORT_FAMILY_IPV4), + OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"), + TRANSPORT_FAMILY_IPV6), + OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"), + N_("report that we have only objects reachable from this object")), + OPT_BOOL(0, "negotiate-only", &negotiate_only, + N_("do not fetch a packfile; instead, print ancestors of negotiation tips")), + OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), + OPT_BOOL(0, "auto-maintenance", &enable_auto_gc, + N_("run 'maintenance --auto' after fetching")), + OPT_BOOL(0, "auto-gc", &enable_auto_gc, + N_("run 'maintenance --auto' after fetching")), + OPT_BOOL(0, "show-forced-updates", &config.show_forced_updates, + N_("check for forced-updates on all updated branches")), + OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph, + N_("write the commit-graph after fetching")), + OPT_BOOL(0, "stdin", &stdin_refspecs, + N_("accept refspecs from stdin")), + OPT_END() + }; packet_trace_identity("fetch"); @@ -2152,7 +2238,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) free(anon); } - git_config(git_fetch_config, NULL); + git_config(git_fetch_config, &config); if (the_repository->gitdir) { prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; @@ -2162,7 +2248,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) builtin_fetch_options, builtin_fetch_usage, 0); if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT) - recurse_submodules = recurse_submodules_cli; + config.recurse_submodules = recurse_submodules_cli; if (negotiate_only) { switch (recurse_submodules_cli) { @@ -2173,7 +2259,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) * submodules. Skip it by setting recurse_submodules to * RECURSE_SUBMODULES_OFF. */ - recurse_submodules = RECURSE_SUBMODULES_OFF; + config.recurse_submodules = RECURSE_SUBMODULES_OFF; break; default: @@ -2182,15 +2268,35 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } } - if (recurse_submodules != RECURSE_SUBMODULES_OFF) { - int *sfjc = submodule_fetch_jobs_config == -1 - ? &submodule_fetch_jobs_config : NULL; - int *rs = recurse_submodules == RECURSE_SUBMODULES_DEFAULT - ? &recurse_submodules : NULL; + if (config.recurse_submodules != RECURSE_SUBMODULES_OFF) { + int *sfjc = config.submodule_fetch_jobs == -1 + ? &config.submodule_fetch_jobs : NULL; + int *rs = config.recurse_submodules == RECURSE_SUBMODULES_DEFAULT + ? &config.recurse_submodules : NULL; fetch_config_from_gitmodules(sfjc, rs); } + + if (porcelain) { + switch (recurse_submodules_cli) { + case RECURSE_SUBMODULES_OFF: + case RECURSE_SUBMODULES_DEFAULT: + /* + * Reference updates in submodules would be ambiguous + * in porcelain mode, so we reject this combination. + */ + config.recurse_submodules = RECURSE_SUBMODULES_OFF; + break; + + default: + die(_("options '%s' and '%s' cannot be used together"), + "--porcelain", "--recurse-submodules"); + } + + config.display_format = DISPLAY_FORMAT_PORCELAIN; + } + if (negotiate_only && !negotiation_tip.nr) die(_("--negotiate-only needs one or more --negotiation-tip=*")); @@ -2289,7 +2395,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } else if (remote) { if (filter_options.choice || repo_has_promisor_remote(the_repository)) fetch_one_setup_partial(remote); - result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs); + result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs, + &config); } else { int max_children = max_jobs; @@ -2306,13 +2413,12 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) "from one remote")); if (max_children < 0) - max_children = fetch_parallel_config; + max_children = config.parallel; /* TODO should this also die if we have a previous partial-clone? */ - result = fetch_multiple(&list, max_children); + result = fetch_multiple(&list, max_children, &config); } - /* * This is only needed after fetch_one(), which does not fetch * submodules by itself. @@ -2322,20 +2428,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) * the fetched history from each remote, so there is no need * to fetch submodules from here. */ - if (!result && remote && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { + if (!result && remote && (config.recurse_submodules != RECURSE_SUBMODULES_OFF)) { struct strvec options = STRVEC_INIT; int max_children = max_jobs; if (max_children < 0) - max_children = submodule_fetch_jobs_config; + max_children = config.submodule_fetch_jobs; if (max_children < 0) - max_children = fetch_parallel_config; + max_children = config.parallel; - add_options_to_argv(&options); + add_options_to_argv(&options, &config); result = fetch_submodules(the_repository, &options, submodule_prefix, - recurse_submodules, + config.recurse_submodules, recurse_submodules_default, verbosity < 0, max_children); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 0bdc49a6e1..695fc8f4a5 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -22,7 +22,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) int i; struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; - int maxcount = 0, icase = 0; + int maxcount = 0, icase = 0, omit_empty = 0; struct ref_array array; struct ref_filter filter; struct ref_format format = REF_FORMAT_INIT; @@ -40,6 +40,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) N_("quote placeholders suitably for python"), QUOTE_PYTHON), OPT_BIT(0 , "tcl", &format.quote_style, N_("quote placeholders suitably for Tcl"), QUOTE_TCL), + OPT_BOOL(0, "omit-empty", &omit_empty, + N_("do not output a newline after empty formatted refs")), OPT_GROUP(""), OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")), @@ -112,7 +114,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) if (format_ref_array_item(array.items[i], &format, &output, &err)) die("%s", err.buf); fwrite(output.buf, 1, output.len, stdout); - putchar('\n'); + if (output.len || !omit_empty) + putchar('\n'); } strbuf_release(&err); diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c index 598ca16c46..37daf7bec1 100644 --- a/builtin/for-each-repo.c +++ b/builtin/for-each-repo.c @@ -3,6 +3,8 @@ #include "builtin.h" #include "gettext.h" #include "parse-options.h" +#include "path.h" +#include "repository.h" #include "run-command.h" #include "string-list.h" diff --git a/builtin/fsck.c b/builtin/fsck.c index 095b39d398..dcc165bf0c 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -19,11 +19,15 @@ #include "streaming.h" #include "decorate.h" #include "packfile.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "replace-object.h" #include "resolve-undo.h" #include "run-command.h" #include "worktree.h" +#include "pack-revindex.h" +#include "pack-bitmap.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -53,6 +57,8 @@ static int name_objects; #define ERROR_REFS 010 #define ERROR_COMMIT_GRAPH 020 #define ERROR_MULTI_PACK_INDEX 040 +#define ERROR_PACK_REV_INDEX 0100 +#define ERROR_BITMAP 0200 static const char *describe_object(const struct object_id *oid) { @@ -856,6 +862,38 @@ static int mark_packed_for_connectivity(const struct object_id *oid, return 0; } +static int check_pack_rev_indexes(struct repository *r, int show_progress) +{ + struct progress *progress = NULL; + uint32_t pack_count = 0; + int res = 0; + + if (show_progress) { + for (struct packed_git *p = get_all_packs(r); p; p = p->next) + pack_count++; + progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count); + pack_count = 0; + } + + for (struct packed_git *p = get_all_packs(r); p; p = p->next) { + int load_error = load_pack_revindex_from_disk(p); + + if (load_error < 0) { + error(_("unable to load rev-index for pack '%s'"), p->pack_name); + res = ERROR_PACK_REV_INDEX; + } else if (!load_error && + !load_pack_revindex(r, p) && + verify_pack_revindex(p)) { + error(_("invalid rev-index for pack '%s'"), p->pack_name); + res = ERROR_PACK_REV_INDEX; + } + display_progress(progress, ++pack_count); + } + stop_progress(&progress); + + return res; +} + static char const * const fsck_usage[] = { N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" @@ -1019,6 +1057,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) free_worktrees(worktrees); } + errors_found |= check_pack_rev_indexes(the_repository, show_progress); + if (verify_bitmap_files(the_repository)) + errors_found |= ERROR_BITMAP; + check_connectivity(); if (the_repository->settings.core_commit_graph) { diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 42af6a2cc7..f6dd9a784c 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -14,6 +14,7 @@ #include "simple-ipc.h" #include "khash.h" #include "pkt-line.h" +#include "trace2.h" static const char * const builtin_fsmonitor__daemon_usage[] = { N_("git fsmonitor--daemon start [<options>]"), diff --git a/builtin/gc.c b/builtin/gc.c index edd98d35a5..f3942188a6 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -12,6 +12,7 @@ #include "builtin.h" #include "abspath.h" +#include "date.h" #include "environment.h" #include "hex.h" #include "repository.h" @@ -25,6 +26,7 @@ #include "commit.h" #include "commit-graph.h" #include "packfile.h" +#include "object-file.h" #include "object-store.h" #include "pack.h" #include "pack-objects.h" @@ -37,6 +39,7 @@ #include "gettext.h" #include "hook.h" #include "setup.h" +#include "trace2.h" #include "wrapper.h" #define FAILED_RUN "failed to run %s" @@ -48,7 +51,7 @@ static const char * const builtin_gc_usage[] = { static int pack_refs = 1; static int prune_reflogs = 1; -static int cruft_packs = -1; +static int cruft_packs = 1; static int aggressive_depth = 50; static int aggressive_window = 250; static int gc_auto_threshold = 6700; @@ -219,7 +222,7 @@ static struct packed_git *find_base_packs(struct string_list *packs, struct packed_git *p, *base = NULL; for (p = get_all_packs(the_repository); p; p = p->next) { - if (!p->pack_local) + if (!p->pack_local || p->is_cruft) continue; if (limit) { if (p->pack_size >= limit) @@ -608,10 +611,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (prune_expire && parse_expiry_date(prune_expire, &dummy)) die(_("failed to parse prune expiry value %s"), prune_expire); - prepare_repo_settings(the_repository); - if (cruft_packs < 0) - cruft_packs = the_repository->settings.gc_cruft_packs; - if (aggressive) { strvec_push(&repack, "-f"); if (aggressive_depth > 0) @@ -1687,11 +1686,11 @@ static int get_schedule_cmd(const char **cmd, int *is_available) if (is_available) *is_available = 0; - string_list_split_in_place(&list, testing, ',', -1); + string_list_split_in_place(&list, testing, ",", -1); for_each_string_list_item(item, &list) { struct string_list pair = STRING_LIST_INIT_NODUP; - if (string_list_split_in_place(&pair, item->string, ':', 2) != 2) + if (string_list_split_in_place(&pair, item->string, ":", 2) != 2) continue; if (!strcmp(*cmd, pair.items[0].string)) { diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c index d5b871b21d..564cfcac4f 100644 --- a/builtin/get-tar-commit-id.c +++ b/builtin/get-tar-commit-id.c @@ -35,7 +35,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv UNUSED, const char *prefix die_errno("git get-tar-commit-id: read error"); if (n != HEADERSIZE) die_errno("git get-tar-commit-id: EOF before reading tar header"); - if (header->typeflag[0] != 'g') + if (header->typeflag[0] != TYPEFLAG_GLOBAL_HEADER) return 1; len = strtol(content, &end, 10); diff --git a/builtin/grep.c b/builtin/grep.c index a1b68d90bd..b86c754def 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -26,8 +26,11 @@ #include "setup.h" #include "submodule.h" #include "submodule-config.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "packfile.h" +#include "pager.h" #include "write-or-die.h" static const char *grep_prefix; diff --git a/builtin/hash-object.c b/builtin/hash-object.c index a15fe4fd3f..a380121166 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -9,6 +9,7 @@ #include "config.h" #include "gettext.h" #include "hex.h" +#include "object-file.h" #include "object-store.h" #include "blob.h" #include "quote.h" diff --git a/builtin/help.c b/builtin/help.c index 87333a02ec..d3cf4af3f6 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -6,7 +6,9 @@ #include "builtin.h" #include "exec-cmd.h" #include "gettext.h" +#include "pager.h" #include "parse-options.h" +#include "path.h" #include "run-command.h" #include "config-list.h" #include "help.h" diff --git a/builtin/index-pack.c b/builtin/index-pack.c index b17e79cd40..bb67e16655 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -17,7 +17,10 @@ #include "streaming.h" #include "thread-utils.h" #include "packfile.h" +#include "pack-revindex.h" +#include "object-file.h" #include "object-store.h" +#include "oid-array.h" #include "replace-object.h" #include "promisor-remote.h" #include "setup.h" @@ -1753,12 +1756,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) fsck_options.walk = mark_link; reset_pack_idx_option(&opts); + opts.flags |= WRITE_REV; git_config(git_index_pack_config, &opts); if (prefix && chdir(prefix)) die(_("Cannot come back to cwd")); - if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0)) - rev_index = 1; + if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0)) + rev_index = 0; else rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV)); diff --git a/builtin/init-db.c b/builtin/init-db.c index ba6e0b20fa..aef4036105 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -6,12 +6,15 @@ #include "cache.h" #include "abspath.h" #include "config.h" +#include "copy.h" #include "environment.h" #include "gettext.h" #include "refs.h" #include "builtin.h" #include "exec-cmd.h" +#include "object-file.h" #include "parse-options.h" +#include "path.h" #include "setup.h" #include "worktree.h" #include "wrapper.h" diff --git a/builtin/log.c b/builtin/log.c index 7d19578963..c85f13a5d5 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -12,7 +12,10 @@ #include "gettext.h" #include "hex.h" #include "refs.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" +#include "pager.h" #include "color.h" #include "commit.h" #include "diff.h" @@ -20,6 +23,7 @@ #include "revision.h" #include "log-tree.h" #include "builtin.h" +#include "oid-array.h" #include "tag.h" #include "reflog-walk.h" #include "patch-ids.h" @@ -40,6 +44,7 @@ #include "commit-reach.h" #include "range-diff.h" #include "tmp-objdir.h" +#include "tree.h" #include "write-or-die.h" #define MAIL_DEFAULT_WRAP 72 @@ -861,7 +866,7 @@ static void log_setup_revisions_tweak(struct rev_info *rev, struct setup_revision_opt *opt) { if (rev->diffopt.flags.default_follow_renames && - rev->prune_data.nr == 1) + diff_check_follow_pathspec(&rev->prune_data, 0)) rev->diffopt.flags.follow_renames = 1; if (rev->first_parent_only) @@ -1401,7 +1406,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, } } -static const char *clean_message_id(const char *msg_id) +static char *clean_message_id(const char *msg_id) { char ch; const char *a, *z, *m; @@ -1419,7 +1424,7 @@ static const char *clean_message_id(const char *msg_id) if (!z) die(_("insane in-reply-to: %s"), msg_id); if (++z == m) - return a; + return xstrdup(a); return xmemdupz(a, z - a); } @@ -2305,11 +2310,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (in_reply_to || thread || cover_letter) { rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids)); - string_list_init_nodup(rev.ref_message_ids); + string_list_init_dup(rev.ref_message_ids); } if (in_reply_to) { - const char *msgid = clean_message_id(in_reply_to); - string_list_append(rev.ref_message_ids, msgid); + char *msgid = clean_message_id(in_reply_to); + string_list_append_nodup(rev.ref_message_ids, msgid); } rev.numbered_files = just_numbers; rev.patch_suffix = fmt_patch_suffix; @@ -2365,8 +2370,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) && (!cover_letter || rev.nr > 1)) free(rev.message_id); else - string_list_append(rev.ref_message_ids, - rev.message_id); + string_list_append_nodup(rev.ref_message_ids, + rev.message_id); } gen_message_id(&rev, oid_to_hex(&commit->object.oid)); } @@ -2415,6 +2420,7 @@ done: strbuf_release(&rdiff_title); strbuf_release(&sprefix); 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); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index ed35fa8d8e..72012c0f0f 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -8,10 +8,12 @@ #include "cache.h" #include "repository.h" #include "config.h" +#include "convert.h" #include "quote.h" #include "dir.h" #include "builtin.h" #include "gettext.h" +#include "object-name.h" #include "strbuf.h" #include "tree.h" #include "cache-tree.h" @@ -23,6 +25,9 @@ #include "setup.h" #include "submodule.h" #include "submodule-config.h" +#include "object-store.h" +#include "hex.h" + static int abbrev; static int show_deleted; @@ -239,6 +244,24 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } +static void expand_objectsize(struct strbuf *line, const struct object_id *oid, + const enum object_type type, unsigned int padded) +{ + if (type == OBJ_BLOB) { + unsigned long size; + if (oid_object_info(the_repository, oid, &size) < 0) + die(_("could not get object info about '%s'"), + oid_to_hex(oid)); + if (padded) + strbuf_addf(line, "%7"PRIuMAX, (uintmax_t)size); + else + strbuf_addf(line, "%"PRIuMAX, (uintmax_t)size); + } else if (padded) { + strbuf_addf(line, "%7s", "-"); + } else { + strbuf_addstr(line, "-"); + } +} struct show_index_data { const char *pathname; struct index_state *istate; @@ -270,6 +293,12 @@ static size_t expand_show_index(struct strbuf *sb, const char *start, strbuf_addf(sb, "%06o", data->ce->ce_mode); else if (skip_prefix(start, "(objectname)", &p)) strbuf_add_unique_abbrev(sb, &data->ce->oid, abbrev); + else if (skip_prefix(start, "(objecttype)", &p)) + strbuf_addstr(sb, type_name(object_type(data->ce->ce_mode))); + else if (skip_prefix(start, "(objectsize:padded)", &p)) + expand_objectsize(sb, &data->ce->oid, object_type(data->ce->ce_mode), 1); + else if (skip_prefix(start, "(objectsize)", &p)) + expand_objectsize(sb, &data->ce->oid, object_type(data->ce->ce_mode), 0); else if (skip_prefix(start, "(stage)", &p)) strbuf_addf(sb, "%d", ce_stage(data->ce)); else if (skip_prefix(start, "(eolinfo:index)", &p)) diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 3c74c4a104..cb6cb77e08 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -3,6 +3,7 @@ #include "gettext.h" #include "hex.h" #include "transport.h" +#include "pkt-line.h" #include "ref-filter.h" #include "remote.h" #include "refs.h" diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index f32e6be219..077977a461 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -7,6 +7,7 @@ #include "config.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "object-store.h" #include "blob.h" #include "tree.h" diff --git a/builtin/merge-base.c b/builtin/merge-base.c index 3f22273b40..854019a32d 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -7,6 +7,7 @@ #include "refs.h" #include "diff.h" #include "revision.h" +#include "object-name.h" #include "parse-options.h" #include "repository.h" #include "commit-reach.h" diff --git a/builtin/merge-index.c b/builtin/merge-index.c index b747b4ed98..ab16e70f23 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,6 +1,7 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" #include "hex.h" +#include "repository.h" #include "run-command.h" static const char *pgm; diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 91ed55f3ab..b9e980384a 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -1,9 +1,13 @@ #include "cache.h" #include "builtin.h" +#include "advice.h" #include "commit.h" #include "gettext.h" +#include "hash.h" #include "tag.h" #include "merge-recursive.h" +#include "object-name.h" +#include "repository.h" #include "xdiff-interface.h" static const char builtin_merge_recursive_usage[] = diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 803e380856..4325897a80 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -8,6 +8,7 @@ #include "commit.h" #include "commit-reach.h" #include "merge-ort.h" +#include "object-name.h" #include "object-store.h" #include "parse-options.h" #include "repository.h" @@ -15,6 +16,8 @@ #include "exec-cmd.h" #include "merge-blobs.h" #include "quote.h" +#include "tree.h" +#include "config.h" static int line_termination = '\n'; @@ -445,7 +448,7 @@ static int real_merge(struct merge_tree_options *o, base_commit = lookup_commit_reference_by_name(merge_base); if (!base_commit) - die(_("could not lookup commit %s"), merge_base); + die(_("could not lookup commit '%s'"), merge_base); opt.ancestor = merge_base; base_tree = repo_get_commit_tree(the_repository, base_commit); @@ -626,6 +629,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) if (argc != expected_remaining_argc) usage_with_options(merge_tree_usage, mt_options); + git_config(git_default_config, NULL); + /* Do the relevant type of merge */ if (o.mode == MODE_REAL) return real_merge(&o, merge_base, argv[0], argv[1], prefix); diff --git a/builtin/merge.c b/builtin/merge.c index a99be9610e..8da3e46abb 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -9,11 +9,14 @@ #define USE_THE_INDEX_VARIABLE #include "cache.h" #include "abspath.h" +#include "advice.h" #include "alloc.h" #include "config.h" +#include "editor.h" #include "environment.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "parse-options.h" #include "builtin.h" #include "lockfile.h" diff --git a/builtin/mktag.c b/builtin/mktag.c index b3f6d7ea38..44fa56eff3 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -4,6 +4,7 @@ #include "parse-options.h" #include "tag.h" #include "replace-object.h" +#include "object-file.h" #include "object-store.h" #include "fsck.h" #include "config.h" diff --git a/builtin/mv.c b/builtin/mv.c index b7c5ffbd8c..665bd27448 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -6,16 +6,19 @@ #define USE_THE_INDEX_VARIABLE #include "builtin.h" #include "abspath.h" +#include "advice.h" #include "alloc.h" #include "config.h" #include "environment.h" #include "gettext.h" +#include "object-file.h" #include "pathspec.h" #include "lockfile.h" #include "dir.h" #include "cache-tree.h" #include "string-list.h" #include "parse-options.h" +#include "repository.h" #include "setup.h" #include "submodule.h" #include "entry.h" diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 831d360a78..4d15a23fc4 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -8,6 +8,8 @@ #include "commit.h" #include "tag.h" #include "refs.h" +#include "object-name.h" +#include "pager.h" #include "parse-options.h" #include "prio-queue.h" #include "hash-lookup.h" @@ -571,7 +573,11 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) N_("ignore refs matching <pattern>")), OPT_GROUP(""), OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")), - OPT_BOOL(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead")), + OPT_BOOL_F(0, + "stdin", + &transform_stdin, + N_("deprecated: use --annotate-stdin instead"), + PARSE_OPT_HIDDEN), OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")), OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")), OPT_BOOL(0, "always", &always, diff --git a/builtin/notes.c b/builtin/notes.c index 4ff44f1e3d..d5788352b6 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -10,9 +10,11 @@ #include "cache.h" #include "config.h" #include "builtin.h" +#include "editor.h" #include "gettext.h" #include "hex.h" #include "notes.h" +#include "object-name.h" #include "object-store.h" #include "repository.h" #include "blob.h" diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 77d88f85b0..9cfc8801f9 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -33,6 +33,7 @@ #include "strvec.h" #include "list.h" #include "packfile.h" +#include "object-file.h" #include "object-store.h" #include "replace-object.h" #include "dir.h" @@ -1330,7 +1331,7 @@ static int no_try_delta(const char *path) if (!check) check = attr_check_initl("delta", NULL); - git_check_attr(the_repository->index, NULL, path, check); + git_check_attr(the_repository->index, path, check); if (ATTR_FALSE(check->items[0].value)) return 1; return 0; @@ -3359,16 +3360,16 @@ static void read_packs_list_from_stdin(void) } string_list_sort(&include_packs); + string_list_remove_duplicates(&include_packs, 0); string_list_sort(&exclude_packs); + string_list_remove_duplicates(&exclude_packs, 0); for (p = get_all_packs(the_repository); p; p = p->next) { const char *pack_name = pack_basename(p); - item = string_list_lookup(&include_packs, pack_name); - if (!item) - item = string_list_lookup(&exclude_packs, pack_name); - - if (item) + if ((item = string_list_lookup(&include_packs, pack_name))) + item->util = p; + if ((item = string_list_lookup(&exclude_packs, pack_name))) item->util = p; } @@ -4293,9 +4294,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) } reset_pack_idx_option(&pack_idx_opts); + pack_idx_opts.flags |= WRITE_REV; git_config(git_pack_config, NULL); - if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0)) - pack_idx_opts.flags |= WRITE_REV; + if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0)) + pack_idx_opts.flags &= ~WRITE_REV; progress = isatty(2); argc = parse_options(argc, argv, prefix, pack_objects_options, diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 9833815fb3..bcf383cac9 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -4,22 +4,45 @@ #include "parse-options.h" #include "refs.h" #include "repository.h" +#include "revision.h" static char const * const pack_refs_usage[] = { - N_("git pack-refs [--all] [--no-prune]"), + N_("git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]"), NULL }; int cmd_pack_refs(int argc, const char **argv, const char *prefix) { unsigned int flags = PACK_REFS_PRUNE; + static struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; + static struct string_list included_refs = STRING_LIST_INIT_NODUP; + struct pack_refs_opts pack_refs_opts = { .exclusions = &excludes, + .includes = &included_refs, + .flags = flags }; + static struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP; + struct string_list_item *item; + struct option opts[] = { - OPT_BIT(0, "all", &flags, N_("pack everything"), PACK_REFS_ALL), - OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE), + OPT_BIT(0, "all", &pack_refs_opts.flags, N_("pack everything"), PACK_REFS_ALL), + OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE), + OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"), + N_("references to include")), + OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"), + N_("references to exclude")), OPT_END(), }; git_config(git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); - return refs_pack_refs(get_main_ref_store(the_repository), flags); + + for_each_string_list_item(item, &option_excluded_refs) + add_ref_exclusion(pack_refs_opts.exclusions, item->string); + + if (pack_refs_opts.flags & PACK_REFS_ALL) + string_list_append(pack_refs_opts.includes, "*"); + + if (!pack_refs_opts.includes->nr) + string_list_append(pack_refs_opts.includes, "refs/tags/*"); + + return refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); } diff --git a/builtin/prune.c b/builtin/prune.c index 5c0952f5c6..5dc9b20720 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -11,6 +11,8 @@ #include "progress.h" #include "prune-packed.h" #include "replace-object.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "shallow.h" diff --git a/builtin/pull.c b/builtin/pull.c index 5405d09f22..0c7bac97b7 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -7,10 +7,12 @@ */ #define USE_THE_INDEX_VARIABLE #include "cache.h" +#include "advice.h" #include "config.h" #include "builtin.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "parse-options.h" #include "exec-cmd.h" #include "run-command.h" @@ -1045,7 +1047,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (!opt_autostash) require_clean_work_tree(the_repository, N_("pull with rebase"), - _("please commit or stash them."), 1, 0); + _("Please commit or stash them."), 1, 0); if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs)) oidclr(&rebase_fork_point); diff --git a/builtin/push.c b/builtin/push.c index fa550b8f80..dbdf609daf 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -2,6 +2,7 @@ * "git push" */ #include "cache.h" +#include "advice.h" #include "branch.h" #include "config.h" #include "environment.h" @@ -13,9 +14,12 @@ #include "remote.h" #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" +#include "trace2.h" #include "color.h" static const char * const push_usage[] = { @@ -591,11 +595,12 @@ int cmd_push(int argc, const char **argv, const char *prefix) struct option options[] = { OPT__VERBOSITY(&verbosity), OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")), - OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL), + OPT_BIT( 0 , "all", &flags, N_("push all branches"), TRANSPORT_PUSH_ALL), + OPT_ALIAS( 0 , "branches", "all"), OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"), (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")), - OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")), + OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --branches or --mirror)")), OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN), OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE), @@ -638,7 +643,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) set_push_cert_flags(&flags, push_cert); if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR)))) - die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--mirror/--tags"); + die(_("options '%s' and '%s' cannot be used together"), "--delete", "--all/--branches/--mirror/--tags"); if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); diff --git a/builtin/range-diff.c b/builtin/range-diff.c index b72af527f0..04339a92ea 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -1,6 +1,7 @@ #include "cache.h" #include "builtin.h" #include "gettext.h" +#include "object-name.h" #include "parse-options.h" #include "range-diff.h" #include "config.h" diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 600d4f748f..440f19b1b8 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -11,6 +11,7 @@ #include "hex.h" #include "lockfile.h" #include "object.h" +#include "object-name.h" #include "tree.h" #include "tree-walk.h" #include "cache-tree.h" @@ -18,6 +19,7 @@ #include "dir.h" #include "builtin.h" #include "parse-options.h" +#include "repository.h" #include "resolve-undo.h" #include "setup.h" #include "submodule.h" diff --git a/builtin/rebase.c b/builtin/rebase.c index 680fe3c145..ace1d5e8d1 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -21,6 +21,8 @@ #include "cache-tree.h" #include "unpack-trees.h" #include "lockfile.h" +#include "object-file.h" +#include "object-name.h" #include "parse-options.h" #include "commit.h" #include "diff.h" @@ -32,6 +34,7 @@ #include "sequencer.h" #include "rebase-interactive.h" #include "reset.h" +#include "trace2.h" #include "hook.h" #include "wrapper.h" @@ -121,7 +124,8 @@ struct rebase_options { struct string_list exec; int allow_empty_message; int rebase_merges, rebase_cousins; - char *strategy, *strategy_opts; + char *strategy; + struct string_list strategy_opts; struct strbuf git_format_patch_opt; int reschedule_failed_exec; int reapply_cherry_picks; @@ -150,6 +154,7 @@ struct rebase_options { .config_rebase_merges = -1, \ .update_refs = -1, \ .config_update_refs = -1, \ + .strategy_opts = STRING_LIST_INIT_NODUP,\ } static struct replay_opts get_replay_opts(const struct rebase_options *opts) @@ -183,8 +188,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) replay.default_strategy = NULL; } - if (opts->strategy_opts) - parse_strategy_opts(&replay, opts->strategy_opts); + for (size_t i = 0; i < opts->strategy_opts.nr; i++) + strvec_push(&replay.xopts, opts->strategy_opts.items[i].string); if (opts->squash_onto) { oidcpy(&replay.squash_onto, opts->squash_onto); @@ -492,24 +497,6 @@ static int read_basic_state(struct rebase_options *opts) opts->gpg_sign_opt = xstrdup(buf.buf); } - if (file_exists(state_dir_path("strategy", opts))) { - strbuf_reset(&buf); - if (!read_oneliner(&buf, state_dir_path("strategy", opts), - READ_ONELINER_WARN_MISSING)) - return -1; - free(opts->strategy); - opts->strategy = xstrdup(buf.buf); - } - - if (file_exists(state_dir_path("strategy_opts", opts))) { - strbuf_reset(&buf); - if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts), - READ_ONELINER_WARN_MISSING)) - return -1; - free(opts->strategy_opts); - opts->strategy_opts = xstrdup(buf.buf); - } - strbuf_release(&buf); return 0; @@ -527,12 +514,6 @@ static int rebase_write_basic_state(struct rebase_options *opts) write_file(state_dir_path("quiet", opts), "%s", ""); if (opts->flags & REBASE_VERBOSE) write_file(state_dir_path("verbose", opts), "%s", ""); - if (opts->strategy) - write_file(state_dir_path("strategy", opts), "%s", - opts->strategy); - if (opts->strategy_opts) - write_file(state_dir_path("strategy_opts", opts), "%s", - opts->strategy_opts); if (opts->allow_rerere_autoupdate > 0) write_file(state_dir_path("allow_rerere_autoupdate", opts), "-%s-rerere-autoupdate", @@ -1089,7 +1070,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) struct object_id branch_base; int ignore_whitespace = 0; const char *gpg_sign = NULL; - struct string_list strategy_options = STRING_LIST_INIT_NODUP; struct object_id squash_onto; char *squash_onto_name = NULL; char *keep_base_onto_name = NULL; @@ -1197,7 +1177,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) N_("use 'merge-base --fork-point' to refine upstream")), OPT_STRING('s', "strategy", &options.strategy, N_("strategy"), N_("use the given merge strategy")), - OPT_STRING_LIST('X', "strategy-option", &strategy_options, + OPT_STRING_LIST('X', "strategy-option", &options.strategy_opts, N_("option"), N_("pass the argument through to the merge " "strategy")), @@ -1500,23 +1480,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) } else { /* REBASE_MERGE */ if (ignore_whitespace) { - string_list_append(&strategy_options, + string_list_append(&options.strategy_opts, "ignore-space-change"); } } - if (strategy_options.nr) { - int i; - - if (!options.strategy) - options.strategy = "ort"; - - strbuf_reset(&buf); - for (i = 0; i < strategy_options.nr; i++) - strbuf_addf(&buf, " --%s", - strategy_options.items[i].string); - options.strategy_opts = xstrdup(buf.buf); - } + if (options.strategy_opts.nr && !options.strategy) + options.strategy = "ort"; if (options.strategy) { options.strategy = xstrdup(options.strategy); @@ -1898,10 +1868,9 @@ cleanup: free(options.gpg_sign_opt); string_list_clear(&options.exec, 0); free(options.strategy); - free(options.strategy_opts); + string_list_clear(&options.strategy_opts, 0); strbuf_release(&options.git_format_patch_opt); free(squash_onto_name); free(keep_base_onto_name); - string_list_clear(&strategy_options, 0); return !!ret; } diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 9109552533..1a31a58367 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -29,9 +29,13 @@ #include "tmp-objdir.h" #include "oidset.h" #include "packfile.h" +#include "object-name.h" #include "object-store.h" #include "protocol.h" #include "commit-reach.h" +#include "server-info.h" +#include "trace.h" +#include "trace2.h" #include "worktree.h" #include "shallow.h" #include "parse-options.h" @@ -2093,7 +2097,7 @@ static struct command *read_head_info(struct packet_reader *reader, const char *feature_list = reader->line + linelen + 1; const char *hash = NULL; const char *client_sid; - int len = 0; + size_t len = 0; if (parse_feature_request(feature_list, "report-status")) report_status = 1; if (parse_feature_request(feature_list, "report-status-v2")) diff --git a/builtin/repack.c b/builtin/repack.c index df4d8e0f0b..0541c3ce15 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -7,6 +7,7 @@ #include "hex.h" #include "parse-options.h" #include "run-command.h" +#include "server-info.h" #include "sigchain.h" #include "strbuf.h" #include "string-list.h" @@ -325,7 +326,8 @@ static int geometry_cmp(const void *va, const void *vb) } static void init_pack_geometry(struct pack_geometry **geometry_p, - struct string_list *existing_kept_packs) + struct string_list *existing_kept_packs, + const struct pack_objects_args *args) { struct packed_git *p; struct pack_geometry *geometry; @@ -335,6 +337,14 @@ static void init_pack_geometry(struct pack_geometry **geometry_p, geometry = *geometry_p; for (p = get_all_packs(the_repository); p; p = p->next) { + if (args->local && !p->pack_local) + /* + * When asked to only repack local packfiles we skip + * over any packfiles that are borrowed from alternate + * object directories. + */ + continue; + if (!pack_kept_objects) { /* * Any pack that has its pack_keep bit set will appear @@ -448,8 +458,10 @@ static void split_pack_geometry(struct pack_geometry *geometry, int factor) geometry->split = split; } -static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry) +static struct packed_git *get_preferred_pack(struct pack_geometry *geometry) { + uint32_t i; + if (!geometry) { /* * No geometry means either an all-into-one repack (in which @@ -464,7 +476,21 @@ static struct packed_git *get_largest_active_pack(struct pack_geometry *geometry } if (geometry->split == geometry->pack_nr) return NULL; - return geometry->pack[geometry->pack_nr - 1]; + + /* + * The preferred pack is the largest pack above the split line. In + * other words, it is the largest pack that does not get rolled up in + * the geometric repack. + */ + for (i = geometry->pack_nr; i > geometry->split; i--) + /* + * A pack that is not local would never be included in a + * multi-pack index. We thus skip over any non-local packs. + */ + if (geometry->pack[i - 1]->pack_local) + return geometry->pack[i - 1]; + + return NULL; } static void clear_pack_geometry(struct pack_geometry *geometry) @@ -558,6 +584,17 @@ static void midx_included_packs(struct string_list *include, for (i = geometry->split; i < geometry->pack_nr; i++) { struct packed_git *p = geometry->pack[i]; + /* + * The multi-pack index never refers to packfiles part + * of an alternate object database, so we skip these. + * While git-multi-pack-index(1) would silently ignore + * them anyway, this allows us to skip executing the + * command completely when we have only non-local + * packfiles. + */ + if (!p->pack_local) + continue; + strbuf_addstr(&buf, pack_basename(p)); strbuf_strip_suffix(&buf, ".pack"); strbuf_addstr(&buf, ".idx"); @@ -591,7 +628,7 @@ static int write_midx_included_packs(struct string_list *include, { struct child_process cmd = CHILD_PROCESS_INIT; struct string_list_item *item; - struct packed_git *largest = get_largest_active_pack(geometry); + struct packed_git *preferred = get_preferred_pack(geometry); FILE *in; int ret; @@ -612,9 +649,9 @@ static int write_midx_included_packs(struct string_list *include, if (write_bitmaps) strvec_push(&cmd.args, "--bitmap"); - if (largest) + if (preferred) strvec_pushf(&cmd.args, "--preferred-pack=%s", - pack_basename(largest)); + pack_basename(preferred)); if (refs_snapshot) strvec_pushf(&cmd.args, "--refs-snapshot=%s", refs_snapshot); @@ -774,7 +811,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("same as -a, pack unreachable cruft objects separately"), PACK_CRUFT), OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"), - N_("with -C, expire objects older than this")), + N_("with --cruft, expire objects older than this")), OPT_BOOL('d', NULL, &delete_redundant, N_("remove redundant packs, and run git-prune-packed")), OPT_BOOL('f', NULL, &po_args.no_reuse_delta, @@ -853,6 +890,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (write_bitmaps && !(pack_everything & ALL_INTO_ONE) && !write_midx) die(_(incremental_bitmap_conflict_error)); + if (write_bitmaps && po_args.local && has_alt_odb(the_repository)) { + /* + * When asked to do a local repack, but we have + * packfiles that are inherited from an alternate, then + * we cannot guarantee that the multi-pack-index would + * have full coverage of all objects. We thus disable + * writing bitmaps in that case. + */ + warning(_("disabling bitmap writing, as some objects are not being packed")); + write_bitmaps = 0; + } + if (write_midx && write_bitmaps) { struct strbuf path = STRBUF_INIT; @@ -875,7 +924,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (geometric_factor) { if (pack_everything) die(_("options '%s' and '%s' cannot be used together"), "--geometric", "-A/-a"); - init_pack_geometry(&geometry, &existing_kept_packs); + init_pack_geometry(&geometry, &existing_kept_packs, &po_args); split_pack_geometry(geometry, geometric_factor); } diff --git a/builtin/replace.c b/builtin/replace.c index d2adc8ab61..981f189443 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -11,12 +11,15 @@ #include "cache.h" #include "config.h" #include "builtin.h" +#include "editor.h" #include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" #include "parse-options.h" #include "run-command.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "replace-object.h" #include "repository.h" diff --git a/builtin/rerere.c b/builtin/rerere.c index d4a03707b1..d4bd52797f 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -4,6 +4,7 @@ #include "dir.h" #include "gettext.h" #include "parse-options.h" +#include "repository.h" #include "string-list.h" #include "rerere.h" #include "wrapper.h" diff --git a/builtin/reset.c b/builtin/reset.c index 0ed329236c..f99f32d580 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -9,6 +9,7 @@ */ #define USE_THE_INDEX_VARIABLE #include "builtin.h" +#include "advice.h" #include "config.h" #include "environment.h" #include "gettext.h" @@ -23,12 +24,15 @@ #include "diffcore.h" #include "tree.h" #include "branch.h" +#include "object-name.h" #include "parse-options.h" #include "unpack-trees.h" #include "cache-tree.h" #include "setup.h" #include "submodule.h" #include "submodule-config.h" +#include "trace.h" +#include "trace2.h" #include "dir.h" #include "add-interactive.h" diff --git a/builtin/rev-list.c b/builtin/rev-list.c index a3dbbb6338..6dc8be492a 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -10,6 +10,8 @@ #include "list-objects-filter.h" #include "list-objects-filter-options.h" #include "object.h" +#include "object-name.h" +#include "object-file.h" #include "object-store.h" #include "pack.h" #include "pack-bitmap.h" diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 1af2089f9b..852e49e340 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -15,6 +15,7 @@ #include "refs.h" #include "quote.h" #include "builtin.h" +#include "object-name.h" #include "parse-options.h" #include "diff.h" #include "revision.h" diff --git a/builtin/revert.c b/builtin/revert.c index f72761bf88..0240ec8593 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -45,20 +45,6 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts) return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage; } -static int option_parse_x(const struct option *opt, - const char *arg, int unset) -{ - struct replay_opts **opts_ptr = opt->value; - struct replay_opts *opts = *opts_ptr; - - if (unset) - return 0; - - ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc); - opts->xopts[opts->xopts_nr++] = xstrdup(arg); - return 0; -} - static int option_parse_m(const struct option *opt, const char *arg, int unset) { @@ -116,8 +102,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, 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_CALLBACK('X', "strategy-option", &opts, N_("option"), - N_("option for merge strategy"), option_parse_x), + 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"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_END() @@ -178,7 +164,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, "--signoff", opts->signoff, "--mainline", opts->mainline, "--strategy", opts->strategy ? 1 : 0, - "--strategy-option", opts->xopts ? 1 : 0, + "--strategy-option", opts->xopts.nr ? 1 : 0, "-x", opts->record_origin, "--ff", opts->allow_ff, "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE, diff --git a/builtin/rm.c b/builtin/rm.c index 6be9281742..b4589c824c 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -12,8 +12,11 @@ #include "dir.h" #include "cache-tree.h" #include "gettext.h" +#include "hash.h" #include "tree-walk.h" +#include "object-name.h" #include "parse-options.h" +#include "repository.h" #include "string-list.h" #include "setup.h" #include "submodule.h" diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 463a8d11c3..7ef4a642c1 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -2,13 +2,16 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "pretty.h" #include "refs.h" #include "builtin.h" #include "color.h" #include "strvec.h" +#include "object-name.h" #include "parse-options.h" +#include "repository.h" #include "dir.h" #include "commit-slab.h" #include "date.h" diff --git a/builtin/show-index.c b/builtin/show-index.c index d4bbbbcd6c..d839e55335 100644 --- a/builtin/show-index.c +++ b/builtin/show-index.c @@ -1,9 +1,11 @@ #include "builtin.h" #include "cache.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>]", diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 138d30a005..a2243b4219 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -4,6 +4,7 @@ #include "gettext.h" #include "hex.h" #include "refs.h" +#include "object-name.h" #include "object-store.h" #include "object.h" #include "tag.h" diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 5e917ead7b..40d420f06c 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -4,6 +4,8 @@ #include "dir.h" #include "environment.h" #include "gettext.h" +#include "object-file.h" +#include "object-name.h" #include "parse-options.h" #include "pathspec.h" #include "repository.h" diff --git a/builtin/stash.c b/builtin/stash.c index 735d27039e..a7e17ffe38 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -5,6 +5,7 @@ #include "environment.h" #include "gettext.h" #include "hex.h" +#include "object-name.h" #include "parse-options.h" #include "refs.h" #include "lockfile.h" diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 569068e6a2..6a16208e8a 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -24,6 +24,8 @@ #include "revision.h" #include "diffcore.h" #include "diff.h" +#include "object-file.h" +#include "object-name.h" #include "object-store.h" #include "advice.h" #include "branch.h" @@ -2022,14 +2024,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, strbuf_reset(&sb); strbuf_addf(&sb, "submodule.%s.url", sub->name); if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) { - if (starts_with_dot_slash(sub->url) || - starts_with_dot_dot_slash(sub->url)) { + if (sub->url && (starts_with_dot_slash(sub->url) || + starts_with_dot_dot_slash(sub->url))) { url = resolve_relative_url(sub->url, NULL, 0); need_free_url = 1; } else url = sub->url; } + if (!url) + die(_("cannot clone submodule '%s' without a URL"), sub->name); + strbuf_reset(&sb); strbuf_addf(&sb, "%s/.git", ce->name); needs_cloning = !file_exists(sb.buf); diff --git a/builtin/tag.c b/builtin/tag.c index 782bb3aa2f..49b64c7a28 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -7,12 +7,15 @@ */ #include "cache.h" +#include "advice.h" #include "config.h" #include "builtin.h" +#include "editor.h" #include "environment.h" #include "gettext.h" #include "hex.h" #include "refs.h" +#include "object-name.h" #include "object-store.h" #include "tag.h" #include "run-command.h" @@ -41,6 +44,7 @@ static const char * const git_tag_usage[] = { static unsigned int colopts; static int force_sign_annotate; static int config_sign_tag = -1; /* unspecified */ +static int omit_empty = 0; static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format) @@ -79,7 +83,8 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, if (format_ref_array_item(array.items[i], format, &output, &err)) die("%s", err.buf); fwrite(output.buf, 1, output.len, stdout); - putchar('\n'); + if (output.len || !omit_empty) + putchar('\n'); } strbuf_release(&err); @@ -266,11 +271,10 @@ static const char message_advice_nested_tag[] = static void create_tag(const struct object_id *object, const char *object_ref, const char *tag, struct strbuf *buf, struct create_tag_options *opt, - struct object_id *prev, struct object_id *result) + struct object_id *prev, struct object_id *result, char *path) { enum object_type type; struct strbuf header = STRBUF_INIT; - char *path = NULL; type = oid_object_info(the_repository, object, NULL); if (type <= OBJ_NONE) @@ -294,7 +298,6 @@ static void create_tag(const struct object_id *object, const char *object_ref, int fd; /* write the template message before editing: */ - path = git_pathdup("TAG_EDITMSG"); fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (opt->message_given) { @@ -336,10 +339,6 @@ static void create_tag(const struct object_id *object, const char *object_ref, path); exit(128); } - if (path) { - unlink_or_warn(path); - free(path); - } } static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb) @@ -474,6 +473,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")), OPT_MERGED(&filter, N_("print only tags that are merged")), OPT_NO_MERGED(&filter, N_("print only tags that are not merged")), + OPT_BOOL(0, "omit-empty", &omit_empty, + N_("do not output a newline after empty formatted refs")), OPT_REF_SORT(&sorting_options), { OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"), @@ -488,6 +489,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) }; int ret = 0; const char *only_in_list = NULL; + char *path = NULL; setup_ref_filter_porcelain_msg(); @@ -622,7 +624,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object); + path = git_pathdup("TAG_EDITMSG"); + create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, + path); } transaction = ref_transaction_begin(&err); @@ -630,8 +634,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix) ref_transaction_update(transaction, ref.buf, &object, &prev, create_reflog ? REF_FORCE_CREATE_REFLOG : 0, reflog_msg.buf, &err) || - ref_transaction_commit(transaction, &err)) + ref_transaction_commit(transaction, &err)) { + if (path) + fprintf(stderr, + _("The tag message has been left in %s\n"), + path); die("%s", err.buf); + } + if (path) { + unlink_or_warn(path); + free(path); + } ref_transaction_free(transaction); if (force && !is_null_oid(&prev) && !oideq(&prev, &object)) printf(_("Updated tag '%s' (was %s)\n"), tag, diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index 00179180c7..b35a4b9dfe 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -1,6 +1,7 @@ #include "builtin.h" #include "config.h" #include "hex.h" +#include "object-name.h" #include "object-store.h" #include "wrapper.h" diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 585e81b106..2c52c3a741 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -4,6 +4,7 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "git-zlib.h" #include "hex.h" #include "object-store.h" #include "object.h" diff --git a/builtin/update-index.c b/builtin/update-index.c index 03cda5e60d..5fab9ad2ec 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -9,19 +9,23 @@ #include "config.h" #include "environment.h" #include "gettext.h" +#include "hash.h" #include "hex.h" #include "lockfile.h" #include "quote.h" #include "cache-tree.h" #include "tree-walk.h" #include "builtin.h" +#include "object-file.h" #include "refs.h" #include "resolve-undo.h" #include "parse-options.h" #include "pathspec.h" #include "dir.h" +#include "repository.h" #include "setup.h" #include "split-index.h" +#include "symlinks.h" #include "fsmonitor.h" #include "write-or-die.h" diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 3ffd75b3e7..0c59b1c9ef 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -1,10 +1,13 @@ #include "cache.h" #include "config.h" #include "gettext.h" +#include "hash.h" #include "refs.h" #include "builtin.h" +#include "object-name.h" #include "parse-options.h" #include "quote.h" +#include "repository.h" #include "strvec.h" static const char * const git_update_ref_usage[] = { diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index e7bff27ae4..19dce3c065 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -3,6 +3,7 @@ #include "builtin.h" #include "gettext.h" #include "parse-options.h" +#include "server-info.h" static const char * const update_server_info_usage[] = { "git update-server-info [-f | --force]", diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index 7f9320ac6d..44ad400e18 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -6,6 +6,7 @@ #include "archive.h" #include "pkt-line.h" #include "sideband.h" +#include "repository.h" #include "run-command.h" #include "strvec.h" diff --git a/builtin/var.c b/builtin/var.c index acb988d2d5..2149998980 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -5,7 +5,9 @@ */ #include "builtin.h" #include "config.h" +#include "editor.h" #include "ident.h" +#include "pager.h" #include "refs.h" static const char var_usage[] = "git var (-l | <variable>)"; diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 4d10aa98b1..5d99b82a64 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -9,6 +9,7 @@ #include "config.h" #include "builtin.h" #include "gettext.h" +#include "object-name.h" #include "object-store.h" #include "repository.h" #include "commit.h" diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index 28d0da6845..c6019a0ad8 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -11,6 +11,7 @@ #include "gettext.h" #include "tag.h" #include "run-command.h" +#include "object-name.h" #include "parse-options.h" #include "gpg-interface.h" #include "ref-filter.h" diff --git a/builtin/worktree.c b/builtin/worktree.c index 5f62084334..2931cd0230 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -3,16 +3,20 @@ #include "advice.h" #include "checkout.h" #include "config.h" +#include "copy.h" #include "builtin.h" #include "dir.h" #include "environment.h" #include "gettext.h" #include "hex.h" +#include "object-file.h" +#include "object-name.h" #include "parse-options.h" #include "strvec.h" #include "branch.h" #include "refs.h" #include "remote.h" +#include "repository.h" #include "run-command.h" #include "hook.h" #include "sigchain.h" @@ -516,7 +520,7 @@ static int add_worktree(const char *path, const char *refname, * values from the current worktree into the new one, that way the * new worktree behaves the same as this one. */ - if (repository_format_worktree_config) + if (the_repository->repository_format_worktree_config) copy_filtered_worktree_config(sb_repo.buf); strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf); diff --git a/builtin/write-tree.c b/builtin/write-tree.c index 6085f64d10..84b83318c9 100644 --- a/builtin/write-tree.c +++ b/builtin/write-tree.c @@ -13,6 +13,7 @@ #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>/]"), @@ -41,6 +42,9 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix) argc = parse_options(argc, argv, cmd_prefix, write_tree_options, write_tree_usage, 0); + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + ret = write_index_as_tree(&oid, &the_index, get_index_file(), flags, tree_prefix); switch (ret) { |
