diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/bisect--helper.c | 183 | ||||
-rw-r--r-- | builtin/checkout.c | 3 | ||||
-rw-r--r-- | builtin/clone.c | 34 | ||||
-rw-r--r-- | builtin/diff-files.c | 2 | ||||
-rw-r--r-- | builtin/diff-index.c | 2 | ||||
-rw-r--r-- | builtin/diff-tree.c | 2 | ||||
-rw-r--r-- | builtin/diff.c | 2 | ||||
-rw-r--r-- | builtin/fetch-pack.c | 3 | ||||
-rw-r--r-- | builtin/fetch.c | 18 | ||||
-rw-r--r-- | builtin/grep.c | 8 | ||||
-rw-r--r-- | builtin/index-pack.c | 69 | ||||
-rw-r--r-- | builtin/log.c | 12 | ||||
-rw-r--r-- | builtin/ls-remote.c | 9 | ||||
-rw-r--r-- | builtin/name-rev.c | 10 | ||||
-rw-r--r-- | builtin/pack-objects.c | 9 | ||||
-rw-r--r-- | builtin/range-diff.c | 30 | ||||
-rw-r--r-- | builtin/repack.c | 1 | ||||
-rw-r--r-- | builtin/sparse-checkout.c | 5 | ||||
-rw-r--r-- | builtin/submodule--helper.c | 2 | ||||
-rw-r--r-- | builtin/worktree.c | 110 |
20 files changed, 341 insertions, 173 deletions
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c index 709eb713a3..d69e13335d 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 }; @@ -904,28 +903,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 +1053,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 +1078,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 +1101,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/checkout.c b/builtin/checkout.c index c9ba23c279..2d6550bc3c 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -821,9 +821,6 @@ static int merge_working_tree(const struct checkout_opts *opts, } } - if (!active_cache_tree) - active_cache_tree = cache_tree(); - if (!cache_tree_fully_valid(active_cache_tree)) cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR); 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 4742a4559b..bb85266102 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -36,7 +36,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) */ rev.diffopt.ita_invisible_in_index = 1; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, &rev, NULL); while (1 < argc && argv[1][0] == '-') { diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 7f5281c461..c33d7af478 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -25,7 +25,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ repo_init_revisions(the_repository, &rev, prefix); rev.abbrev = 0; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, &rev, NULL); for (i = 1; i < argc; i++) { diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 9fc95e959f..178d12f07f 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -126,7 +126,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) memset(&s_r_opt, 0, sizeof(s_r_opt)); s_r_opt.tweak = diff_tree_tweak_rev; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, opt, &s_r_opt); memset(&w, 0, sizeof(w)); diff --git a/builtin/diff.c b/builtin/diff.c index 5cfe1717e8..0f4859abf7 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -453,7 +453,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) init_diff_ui_defaults(); git_config(git_diff_ui_config, NULL); - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); repo_init_revisions(the_repository, &rev, prefix); 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/grep.c b/builtin/grep.c index ca259af441..e348e6bb32 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -216,8 +216,6 @@ static void start_threads(struct grep_opt *opt) int err; struct grep_opt *o = grep_opt_dup(opt); o->output = strbuf_out; - if (i) - o->debug = 0; compile_grep_patterns(o); err = pthread_create(&threads[i], NULL, run, o); @@ -936,9 +934,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) N_("indicate hit with exit status without output")), OPT_BOOL(0, "all-match", &opt.all_match, N_("show only matches from files that match all patterns")), - OPT_SET_INT_F(0, "debug", &opt.debug, - N_("show parse tree for grep expression"), - 1, PARSE_OPT_HIDDEN), OPT_GROUP(""), { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager, N_("pager"), N_("show matching files in the pager"), @@ -1157,6 +1152,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 557bd2f348..54f74c4874 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -17,7 +17,7 @@ #include "promisor-remote.h" static const char index_pack_usage[] = -"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; +"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])"; struct object_entry { struct pack_idx_entry idx; @@ -1436,15 +1436,15 @@ static void fix_unresolved_deltas(struct hashfile *f) free(sorted_by_pos); } -static const char *derive_filename(const char *pack_name, const char *suffix, - struct strbuf *buf) +static const char *derive_filename(const char *pack_name, const char *strip, + const char *suffix, struct strbuf *buf) { size_t len; - if (!strip_suffix(pack_name, ".pack", &len)) - die(_("packfile name '%s' does not end with '.pack'"), - pack_name); + if (!strip_suffix(pack_name, strip, &len) || !len || + pack_name[len - 1] != '.') + die(_("packfile name '%s' does not end with '.%s'"), + pack_name, strip); strbuf_add(buf, pack_name, len); - strbuf_addch(buf, '.'); strbuf_addstr(buf, suffix); return buf->buf; } @@ -1459,7 +1459,7 @@ static void write_special_file(const char *suffix, const char *msg, int msg_len = strlen(msg); if (pack_name) - filename = derive_filename(pack_name, suffix, &name_buf); + filename = derive_filename(pack_name, "pack", suffix, &name_buf); else filename = odb_pack_name(&name_buf, hash, suffix); @@ -1484,12 +1484,14 @@ static void write_special_file(const char *suffix, const char *msg, static void final(const char *final_pack_name, const char *curr_pack_name, const char *final_index_name, const char *curr_index_name, + const char *final_rev_index_name, const char *curr_rev_index_name, const char *keep_msg, const char *promisor_msg, unsigned char *hash) { const char *report = "pack"; struct strbuf pack_name = STRBUF_INIT; struct strbuf index_name = STRBUF_INIT; + struct strbuf rev_index_name = STRBUF_INIT; int err; if (!from_stdin) { @@ -1524,6 +1526,16 @@ static void final(const char *final_pack_name, const char *curr_pack_name, } else chmod(final_index_name, 0444); + if (curr_rev_index_name) { + if (final_rev_index_name != curr_rev_index_name) { + if (!final_rev_index_name) + final_rev_index_name = odb_pack_name(&rev_index_name, hash, "rev"); + if (finalize_object_file(curr_rev_index_name, final_rev_index_name)) + die(_("cannot store reverse index file")); + } else + chmod(final_rev_index_name, 0444); + } + if (do_fsck_object) { struct packed_git *p; p = add_packed_git(final_index_name, strlen(final_index_name), 0); @@ -1553,6 +1565,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, } } + strbuf_release(&rev_index_name); strbuf_release(&index_name); strbuf_release(&pack_name); } @@ -1578,6 +1591,12 @@ static int git_index_pack_config(const char *k, const char *v, void *cb) } return 0; } + if (!strcmp(k, "pack.writereverseindex")) { + if (git_config_bool(k, v)) + opts->flags |= WRITE_REV; + else + opts->flags &= ~WRITE_REV; + } return git_default_config(k, v, cb); } @@ -1695,12 +1714,14 @@ static void show_pack_info(int stat_only) int cmd_index_pack(int argc, const char **argv, const char *prefix) { - int i, fix_thin_pack = 0, verify = 0, stat_only = 0; + int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; const char *curr_index; - const char *index_name = NULL, *pack_name = NULL; + const char *curr_rev_index = NULL; + const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; const char *keep_msg = NULL; const char *promisor_msg = NULL; struct strbuf index_name_buf = STRBUF_INIT; + struct strbuf rev_index_name_buf = STRBUF_INIT; struct pack_idx_entry **idx_objects; struct pack_idx_option opts; unsigned char pack_hash[GIT_MAX_RAWSZ]; @@ -1727,6 +1748,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (prefix && chdir(prefix)) die(_("Cannot come back to cwd")); + if (git_env_bool(GIT_TEST_WRITE_REV_INDEX, 0)) + rev_index = 1; + else + rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV)); + for (i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -1805,6 +1831,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (hash_algo == GIT_HASH_UNKNOWN) die(_("unknown hash algorithm '%s'"), arg); repo_set_hash_algo(the_repository, hash_algo); + } else if (!strcmp(arg, "--rev-index")) { + rev_index = 1; + } else if (!strcmp(arg, "--no-rev-index")) { + rev_index = 0; } else usage(index_pack_usage); continue; @@ -1824,7 +1854,16 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (from_stdin && hash_algo) die(_("--object-format cannot be used with --stdin")); if (!index_name && pack_name) - index_name = derive_filename(pack_name, "idx", &index_name_buf); + index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf); + + opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY); + if (rev_index) { + opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV; + if (index_name) + rev_index_name = derive_filename(index_name, + "idx", "rev", + &rev_index_name_buf); + } if (verify) { if (!index_name) @@ -1878,11 +1917,16 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) for (i = 0; i < nr_objects; i++) idx_objects[i] = &objects[i].idx; curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash); + if (rev_index) + curr_rev_index = write_rev_file(rev_index_name, idx_objects, + nr_objects, pack_hash, + opts.flags); free(idx_objects); if (!verify) final(pack_name, curr_pack, index_name, curr_index, + rev_index_name, curr_rev_index, keep_msg, promisor_msg, pack_hash); else @@ -1893,10 +1937,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) free(objects); strbuf_release(&index_name_buf); + strbuf_release(&rev_index_name_buf); if (pack_name == NULL) free((void *) curr_pack); if (index_name == NULL) free((void *) curr_index); + if (rev_index_name == NULL) + free((void *) curr_rev_index); /* * Let the caller know this pack is not self contained diff --git a/builtin/log.c b/builtin/log.c index d0cbaaf68a..be29c3f89f 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1223,14 +1223,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 +1678,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); diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 092917eca2..ef604752a0 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; @@ -94,9 +95,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) } 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/name-rev.c b/builtin/name-rev.c index 3fe71a8c01..b221d30014 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -390,10 +390,10 @@ static void name_tips(void) } } -static const unsigned char *nth_tip_table_ent(size_t ix, void *table_) +static const struct object_id *nth_tip_table_ent(size_t ix, const void *table_) { - struct tip_table_entry *table = table_; - return table[ix].oid.hash; + const struct tip_table_entry *table = table_; + return &table[ix].oid; } static const char *get_exact_ref_match(const struct object *o) @@ -408,8 +408,8 @@ static const char *get_exact_ref_match(const struct object *o) tip_table.sorted = 1; } - found = hash_pos(o->oid.hash, tip_table.table, tip_table.nr, - nth_tip_table_ent); + found = oid_pos(&o->oid, tip_table.table, tip_table.nr, + nth_tip_table_ent); if (0 <= found) return tip_table.table[found].refname; return NULL; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 13cde5896a..6d62aaf59a 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2953,6 +2953,13 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.version); return 0; } + if (!strcmp(k, "pack.writereverseindex")) { + if (git_config_bool(k, v)) + pack_idx_opts.flags |= WRITE_REV; + else + pack_idx_opts.flags &= ~WRITE_REV; + return 0; + } if (!strcmp(k, "uploadpack.blobpackfileuri")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); const char *oid_end, *pack_end; @@ -3592,6 +3599,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) reset_pack_idx_option(&pack_idx_opts); git_config(git_pack_config, NULL); + if (git_env_bool(GIT_TEST_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/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/repack.c b/builtin/repack.c index 2158b48f4c..01440de2d5 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -209,6 +209,7 @@ static struct { } exts[] = { {".pack"}, {".idx"}, + {".rev", 1}, {".bitmap", 1}, {".promisor", 1}, }; diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index e3140db2a0..2306a9ad98 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -22,11 +22,6 @@ static char const * const builtin_sparse_checkout_usage[] = { NULL }; -static char *get_sparse_checkout_filename(void) -{ - return git_pathdup("info/sparse-checkout"); -} - static void write_patterns_to_file(FILE *fp, struct pattern_list *pl) { int i; diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index c2bd882d17..9d505a6329 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1257,7 +1257,7 @@ static int compute_summary_module_list(struct object_id *head_oid, git_config(git_diff_basic_config, NULL); init_revisions(&rev, info->prefix); rev.abbrev = 0; - precompose_argv(diff_args.nr, diff_args.v); + precompose_argv_prefix(diff_args.nr, diff_args.v, NULL); setup_revisions(diff_args.nr, diff_args.v, &rev, NULL); rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = submodule_summary_callback; diff --git a/builtin/worktree.c b/builtin/worktree.c index 71287b2da6..1cd5c2016e 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -12,6 +12,7 @@ #include "submodule.h" #include "utf8.h" #include "worktree.h" +#include "quote.h" static const char * const worktree_usage[] = { N_("git worktree add [<options>] <path> [<commit-ish>]"), @@ -67,79 +68,6 @@ static void delete_worktrees_dir_if_empty(void) rmdir(git_path("worktrees")); /* ignore failed removal */ } -/* - * Return true if worktree entry should be pruned, along with the reason for - * pruning. Otherwise, return false and the worktree's path, or NULL if it - * cannot be determined. Caller is responsible for freeing returned path. - */ -static int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath) -{ - struct stat st; - char *path; - int fd; - size_t len; - ssize_t read_result; - - *wtpath = NULL; - if (!is_directory(git_path("worktrees/%s", id))) { - strbuf_addstr(reason, _("not a valid directory")); - return 1; - } - if (file_exists(git_path("worktrees/%s/locked", id))) - return 0; - if (stat(git_path("worktrees/%s/gitdir", id), &st)) { - strbuf_addstr(reason, _("gitdir file does not exist")); - return 1; - } - fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY); - if (fd < 0) { - strbuf_addf(reason, _("unable to read gitdir file (%s)"), - strerror(errno)); - return 1; - } - len = xsize_t(st.st_size); - path = xmallocz(len); - - read_result = read_in_full(fd, path, len); - if (read_result < 0) { - strbuf_addf(reason, _("unable to read gitdir file (%s)"), - strerror(errno)); - close(fd); - free(path); - return 1; - } - close(fd); - - if (read_result != len) { - strbuf_addf(reason, - _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"), - (uintmax_t)len, (uintmax_t)read_result); - free(path); - return 1; - } - while (len && (path[len - 1] == '\n' || path[len - 1] == '\r')) - len--; - if (!len) { - strbuf_addstr(reason, _("invalid gitdir file")); - free(path); - return 1; - } - path[len] = '\0'; - if (!file_exists(path)) { - if (stat(git_path("worktrees/%s/index", id), &st) || - st.st_mtime <= expire) { - strbuf_addstr(reason, _("gitdir file points to non-existent location")); - free(path); - return 1; - } else { - *wtpath = path; - return 0; - } - } - *wtpath = path; - return 0; -} - static void prune_worktree(const char *id, const char *reason) { if (show_only || verbose) @@ -195,7 +123,7 @@ static void prune_worktrees(void) if (is_dot_or_dotdot(d->d_name)) continue; strbuf_reset(&reason); - if (should_prune_worktree(d->d_name, &reason, &path)) + if (should_prune_worktree(d->d_name, &reason, &path, expire)) prune_worktree(d->d_name, reason.buf); else if (path) string_list_append(&kept, path)->util = xstrdup(d->d_name); @@ -642,6 +570,8 @@ static int add(int ac, const char **av, const char *prefix) static void show_worktree_porcelain(struct worktree *wt) { + const char *reason; + printf("worktree %s\n", wt->path); if (wt->is_bare) printf("bare\n"); @@ -652,6 +582,20 @@ static void show_worktree_porcelain(struct worktree *wt) else if (wt->head_ref) printf("branch %s\n", wt->head_ref); } + + reason = worktree_lock_reason(wt); + if (reason && *reason) { + struct strbuf sb = STRBUF_INIT; + quote_c_style(reason, &sb, NULL, 0); + printf("locked %s\n", sb.buf); + strbuf_release(&sb); + } else if (reason) + printf("locked\n"); + + reason = worktree_prune_reason(wt, expire); + if (reason) + printf("prunable %s\n", reason); + printf("\n"); } @@ -660,6 +604,7 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) struct strbuf sb = STRBUF_INIT; int cur_path_len = strlen(wt->path); int path_adj = cur_path_len - utf8_strwidth(wt->path); + const char *reason; strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path); if (wt->is_bare) @@ -677,9 +622,18 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) strbuf_addstr(&sb, "(error)"); } - if (!is_main_worktree(wt) && worktree_lock_reason(wt)) + reason = worktree_lock_reason(wt); + if (verbose && reason && *reason) + strbuf_addf(&sb, "\n\tlocked: %s", reason); + else if (reason) strbuf_addstr(&sb, " locked"); + reason = worktree_prune_reason(wt, expire); + if (verbose && reason) + strbuf_addf(&sb, "\n\tprunable: %s", reason); + else if (reason) + strbuf_addstr(&sb, " prunable"); + printf("%s\n", sb.buf); strbuf_release(&sb); } @@ -723,12 +677,18 @@ static int list(int ac, const char **av, const char *prefix) struct option options[] = { OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")), + OPT__VERBOSE(&verbose, N_("show extended annotations and reasons, if available")), + OPT_EXPIRY_DATE(0, "expire", &expire, + N_("add 'prunable' annotation to worktrees older than <time>")), OPT_END() }; + expire = TIME_MAX; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); if (ac) usage_with_options(worktree_usage, options); + else if (verbose && porcelain) + die(_("--verbose and --porcelain are mutually exclusive")); else { struct worktree **worktrees = get_worktrees(); int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i; |