diff options
Diffstat (limited to 'builtin')
34 files changed, 499 insertions, 185 deletions
diff --git a/builtin/add.c b/builtin/add.c index a825887c50..ea762a41e3 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -38,19 +38,27 @@ struct update_callback_data { int add_errors; }; -static void chmod_pathspec(struct pathspec *pathspec, char flip) +static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only) { - int i; + int i, ret = 0; for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; + int err; if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL)) continue; - if (chmod_cache_entry(ce, flip) < 0) - fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name); + if (!show_only) + err = chmod_cache_entry(ce, flip); + else + err = S_ISREG(ce->ce_mode) ? 0 : -1; + + if (err < 0) + ret = error(_("cannot chmod %cx '%s'"), flip, ce->name); } + + return ret; } static int fix_unmerged_status(struct diff_filepair *p, @@ -609,7 +617,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) exit_status |= add_files(&dir, flags); if (chmod_arg && pathspec.nr) - chmod_pathspec(&pathspec, chmod_arg[0]); + exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only); unplug_bulk_checkin(); finish: diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 709eb713a3..1fdb7d9d10 100644 --- a/builtin/bisect--helper.c +++ b/builtin/bisect--helper.c @@ -21,16 +21,15 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT") static const char * const git_bisect_helper_usage[] = { N_("git bisect--helper --bisect-reset [<commit>]"), - N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"), - N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"), N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"), N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"), N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]" " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"), N_("git bisect--helper --bisect-next"), - N_("git bisect--helper --bisect-auto-next"), N_("git bisect--helper --bisect-state (bad|new) [<rev>]"), N_("git bisect--helper --bisect-state (good|old) [<rev>...]"), + N_("git bisect--helper --bisect-replay <filename>"), + N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"), NULL }; @@ -875,12 +874,19 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, const char **a */ for (; argc; argc--, argv++) { + struct commit *commit; + if (get_oid(*argv, &oid)){ error(_("Bad rev input: %s"), *argv); oid_array_clear(&revs); return BISECT_FAILED; } - oid_array_append(&revs, &oid); + + commit = lookup_commit_reference(the_repository, &oid); + if (!commit) + die(_("Bad rev input (not a commit): %s"), *argv); + + oid_array_append(&revs, &commit->object.oid); } if (strbuf_read_file(&buf, git_path_bisect_expected_rev(), 0) < the_hash_algo->hexsz || @@ -904,28 +910,148 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, const char **a return bisect_auto_next(terms, NULL); } +static enum bisect_error bisect_log(void) +{ + int fd, status; + const char* filename = git_path_bisect_log(); + + if (is_empty_or_missing_file(filename)) + return error(_("We are not bisecting.")); + + fd = open(filename, O_RDONLY); + if (fd < 0) + return BISECT_FAILED; + + status = copy_fd(fd, STDOUT_FILENO); + close(fd); + return status ? BISECT_FAILED : BISECT_OK; +} + +static int process_replay_line(struct bisect_terms *terms, struct strbuf *line) +{ + const char *p = line->buf + strspn(line->buf, " \t"); + char *word_end, *rev; + + if ((!skip_prefix(p, "git bisect", &p) && + !skip_prefix(p, "git-bisect", &p)) || !isspace(*p)) + return 0; + p += strspn(p, " \t"); + + word_end = (char *)p + strcspn(p, " \t"); + rev = word_end + strspn(word_end, " \t"); + *word_end = '\0'; /* NUL-terminate the word */ + + get_terms(terms); + if (check_and_set_terms(terms, p)) + return -1; + + if (!strcmp(p, "start")) { + struct strvec argv = STRVEC_INIT; + int res; + sq_dequote_to_strvec(rev, &argv); + res = bisect_start(terms, argv.v, argv.nr); + strvec_clear(&argv); + return res; + } + + if (one_of(p, terms->term_good, + terms->term_bad, "skip", NULL)) + return bisect_write(p, rev, terms, 0); + + if (!strcmp(p, "terms")) { + struct strvec argv = STRVEC_INIT; + int res; + sq_dequote_to_strvec(rev, &argv); + res = bisect_terms(terms, argv.nr == 1 ? argv.v[0] : NULL); + strvec_clear(&argv); + return res; + } + error(_("'%s'?? what are you talking about?"), p); + + return -1; +} + +static enum bisect_error bisect_replay(struct bisect_terms *terms, const char *filename) +{ + FILE *fp = NULL; + enum bisect_error res = BISECT_OK; + struct strbuf line = STRBUF_INIT; + + if (is_empty_or_missing_file(filename)) + return error(_("cannot read file '%s' for replaying"), filename); + + if (bisect_reset(NULL)) + return BISECT_FAILED; + + fp = fopen(filename, "r"); + if (!fp) + return BISECT_FAILED; + + while ((strbuf_getline(&line, fp) != EOF) && !res) + res = process_replay_line(terms, &line); + + strbuf_release(&line); + fclose(fp); + + if (res) + return BISECT_FAILED; + + return bisect_auto_next(terms, NULL); +} + +static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **argv, int argc) +{ + int i; + enum bisect_error res; + struct strvec argv_state = STRVEC_INIT; + + strvec_push(&argv_state, "skip"); + + for (i = 0; i < argc; i++) { + const char *dotdot = strstr(argv[i], ".."); + + if (dotdot) { + struct rev_info revs; + struct commit *commit; + + init_revisions(&revs, NULL); + setup_revisions(2, argv + i - 1, &revs, NULL); + + if (prepare_revision_walk(&revs)) + die(_("revision walk setup failed\n")); + while ((commit = get_revision(&revs)) != NULL) + strvec_push(&argv_state, + oid_to_hex(&commit->object.oid)); + + reset_revision_walk(); + } else { + strvec_push(&argv_state, argv[i]); + } + } + res = bisect_state(terms, argv_state.v, argv_state.nr); + + strvec_clear(&argv_state); + return res; +} + int cmd_bisect__helper(int argc, const char **argv, const char *prefix) { enum { BISECT_RESET = 1, - BISECT_WRITE, - CHECK_AND_SET_TERMS, BISECT_NEXT_CHECK, BISECT_TERMS, BISECT_START, BISECT_AUTOSTART, BISECT_NEXT, - BISECT_AUTO_NEXT, - BISECT_STATE + BISECT_STATE, + BISECT_LOG, + BISECT_REPLAY, + BISECT_SKIP } cmdmode = 0; int res = 0, nolog = 0; struct option options[] = { OPT_CMDMODE(0, "bisect-reset", &cmdmode, N_("reset the bisection state"), BISECT_RESET), - OPT_CMDMODE(0, "bisect-write", &cmdmode, - N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE), - OPT_CMDMODE(0, "check-and-set-terms", &cmdmode, - N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS), OPT_CMDMODE(0, "bisect-next-check", &cmdmode, N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK), OPT_CMDMODE(0, "bisect-terms", &cmdmode, @@ -934,10 +1060,14 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("start the bisect session"), BISECT_START), OPT_CMDMODE(0, "bisect-next", &cmdmode, N_("find the next bisection commit"), BISECT_NEXT), - OPT_CMDMODE(0, "bisect-auto-next", &cmdmode, - N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT), OPT_CMDMODE(0, "bisect-state", &cmdmode, N_("mark the state of ref (or refs)"), BISECT_STATE), + OPT_CMDMODE(0, "bisect-log", &cmdmode, + N_("list the bisection steps so far"), BISECT_LOG), + OPT_CMDMODE(0, "bisect-replay", &cmdmode, + N_("replay the bisection process from the given file"), BISECT_REPLAY), + OPT_CMDMODE(0, "bisect-skip", &cmdmode, + N_("skip some commits for checkout"), BISECT_SKIP), OPT_BOOL(0, "no-log", &nolog, N_("no log for BISECT_WRITE")), OPT_END() @@ -955,18 +1085,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) case BISECT_RESET: if (argc > 1) return error(_("--bisect-reset requires either no argument or a commit")); - return !!bisect_reset(argc ? argv[0] : NULL); - case BISECT_WRITE: - if (argc != 4 && argc != 5) - return error(_("--bisect-write requires either 4 or 5 arguments")); - set_terms(&terms, argv[3], argv[2]); - res = bisect_write(argv[0], argv[1], &terms, nolog); - break; - case CHECK_AND_SET_TERMS: - if (argc != 3) - return error(_("--check-and-set-terms requires 3 arguments")); - set_terms(&terms, argv[2], argv[1]); - res = check_and_set_terms(&terms, argv[0]); + res = bisect_reset(argc ? argv[0] : NULL); break; case BISECT_NEXT_CHECK: if (argc != 2 && argc != 3) @@ -989,17 +1108,26 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) get_terms(&terms); res = bisect_next(&terms, prefix); break; - case BISECT_AUTO_NEXT: - if (argc) - return error(_("--bisect-auto-next requires 0 arguments")); - get_terms(&terms); - res = bisect_auto_next(&terms, prefix); - break; case BISECT_STATE: set_terms(&terms, "bad", "good"); get_terms(&terms); res = bisect_state(&terms, argv, argc); break; + case BISECT_LOG: + if (argc) + return error(_("--bisect-log requires 0 arguments")); + res = bisect_log(); + break; + case BISECT_REPLAY: + if (argc != 1) + return error(_("no logfile given")); + set_terms(&terms, "bad", "good"); + res = bisect_replay(&terms, argv[0]); + break; + case BISECT_SKIP: + set_terms(&terms, "bad", "good"); + res = bisect_skip(&terms, argv, argc); + break; default: BUG("unknown subcommand %d", cmdmode); } diff --git a/builtin/blame.c b/builtin/blame.c index b66e938022..641523ff9a 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -425,13 +425,11 @@ static void setup_default_color_by_age(void) parse_color_fields("blue,12 month ago,white,1 month ago,red"); } -static void determine_line_heat(struct blame_entry *ent, const char **dest_color) +static void determine_line_heat(struct commit_info *ci, const char **dest_color) { int i = 0; - struct commit_info ci; - get_commit_info(ent->suspect->commit, &ci, 1); - while (i < colorfield_nr && ci.author_time > colorfield[i].hop) + while (i < colorfield_nr && ci->author_time > colorfield[i].hop) i++; *dest_color = colorfield[i].col; @@ -453,7 +451,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int cp = blame_nth_line(sb, ent->lno); if (opt & OUTPUT_SHOW_AGE_WITH_COLOR) { - determine_line_heat(ent, &default_color); + determine_line_heat(&ci, &default_color); color = default_color; reset = GIT_COLOR_RESET; } diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 4bbfc92dce..023e49e271 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -23,22 +23,35 @@ static struct checkout state = CHECKOUT_INIT; static void write_tempfile_record(const char *name, const char *prefix) { int i; + int have_tempname = 0; if (CHECKOUT_ALL == checkout_stage) { - for (i = 1; i < 4; i++) { - if (i > 1) - putchar(' '); - if (topath[i][0]) - fputs(topath[i], stdout); - else - putchar('.'); + for (i = 1; i < 4; i++) + if (topath[i][0]) { + have_tempname = 1; + break; + } + + if (have_tempname) { + for (i = 1; i < 4; i++) { + if (i > 1) + putchar(' '); + if (topath[i][0]) + fputs(topath[i], stdout); + else + putchar('.'); + } } - } else + } else if (topath[checkout_stage][0]) { + have_tempname = 1; fputs(topath[checkout_stage], stdout); + } - putchar('\t'); - write_name_quoted_relative(name, prefix, stdout, - nul_term_line ? '\0' : '\n'); + if (have_tempname) { + putchar('\t'); + write_name_quoted_relative(name, prefix, stdout, + nul_term_line ? '\0' : '\n'); + } for (i = 0; i < 4; i++) { topath[i][0] = 0; diff --git a/builtin/clean.c b/builtin/clean.c index 687ab473c2..995053b791 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -623,7 +623,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) nr += chosen[i]; } - result = xcalloc(st_add(nr, 1), sizeof(int)); + CALLOC_ARRAY(result, st_add(nr, 1)); for (i = 0; i < stuff->nr && j < nr; i++) { if (chosen[i]) result[j++] = i; diff --git a/builtin/clone.c b/builtin/clone.c index e335734b4c..51e844a2de 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -979,7 +979,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) int err = 0, complete_refs_before_fetch = 1; int submodule_progress; - struct strvec ref_prefixes = STRVEC_INIT; + struct transport_ls_refs_options transport_ls_refs_options = + TRANSPORT_LS_REFS_OPTIONS_INIT; packet_trace_identity("clone"); @@ -1257,14 +1258,17 @@ int cmd_clone(int argc, const char **argv, const char *prefix) transport->smart_options->check_self_contained_and_connected = 1; - strvec_push(&ref_prefixes, "HEAD"); - refspec_ref_prefixes(&remote->fetch, &ref_prefixes); + strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); + refspec_ref_prefixes(&remote->fetch, + &transport_ls_refs_options.ref_prefixes); if (option_branch) - expand_ref_prefix(&ref_prefixes, option_branch); + expand_ref_prefix(&transport_ls_refs_options.ref_prefixes, + option_branch); if (!option_no_tags) - strvec_push(&ref_prefixes, "refs/tags/"); + strvec_push(&transport_ls_refs_options.ref_prefixes, + "refs/tags/"); - refs = transport_get_remote_refs(transport, &ref_prefixes); + refs = transport_get_remote_refs(transport, &transport_ls_refs_options); if (refs) { int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport)); @@ -1326,8 +1330,19 @@ int cmd_clone(int argc, const char **argv, const char *prefix) remote_head = NULL; option_no_checkout = 1; if (!option_bare) { - const char *branch = git_default_branch_name(0); - char *ref = xstrfmt("refs/heads/%s", branch); + const char *branch; + char *ref; + + if (transport_ls_refs_options.unborn_head_target && + skip_prefix(transport_ls_refs_options.unborn_head_target, + "refs/heads/", &branch)) { + ref = transport_ls_refs_options.unborn_head_target; + transport_ls_refs_options.unborn_head_target = NULL; + create_symref("HEAD", ref, reflog_msg.buf); + } else { + branch = git_default_branch_name(0); + ref = xstrfmt("refs/heads/%s", branch); + } install_branch_config(0, branch, remote_name, ref); free(ref); @@ -1380,6 +1395,7 @@ cleanup: strbuf_release(&key); junk_mode = JUNK_LEAVE_ALL; - strvec_clear(&ref_prefixes); + strvec_clear(&transport_ls_refs_options.ref_prefixes); + free(transport_ls_refs_options.unborn_head_target); return err; } diff --git a/builtin/diff-files.c b/builtin/diff-files.c index bb85266102..70103c4095 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -54,6 +54,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) } if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_RAW; + rev.diffopt.rotate_to_strict = 1; /* * Make sure there are NO revision (i.e. pending object) parameter, diff --git a/builtin/diff-index.c b/builtin/diff-index.c index c33d7af478..176fe7ff2b 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -41,6 +41,8 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_RAW; + rev.diffopt.rotate_to_strict = 1; + /* * Make sure there is one revision (i.e. pending object), * and there is no revision filtering parameters. diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 178d12f07f..f33d30d57b 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -156,6 +156,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) if (merge_base && opt->pending.nr != 2) die(_("--merge-base only works with two commits")); + opt->diffopt.rotate_to_strict = 1; + /* * NOTE! We expect "a..b" to expand to "^a b" but it is * perfectly valid for revision range parser to yield "b ^a", @@ -192,6 +194,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int saved_nrl = 0; int saved_dcctc = 0; + opt->diffopt.rotate_to_strict = 0; if (opt->diffopt.detect_rename) { if (!the_index.cache) repo_read_index(the_repository); diff --git a/builtin/diff.c b/builtin/diff.c index 0f4859abf7..617b9a4101 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -491,6 +491,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } rev.diffopt.flags.recursive = 1; + rev.diffopt.rotate_to_strict = 1; setup_diff_pager(&rev.diffopt); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index dd4d09cece..3afa81cf9a 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -3322,7 +3322,7 @@ static void option_rewrite_submodules(const char *arg, struct string_list *list) die(_("Expected format name:filename for submodule rewrite option")); *f = '\0'; f++; - ms = xcalloc(1, sizeof(*ms)); + CALLOC_ARRAY(ms, 1); fp = fopen(f, "r"); if (!fp) @@ -3519,9 +3519,9 @@ int cmd_fast_import(int argc, const char **argv, const char *prefix) alloc_objects(object_entry_alloc); strbuf_init(&command_buf, 0); - atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*)); - branch_table = xcalloc(branch_table_sz, sizeof(struct branch*)); - avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); + CALLOC_ARRAY(atom_table, atom_table_sz); + CALLOC_ARRAY(branch_table, branch_table_sz); + CALLOC_ARRAY(avail_tree_table, avail_tree_table_sz); marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set)); hashmap_init(&object_table, object_entry_hashcmp, NULL, 0); diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 58b7c1fbdc..c2d96f4c89 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -220,7 +220,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) version = discover_version(&reader); switch (version) { case protocol_v2: - get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL, args.stateless_rpc); + get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL, + args.stateless_rpc); break; case protocol_v1: case protocol_v0: diff --git a/builtin/fetch.c b/builtin/fetch.c index 91f3d20696..0b90de87c7 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1455,7 +1455,8 @@ static int do_fetch(struct transport *transport, int autotags = (transport->remote->fetch_tags == 1); int retcode = 0; const struct ref *remote_refs; - struct strvec ref_prefixes = STRVEC_INIT; + struct transport_ls_refs_options transport_ls_refs_options = + TRANSPORT_LS_REFS_OPTIONS_INIT; int must_list_refs = 1; if (tags == TAGS_DEFAULT) { @@ -1475,7 +1476,7 @@ static int do_fetch(struct transport *transport, if (rs->nr) { int i; - refspec_ref_prefixes(rs, &ref_prefixes); + refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes); /* * We can avoid listing refs if all of them are exact @@ -1489,22 +1490,25 @@ static int do_fetch(struct transport *transport, } } } else if (transport->remote && transport->remote->fetch.nr) - refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes); + refspec_ref_prefixes(&transport->remote->fetch, + &transport_ls_refs_options.ref_prefixes); if (tags == TAGS_SET || tags == TAGS_DEFAULT) { must_list_refs = 1; - if (ref_prefixes.nr) - strvec_push(&ref_prefixes, "refs/tags/"); + if (transport_ls_refs_options.ref_prefixes.nr) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "refs/tags/"); } if (must_list_refs) { trace2_region_enter("fetch", "remote_refs", the_repository); - remote_refs = transport_get_remote_refs(transport, &ref_prefixes); + remote_refs = transport_get_remote_refs(transport, + &transport_ls_refs_options); trace2_region_leave("fetch", "remote_refs", the_repository); } else remote_refs = NULL; - strvec_clear(&ref_prefixes); + strvec_clear(&transport_ls_refs_options.ref_prefixes); ref_map = get_ref_map(transport->remote, remote_refs, rs, tags, &autotags); diff --git a/builtin/gc.c b/builtin/gc.c index 4c40594d66..ef7226d7bc 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -54,7 +54,6 @@ static const char *prune_worktrees_expire = "3.months.ago"; static unsigned long big_pack_threshold; static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE; -static struct strvec pack_refs_cmd = STRVEC_INIT; static struct strvec reflog = STRVEC_INIT; static struct strvec repack = STRVEC_INIT; static struct strvec prune = STRVEC_INIT; @@ -163,6 +162,15 @@ static void gc_config(void) git_config(git_default_config, NULL); } +struct maintenance_run_opts; +static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts) +{ + struct strvec pack_refs_cmd = STRVEC_INIT; + strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL); + + return run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD); +} + static int too_many_loose_objects(void) { /* @@ -518,8 +526,8 @@ static void gc_before_repack(void) if (done++) return; - if (pack_refs && run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD)) - die(FAILED_RUN, pack_refs_cmd.v[0]); + if (pack_refs && maintenance_task_pack_refs(NULL)) + die(FAILED_RUN, "pack-refs"); if (prune_reflogs && run_command_v_opt(reflog.v, RUN_GIT_CMD)) die(FAILED_RUN, reflog.v[0]); @@ -556,7 +564,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage_with_options(builtin_gc_usage, builtin_gc_options); - strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL); strvec_pushl(&reflog, "reflog", "expire", "--all", NULL); strvec_pushl(&repack, "repack", "-d", "-l", NULL); strvec_pushl(&prune, "prune", "--expire", NULL); @@ -1224,6 +1231,7 @@ enum maintenance_task_label { TASK_INCREMENTAL_REPACK, TASK_GC, TASK_COMMIT_GRAPH, + TASK_PACK_REFS, /* Leave as final value */ TASK__COUNT @@ -1255,6 +1263,11 @@ static struct maintenance_task tasks[] = { maintenance_task_commit_graph, should_write_commit_graph, }, + [TASK_PACK_REFS] = { + "pack-refs", + maintenance_task_pack_refs, + NULL, + }, }; static int compare_tasks_by_selection(const void *a_, const void *b_) @@ -1339,6 +1352,8 @@ static void initialize_maintenance_strategy(void) tasks[TASK_INCREMENTAL_REPACK].schedule = SCHEDULE_DAILY; tasks[TASK_LOOSE_OBJECTS].enabled = 1; tasks[TASK_LOOSE_OBJECTS].schedule = SCHEDULE_DAILY; + tasks[TASK_PACK_REFS].enabled = 1; + tasks[TASK_PACK_REFS].schedule = SCHEDULE_WEEKLY; } } @@ -1446,11 +1461,23 @@ static int maintenance_run(int argc, const char **argv, const char *prefix) return maintenance_run_tasks(&opts); } +static char *get_maintpath(void) +{ + struct strbuf sb = STRBUF_INIT; + const char *p = the_repository->worktree ? + the_repository->worktree : the_repository->gitdir; + + strbuf_realpath(&sb, p, 1); + return strbuf_detach(&sb, NULL); +} + static int maintenance_register(void) { + int rc; char *config_value; struct child_process config_set = CHILD_PROCESS_INIT; struct child_process config_get = CHILD_PROCESS_INIT; + char *maintpath = get_maintpath(); /* Disable foreground maintenance */ git_config_set("maintenance.auto", "false"); @@ -1463,40 +1490,44 @@ static int maintenance_register(void) config_get.git_cmd = 1; strvec_pushl(&config_get.args, "config", "--global", "--get", - "--fixed-value", "maintenance.repo", - the_repository->worktree ? the_repository->worktree - : the_repository->gitdir, - NULL); + "--fixed-value", "maintenance.repo", maintpath, NULL); config_get.out = -1; - if (start_command(&config_get)) - return error(_("failed to run 'git config'")); + if (start_command(&config_get)) { + rc = error(_("failed to run 'git config'")); + goto done; + } /* We already have this value in our config! */ - if (!finish_command(&config_get)) - return 0; + if (!finish_command(&config_get)) { + rc = 0; + goto done; + } config_set.git_cmd = 1; strvec_pushl(&config_set.args, "config", "--add", "--global", "maintenance.repo", - the_repository->worktree ? the_repository->worktree - : the_repository->gitdir, - NULL); + maintpath, NULL); - return run_command(&config_set); + rc = run_command(&config_set); + +done: + free(maintpath); + return rc; } static int maintenance_unregister(void) { + int rc; struct child_process config_unset = CHILD_PROCESS_INIT; + char *maintpath = get_maintpath(); config_unset.git_cmd = 1; strvec_pushl(&config_unset.args, "config", "--global", "--unset", - "--fixed-value", "maintenance.repo", - the_repository->worktree ? the_repository->worktree - : the_repository->gitdir, - NULL); + "--fixed-value", "maintenance.repo", maintpath, NULL); - return run_command(&config_unset); + rc = run_command(&config_unset); + free(maintpath); + return rc; } static const char *get_frequency(enum schedule_priority schedule) diff --git a/builtin/grep.c b/builtin/grep.c index c69fe99340..5de725f904 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -211,7 +211,7 @@ static void start_threads(struct grep_opt *opt) strbuf_init(&todo[i].out, 0); } - threads = xcalloc(num_threads, sizeof(*threads)); + CALLOC_ARRAY(threads, num_threads); for (i = 0; i < num_threads; i++) { int err; struct grep_opt *o = grep_opt_dup(opt); @@ -506,6 +506,10 @@ static int grep_cache(struct grep_opt *opt, for (nr = 0; nr < repo->index->cache_nr; nr++) { const struct cache_entry *ce = repo->index->cache[nr]; + + if (!cached && ce_skip_worktree(ce)) + continue; + strbuf_setlen(&name, name_base_len); strbuf_addstr(&name, ce->name); @@ -518,8 +522,7 @@ static int grep_cache(struct grep_opt *opt, * cache entry are identical, even if worktree file has * been modified, so use cache version instead */ - if (cached || (ce->ce_flags & CE_VALID) || - ce_skip_worktree(ce)) { + if (cached || (ce->ce_flags & CE_VALID)) { if (ce_stage(ce) || ce_intent_to_add(ce)) continue; hit |= grep_oid(opt, &ce->oid, name.buf, @@ -1152,6 +1155,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (!use_index && (untracked || cached)) die(_("--cached or --untracked cannot be used with --no-index")); + if (untracked && cached) + die(_("--untracked cannot be used with --cached")); + if (!use_index || untracked) { int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude; hit = grep_directory(&opt, &pathspec, use_exclude, use_index); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 54f74c4874..21899687e2 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -185,7 +185,7 @@ static void init_thread(void) if (show_stat) pthread_mutex_init(&deepest_delta_mutex, NULL); pthread_key_create(&key, NULL); - thread_data = xcalloc(nr_threads, sizeof(*thread_data)); + CALLOC_ARRAY(thread_data, nr_threads); for (i = 0; i < nr_threads; i++) { thread_data[i].pack_fd = open(curr_pack, O_RDONLY); if (thread_data[i].pack_fd == -1) @@ -1674,7 +1674,7 @@ static void show_pack_info(int stat_only) unsigned long *chain_histogram = NULL; if (deepest_delta) - chain_histogram = xcalloc(deepest_delta, sizeof(unsigned long)); + CALLOC_ARRAY(chain_histogram, deepest_delta); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; @@ -1712,6 +1712,22 @@ static void show_pack_info(int stat_only) } } +static int print_dangling_gitmodules(struct fsck_options *o, + const struct object_id *oid, + enum object_type object_type, + int msg_type, const char *message) +{ + /* + * NEEDSWORK: Plumb the MSG_ID (from fsck.c) here and use it + * instead of relying on this string check. + */ + if (starts_with(message, "gitmodulesMissing")) { + printf("%s\n", oid_to_hex(oid)); + return 0; + } + return fsck_error_function(o, oid, object_type, msg_type, message); +} + int cmd_index_pack(int argc, const char **argv, const char *prefix) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; @@ -1896,10 +1912,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) curr_pack = open_pack_file(pack_name); parse_pack_header(); - objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry)); + CALLOC_ARRAY(objects, st_add(nr_objects, 1)); if (show_stat) - obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat)); - ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry)); + CALLOC_ARRAY(obj_stat, st_add(nr_objects, 1)); + CALLOC_ARRAY(ofs_deltas, nr_objects); parse_pack_objects(pack_hash); if (report_end_of_input) write_in_full(2, "\0", 1); @@ -1932,8 +1948,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) else close(input_fd); - if (do_fsck_object && fsck_finish(&fsck_options)) - die(_("fsck error in pack objects")); + if (do_fsck_object) { + struct fsck_options fo = fsck_options; + + fo.error_func = print_dangling_gitmodules; + if (fsck_finish(&fo)) + die(_("fsck error in pack objects")); + } free(objects); strbuf_release(&index_name_buf); diff --git a/builtin/log.c b/builtin/log.c index d0cbaaf68a..f67b67d80e 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -307,10 +307,11 @@ static struct itimerval early_output_timer; static void log_show_early(struct rev_info *revs, struct commit_list *list) { - int i = revs->early_output, close_file = revs->diffopt.close_file; + int i = revs->early_output; int show_header = 1; + int no_free = revs->diffopt.no_free; - revs->diffopt.close_file = 0; + revs->diffopt.no_free = 0; sort_in_topological_order(&list, revs->sort_order); while (list && i) { struct commit *commit = list->item; @@ -327,8 +328,8 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list) case commit_ignore: break; case commit_error: - if (close_file) - fclose(revs->diffopt.file); + revs->diffopt.no_free = no_free; + diff_free(&revs->diffopt); return; } list = list->next; @@ -336,8 +337,8 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list) /* Did we already get enough commits for the early output? */ if (!i) { - if (close_file) - fclose(revs->diffopt.file); + revs->diffopt.no_free = 0; + diff_free(&revs->diffopt); return; } @@ -401,7 +402,7 @@ static int cmd_log_walk(struct rev_info *rev) { struct commit *commit; int saved_nrl = 0; - int saved_dcctc = 0, close_file = rev->diffopt.close_file; + int saved_dcctc = 0; if (rev->early_output) setup_early_output(); @@ -417,7 +418,7 @@ static int cmd_log_walk(struct rev_info *rev) * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to * retain that state information if replacing rev->diffopt in this loop */ - rev->diffopt.close_file = 0; + rev->diffopt.no_free = 1; while ((commit = get_revision(rev)) != NULL) { if (!log_tree_commit(rev, commit) && rev->max_count >= 0) /* @@ -442,8 +443,8 @@ static int cmd_log_walk(struct rev_info *rev) } rev->diffopt.degraded_cc_to_c = saved_dcctc; rev->diffopt.needed_rename_limit = saved_nrl; - if (close_file) - fclose(rev->diffopt.file); + rev->diffopt.no_free = 0; + diff_free(&rev->diffopt); if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF && rev->diffopt.flags.check_failed) { @@ -1223,14 +1224,20 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, */ struct diff_options opts; struct strvec other_arg = STRVEC_INIT; + struct range_diff_options range_diff_opts = { + .creation_factor = rev->creation_factor, + .dual_color = 1, + .diffopt = &opts, + .other_arg = &other_arg + }; + diff_setup(&opts); opts.file = rev->diffopt.file; opts.use_color = rev->diffopt.use_color; diff_setup_done(&opts); fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title); get_notes_args(&other_arg, rev); - show_range_diff(rev->rdiff1, rev->rdiff2, - rev->creation_factor, 1, &opts, &other_arg); + show_range_diff(rev->rdiff1, rev->rdiff2, &range_diff_opts); strvec_clear(&other_arg); } } @@ -1672,7 +1679,7 @@ static void infer_range_diff_ranges(struct strbuf *r1, struct commit *head) { const char *head_oid = oid_to_hex(&head->object.oid); - int prev_is_range = !!strstr(prev, ".."); + int prev_is_range = is_range_diff_range(prev); if (prev_is_range) strbuf_addstr(r1, prev); @@ -1955,7 +1962,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) * file, but but we must instruct it not to close after each * diff. */ - rev.diffopt.close_file = 0; + rev.diffopt.no_free = 1; } else { int saved; diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 092917eca2..abfa984737 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -45,7 +45,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) int show_symref_target = 0; const char *uploadpack = NULL; const char **pattern = NULL; - struct strvec ref_prefixes = STRVEC_INIT; + struct transport_ls_refs_options transport_options = + TRANSPORT_LS_REFS_OPTIONS_INIT; int i; struct string_list server_options = STRING_LIST_INIT_DUP; @@ -87,16 +88,16 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) if (argc > 1) { int i; - pattern = xcalloc(argc, sizeof(const char *)); + CALLOC_ARRAY(pattern, argc); for (i = 1; i < argc; i++) { pattern[i - 1] = xstrfmt("*/%s", argv[i]); } } if (flags & REF_TAGS) - strvec_push(&ref_prefixes, "refs/tags/"); + strvec_push(&transport_options.ref_prefixes, "refs/tags/"); if (flags & REF_HEADS) - strvec_push(&ref_prefixes, "refs/heads/"); + strvec_push(&transport_options.ref_prefixes, "refs/heads/"); remote = remote_get(dest); if (!remote) { @@ -118,7 +119,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) if (server_options.nr) transport->server_options = &server_options; - ref = transport_get_remote_refs(transport, &ref_prefixes); + ref = transport_get_remote_refs(transport, &transport_options); if (ref) { int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport)); repo_set_hash_algo(the_repository, hash_algo); diff --git a/builtin/merge.c b/builtin/merge.c index eb00b273e6..388619536a 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -210,7 +210,7 @@ static struct strategy *get_strategy(const char *name) exit(1); } - ret = xcalloc(1, sizeof(struct strategy)); + CALLOC_ARRAY(ret, 1); ret->name = xstrdup(name); ret->attr = NO_TRIVIAL; return ret; diff --git a/builtin/mv.c b/builtin/mv.c index 7dac714af9..3fccdcb645 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -221,7 +221,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) } argc += last - first; } - } else if (!(ce = cache_file_exists(src, length, ignore_case))) { + } else if (!(ce = cache_file_exists(src, length, 0))) { bad = _("not under version control"); } else if (ce_stage(ce)) { bad = _("conflicted"); diff --git a/builtin/notes.c b/builtin/notes.c index 2987c08a2e..74bba39ca8 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -373,7 +373,7 @@ static int list(int argc, const char **argv, const char *prefix) git_notes_list_usage, 0); if (1 < argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_list_usage, options); } @@ -428,7 +428,7 @@ static int add(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_ARGV0); if (2 < argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_add_usage, options); } @@ -506,7 +506,7 @@ static int copy(int argc, const char **argv, const char *prefix) if (from_stdin || rewrite_cmd) { if (argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_copy_usage, options); } else { return notes_copy_from_stdin(force, rewrite_cmd); @@ -514,11 +514,11 @@ static int copy(int argc, const char **argv, const char *prefix) } if (argc < 1) { - error(_("too few parameters")); + error(_("too few arguments")); usage_with_options(git_notes_copy_usage, options); } if (2 < argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_copy_usage, options); } @@ -595,7 +595,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_ARGV0); if (2 < argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(usage, options); } @@ -662,7 +662,7 @@ static int show(int argc, const char **argv, const char *prefix) 0); if (1 < argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_show_usage, options); } @@ -730,7 +730,7 @@ static int merge_commit(struct notes_merge_options *o) else oidclr(&parent_oid); - t = xcalloc(1, sizeof(struct notes_tree)); + CALLOC_ARRAY(t, 1); init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); o->local_ref = local_ref_to_free = @@ -812,7 +812,7 @@ static int merge(int argc, const char **argv, const char *prefix) error(_("must specify a notes ref to merge")); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_merge_usage, options); } @@ -960,7 +960,7 @@ static int prune(int argc, const char **argv, const char *prefix) 0); if (argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_prune_usage, options); } @@ -982,7 +982,7 @@ static int get_ref(int argc, const char **argv, const char *prefix) git_notes_get_ref_usage, 0); if (argc) { - error(_("too many parameters")); + error(_("too many arguments")); usage_with_options(git_notes_get_ref_usage, options); } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d62aaf59a..4bb602688c 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1635,7 +1635,7 @@ static void add_preferred_base(struct object_id *oid) } } - it = xcalloc(1, sizeof(*it)); + CALLOC_ARRAY(it, 1); it->next = pbase_tree; pbase_tree = it; @@ -2096,7 +2096,7 @@ static void get_object_details(void) progress_state = start_progress(_("Counting objects"), to_pack.nr_objects); - sorted_by_offset = xcalloc(to_pack.nr_objects, sizeof(struct object_entry *)); + CALLOC_ARRAY(sorted_by_offset, to_pack.nr_objects); for (i = 0; i < to_pack.nr_objects; i++) sorted_by_offset[i] = to_pack.objects + i; QSORT(sorted_by_offset, to_pack.nr_objects, pack_offset_sort); @@ -2428,7 +2428,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size, struct unpacked *array; unsigned long mem_usage = 0; - array = xcalloc(window, sizeof(struct unpacked)); + CALLOC_ARRAY(array, window); for (;;) { struct object_entry *entry; @@ -2665,7 +2665,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size, if (progress > pack_to_stdout) fprintf_ln(stderr, _("Delta compression using up to %d threads"), delta_search_threads); - p = xcalloc(delta_search_threads, sizeof(*p)); + CALLOC_ARRAY(p, delta_search_threads); /* Partition the work amongst work threads. */ for (i = 0; i < delta_search_threads; i++) { diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 6e115a811a..7102996c75 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -373,7 +373,7 @@ static void sort_pack_list(struct pack_list **pl) return; /* prepare an array of packed_list for easier sorting */ - ary = xcalloc(n, sizeof(struct pack_list *)); + CALLOC_ARRAY(ary, n); for (n = 0, p = *pl; p; p = p->next) ary[n++] = p; diff --git a/builtin/push.c b/builtin/push.c index 03adb58602..194967ed79 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -115,7 +115,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo) else refspec_appendf(&rs, "refs/tags/%s", ref); } else if (deleterefs) { - if (strchr(ref, ':')) + if (strchr(ref, ':') || !*ref) die(_("--delete only accepts plain target ref names")); refspec_appendf(&rs, ":%s", ref); } else if (!strchr(ref, ':')) { diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 24c4162f74..78bc9fa770 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -3,6 +3,7 @@ #include "parse-options.h" #include "range-diff.h" #include "config.h" +#include "revision.h" static const char * const builtin_range_diff_usage[] = { N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"), @@ -13,18 +14,27 @@ NULL int cmd_range_diff(int argc, const char **argv, const char *prefix) { - int creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; struct diff_options diffopt = { NULL }; struct strvec other_arg = STRVEC_INIT; - int simple_color = -1; + struct range_diff_options range_diff_opts = { + .creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT, + .diffopt = &diffopt, + .other_arg = &other_arg + }; + int simple_color = -1, left_only = 0, right_only = 0; struct option range_diff_options[] = { - OPT_INTEGER(0, "creation-factor", &creation_factor, + OPT_INTEGER(0, "creation-factor", + &range_diff_opts.creation_factor, N_("Percentage by which creation is weighted")), OPT_BOOL(0, "no-dual-color", &simple_color, N_("use simple diff colors")), OPT_PASSTHRU_ARGV(0, "notes", &other_arg, N_("notes"), N_("passed to 'git log'"), PARSE_OPT_OPTARG), + OPT_BOOL(0, "left-only", &left_only, + N_("only emit output related to the first range")), + OPT_BOOL(0, "right-only", &right_only, + N_("only emit output related to the second range")), OPT_END() }; struct option *options; @@ -46,12 +56,12 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) diffopt.use_color = 1; if (argc == 2) { - if (!strstr(argv[0], "..")) - die(_("no .. in range: '%s'"), argv[0]); + if (!is_range_diff_range(argv[0])) + die(_("not a commit range: '%s'"), argv[0]); strbuf_addstr(&range1, argv[0]); - if (!strstr(argv[1], "..")) - die(_("no .. in range: '%s'"), argv[1]); + if (!is_range_diff_range(argv[1])) + die(_("not a commit range: '%s'"), argv[1]); strbuf_addstr(&range2, argv[1]); } else if (argc == 3) { strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); @@ -81,8 +91,10 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) } FREE_AND_NULL(options); - res = show_range_diff(range1.buf, range2.buf, creation_factor, - simple_color < 1, &diffopt, &other_arg); + range_diff_opts.dual_color = simple_color < 1; + range_diff_opts.left_only = left_only; + range_diff_opts.right_only = right_only; + res = show_range_diff(range1.buf, range2.buf, &range_diff_opts); strvec_clear(&other_arg); strbuf_release(&range1); diff --git a/builtin/rebase.c b/builtin/rebase.c index 840dbd7eb7..de400f9a19 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -102,6 +102,7 @@ struct rebase_options { int reschedule_failed_exec; int use_legacy_rebase; int reapply_cherry_picks; + int fork_point; }; #define REBASE_OPTIONS_INIT { \ @@ -111,7 +112,8 @@ struct rebase_options { .default_backend = "merge", \ .flags = REBASE_NO_QUIET, \ .git_am_opts = STRVEC_INIT, \ - .git_format_patch_opt = STRBUF_INIT \ + .git_format_patch_opt = STRBUF_INIT, \ + .fork_point = -1, \ } static struct replay_opts get_replay_opts(const struct rebase_options *opts) @@ -1095,6 +1097,11 @@ static int rebase_config(const char *var, const char *value, void *data) return 0; } + if (!strcmp(var, "rebase.forkpoint")) { + opts->fork_point = git_config_bool(var, value) ? -1 : 0; + return 0; + } + if (!strcmp(var, "rebase.usebuiltin")) { opts->use_legacy_rebase = !git_config_bool(var, value); return 0; @@ -1306,7 +1313,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) const char *gpg_sign = NULL; struct string_list exec = STRING_LIST_INIT_NODUP; const char *rebase_merges = NULL; - int fork_point = -1; struct string_list strategy_options = STRING_LIST_INIT_NODUP; struct object_id squash_onto; char *squash_onto_name = NULL; @@ -1406,7 +1412,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) N_("mode"), N_("try to rebase merges instead of skipping them"), PARSE_OPT_OPTARG, NULL, (intptr_t)""}, - OPT_BOOL(0, "fork-point", &fork_point, + OPT_BOOL(0, "fork-point", &options.fork_point, N_("use 'merge-base --fork-point' to refine upstream")), OPT_STRING('s', "strategy", &options.strategy, N_("strategy"), N_("use the given merge strategy")), @@ -1494,7 +1500,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) die(_("cannot combine '--keep-base' with '--root'")); } - if (options.root && fork_point > 0) + if (options.root && options.fork_point > 0) die(_("cannot combine '--root' with '--fork-point'")); if (action != ACTION_NONE && !in_progress) @@ -1840,8 +1846,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) NULL); if (!options.upstream_name) error_on_missing_default_upstream(); - if (fork_point < 0) - fork_point = 1; + if (options.fork_point < 0) + options.fork_point = 1; } else { options.upstream_name = argv[0]; argc--; @@ -1945,7 +1951,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) } else BUG("unexpected number of arguments left to parse"); - if (fork_point > 0) { + if (options.fork_point > 0) { struct commit *head = lookup_commit_reference(the_repository, &options.orig_head); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index d49d050e6e..6bc12c828a 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -358,7 +358,7 @@ static void proc_receive_ref_append(const char *prefix) char *p; int len; - ref_pattern = xcalloc(1, sizeof(struct proc_receive_ref)); + CALLOC_ARRAY(ref_pattern, 1); p = strchr(prefix, ':'); if (p) { while (prefix < p) { @@ -764,7 +764,7 @@ static void prepare_push_cert_sha1(struct child_process *proc) memset(&sigcheck, '\0', sizeof(sigcheck)); - bogs = parse_signature(push_cert.buf, push_cert.len); + bogs = parse_signed_buffer(push_cert.buf, push_cert.len); check_signature(push_cert.buf, bogs, push_cert.buf + bogs, push_cert.len - bogs, &sigcheck); @@ -1024,7 +1024,7 @@ static int read_proc_receive_report(struct packet_reader *reader, } if (new_report) { if (!hint->report) { - hint->report = xcalloc(1, sizeof(struct ref_push_report)); + CALLOC_ARRAY(hint->report, 1); report = hint->report; } else { report = hint->report; @@ -2050,7 +2050,7 @@ static void queue_commands_from_cert(struct command **tail, die("malformed push certificate %.*s", 100, push_cert->buf); else boc += 2; - eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len); + eoc = push_cert->buf + parse_signed_buffer(push_cert->buf, push_cert->len); while (boc < eoc) { const char *eol = memchr(boc, '\n', eoc - boc); @@ -2275,7 +2275,7 @@ static const char *unpack(int err_fd, struct shallow_info *si) status = start_command(&child); if (status) return "index-pack fork failed"; - pack_lockfile = index_pack_lockfile(child.out); + pack_lockfile = index_pack_lockfile(child.out, NULL); close(child.out); status = finish_command(&child); if (status) @@ -2313,11 +2313,9 @@ static void prepare_shallow_update(struct shallow_info *si) ALLOC_ARRAY(si->used_shallow, si->shallow->nr); assign_shallow_commits_to_refs(si, si->used_shallow, NULL); - si->need_reachability_test = - xcalloc(si->shallow->nr, sizeof(*si->need_reachability_test)); - si->reachable = - xcalloc(si->shallow->nr, sizeof(*si->reachable)); - si->shallow_ref = xcalloc(si->ref->nr, sizeof(*si->shallow_ref)); + CALLOC_ARRAY(si->need_reachability_test, si->shallow->nr); + CALLOC_ARRAY(si->reachable, si->shallow->nr); + CALLOC_ARRAY(si->shallow_ref, si->ref->nr); for (i = 0; i < si->nr_ours; i++) si->need_reachability_test[si->ours[i]] = 1; diff --git a/builtin/reflog.c b/builtin/reflog.c index ca1d8079f3..09541d1c80 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -602,6 +602,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) */ if (cb.cmd.stalefix) { repo_init_revisions(the_repository, &cb.cmd.revs, prefix); + cb.cmd.revs.do_not_die_on_missing_tree = 1; + cb.cmd.revs.ignore_missing = 1; + cb.cmd.revs.ignore_missing_links = 1; if (flags & EXPIRE_REFLOGS_VERBOSE) printf(_("Marking reachable objects...")); mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL); diff --git a/builtin/remote.c b/builtin/remote.c index d11a5589e4..717b662d45 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -221,7 +221,7 @@ static int add(int argc, const char **argv) if (fetch_tags != TAGS_DEFAULT) { strbuf_reset(&buf); - strbuf_addf(&buf, "remote.%s.tagopt", name); + strbuf_addf(&buf, "remote.%s.tagOpt", name); git_config_set(buf.buf, fetch_tags == TAGS_SET ? "--tags" : "--no-tags"); } @@ -746,7 +746,7 @@ static int mv(int argc, const char **argv) } if (info->push_remote_name && !strcmp(info->push_remote_name, rename.old_name)) { strbuf_reset(&buf); - strbuf_addf(&buf, "branch.%s.pushremote", item->string); + strbuf_addf(&buf, "branch.%s.pushRemote", item->string); git_config_set(buf.buf, rename.new_name); } } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 25c6c3b38d..b4d8ea0a35 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -80,6 +80,19 @@ static int arg_show_object_names = 1; #define DEFAULT_OIDSET_SIZE (16*1024) +static int show_disk_usage; +static off_t total_disk_usage; + +static off_t get_object_disk_usage(struct object *obj) +{ + off_t size; + struct object_info oi = OBJECT_INFO_INIT; + oi.disk_sizep = &size; + if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0) + die(_("unable to get disk usage of %s"), oid_to_hex(&obj->oid)); + return size; +} + static void finish_commit(struct commit *commit); static void show_commit(struct commit *commit, void *data) { @@ -88,6 +101,9 @@ static void show_commit(struct commit *commit, void *data) display_progress(progress, ++progress_counter); + if (show_disk_usage) + total_disk_usage += get_object_disk_usage(&commit->object); + if (info->flags & REV_LIST_QUIET) { finish_commit(commit); return; @@ -258,6 +274,8 @@ static void show_object(struct object *obj, const char *name, void *cb_data) if (finish_object(obj, name, cb_data)) return; display_progress(progress, ++progress_counter); + if (show_disk_usage) + total_disk_usage += get_object_disk_usage(obj); if (info->flags & REV_LIST_QUIET) return; @@ -452,6 +470,23 @@ static int try_bitmap_traversal(struct rev_info *revs, return 0; } +static int try_bitmap_disk_usage(struct rev_info *revs, + struct list_objects_filter_options *filter) +{ + struct bitmap_index *bitmap_git; + + if (!show_disk_usage) + return -1; + + bitmap_git = prepare_bitmap_walk(revs, filter); + if (!bitmap_git) + return -1; + + printf("%"PRIuMAX"\n", + (uintmax_t)get_disk_usage_from_bitmap(bitmap_git, revs)); + return 0; +} + int cmd_rev_list(int argc, const char **argv, const char *prefix) { struct rev_info revs; @@ -584,6 +619,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) continue; } + if (!strcmp(arg, "--disk-usage")) { + show_disk_usage = 1; + info.flags |= REV_LIST_QUIET; + continue; + } + usage(rev_list_usage); } @@ -626,6 +667,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (use_bitmap_index) { if (!try_bitmap_count(&revs, &filter_options)) return 0; + if (!try_bitmap_disk_usage(&revs, &filter_options)) + return 0; if (!try_bitmap_traversal(&revs, &filter_options)) return 0; } @@ -690,5 +733,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) printf("%d\n", revs.count_left + revs.count_right); } + if (show_disk_usage) + printf("%"PRIuMAX"\n", (uintmax_t)total_disk_usage); + return 0; } diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 2306a9ad98..d7da50ada5 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -64,7 +64,7 @@ static int sparse_checkout_list(int argc, const char **argv) pl.use_cone_patterns = core_sparse_checkout_cone; sparse_filename = get_sparse_checkout_filename(); - res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL); + res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0); free(sparse_filename); if (res < 0) { @@ -321,7 +321,7 @@ static int sparse_checkout_init(int argc, const char **argv) memset(&pl, 0, sizeof(pl)); sparse_filename = get_sparse_checkout_filename(); - res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL); + res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0); /* If we already have a sparse-checkout file, use it. */ if (res >= 0) { @@ -483,7 +483,7 @@ static void add_patterns_cone_mode(int argc, const char **argv, existing.use_cone_patterns = core_sparse_checkout_cone; if (add_patterns_from_file_to_list(sparse_filename, "", 0, - &existing, NULL)) + &existing, NULL, 0)) die(_("unable to load existing sparse-checkout patterns")); free(sparse_filename); @@ -507,7 +507,7 @@ static void add_patterns_literal(int argc, const char **argv, { char *sparse_filename = get_sparse_checkout_filename(); if (add_patterns_from_file_to_list(sparse_filename, "", 0, - pl, NULL)) + pl, NULL, 0)) die(_("unable to load existing sparse-checkout patterns")); free(sparse_filename); add_patterns_from_input(pl, argc, argv); diff --git a/builtin/stash.c b/builtin/stash.c index 9bc85f91cd..ba774cce67 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -87,7 +87,7 @@ static const char * const git_stash_save_usage[] = { NULL }; -static const char *ref_stash = "refs/stash"; +static const char ref_stash[] = "refs/stash"; static struct strbuf stash_index_path = STRBUF_INIT; /* @@ -222,7 +222,7 @@ static int clear_stash(int argc, const char **argv, const char *prefix) PARSE_OPT_STOP_AT_NON_OPTION); if (argc) - return error(_("git stash clear with parameters is " + return error(_("git stash clear with arguments is " "unimplemented")); return do_clear_stash(); diff --git a/builtin/tag.c b/builtin/tag.c index e8b85eefd8..d403417b56 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -198,11 +198,17 @@ static void write_tag_body(int fd, const struct object_id *oid) { unsigned long size; enum object_type type; - char *buf, *sp; + char *buf, *sp, *orig; + struct strbuf payload = STRBUF_INIT; + struct strbuf signature = STRBUF_INIT; - buf = read_object_file(oid, &type, &size); + orig = buf = read_object_file(oid, &type, &size); if (!buf) return; + if (parse_signature(buf, size, &payload, &signature)) { + buf = payload.buf; + size = payload.len; + } /* skip header */ sp = strstr(buf, "\n\n"); @@ -211,9 +217,11 @@ static void write_tag_body(int fd, const struct object_id *oid) return; } sp += 2; /* skip the 2 LFs */ - write_or_die(fd, sp, parse_signature(sp, buf + size - sp)); + write_or_die(fd, sp, buf + size - sp); - free(buf); + free(orig); + strbuf_release(&payload); + strbuf_release(&signature); } static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result) @@ -564,7 +572,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) object_ref = argc == 2 ? argv[1] : "HEAD"; if (argc > 2) - die(_("too many params")); + die(_("too many arguments")); if (get_oid(object_ref, &object)) die(_("Failed to resolve '%s' as a valid ref."), object_ref); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index dd4a75e030..a4ba2ebac6 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -46,7 +46,7 @@ static struct obj_buffer *lookup_object_buffer(struct object *base) static void add_object_buffer(struct object *object, char *buffer, unsigned long size) { struct obj_buffer *obj; - obj = xcalloc(1, sizeof(struct obj_buffer)); + CALLOC_ARRAY(obj, 1); obj->buffer = buffer; obj->size = size; if (add_decoration(&obj_decorate, object, obj)) @@ -500,7 +500,7 @@ static void unpack_all(void) if (!quiet) progress = start_progress(_("Unpacking objects"), nr_objects); - obj_list = xcalloc(nr_objects, sizeof(*obj_list)); + CALLOC_ARRAY(obj_list, nr_objects); for (i = 0; i < nr_objects; i++) { unpack_one(i); display_progress(progress, i + 1); |