diff options
author | Vincent Ambo <tazjin@google.com> | 2020-05-25T23·06+0100 |
---|---|---|
committer | Vincent Ambo <tazjin@google.com> | 2020-05-25T23·06+0100 |
commit | 93ba78d6f4632ef1c5228965e3edc8c0faf88c1e (patch) | |
tree | 85730c182a9f5f492ade8e8ccdb1c2356f9900bd /third_party/git/builtin | |
parent | 6f8fbf4aa4b1654ab27d4829e114538761817de0 (diff) |
revert(3p/git): Revert merge of git upstream at v2.26.2 r/852
This causes cgit to serve error pages, which is undesirable. This reverts commit 5229c9b232de5bfa959ad6ebbb4c8192ac513352, reversing changes made to f2b211131f2347342dde63975b09cf603149f1a3.
Diffstat (limited to 'third_party/git/builtin')
56 files changed, 1456 insertions, 3403 deletions
diff --git a/third_party/git/builtin/add.c b/third_party/git/builtin/add.c index 18a0881ecf95..dd18e5c9b670 100644 --- a/third_party/git/builtin/add.c +++ b/third_party/git/builtin/add.c @@ -20,7 +20,6 @@ #include "bulk-checkin.h" #include "argv-array.h" #include "submodule.h" -#include "add-interactive.h" static const char * const builtin_add_usage[] = { N_("git add [<options>] [--] <pathspec>..."), @@ -29,9 +28,6 @@ static const char * const builtin_add_usage[] = { static int patch_interactive, add_interactive, edit_interactive; static int take_worktree_changes; static int add_renormalize; -static int pathspec_file_nul; -static const char *pathspec_from_file; -static int legacy_stash_p; /* support for the scripted `git stash` */ struct update_callback_data { int flags; @@ -189,34 +185,6 @@ int run_add_interactive(const char *revision, const char *patch_mode, { int status, i; struct argv_array argv = ARGV_ARRAY_INIT; - int use_builtin_add_i = - git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1); - - if (use_builtin_add_i < 0) - git_config_get_bool("add.interactive.usebuiltin", - &use_builtin_add_i); - - if (use_builtin_add_i == 1) { - enum add_p_mode mode; - - if (!patch_mode) - return !!run_add_i(the_repository, pathspec); - - if (!strcmp(patch_mode, "--patch")) - mode = ADD_P_ADD; - else if (!strcmp(patch_mode, "--patch=stash")) - mode = ADD_P_STASH; - else if (!strcmp(patch_mode, "--patch=reset")) - mode = ADD_P_RESET; - else if (!strcmp(patch_mode, "--patch=checkout")) - mode = ADD_P_CHECKOUT; - else if (!strcmp(patch_mode, "--patch=worktree")) - mode = ADD_P_WORKTREE; - else - die("'%s' not supported", patch_mode); - - return !!run_add_p(the_repository, mode, revision, pathspec); - } argv_array_push(&argv, "add--interactive"); if (patch_mode) @@ -341,10 +309,6 @@ static struct option builtin_add_options[] = { N_("override the executable bit of the listed files")), OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo, N_("warn when adding an embedded repository")), - OPT_HIDDEN_BOOL(0, "legacy-stash-p", &legacy_stash_p, - N_("backend for `git stash -p`")), - OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), OPT_END(), }; @@ -355,7 +319,6 @@ static int add_config(const char *var, const char *value, void *cb) ignore_add_errors = git_config_bool(var, value); return 0; } - return git_default_config(var, value, cb); } @@ -406,10 +369,7 @@ static int add_files(struct dir_struct *dir, int flags) fprintf(stderr, _(ignore_error)); for (i = 0; i < dir->ignored_nr; i++) fprintf(stderr, "%s\n", dir->ignored[i]->name); - if (advice_add_ignored_file) - advise(_("Use -f if you really want to add them.\n" - "Turn this message off by running\n" - "\"git config advice.addIgnoredFile false\"")); + fprintf(stderr, _("Use -f if you really want to add them.\n")); exit_status = 1; } @@ -442,28 +402,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) builtin_add_usage, PARSE_OPT_KEEP_ARGV0); if (patch_interactive) add_interactive = 1; - if (add_interactive) { - if (pathspec_from_file) - die(_("--pathspec-from-file is incompatible with --interactive/--patch")); + if (add_interactive) exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive)); - } - if (legacy_stash_p) { - struct pathspec pathspec; - - parse_pathspec(&pathspec, 0, - PATHSPEC_PREFER_FULL | - PATHSPEC_SYMLINK_LEADING_PATH | - PATHSPEC_PREFIX_ORIGIN, - prefix, argv); - - return run_add_interactive(NULL, "--patch=stash", &pathspec); - } - if (edit_interactive) { - if (pathspec_from_file) - die(_("--pathspec-from-file is incompatible with --edit")); + if (edit_interactive) return(edit_patch(argc, argv, prefix)); - } argc--; argv++; @@ -475,6 +418,10 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (addremove && take_worktree_changes) die(_("-A and -u are mutually incompatible")); + if (!take_worktree_changes && addremove_explicit < 0 && argc) + /* Turn "git add pathspec..." to "git add -A pathspec..." */ + addremove = 1; + if (!show_only && ignore_missing) die(_("Option --ignore-missing can only be used together with --dry-run")); @@ -487,6 +434,19 @@ int cmd_add(int argc, const char **argv, const char *prefix) hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + flags = ((verbose ? ADD_CACHE_VERBOSE : 0) | + (show_only ? ADD_CACHE_PRETEND : 0) | + (intent_to_add ? ADD_CACHE_INTENT : 0) | + (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) | + (!(addremove || take_worktree_changes) + ? ADD_CACHE_IGNORE_REMOVAL : 0)); + + if (require_pathspec && argc == 0) { + fprintf(stderr, _("Nothing specified, nothing added.\n")); + fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n")); + return 0; + } + /* * Check the "pathspec '%s' did not match any files" block * below before enabling new magic. @@ -496,38 +456,6 @@ int cmd_add(int argc, const char **argv, const char *prefix) PATHSPEC_SYMLINK_LEADING_PATH, prefix, argv); - if (pathspec_from_file) { - if (pathspec.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - parse_pathspec_file(&pathspec, PATHSPEC_ATTR, - PATHSPEC_PREFER_FULL | - PATHSPEC_SYMLINK_LEADING_PATH, - prefix, pathspec_from_file, pathspec_file_nul); - } else if (pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - - if (require_pathspec && pathspec.nr == 0) { - fprintf(stderr, _("Nothing specified, nothing added.\n")); - if (advice_add_empty_pathspec) - advise( _("Maybe you wanted to say 'git add .'?\n" - "Turn this message off by running\n" - "\"git config advice.addEmptyPathspec false\"")); - return 0; - } - - if (!take_worktree_changes && addremove_explicit < 0 && pathspec.nr) - /* Turn "git add pathspec..." to "git add -A pathspec..." */ - addremove = 1; - - flags = ((verbose ? ADD_CACHE_VERBOSE : 0) | - (show_only ? ADD_CACHE_PRETEND : 0) | - (intent_to_add ? ADD_CACHE_INTENT : 0) | - (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) | - (!(addremove || take_worktree_changes) - ? ADD_CACHE_IGNORE_REMOVAL : 0)); - if (read_cache_preload(&pathspec) < 0) die(_("index file corrupt")); diff --git a/third_party/git/builtin/am.c b/third_party/git/builtin/am.c index e3dfd93c258f..1aea657a7f0b 100644 --- a/third_party/git/builtin/am.c +++ b/third_party/git/builtin/am.c @@ -24,6 +24,7 @@ #include "sequencer.h" #include "revision.h" #include "merge-recursive.h" +#include "revision.h" #include "log-tree.h" #include "notes-utils.h" #include "rerere.h" @@ -81,11 +82,6 @@ enum signoff_type { SIGNOFF_EXPLICIT /* --signoff was set on the command-line */ }; -enum show_patch_type { - SHOW_PATCH_RAW = 0, - SHOW_PATCH_DIFF = 1, -}; - struct am_state { /* state directory path */ char *dir; @@ -1076,6 +1072,19 @@ static const char *msgnum(const struct am_state *state) } /** + * Refresh and write index. + */ +static void refresh_and_write_cache(void) +{ + struct lock_file lock_file = LOCK_INIT; + + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + refresh_cache(REFRESH_QUIET); + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) + die(_("unable to write index file")); +} + +/** * Dies with a user-friendly message on how to proceed after resolving the * problem. This message can be overridden with state->resolvemsg. */ @@ -1263,9 +1272,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit) buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding()); ident_line = find_commit_header(buffer, "author", &ident_len); - if (!ident_line) - die(_("missing author line in commit %s"), - oid_to_hex(&commit->object.oid)); + if (split_ident_line(&id, ident_line, ident_len) < 0) die(_("invalid ident line: %.*s"), (int)ident_len, ident_line); @@ -1531,7 +1538,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); o.branch2 = their_tree_name; - o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE; + o.detect_directory_renames = 0; if (state->quiet) o.verbosity = 0; @@ -1696,8 +1703,7 @@ static void am_run(struct am_state *state, int resume) unlink(am_path(state, "dirtyindex")); - if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) - die(_("unable to write index file")); + refresh_and_write_cache(); if (repo_index_has_changes(the_repository, NULL, &sb)) { write_state_bool(state, "dirtyindex", 1); @@ -1768,7 +1774,7 @@ static void am_run(struct am_state *state, int resume) linelen(state->msg), state->msg); if (advice_amworkdir) - advise(_("Use 'git am --show-current-patch=diff' to see the failed patch")); + advise(_("Use 'git am --show-current-patch' to see the failed patch")); die_user_resolve(state); } @@ -2066,7 +2072,7 @@ static void am_abort(struct am_state *state) am_destroy(state); } -static int show_patch(struct am_state *state, enum show_patch_type sub_mode) +static int show_patch(struct am_state *state) { struct strbuf sb = STRBUF_INIT; const char *patch_path; @@ -2083,17 +2089,7 @@ static int show_patch(struct am_state *state, enum show_patch_type sub_mode) return ret; } - switch (sub_mode) { - case SHOW_PATCH_RAW: - patch_path = am_path(state, msgnum(state)); - break; - case SHOW_PATCH_DIFF: - patch_path = am_path(state, "patch"); - break; - default: - BUG("invalid mode for --show-current-patch"); - } - + patch_path = am_path(state, msgnum(state)); len = strbuf_read_file(&sb, patch_path, 0); if (len < 0) die_errno(_("failed to read '%s'"), patch_path); @@ -2133,7 +2129,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int return 0; } -enum resume_type { +enum resume_mode { RESUME_FALSE = 0, RESUME_APPLY, RESUME_RESOLVED, @@ -2143,45 +2139,6 @@ enum resume_type { RESUME_SHOW_PATCH }; -struct resume_mode { - enum resume_type mode; - enum show_patch_type sub_mode; -}; - -static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset) -{ - int *opt_value = opt->value; - struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode); - - /* - * Please update $__git_showcurrentpatch in git-completion.bash - * when you add new options - */ - const char *valid_modes[] = { - [SHOW_PATCH_DIFF] = "diff", - [SHOW_PATCH_RAW] = "raw" - }; - int new_value = SHOW_PATCH_RAW; - - if (arg) { - for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) { - if (!strcmp(arg, valid_modes[new_value])) - break; - } - if (new_value >= ARRAY_SIZE(valid_modes)) - return error(_("Invalid value for --show-current-patch: %s"), arg); - } - - if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode) - return error(_("--show-current-patch=%s is incompatible with " - "--show-current-patch=%s"), - arg, valid_modes[resume->sub_mode]); - - resume->mode = RESUME_SHOW_PATCH; - resume->sub_mode = new_value; - return 0; -} - static int git_am_config(const char *k, const char *v, void *cb) { int status; @@ -2199,7 +2156,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) int binary = -1; int keep_cr = -1; int patch_format = PATCH_FORMAT_UNKNOWN; - struct resume_mode resume = { .mode = RESUME_FALSE }; + enum resume_mode resume = RESUME_FALSE; int in_progress; int ret = 0; @@ -2268,26 +2225,24 @@ int cmd_am(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG), OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL, N_("override error message when patch failure occurs")), - OPT_CMDMODE(0, "continue", &resume.mode, + OPT_CMDMODE(0, "continue", &resume, N_("continue applying patches after resolving a conflict"), RESUME_RESOLVED), - OPT_CMDMODE('r', "resolved", &resume.mode, + OPT_CMDMODE('r', "resolved", &resume, N_("synonyms for --continue"), RESUME_RESOLVED), - OPT_CMDMODE(0, "skip", &resume.mode, + OPT_CMDMODE(0, "skip", &resume, N_("skip the current patch"), RESUME_SKIP), - OPT_CMDMODE(0, "abort", &resume.mode, + OPT_CMDMODE(0, "abort", &resume, N_("restore the original branch and abort the patching operation."), RESUME_ABORT), - OPT_CMDMODE(0, "quit", &resume.mode, + OPT_CMDMODE(0, "quit", &resume, N_("abort the patching operation but keep HEAD where it is."), RESUME_QUIT), - { OPTION_CALLBACK, 0, "show-current-patch", &resume.mode, - "(diff|raw)", - N_("show the patch being applied"), - PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - parse_opt_show_current_patch, RESUME_SHOW_PATCH }, + OPT_CMDMODE(0, "show-current-patch", &resume, + N_("show the patch being applied."), + RESUME_SHOW_PATCH), OPT_BOOL(0, "committer-date-is-author-date", &state.committer_date_is_author_date, N_("lie about committer date")), @@ -2337,12 +2292,12 @@ int cmd_am(int argc, const char **argv, const char *prefix) * intend to feed us a patch but wanted to continue * unattended. */ - if (argc || (resume.mode == RESUME_FALSE && !isatty(0))) + if (argc || (resume == RESUME_FALSE && !isatty(0))) die(_("previous rebase directory %s still exists but mbox given."), state.dir); - if (resume.mode == RESUME_FALSE) - resume.mode = RESUME_APPLY; + if (resume == RESUME_FALSE) + resume = RESUME_APPLY; if (state.signoff == SIGNOFF_EXPLICIT) am_append_signoff(&state); @@ -2356,7 +2311,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) * stray directories. */ if (file_exists(state.dir) && !state.rebasing) { - if (resume.mode == RESUME_ABORT || resume.mode == RESUME_QUIT) { + if (resume == RESUME_ABORT || resume == RESUME_QUIT) { am_destroy(&state); am_state_release(&state); return 0; @@ -2367,7 +2322,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) state.dir); } - if (resume.mode) + if (resume) die(_("Resolve operation not in progress, we are not resuming.")); for (i = 0; i < argc; i++) { @@ -2385,7 +2340,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) argv_array_clear(&paths); } - switch (resume.mode) { + switch (resume) { case RESUME_FALSE: am_run(&state, 0); break; @@ -2406,7 +2361,7 @@ int cmd_am(int argc, const char **argv, const char *prefix) am_destroy(&state); break; case RESUME_SHOW_PATCH: - ret = show_patch(&state, resume.sub_mode); + ret = show_patch(&state); break; default: BUG("invalid resume value"); diff --git a/third_party/git/builtin/bisect--helper.c b/third_party/git/builtin/bisect--helper.c index c1c40b516df7..1fbe156e67a4 100644 --- a/third_party/git/builtin/bisect--helper.c +++ b/third_party/git/builtin/bisect--helper.c @@ -52,8 +52,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad, terms->term_bad = xstrdup(bad); } -static const char vocab_bad[] = "bad|new"; -static const char vocab_good[] = "good|old"; +static const char *vocab_bad = "bad|new"; +static const char *vocab_good = "good|old"; /* * Check whether the string `term` belongs to the set of strings @@ -169,12 +169,11 @@ static int bisect_reset(const char *commit) argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL); if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { - error(_("could not check out original" - " HEAD '%s'. Try 'git bisect" - " reset <commit>'."), branch.buf); strbuf_release(&branch); argv_array_clear(&argv); - return -1; + return error(_("could not check out original" + " HEAD '%s'. Try 'git bisect" + " reset <commit>'."), branch.buf); } argv_array_clear(&argv); } @@ -206,31 +205,31 @@ static int bisect_write(const char *state, const char *rev, struct object_id oid; struct commit *commit; FILE *fp = NULL; - int res = 0; + int retval = 0; if (!strcmp(state, terms->term_bad)) { strbuf_addf(&tag, "refs/bisect/%s", state); } else if (one_of(state, terms->term_good, "skip", NULL)) { strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev); } else { - res = error(_("Bad bisect_write argument: %s"), state); + retval = error(_("Bad bisect_write argument: %s"), state); goto finish; } if (get_oid(rev, &oid)) { - res = error(_("couldn't get the oid of the rev '%s'"), rev); + retval = error(_("couldn't get the oid of the rev '%s'"), rev); goto finish; } if (update_ref(NULL, tag.buf, &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR)) { - res = -1; + retval = -1; goto finish; } fp = fopen(git_path_bisect_log(), "a"); if (!fp) { - res = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log()); + retval = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log()); goto finish; } @@ -244,7 +243,7 @@ finish: if (fp) fclose(fp); strbuf_release(&tag); - return res; + return retval; } static int check_and_set_terms(struct bisect_terms *terms, const char *cmd) @@ -282,23 +281,35 @@ static int mark_good(const char *refname, const struct object_id *oid, return 1; } -static const char need_bad_and_good_revision_warning[] = +static const char *need_bad_and_good_revision_warning = N_("You need to give me at least one %s and %s revision.\n" "You can use \"git bisect %s\" and \"git bisect %s\" for that."); -static const char need_bisect_start_warning[] = +static const char *need_bisect_start_warning = N_("You need to start by \"git bisect start\".\n" "You then need to give me at least one %s and %s revision.\n" "You can use \"git bisect %s\" and \"git bisect %s\" for that."); -static int decide_next(const struct bisect_terms *terms, - const char *current_term, int missing_good, - int missing_bad) +static int bisect_next_check(const struct bisect_terms *terms, + const char *current_term) { + int missing_good = 1, missing_bad = 1, retval = 0; + const char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad); + const char *good_glob = xstrfmt("%s-*", terms->term_good); + + if (ref_exists(bad_ref)) + missing_bad = 0; + + for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/", + (void *) &missing_good); + if (!missing_good && !missing_bad) - return 0; - if (!current_term) - return -1; + goto finish; + + if (!current_term) { + retval = -1; + goto finish; + } if (missing_good && !missing_bad && !strcmp(current_term, terms->term_good)) { @@ -309,7 +320,7 @@ static int decide_next(const struct bisect_terms *terms, */ warning(_("bisecting only with a %s commit"), terms->term_bad); if (!isatty(0)) - return 0; + goto finish; /* * TRANSLATORS: Make sure to include [Y] and [n] in your * translation. The program will only accept English input @@ -317,35 +328,21 @@ static int decide_next(const struct bisect_terms *terms, */ yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO); if (starts_with(yesno, "N") || starts_with(yesno, "n")) - return -1; - return 0; + retval = -1; + goto finish; + } + if (!is_empty_or_missing_file(git_path_bisect_start())) { + retval = error(_(need_bad_and_good_revision_warning), + vocab_bad, vocab_good, vocab_bad, vocab_good); + } else { + retval = error(_(need_bisect_start_warning), + vocab_good, vocab_bad, vocab_good, vocab_bad); } - if (!is_empty_or_missing_file(git_path_bisect_start())) - return error(_(need_bad_and_good_revision_warning), - vocab_bad, vocab_good, vocab_bad, vocab_good); - else - return error(_(need_bisect_start_warning), - vocab_good, vocab_bad, vocab_good, vocab_bad); -} - -static int bisect_next_check(const struct bisect_terms *terms, - const char *current_term) -{ - int missing_good = 1, missing_bad = 1; - char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad); - char *good_glob = xstrfmt("%s-*", terms->term_good); - - if (ref_exists(bad_ref)) - missing_bad = 0; - - for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/", - (void *) &missing_good); - - free(good_glob); - free(bad_ref); - - return decide_next(terms, current_term, missing_good, missing_bad); +finish: + free((void *) good_glob); + free((void *) bad_ref); + return retval; } static int get_terms(struct bisect_terms *terms) @@ -399,7 +396,7 @@ static int bisect_terms(struct bisect_terms *terms, const char *option) static int bisect_append_log_quoted(const char **argv) { - int res = 0; + int retval = 0; FILE *fp = fopen(git_path_bisect_log(), "a"); struct strbuf orig_args = STRBUF_INIT; @@ -407,25 +404,25 @@ static int bisect_append_log_quoted(const char **argv) return -1; if (fprintf(fp, "git bisect start") < 1) { - res = -1; + retval = -1; goto finish; } sq_quote_argv(&orig_args, argv); if (fprintf(fp, "%s\n", orig_args.buf) < 1) - res = -1; + retval = -1; finish: fclose(fp); strbuf_release(&orig_args); - return res; + return retval; } static int bisect_start(struct bisect_terms *terms, int no_checkout, const char **argv, int argc) { int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0; - int flags, pathspec_pos, res = 0; + int flags, pathspec_pos, retval = 0; struct string_list revs = STRING_LIST_INIT_DUP; struct string_list states = STRING_LIST_INIT_DUP; struct strbuf start_head = STRBUF_INIT; @@ -526,7 +523,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, argv_array_pushl(&argv, "checkout", start_head.buf, "--", NULL); if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { - res = error(_("checking out '%s' failed." + retval = error(_("checking out '%s' failed." " Try 'git bisect start " "<valid-branch>'."), start_head.buf); @@ -574,12 +571,12 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, if (no_checkout) { if (get_oid(start_head.buf, &oid) < 0) { - res = error(_("invalid ref: '%s'"), start_head.buf); + retval = error(_("invalid ref: '%s'"), start_head.buf); goto finish; } if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR)) { - res = -1; + retval = -1; goto finish; } } @@ -591,26 +588,26 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, for (i = 0; i < states.nr; i++) if (bisect_write(states.items[i].string, revs.items[i].string, terms, 1)) { - res = -1; + retval = -1; goto finish; } if (must_write_terms && write_terms(terms->term_bad, terms->term_good)) { - res = -1; + retval = -1; goto finish; } - res = bisect_append_log_quoted(argv); - if (res) - res = -1; + retval = bisect_append_log_quoted(argv); + if (retval) + retval = -1; finish: string_list_clear(&revs, 0); string_list_clear(&states, 0); strbuf_release(&start_head); strbuf_release(&bisect_names); - return res; + return retval; } int cmd_bisect__helper(int argc, const char **argv, const char *prefix) @@ -666,8 +663,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) switch (cmdmode) { case NEXT_ALL: - res = bisect_next_all(the_repository, prefix, no_checkout); - break; + return bisect_next_all(the_repository, prefix, no_checkout); case WRITE_TERMS: if (argc != 2) return error(_("--write-terms requires two arguments")); @@ -714,13 +710,5 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) return error("BUG: unknown subcommand '%d'", cmdmode); } free_terms(&terms); - - /* - * Handle early success - * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all - */ - if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) - res = BISECT_OK; - - return abs(res); + return !!res; } diff --git a/third_party/git/builtin/blame.c b/third_party/git/builtin/blame.c index edd4bf7e3bb3..7ebd51ae4d2e 100644 --- a/third_party/git/builtin/blame.c +++ b/third_party/git/builtin/blame.c @@ -26,6 +26,7 @@ #include "progress.h" #include "object-store.h" #include "blame.h" +#include "string-list.h" #include "refs.h" static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"); @@ -319,18 +320,18 @@ static const char *format_time(timestamp_t time, const char *tz_str, return time_buf.buf; } -#define OUTPUT_ANNOTATE_COMPAT (1U<<0) -#define OUTPUT_LONG_OBJECT_NAME (1U<<1) -#define OUTPUT_RAW_TIMESTAMP (1U<<2) -#define OUTPUT_PORCELAIN (1U<<3) -#define OUTPUT_SHOW_NAME (1U<<4) -#define OUTPUT_SHOW_NUMBER (1U<<5) -#define OUTPUT_SHOW_SCORE (1U<<6) -#define OUTPUT_NO_AUTHOR (1U<<7) -#define OUTPUT_SHOW_EMAIL (1U<<8) -#define OUTPUT_LINE_PORCELAIN (1U<<9) -#define OUTPUT_COLOR_LINE (1U<<10) -#define OUTPUT_SHOW_AGE_WITH_COLOR (1U<<11) +#define OUTPUT_ANNOTATE_COMPAT 001 +#define OUTPUT_LONG_OBJECT_NAME 002 +#define OUTPUT_RAW_TIMESTAMP 004 +#define OUTPUT_PORCELAIN 010 +#define OUTPUT_SHOW_NAME 020 +#define OUTPUT_SHOW_NUMBER 040 +#define OUTPUT_SHOW_SCORE 0100 +#define OUTPUT_NO_AUTHOR 0200 +#define OUTPUT_SHOW_EMAIL 0400 +#define OUTPUT_LINE_PORCELAIN 01000 +#define OUTPUT_COLOR_LINE 02000 +#define OUTPUT_SHOW_AGE_WITH_COLOR 04000 static void emit_porcelain_details(struct blame_origin *suspect, int repeat) { @@ -459,7 +460,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int for (cnt = 0; cnt < ent->num_lines; cnt++) { char ch; - int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? the_hash_algo->hexsz : abbrev; + int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev; if (opt & OUTPUT_COLOR_LINE) { if (cnt > 0) { @@ -861,6 +862,14 @@ int cmd_blame(int argc, const char **argv, const char *prefix) OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("Ignore revisions from <file>")), OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE), OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR), + + /* + * The following two options are parsed by parse_revision_opt() + * and are only included here to get included in the "-h" + * output: + */ + { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, NULL, 0, parse_opt_unknown_cb }, + OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL), OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")), OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")), @@ -876,7 +885,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix) struct range_set ranges; unsigned int range_i; long anchor; - const int hexsz = the_hash_algo->hexsz; setup_default_color_by_age(); git_config(git_blame_config, &output_option); @@ -923,11 +931,11 @@ parse_done: } else if (show_progress < 0) show_progress = isatty(2); - if (0 < abbrev && abbrev < hexsz) + if (0 < abbrev && abbrev < GIT_SHA1_HEXSZ) /* one more abbrev length is needed for the boundary commit */ abbrev++; else if (!abbrev) - abbrev = hexsz; + abbrev = GIT_SHA1_HEXSZ; if (revs_file && read_ancestry(revs_file)) die_errno("reading graft file '%s' failed", revs_file); diff --git a/third_party/git/builtin/branch.c b/third_party/git/builtin/branch.c index d8297f80ffc7..2ef214632f02 100644 --- a/third_party/git/builtin/branch.c +++ b/third_party/git/builtin/branch.c @@ -624,7 +624,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_SET_INT_F(0, "set-upstream", &track, N_("do not use"), BRANCH_TRACK_OVERRIDE, PARSE_OPT_HIDDEN), OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")), - OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("unset the upstream info")), + OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")), OPT__COLOR(&branch_use_color, N_("use colored output")), OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"), FILTER_REFS_REMOTES), diff --git a/third_party/git/builtin/bundle.c b/third_party/git/builtin/bundle.c index f049d27a1440..1ea4bfdfc198 100644 --- a/third_party/git/builtin/bundle.c +++ b/third_party/git/builtin/bundle.c @@ -1,6 +1,4 @@ #include "builtin.h" -#include "argv-array.h" -#include "parse-options.h" #include "cache.h" #include "bundle.h" @@ -11,184 +9,59 @@ * bundle supporting "fetch", "pull", and "ls-remote". */ -static const char * const builtin_bundle_usage[] = { - N_("git bundle create [<options>] <file> <git-rev-list args>"), - N_("git bundle verify [<options>] <file>"), - N_("git bundle list-heads <file> [<refname>...]"), - N_("git bundle unbundle <file> [<refname>...]"), - NULL -}; +static const char builtin_bundle_usage[] = + "git bundle create <file> <git-rev-list args>\n" + " or: git bundle verify <file>\n" + " or: git bundle list-heads <file> [<refname>...]\n" + " or: git bundle unbundle <file> [<refname>...]"; -static const char * const builtin_bundle_create_usage[] = { - N_("git bundle create [<options>] <file> <git-rev-list args>"), - NULL -}; - -static const char * const builtin_bundle_verify_usage[] = { - N_("git bundle verify [<options>] <file>"), - NULL -}; - -static const char * const builtin_bundle_list_heads_usage[] = { - N_("git bundle list-heads <file> [<refname>...]"), - NULL -}; - -static const char * const builtin_bundle_unbundle_usage[] = { - N_("git bundle unbundle <file> [<refname>...]"), - NULL -}; - -static int verbose; - -static int parse_options_cmd_bundle(int argc, - const char **argv, - const char* prefix, - const char * const usagestr[], - const struct option options[], - const char **bundle_file) { - int newargc; - newargc = parse_options(argc, argv, NULL, options, usagestr, - PARSE_OPT_STOP_AT_NON_OPTION); - if (argc < 1) - usage_with_options(usagestr, options); - *bundle_file = prefix_filename(prefix, argv[0]); - return newargc; -} - -static int cmd_bundle_create(int argc, const char **argv, const char *prefix) { - int all_progress_implied = 0; - int progress = isatty(STDERR_FILENO); - struct argv_array pack_opts; - - struct option options[] = { - OPT_SET_INT('q', "quiet", &progress, - N_("do not show progress meter"), 0), - OPT_SET_INT(0, "progress", &progress, - N_("show progress meter"), 1), - OPT_SET_INT(0, "all-progress", &progress, - N_("show progress meter during object writing phase"), 2), - OPT_BOOL(0, "all-progress-implied", - &all_progress_implied, - N_("similar to --all-progress when progress meter is shown")), - OPT_END() - }; - const char* bundle_file; - - argc = parse_options_cmd_bundle(argc, argv, prefix, - builtin_bundle_create_usage, options, &bundle_file); - /* bundle internals use argv[1] as further parameters */ - - argv_array_init(&pack_opts); - if (progress == 0) - argv_array_push(&pack_opts, "--quiet"); - else if (progress == 1) - argv_array_push(&pack_opts, "--progress"); - else if (progress == 2) - argv_array_push(&pack_opts, "--all-progress"); - if (progress && all_progress_implied) - argv_array_push(&pack_opts, "--all-progress-implied"); - - if (!startup_info->have_repository) - die(_("Need a repository to create a bundle.")); - return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts); -} - -static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) { - struct bundle_header header; - int bundle_fd = -1; - int quiet = 0; - - struct option options[] = { - OPT_BOOL('q', "quiet", &quiet, - N_("do not show bundle details")), - OPT_END() - }; - const char* bundle_file; - - argc = parse_options_cmd_bundle(argc, argv, prefix, - builtin_bundle_verify_usage, options, &bundle_file); - /* bundle internals use argv[1] as further parameters */ - - memset(&header, 0, sizeof(header)); - if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) - return 1; - close(bundle_fd); - if (verify_bundle(the_repository, &header, !quiet)) - return 1; - fprintf(stderr, _("%s is okay\n"), bundle_file); - return 0; -} - -static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) { - struct bundle_header header; - int bundle_fd = -1; - - struct option options[] = { - OPT_END() - }; - const char* bundle_file; - - argc = parse_options_cmd_bundle(argc, argv, prefix, - builtin_bundle_list_heads_usage, options, &bundle_file); - /* bundle internals use argv[1] as further parameters */ - - memset(&header, 0, sizeof(header)); - if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) - return 1; - close(bundle_fd); - return !!list_bundle_refs(&header, argc, argv); -} - -static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) { +int cmd_bundle(int argc, const char **argv, const char *prefix) +{ struct bundle_header header; + const char *cmd, *bundle_file; int bundle_fd = -1; - struct option options[] = { - OPT_END() - }; - const char* bundle_file; + if (argc < 3) + usage(builtin_bundle_usage); - argc = parse_options_cmd_bundle(argc, argv, prefix, - builtin_bundle_unbundle_usage, options, &bundle_file); - /* bundle internals use argv[1] as further parameters */ + cmd = argv[1]; + bundle_file = prefix_filename(prefix, argv[2]); + argc -= 2; + argv += 2; memset(&header, 0, sizeof(header)); - if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) + if (strcmp(cmd, "create") && (bundle_fd = + read_bundle_header(bundle_file, &header)) < 0) return 1; - if (!startup_info->have_repository) - die(_("Need a repository to unbundle.")); - return !!unbundle(the_repository, &header, bundle_fd, 0) || - list_bundle_refs(&header, argc, argv); -} - -int cmd_bundle(int argc, const char **argv, const char *prefix) -{ - struct option options[] = { - OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")), - OPT_END() - }; - int result; - - argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage, - PARSE_OPT_STOP_AT_NON_OPTION); - - packet_trace_identity("bundle"); - if (argc < 2) - usage_with_options(builtin_bundle_usage, options); - - else if (!strcmp(argv[0], "create")) - result = cmd_bundle_create(argc, argv, prefix); - else if (!strcmp(argv[0], "verify")) - result = cmd_bundle_verify(argc, argv, prefix); - else if (!strcmp(argv[0], "list-heads")) - result = cmd_bundle_list_heads(argc, argv, prefix); - else if (!strcmp(argv[0], "unbundle")) - result = cmd_bundle_unbundle(argc, argv, prefix); - else { - error(_("Unknown subcommand: %s"), argv[0]); - usage_with_options(builtin_bundle_usage, options); + if (!strcmp(cmd, "verify")) { + close(bundle_fd); + if (argc != 1) { + usage(builtin_bundle_usage); + return 1; + } + if (verify_bundle(the_repository, &header, 1)) + return 1; + fprintf(stderr, _("%s is okay\n"), bundle_file); + return 0; + } + if (!strcmp(cmd, "list-heads")) { + close(bundle_fd); + return !!list_bundle_refs(&header, argc, argv); } - return result ? 1 : 0; + if (!strcmp(cmd, "create")) { + if (argc < 2) { + usage(builtin_bundle_usage); + return 1; + } + if (!startup_info->have_repository) + die(_("Need a repository to create a bundle.")); + return !!create_bundle(the_repository, bundle_file, argc, argv); + } else if (!strcmp(cmd, "unbundle")) { + if (!startup_info->have_repository) + die(_("Need a repository to unbundle.")); + return !!unbundle(the_repository, &header, bundle_fd, 0) || + list_bundle_refs(&header, argc, argv); + } else + usage(builtin_bundle_usage); } diff --git a/third_party/git/builtin/cat-file.c b/third_party/git/builtin/cat-file.c index 272f9fc6d7cb..995d47c85aad 100644 --- a/third_party/git/builtin/cat-file.c +++ b/third_party/git/builtin/cat-file.c @@ -15,7 +15,6 @@ #include "sha1-array.h" #include "packfile.h" #include "object-store.h" -#include "promisor-remote.h" struct batch_options { int enabled; @@ -262,7 +261,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, strbuf_addstr(sb, data->rest); } else if (is_atom("deltabase", atom, len)) { if (data->mark_query) - data->info.delta_base_oid = &data->delta_base_oid; + data->info.delta_base_sha1 = data->delta_base_oid.hash; else strbuf_addstr(sb, oid_to_hex(&data->delta_base_oid)); @@ -525,8 +524,8 @@ static int batch_objects(struct batch_options *opt) if (opt->all_objects) { struct object_cb_data cb; - if (has_promisor_remote()) - warning("This repository uses promisor remotes. Some objects may not be loaded."); + if (repository_format_partial_clone) + warning("This repository has extensions.partialClone set. Some objects may not be loaded."); cb.opt = opt; cb.expand = &data; diff --git a/third_party/git/builtin/check-ignore.c b/third_party/git/builtin/check-ignore.c index ea5d0ae3a6a6..599097304b77 100644 --- a/third_party/git/builtin/check-ignore.c +++ b/third_party/git/builtin/check-ignore.c @@ -32,19 +32,19 @@ static const struct option check_ignore_options[] = { OPT_END() }; -static void output_pattern(const char *path, struct path_pattern *pattern) +static void output_exclude(const char *path, struct exclude *exclude) { - char *bang = (pattern && pattern->flags & PATTERN_FLAG_NEGATIVE) ? "!" : ""; - char *slash = (pattern && pattern->flags & PATTERN_FLAG_MUSTBEDIR) ? "/" : ""; + char *bang = (exclude && exclude->flags & EXC_FLAG_NEGATIVE) ? "!" : ""; + char *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? "/" : ""; if (!nul_term_line) { if (!verbose) { write_name_quoted(path, stdout, '\n'); } else { - if (pattern) { - quote_c_style(pattern->pl->src, NULL, stdout, 0); + if (exclude) { + quote_c_style(exclude->el->src, NULL, stdout, 0); printf(":%d:%s%s%s\t", - pattern->srcpos, - bang, pattern->pattern, slash); + exclude->srcpos, + bang, exclude->pattern, slash); } else { printf("::\t"); @@ -56,11 +56,11 @@ static void output_pattern(const char *path, struct path_pattern *pattern) if (!verbose) { printf("%s%c", path, '\0'); } else { - if (pattern) + if (exclude) printf("%s%c%d%c%s%s%s%c%s%c", - pattern->pl->src, '\0', - pattern->srcpos, '\0', - bang, pattern->pattern, slash, '\0', + exclude->el->src, '\0', + exclude->srcpos, '\0', + bang, exclude->pattern, slash, '\0', path, '\0'); else printf("%c%c%c%s%c", '\0', '\0', '\0', path, '\0'); @@ -74,7 +74,7 @@ static int check_ignore(struct dir_struct *dir, const char *full_path; char *seen; int num_ignored = 0, i; - struct path_pattern *pattern; + struct exclude *exclude; struct pathspec pathspec; if (!argc) { @@ -103,18 +103,15 @@ static int check_ignore(struct dir_struct *dir, seen = find_pathspecs_matching_against_index(&pathspec, &the_index); for (i = 0; i < pathspec.nr; i++) { full_path = pathspec.items[i].match; - pattern = NULL; + exclude = NULL; if (!seen[i]) { int dtype = DT_UNKNOWN; - pattern = last_matching_pattern(dir, &the_index, + exclude = last_exclude_matching(dir, &the_index, full_path, &dtype); - if (!verbose && pattern && - pattern->flags & PATTERN_FLAG_NEGATIVE) - pattern = NULL; } - if (!quiet && (pattern || show_non_matching)) - output_pattern(pathspec.items[i].original, pattern); - if (pattern) + if (!quiet && (exclude || show_non_matching)) + output_exclude(pathspec.items[i].original, exclude); + if (exclude) num_ignored++; } free(seen); diff --git a/third_party/git/builtin/checkout.c b/third_party/git/builtin/checkout.c index d6773818b803..6123f732a2c8 100644 --- a/third_party/git/builtin/checkout.c +++ b/third_party/git/builtin/checkout.c @@ -70,8 +70,6 @@ struct checkout_opts { int checkout_worktree; const char *ignore_unmerged_opt; int ignore_unmerged; - int pathspec_file_nul; - const char *pathspec_from_file; const char *new_branch; const char *new_branch_force; @@ -128,7 +126,6 @@ static int update_some(const struct object_id *oid, struct strbuf *base, if (pos >= 0) { struct cache_entry *old = active_cache[pos]; if (ce->ce_mode == old->ce_mode && - !ce_intent_to_add(old) && oideq(&ce->oid, &old->oid)) { old->ce_flags |= CE_UPDATE; discard_cache_entry(ce); @@ -524,8 +521,6 @@ static int checkout_paths(const struct checkout_opts *opts, /* Now we are committed to check them out */ if (opts->checkout_worktree) errs |= checkout_worktree(opts); - else - remove_marked_cache_entries(&the_index, 1); /* * Allow updating the index when checking out from the index. @@ -713,11 +708,11 @@ static int merge_working_tree(const struct checkout_opts *opts, * give up or do a real merge, depending on * whether the merge flag was used. */ + struct tree *result; struct tree *work; struct tree *old_tree; struct merge_options o; struct strbuf sb = STRBUF_INIT; - struct strbuf old_commit_shortname = STRBUF_INIT; if (!opts->merge) return 1; @@ -735,6 +730,13 @@ static int merge_working_tree(const struct checkout_opts *opts, "the following files:\n%s"), sb.buf); strbuf_release(&sb); + if (repo_index_has_changes(the_repository, + get_commit_tree(old_branch_info->commit), + &sb)) + warning(_("staged changes in the following files may be lost: %s"), + sb.buf); + strbuf_release(&sb); + /* Do more real merge */ /* @@ -758,7 +760,7 @@ static int merge_working_tree(const struct checkout_opts *opts, */ init_merge_options(&o, the_repository); o.verbosity = 0; - work = write_in_core_index_as_tree(the_repository); + work = write_tree_from_memory(&o); ret = reset_tree(new_tree, opts, 1, @@ -766,25 +768,19 @@ static int merge_working_tree(const struct checkout_opts *opts, if (ret) return ret; o.ancestor = old_branch_info->name; - if (old_branch_info->name == NULL) { - strbuf_add_unique_abbrev(&old_commit_shortname, - &old_branch_info->commit->object.oid, - DEFAULT_ABBREV); - o.ancestor = old_commit_shortname.buf; - } o.branch1 = new_branch_info->name; o.branch2 = "local"; ret = merge_trees(&o, new_tree, work, - old_tree); + old_tree, + &result); if (ret < 0) exit(128); ret = reset_tree(new_tree, opts, 0, writeout_error); strbuf_release(&o.obuf); - strbuf_release(&old_commit_shortname); if (ret) return ret; } @@ -865,7 +861,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, strbuf_addf(&msg, "checkout: moving from %s to %s", old_desc ? old_desc : "(invalid)", new_branch_info->name); else - strbuf_insertstr(&msg, 0, reflog_msg); + strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg)); if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) { /* Nothing to do. */ @@ -1117,43 +1113,12 @@ static void setup_new_branch_info_and_source_tree( } } -static const char *parse_remote_branch(const char *arg, - struct object_id *rev, - int could_be_checkout_paths) -{ - int num_matches = 0; - const char *remote = unique_tracking_name(arg, rev, &num_matches); - - if (remote && could_be_checkout_paths) { - die(_("'%s' could be both a local file and a tracking branch.\n" - "Please use -- (and optionally --no-guess) to disambiguate"), - arg); - } - - if (!remote && num_matches > 1) { - if (advice_checkout_ambiguous_remote_branch_name) { - advise(_("If you meant to check out a remote tracking branch on, e.g. 'origin',\n" - "you can do so by fully qualifying the name with the --track option:\n" - "\n" - " git checkout --track origin/<name>\n" - "\n" - "If you'd like to always have checkouts of an ambiguous <name> prefer\n" - "one remote, e.g. the 'origin' remote, consider setting\n" - "checkout.defaultRemote=origin in your config.")); - } - - die(_("'%s' matched multiple (%d) remote tracking branches"), - arg, num_matches); - } - - return remote; -} - static int parse_branchname_arg(int argc, const char **argv, int dwim_new_local_branch_ok, struct branch_info *new_branch_info, struct checkout_opts *opts, - struct object_id *rev) + struct object_id *rev, + int *dwim_remotes_matched) { const char **new_branch = &opts->new_branch; int argcount = 0; @@ -1258,9 +1223,13 @@ static int parse_branchname_arg(int argc, const char **argv, recover_with_dwim = 0; if (recover_with_dwim) { - const char *remote = parse_remote_branch(arg, rev, - could_be_checkout_paths); + const char *remote = unique_tracking_name(arg, rev, + dwim_remotes_matched); if (remote) { + if (could_be_checkout_paths) + die(_("'%s' could be both a local file and a tracking branch.\n" + "Please use -- (and optionally --no-guess) to disambiguate"), + arg); *new_branch = arg; arg = remote; /* DWIMmed to create local branch, case (3).(b) */ @@ -1511,8 +1480,6 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts, OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")), OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree, N_("do not limit pathspecs to sparse entries only")), - OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&opts->pathspec_file_nul), OPT_END() }; struct option *newopts = parse_options_concat(prevopts, options); @@ -1525,6 +1492,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix, const char * const usagestr[]) { struct branch_info new_branch_info; + int dwim_remotes_matched = 0; int parseopt_flags = 0; memset(&new_branch_info, 0, sizeof(new_branch_info)); @@ -1632,7 +1600,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix, opts->track == BRANCH_TRACK_UNSPECIFIED && !opts->new_branch; int n = parse_branchname_arg(argc, argv, dwim_ok, - &new_branch_info, opts, &rev); + &new_branch_info, opts, &rev, + &dwim_remotes_matched); argv += n; argc -= n; } else if (!opts->accept_ref && opts->from_treeish) { @@ -1649,6 +1618,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix, die(_("reference is not a tree: %s"), opts->from_treeish); } + if (opts->accept_pathspec && !opts->empty_pathspec_ok && !argc && + !opts->patch_mode) /* patch mode is special */ + die(_("you must specify path(s) to restore")); + if (argc) { parse_pathspec(&opts->pathspec, 0, opts->patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0, @@ -1668,33 +1641,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix, if (opts->force_detach) die(_("git checkout: --detach does not take a path argument '%s'"), argv[0]); - } - if (opts->pathspec_from_file) { - if (opts->pathspec.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - if (opts->force_detach) - die(_("--pathspec-from-file is incompatible with --detach")); - - if (opts->patch_mode) - die(_("--pathspec-from-file is incompatible with --patch")); - - parse_pathspec_file(&opts->pathspec, 0, - 0, - prefix, opts->pathspec_from_file, opts->pathspec_file_nul); - } else if (opts->pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - - if (opts->pathspec.nr) { if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge) die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n" "checking out of the index.")); - } else { - if (opts->accept_pathspec && !opts->empty_pathspec_ok && - !opts->patch_mode) /* patch mode is special */ - die(_("you must specify path(s) to restore")); } if (opts->new_branch) { @@ -1709,10 +1659,28 @@ static int checkout_main(int argc, const char **argv, const char *prefix, } UNLEAK(opts); - if (opts->patch_mode || opts->pathspec.nr) - return checkout_paths(opts, new_branch_info.name); - else + if (opts->patch_mode || opts->pathspec.nr) { + int ret = checkout_paths(opts, new_branch_info.name); + if (ret && dwim_remotes_matched > 1 && + advice_checkout_ambiguous_remote_branch_name) + advise(_("'%s' matched more than one remote tracking branch.\n" + "We found %d remotes with a reference that matched. So we fell back\n" + "on trying to resolve the argument as a path, but failed there too!\n" + "\n" + "If you meant to check out a remote tracking branch on, e.g. 'origin',\n" + "you can do so by fully qualifying the name with the --track option:\n" + "\n" + " git checkout --track origin/<name>\n" + "\n" + "If you'd like to always have checkouts of an ambiguous <name> prefer\n" + "one remote, e.g. the 'origin' remote, consider setting\n" + "checkout.defaultRemote=origin in your config."), + argv[0], + dwim_remotes_matched); + return ret; + } else { return checkout_branch(opts, &new_branch_info); + } } int cmd_checkout(int argc, const char **argv, const char *prefix) @@ -1746,15 +1714,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) opts.checkout_index = -2; /* default on */ opts.checkout_worktree = -2; /* default on */ - if (argc == 3 && !strcmp(argv[1], "-b")) { - /* - * User ran 'git checkout -b <branch>' and expects - * the same behavior as 'git switch -c <branch>'. - */ - opts.switch_branch_doing_nothing_is_ok = 0; - opts.only_merge_on_switching_branches = 1; - } - options = parse_options_dup(checkout_options); options = add_common_options(&opts, options); options = add_common_switch_branch_options(&opts, options); diff --git a/third_party/git/builtin/clean.c b/third_party/git/builtin/clean.c index 5abf087e7c49..d5579da716e0 100644 --- a/third_party/git/builtin/clean.c +++ b/third_party/git/builtin/clean.c @@ -158,8 +158,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, *dir_gone = 1; - if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && - is_nonbare_repository_dir(path)) { + if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) { if (!quiet) { quote_path_relative(path->buf, prefix, "ed); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), @@ -649,7 +648,7 @@ static int filter_by_patterns_cmd(void) struct strbuf confirm = STRBUF_INIT; struct strbuf **ignore_list; struct string_list_item *item; - struct pattern_list *pl; + struct exclude_list *el; int changed = -1, i; for (;;) { @@ -672,7 +671,7 @@ static int filter_by_patterns_cmd(void) break; memset(&dir, 0, sizeof(dir)); - pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude"); + el = add_exclude_list(&dir, EXC_CMDL, "manual exclude"); ignore_list = strbuf_split_max(&confirm, ' ', 0); for (i = 0; ignore_list[i]; i++) { @@ -680,7 +679,7 @@ static int filter_by_patterns_cmd(void) if (!ignore_list[i]->len) continue; - add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1)); + add_exclude(ignore_list[i]->buf, "", 0, el, -(i+1)); } changed = 0; @@ -902,7 +901,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) struct pathspec pathspec; struct strbuf buf = STRBUF_INIT; struct string_list exclude_list = STRING_LIST_INIT_NODUP; - struct pattern_list *pl; + struct exclude_list *el; struct string_list_item *item; const char *qname; struct option options[] = { @@ -947,19 +946,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (force > 1) rm_flags = 0; - else - dir.flags |= DIR_SKIP_NESTED_GIT; dir.flags |= DIR_SHOW_OTHER_DIRECTORIES; - if (argc) { - /* - * Remaining args implies pathspecs specified, and we should - * recurse within those. - */ - remove_directories = 1; - } - if (remove_directories) dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS; @@ -969,9 +958,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (!ignored) setup_standard_excludes(&dir); - pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); + el = add_exclude_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) - add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1)); + add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1)); parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, @@ -1018,7 +1007,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) for_each_string_list_item(item, &del_list) { struct stat st; - strbuf_reset(&abs_path); if (prefix) strbuf_addstr(&abs_path, prefix); @@ -1052,6 +1040,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); } } + strbuf_reset(&abs_path); } strbuf_release(&abs_path); diff --git a/third_party/git/builtin/clone.c b/third_party/git/builtin/clone.c index 1ad26f4d8c81..f665b28ccccf 100644 --- a/third_party/git/builtin/clone.c +++ b/third_party/git/builtin/clone.c @@ -32,6 +32,7 @@ #include "connected.h" #include "packfile.h" #include "list-objects-filter-options.h" +#include "object-store.h" /* * Overall FIXMEs: @@ -59,7 +60,6 @@ static const char *real_git_dir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress = -1; -static int option_sparse_checkout; static enum transport_family family; static struct string_list option_config = STRING_LIST_INIT_NODUP; static struct string_list option_required_reference = STRING_LIST_INIT_NODUP; @@ -147,8 +147,6 @@ static struct option builtin_clone_options[] = { OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), OPT_BOOL(0, "remote-submodules", &option_remote_submodules, N_("any cloned submodules will use their remote-tracking branch")), - OPT_BOOL(0, "sparse", &option_sparse_checkout, - N_("initialize sparse-checkout file to include only files at root")), OPT_END() }; @@ -673,7 +671,7 @@ static void update_remote_refs(const struct ref *refs, const char *msg, struct transport *transport, int check_connectivity, - int check_refs_are_promisor_objects_only) + int check_refs_only) { const struct ref *rm = mapped_refs; @@ -682,8 +680,7 @@ static void update_remote_refs(const struct ref *refs, opt.transport = transport; opt.progress = transport->progress; - opt.check_refs_are_promisor_objects_only = - !!check_refs_are_promisor_objects_only; + opt.check_refs_only = !!check_refs_only; if (check_connected(iterate_ref_map, &rm, &opt)) die(_("remote did not send all necessary objects")); @@ -737,27 +734,6 @@ static void update_head(const struct ref *our, const struct ref *remote, } } -static int git_sparse_checkout_init(const char *repo) -{ - struct argv_array argv = ARGV_ARRAY_INIT; - int result = 0; - argv_array_pushl(&argv, "-C", repo, "sparse-checkout", "init", NULL); - - /* - * We must apply the setting in the current process - * for the later checkout to use the sparse-checkout file. - */ - core_apply_sparse_checkout = 1; - - if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { - error(_("failed to initialize sparse-checkout")); - result = 1; - } - - argv_array_clear(&argv); - return result; -} - static int checkout(int submodule_progress) { struct object_id oid; @@ -809,12 +785,12 @@ static int checkout(int submodule_progress) if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); - err |= run_hook_le(NULL, "post-checkout", oid_to_hex(&null_oid), + err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1), oid_to_hex(&oid), "1", NULL); if (!err && (option_recurse_submodules.nr > 0)) { struct argv_array args = ARGV_ARRAY_INIT; - argv_array_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL); + argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); if (option_shallow_submodules == 1) argv_array_push(&args, "--depth=1"); @@ -833,11 +809,6 @@ static int checkout(int submodule_progress) argv_array_push(&args, "--no-fetch"); } - if (option_single_branch >= 0) - argv_array_push(&args, option_single_branch ? - "--single-branch" : - "--no-single-branch"); - err = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); } @@ -929,7 +900,7 @@ static void dissociate_from_references(void) free(alternates); } -static int path_exists(const char *path) +static int dir_exists(const char *path) { struct stat sb; return !stat(path, &sb); @@ -957,6 +928,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix) struct argv_array ref_prefixes = ARGV_ARRAY_INIT; + fetch_if_missing = 0; + packet_trace_identity("clone"); argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); @@ -1009,7 +982,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) dir = guess_dir_name(repo_name, is_bundle, option_bare); strip_trailing_slashes(dir); - dest_exists = path_exists(dir); + dest_exists = dir_exists(dir); if (dest_exists && !is_empty_dir(dir)) die(_("destination path '%s' already exists and is not " "an empty directory."), dir); @@ -1020,7 +993,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) work_tree = NULL; else { work_tree = getenv("GIT_WORK_TREE"); - if (work_tree && path_exists(work_tree)) + if (work_tree && dir_exists(work_tree)) die(_("working tree '%s' already exists."), work_tree); } @@ -1048,7 +1021,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } if (real_git_dir) { - if (path_exists(real_git_dir)) + if (dir_exists(real_git_dir)) junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL; junk_git_dir = real_git_dir; } else { @@ -1134,9 +1107,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_required_reference.nr || option_optional_reference.nr) setup_reference(); - if (option_sparse_checkout && git_sparse_checkout_init(dir)) - return 1; - remote = remote_get(option_origin); strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix, @@ -1190,11 +1160,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix) transport->server_options = &server_options; if (filter_options.choice) { - const char *spec = - expand_list_objects_filter_spec(&filter_options); + struct strbuf expanded_filter_spec = STRBUF_INIT; + expand_list_objects_filter_spec(&filter_options, + &expanded_filter_spec); transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, - spec); + expanded_filter_spec.buf); transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1"); + strbuf_release(&expanded_filter_spec); } if (transport->smart_options && !deepen && !filter_options.choice) @@ -1296,6 +1268,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } junk_mode = JUNK_LEAVE_REPO; + fetch_if_missing = 1; err = checkout(submodule_progress); strbuf_release(&reflog_msg); diff --git a/third_party/git/builtin/commit-graph.c b/third_party/git/builtin/commit-graph.c index 4a70b33fb5f1..38027b83d9d8 100644 --- a/third_party/git/builtin/commit-graph.c +++ b/third_party/git/builtin/commit-graph.c @@ -8,18 +8,25 @@ #include "object-store.h" static char const * const builtin_commit_graph_usage[] = { - N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"), - N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"), + N_("git commit-graph [--object-dir <objdir>]"), + N_("git commit-graph read [--object-dir <objdir>]"), + N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"), + N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"), NULL }; static const char * const builtin_commit_graph_verify_usage[] = { - N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"), + N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"), + NULL +}; + +static const char * const builtin_commit_graph_read_usage[] = { + N_("git commit-graph read [--object-dir <objdir>]"), NULL }; static const char * const builtin_commit_graph_write_usage[] = { - N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"), + N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"), NULL }; @@ -31,32 +38,11 @@ static struct opts_commit_graph { int append; int split; int shallow; - int progress; } opts; -static struct object_directory *find_odb(struct repository *r, - const char *obj_dir) -{ - struct object_directory *odb; - char *obj_dir_real = real_pathdup(obj_dir, 1); - - prepare_alt_odb(r); - for (odb = r->objects->odb; odb; odb = odb->next) { - if (!strcmp(obj_dir_real, real_path(odb->path))) - break; - } - - free(obj_dir_real); - - if (!odb) - die(_("could not find object directory matching %s"), obj_dir); - return odb; -} - static int graph_verify(int argc, const char **argv) { struct commit_graph *graph = NULL; - struct object_directory *odb = NULL; char *graph_name; int open_ok; int fd; @@ -69,13 +55,9 @@ static int graph_verify(int argc, const char **argv) N_("The object directory to store the graph")), OPT_BOOL(0, "shallow", &opts.shallow, N_("if the commit-graph is split, only verify the tip file")), - OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")), OPT_END(), }; - trace2_cmd_mode("verify"); - - opts.progress = isatty(2); argc = parse_options(argc, argv, NULL, builtin_commit_graph_verify_options, builtin_commit_graph_verify_usage, 0); @@ -84,11 +66,8 @@ static int graph_verify(int argc, const char **argv) opts.obj_dir = get_object_directory(); if (opts.shallow) flags |= COMMIT_GRAPH_VERIFY_SHALLOW; - if (opts.progress) - flags |= COMMIT_GRAPH_WRITE_PROGRESS; - odb = find_odb(the_repository, opts.obj_dir); - graph_name = get_commit_graph_filename(odb); + graph_name = get_commit_graph_filename(opts.obj_dir); open_ok = open_commit_graph(graph_name, &fd, &st); if (!open_ok && errno != ENOENT) die_errno(_("Could not open commit-graph '%s'"), graph_name); @@ -96,9 +75,9 @@ static int graph_verify(int argc, const char **argv) FREE_AND_NULL(graph_name); if (open_ok) - graph = load_commit_graph_one_fd_st(fd, &st, odb); - else - graph = read_commit_graph_one(the_repository, odb); + graph = load_commit_graph_one_fd_st(fd, &st); + else + graph = read_commit_graph_one(the_repository, opts.obj_dir); /* Return failure if open_ok predicted success */ if (!graph) @@ -108,6 +87,64 @@ static int graph_verify(int argc, const char **argv) return verify_commit_graph(the_repository, graph, flags); } +static int graph_read(int argc, const char **argv) +{ + struct commit_graph *graph = NULL; + char *graph_name; + int open_ok; + int fd; + struct stat st; + + static struct option builtin_commit_graph_read_options[] = { + OPT_STRING(0, "object-dir", &opts.obj_dir, + N_("dir"), + N_("The object directory to store the graph")), + OPT_END(), + }; + + argc = parse_options(argc, argv, NULL, + builtin_commit_graph_read_options, + builtin_commit_graph_read_usage, 0); + + if (!opts.obj_dir) + opts.obj_dir = get_object_directory(); + + graph_name = get_commit_graph_filename(opts.obj_dir); + + open_ok = open_commit_graph(graph_name, &fd, &st); + if (!open_ok) + die_errno(_("Could not open commit-graph '%s'"), graph_name); + + graph = load_commit_graph_one_fd_st(fd, &st); + if (!graph) + return 1; + + FREE_AND_NULL(graph_name); + + printf("header: %08x %d %d %d %d\n", + ntohl(*(uint32_t*)graph->data), + *(unsigned char*)(graph->data + 4), + *(unsigned char*)(graph->data + 5), + *(unsigned char*)(graph->data + 6), + *(unsigned char*)(graph->data + 7)); + printf("num_commits: %u\n", graph->num_commits); + printf("chunks:"); + + if (graph->chunk_oid_fanout) + printf(" oid_fanout"); + if (graph->chunk_oid_lookup) + printf(" oid_lookup"); + if (graph->chunk_commit_data) + printf(" commit_metadata"); + if (graph->chunk_extra_edges) + printf(" extra_edges"); + printf("\n"); + + UNLEAK(graph); + + return 0; +} + extern int read_replace_refs; static struct split_commit_graph_opts split_opts; @@ -115,10 +152,9 @@ static int graph_write(int argc, const char **argv) { struct string_list *pack_indexes = NULL; struct string_list *commit_hex = NULL; - struct object_directory *odb = NULL; struct string_list lines; int result = 0; - enum commit_graph_write_flags flags = 0; + unsigned int flags = COMMIT_GRAPH_PROGRESS; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", &opts.obj_dir, @@ -132,7 +168,6 @@ static int graph_write(int argc, const char **argv) N_("start walk at commits listed by stdin")), OPT_BOOL(0, "append", &opts.append, N_("include all commits already in the commit-graph file")), - OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")), OPT_BOOL(0, "split", &opts.split, N_("allow writing an incremental commit-graph file")), OPT_INTEGER(0, "max-commits", &split_opts.max_commits, @@ -144,13 +179,10 @@ static int graph_write(int argc, const char **argv) OPT_END(), }; - opts.progress = isatty(2); split_opts.size_multiple = 2; split_opts.max_commits = 0; split_opts.expire_time = 0; - trace2_cmd_mode("write"); - argc = parse_options(argc, argv, NULL, builtin_commit_graph_write_options, builtin_commit_graph_write_usage, 0); @@ -160,17 +192,14 @@ static int graph_write(int argc, const char **argv) if (!opts.obj_dir) opts.obj_dir = get_object_directory(); if (opts.append) - flags |= COMMIT_GRAPH_WRITE_APPEND; + flags |= COMMIT_GRAPH_APPEND; if (opts.split) - flags |= COMMIT_GRAPH_WRITE_SPLIT; - if (opts.progress) - flags |= COMMIT_GRAPH_WRITE_PROGRESS; + flags |= COMMIT_GRAPH_SPLIT; read_replace_refs = 0; - odb = find_odb(the_repository, opts.obj_dir); if (opts.reachable) { - if (write_commit_graph_reachable(odb, flags, &split_opts)) + if (write_commit_graph_reachable(opts.obj_dir, flags, &split_opts)) return 1; return 0; } @@ -184,15 +213,13 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs) pack_indexes = &lines; - if (opts.stdin_commits) { + if (opts.stdin_commits) commit_hex = &lines; - flags |= COMMIT_GRAPH_WRITE_CHECK_OIDS; - } UNLEAK(buf); } - if (write_commit_graph(odb, + if (write_commit_graph(opts.obj_dir, pack_indexes, commit_hex, flags, @@ -222,9 +249,9 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) builtin_commit_graph_usage, PARSE_OPT_STOP_AT_NON_OPTION); - save_commit_buffer = 0; - if (argc > 0) { + if (!strcmp(argv[0], "read")) + return graph_read(argc, argv); if (!strcmp(argv[0], "verify")) return graph_verify(argc, argv); if (!strcmp(argv[0], "write")) diff --git a/third_party/git/builtin/commit.c b/third_party/git/builtin/commit.c index 7ba33a3bec48..ae7aaf6dc683 100644 --- a/third_party/git/builtin/commit.c +++ b/third_party/git/builtin/commit.c @@ -107,9 +107,9 @@ static int all, also, interactive, patch_interactive, only, amend, signoff; static int edit_flag = -1; /* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; static int config_commit_verbose = -1; /* unspecified */ -static int no_post_rewrite, allow_empty_message, pathspec_file_nul; +static int no_post_rewrite, allow_empty_message; static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg; -static char *sign_commit, *pathspec_from_file; +static char *sign_commit; /* * The default commit message cleanup mode will remove the lines @@ -343,31 +343,11 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix PATHSPEC_PREFER_FULL, prefix, argv); - if (pathspec_from_file) { - if (interactive) - die(_("--pathspec-from-file is incompatible with --interactive/--patch")); - - if (all) - die(_("--pathspec-from-file with -a does not make sense")); - - if (pathspec.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - parse_pathspec_file(&pathspec, 0, - PATHSPEC_PREFER_FULL, - prefix, pathspec_from_file, pathspec_file_nul); - } else if (pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - - if (!pathspec.nr && (also || (only && !amend && !allow_empty))) - die(_("No paths with --include/--only does not make sense.")); - if (read_cache_preload(&pathspec) < 0) die(_("index file corrupt")); if (interactive) { - char *old_index_env = NULL, *old_repo_index_file; + char *old_index_env = NULL; hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); refresh_cache_or_die(refresh_flags); @@ -375,16 +355,12 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix if (write_locked_index(&the_index, &index_lock, 0)) die(_("unable to create temporary index")); - old_repo_index_file = the_repository->index_file; - the_repository->index_file = - (char *)get_lock_file_path(&index_lock); old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT)); - setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1); + setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1); if (interactive_add(argc, argv, prefix, patch_interactive) != 0) die(_("interactive add failed")); - the_repository->index_file = old_repo_index_file; if (old_index_env && *old_index_env) setenv(INDEX_ENVIRONMENT, old_index_env, 1); else @@ -534,7 +510,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int s->nowarn = nowarn; s->is_initial = get_oid(s->reference, &oid) ? 1 : 0; if (!s->is_initial) - oidcpy(&s->oid_commit, &oid); + hashcpy(s->sha1_commit, oid.hash); s->status_format = status_format; s->ignore_submodule_arg = ignore_submodule_arg; @@ -561,7 +537,7 @@ static void export_one(const char *var, const char *s, const char *e, int hack) struct strbuf buf = STRBUF_INIT; if (hack) strbuf_addch(&buf, hack); - strbuf_add(&buf, s, e - s); + strbuf_addf(&buf, "%.*s", (int)(e - s), s); setenv(var, buf.buf, 1); strbuf_release(&buf); } @@ -968,7 +944,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix, */ if (!committable && whence != FROM_MERGE && !allow_empty && !(amend && is_a_merge(current_head))) { - s->hints = advice_status_hints; s->display_comment_prefix = old_display_comment_prefix; run_status(stdout, index_file, prefix, 0, s); if (amend) @@ -1223,6 +1198,8 @@ static int parse_and_validate_options(int argc, const char *argv[], if (also + only + all + interactive > 1) die(_("Only one of --include/--only/--all/--interactive/--patch can be used.")); + if (argc == 0 && (also || (only && !amend && !allow_empty))) + die(_("No paths with --include/--only does not make sense.")); cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor); handle_untracked_files_arg(s); @@ -1429,7 +1406,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) s.is_initial = get_oid(s.reference, &oid) ? 1 : 0; if (!s.is_initial) - oidcpy(&s.oid_commit, &oid); + hashcpy(s.sha1_commit, oid.hash); s.ignore_submodule_arg = ignore_submodule_arg; s.status_format = status_format; @@ -1486,6 +1463,28 @@ static int git_commit_config(const char *k, const char *v, void *cb) return git_status_config(k, v, s); } +int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...) +{ + struct argv_array hook_env = ARGV_ARRAY_INIT; + va_list args; + int ret; + + argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file); + + /* + * Let the hook know that no editor will be launched. + */ + if (!editor_is_used) + argv_array_push(&hook_env, "GIT_EDITOR=:"); + + va_start(args, name); + ret = run_hook_ve(hook_env.argv,name, args); + va_end(args); + argv_array_clear(&hook_env); + + return ret; +} + int cmd_commit(int argc, const char **argv, const char *prefix) { const char *argv_gc_auto[] = {"gc", "--auto", NULL}; @@ -1536,8 +1535,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "amend", &amend, N_("amend previous commit")), OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")), { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, - OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), /* end commit contents options */ OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty, @@ -1693,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) "not exceeded, and then \"git restore --staged :/\" to recover.")); if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) && - write_commit_graph_reachable(the_repository->objects->odb, 0, NULL)) + write_commit_graph_reachable(get_object_directory(), 0, NULL)) return 1; repo_rerere(the_repository, 0); diff --git a/third_party/git/builtin/config.c b/third_party/git/builtin/config.c index ee4aef6a3555..98d65bc0ad4f 100644 --- a/third_party/git/builtin/config.c +++ b/third_party/git/builtin/config.c @@ -29,11 +29,10 @@ static int use_worktree_config; static struct git_config_source given_config_source; static int actions, type; static char *default_value; -static int end_nul; +static int end_null; static int respect_includes_opt = -1; static struct config_options config_options; static int show_origin; -static int show_scope; #define ACTION_GET (1<<0) #define ACTION_GET_ALL (1<<1) @@ -152,11 +151,10 @@ static struct option builtin_config_options[] = { OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH), OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE), OPT_GROUP(N_("Other")), - OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")), + OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")), OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")), - OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")), OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")), OPT_END(), }; @@ -180,34 +178,22 @@ static void check_argc(int argc, int min, int max) static void show_config_origin(struct strbuf *buf) { - const char term = end_nul ? '\0' : '\t'; + const char term = end_null ? '\0' : '\t'; strbuf_addstr(buf, current_config_origin_type()); strbuf_addch(buf, ':'); - if (end_nul) + if (end_null) strbuf_addstr(buf, current_config_name()); else quote_c_style(current_config_name(), buf, NULL, 0); strbuf_addch(buf, term); } -static void show_config_scope(struct strbuf *buf) -{ - const char term = end_nul ? '\0' : '\t'; - const char *scope = config_scope_name(current_config_scope()); - - strbuf_addstr(buf, N_(scope)); - strbuf_addch(buf, term); -} - static int show_all_config(const char *key_, const char *value_, void *cb) { - if (show_origin || show_scope) { + if (show_origin) { struct strbuf buf = STRBUF_INIT; - if (show_scope) - show_config_scope(&buf); - if (show_origin) - show_config_origin(&buf); + show_config_origin(&buf); /* Use fwrite as "buf" can contain \0's if "end_null" is set. */ fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf); @@ -227,8 +213,6 @@ struct strbuf_list { static int format_config(struct strbuf *buf, const char *key_, const char *value_) { - if (show_scope) - show_config_scope(buf); if (show_origin) show_config_origin(buf); if (show_keys) @@ -638,7 +622,6 @@ int cmd_config(int argc, const char **argv, const char *prefix) !strcmp(given_config_source.file, "-")) { given_config_source.file = NULL; given_config_source.use_stdin = 1; - given_config_source.scope = CONFIG_SCOPE_COMMAND; } if (use_global_config) { @@ -654,8 +637,6 @@ int cmd_config(int argc, const char **argv, const char *prefix) */ die(_("$HOME not set")); - given_config_source.scope = CONFIG_SCOPE_GLOBAL; - if (access_or_warn(user_config, R_OK, 0) && xdg_config && !access_or_warn(xdg_config, R_OK, 0)) { given_config_source.file = xdg_config; @@ -665,13 +646,11 @@ int cmd_config(int argc, const char **argv, const char *prefix) free(xdg_config); } } - else if (use_system_config) { + else if (use_system_config) given_config_source.file = git_etc_gitconfig(); - given_config_source.scope = CONFIG_SCOPE_SYSTEM; - } else if (use_local_config) { + else if (use_local_config) given_config_source.file = git_pathdup("config"); - given_config_source.scope = CONFIG_SCOPE_LOCAL; - } else if (use_worktree_config) { + else if (use_worktree_config) { struct worktree **worktrees = get_worktrees(0); if (repository_format_worktree_config) given_config_source.file = git_pathdup("config.worktree"); @@ -683,18 +662,13 @@ int cmd_config(int argc, const char **argv, const char *prefix) "section in \"git help worktree\" for details")); else given_config_source.file = git_pathdup("config"); - given_config_source.scope = CONFIG_SCOPE_LOCAL; free_worktrees(worktrees); } else if (given_config_source.file) { if (!is_absolute_path(given_config_source.file) && prefix) given_config_source.file = prefix_filename(prefix, given_config_source.file); - given_config_source.scope = CONFIG_SCOPE_COMMAND; - } else if (given_config_source.blob) { - given_config_source.scope = CONFIG_SCOPE_COMMAND; } - if (respect_includes_opt == -1) config_options.respect_includes = !given_config_source.file; else @@ -704,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) config_options.git_dir = get_git_dir(); } - if (end_nul) { + if (end_null) { term = '\0'; delim = '\n'; key_delim = '\n'; diff --git a/third_party/git/builtin/describe.c b/third_party/git/builtin/describe.c index 420f4c6401b6..200154297d5e 100644 --- a/third_party/git/builtin/describe.c +++ b/third_party/git/builtin/describe.c @@ -15,6 +15,7 @@ #include "argv-array.h" #include "run-command.h" #include "object-store.h" +#include "revision.h" #include "list-objects.h" #include "commit-slab.h" @@ -63,22 +64,19 @@ static const char *prio_names[] = { }; static int commit_name_neq(const void *unused_cmp_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *entry, + const void *entry_or_key, const void *peeled) { - const struct commit_name *cn1, *cn2; - - cn1 = container_of(eptr, const struct commit_name, entry); - cn2 = container_of(entry_or_key, const struct commit_name, entry); + const struct commit_name *cn1 = entry; + const struct commit_name *cn2 = entry_or_key; return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled); } static inline struct commit_name *find_commit_name(const struct object_id *peeled) { - return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled, - struct commit_name, entry); + return hashmap_get_from_hash(&names, oidhash(peeled), peeled); } static int replace_name(struct commit_name *e, @@ -125,8 +123,8 @@ static void add_to_known_names(const char *path, if (!e) { e = xmalloc(sizeof(struct commit_name)); oidcpy(&e->peeled, peeled); - hashmap_entry_init(&e->entry, oidhash(peeled)); - hashmap_add(&names, &e->entry); + hashmap_entry_init(e, oidhash(peeled)); + hashmap_add(&names, e); e->path = NULL; } e->tag = tag; @@ -315,7 +313,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) */ append_name(n, dst); if (longformat) - append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst); + append_suffix(0, n->tag ? &n->tag->tagged->oid : oid, dst); if (suffix) strbuf_addstr(dst, suffix); return; @@ -332,8 +330,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) struct commit_name *n; init_commit_names(&commit_names); - hashmap_for_each_entry(&names, &iter, n, - entry /* member name */) { + n = hashmap_iter_first(&names, &iter); + for (; n; n = hashmap_iter_next(&iter)) { c = lookup_commit_reference_gently(the_repository, &n->peeled, 1); if (c) @@ -376,25 +374,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) if (!(c->object.flags & t->flag_within)) t->depth++; } - /* Stop if last remaining path already covered by best candidate(s) */ if (annotated_cnt && !list) { - int best_depth = INT_MAX; - unsigned best_within = 0; - for (cur_match = 0; cur_match < match_cnt; cur_match++) { - struct possible_tag *t = &all_matches[cur_match]; - if (t->depth < best_depth) { - best_depth = t->depth; - best_within = t->flag_within; - } else if (t->depth == best_depth) { - best_within |= t->flag_within; - } - } - if ((c->object.flags & best_within) == best_within) { - if (debug) - fprintf(stderr, _("finished search at %s\n"), - oid_to_hex(&c->object.oid)); - break; - } + if (debug) + fprintf(stderr, _("finished search at %s\n"), + oid_to_hex(&c->object.oid)); + break; } while (parents) { struct commit *p = parents->item; diff --git a/third_party/git/builtin/difftool.c b/third_party/git/builtin/difftool.c index c280e682b2ae..16eb8b70ea33 100644 --- a/third_party/git/builtin/difftool.c +++ b/third_party/git/builtin/difftool.c @@ -125,15 +125,12 @@ struct working_tree_entry { }; static int working_tree_entry_cmp(const void *unused_cmp_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *entry, + const void *entry_or_key, const void *unused_keydata) { - const struct working_tree_entry *a, *b; - - a = container_of(eptr, const struct working_tree_entry, entry); - b = container_of(entry_or_key, const struct working_tree_entry, entry); - + const struct working_tree_entry *a = entry; + const struct working_tree_entry *b = entry_or_key; return strcmp(a->path, b->path); } @@ -148,14 +145,12 @@ struct pair_entry { }; static int pair_cmp(const void *unused_cmp_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *entry, + const void *entry_or_key, const void *unused_keydata) { - const struct pair_entry *a, *b; - - a = container_of(eptr, const struct pair_entry, entry); - b = container_of(entry_or_key, const struct pair_entry, entry); + const struct pair_entry *a = entry; + const struct pair_entry *b = entry_or_key; return strcmp(a->path, b->path); } @@ -166,14 +161,14 @@ static void add_left_or_right(struct hashmap *map, const char *path, struct pair_entry *e, *existing; FLEX_ALLOC_STR(e, path, path); - hashmap_entry_init(&e->entry, strhash(path)); - existing = hashmap_get_entry(map, e, entry, NULL); + hashmap_entry_init(e, strhash(path)); + existing = hashmap_get(map, e, NULL); if (existing) { free(e); e = existing; } else { e->left[0] = e->right[0] = '\0'; - hashmap_add(map, &e->entry); + hashmap_add(map, e); } strlcpy(is_right ? e->right : e->left, content, PATH_MAX); } @@ -184,14 +179,12 @@ struct path_entry { }; static int path_entry_cmp(const void *unused_cmp_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *entry, + const void *entry_or_key, const void *key) { - const struct path_entry *a, *b; - - a = container_of(eptr, const struct path_entry, entry); - b = container_of(entry_or_key, const struct path_entry, entry); + const struct path_entry *a = entry; + const struct path_entry *b = entry_or_key; return strcmp(a->path, key ? key : b->path); } @@ -241,8 +234,8 @@ static void changed_files(struct hashmap *result, const char *index_path, while (!strbuf_getline_nul(&buf, fp)) { struct path_entry *entry; FLEX_ALLOC_STR(entry, path, buf.buf); - hashmap_entry_init(&entry->entry, strhash(buf.buf)); - hashmap_add(result, &entry->entry); + hashmap_entry_init(entry, strhash(buf.buf)); + hashmap_add(result, entry); } fclose(fp); if (finish_command(&diff_files)) @@ -468,13 +461,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, /* Avoid duplicate working_tree entries */ FLEX_ALLOC_STR(entry, path, dst_path); - hashmap_entry_init(&entry->entry, strhash(dst_path)); - if (hashmap_get(&working_tree_dups, &entry->entry, - NULL)) { + hashmap_entry_init(entry, strhash(dst_path)); + if (hashmap_get(&working_tree_dups, entry, NULL)) { free(entry); continue; } - hashmap_add(&working_tree_dups, &entry->entry); + hashmap_add(&working_tree_dups, entry); if (!use_wt_file(workdir, dst_path, &roid)) { if (checkout_path(rmode, &roid, dst_path, @@ -538,8 +530,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, * temporary file to both the left and right directories to show the * change in the recorded SHA1 for the submodule. */ - hashmap_for_each_entry(&submodules, &iter, entry, - entry /* member name */) { + hashmap_iter_init(&submodules, &iter); + while ((entry = hashmap_iter_next(&iter))) { if (*entry->left) { add_path(&ldir, ldir_len, entry->path); ensure_leading_directories(ldir.buf); @@ -557,8 +549,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, * shows only the link itself, not the contents of the link target. * This loop replicates that behavior. */ - hashmap_for_each_entry(&symlinks2, &iter, entry, - entry /* member name */) { + hashmap_iter_init(&symlinks2, &iter); + while ((entry = hashmap_iter_next(&iter))) { if (*entry->left) { add_path(&ldir, ldir_len, entry->path); ensure_leading_directories(ldir.buf); diff --git a/third_party/git/builtin/fast-export.c b/third_party/git/builtin/fast-export.c index 85868162eec9..f541f55d333b 100644 --- a/third_party/git/builtin/fast-export.c +++ b/third_party/git/builtin/fast-export.c @@ -40,7 +40,6 @@ static int no_data; static int full_tree; static int reference_excluded_commits; static int show_original_ids; -static int mark_tags; static struct string_list extra_refs = STRING_LIST_INIT_NODUP; static struct string_list tag_refs = STRING_LIST_INIT_NODUP; static struct refspec refspecs = REFSPEC_INIT_FETCH; @@ -127,15 +126,10 @@ struct anonymized_entry { }; static int anonymized_entry_cmp(const void *unused_cmp_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *va, const void *vb, const void *unused_keydata) { - const struct anonymized_entry *a, *b; - - a = container_of(eptr, const struct anonymized_entry, hash); - b = container_of(entry_or_key, const struct anonymized_entry, hash); - + const struct anonymized_entry *a = va, *b = vb; return a->orig_len != b->orig_len || memcmp(a->orig, b->orig, a->orig_len); } @@ -154,10 +148,10 @@ static const void *anonymize_mem(struct hashmap *map, if (!map->cmpfn) hashmap_init(map, anonymized_entry_cmp, NULL, 0); - hashmap_entry_init(&key.hash, memhash(orig, *len)); + hashmap_entry_init(&key, memhash(orig, *len)); key.orig = orig; key.orig_len = *len; - ret = hashmap_get_entry(map, &key, hash, NULL); + ret = hashmap_get(map, &key, NULL); if (!ret) { ret = xmalloc(sizeof(*ret)); @@ -166,7 +160,7 @@ static const void *anonymize_mem(struct hashmap *map, ret->orig_len = *len; ret->anon = generate(orig, len); ret->anon_len = *len; - hashmap_put(map, &ret->hash); + hashmap_put(map, ret); } *len = ret->anon_len; @@ -293,8 +287,7 @@ static void export_blob(const struct object_id *oid) buf = read_object_file(oid, &type, &size); if (!buf) die("could not read blob %s", oid_to_hex(oid)); - if (check_object_signature(the_repository, oid, buf, size, - type_name(type)) < 0) + if (check_object_signature(oid, buf, size, type_name(type)) < 0) die("oid mismatch in blob %s", oid_to_hex(oid)); object = parse_object_buffer(the_repository, oid, type, size, buf, &eaten); @@ -849,39 +842,25 @@ static void handle_tag(const char *name, struct tag *tag) free(buf); return; case REWRITE: - if (tagged->type == OBJ_TAG && !mark_tags) { - die(_("Error: Cannot export nested tags unless --mark-tags is specified.")); - } else if (tagged->type == OBJ_COMMIT) { - p = rewrite_commit((struct commit *)tagged); - if (!p) { - printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(&null_oid)); - free(buf); - return; - } - tagged_mark = get_object_mark(&p->object); - } else { - /* tagged->type is either OBJ_BLOB or OBJ_TAG */ - tagged_mark = get_object_mark(tagged); + if (tagged->type != OBJ_COMMIT) { + die("tag %s tags unexported %s!", + oid_to_hex(&tag->object.oid), + type_name(tagged->type)); + } + p = rewrite_commit((struct commit *)tagged); + if (!p) { + printf("reset %s\nfrom %s\n\n", + name, oid_to_hex(&null_oid)); + free(buf); + return; } + tagged_mark = get_object_mark(&p->object); } } - if (tagged->type == OBJ_TAG) { - printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(&null_oid)); - } - skip_prefix(name, "refs/tags/", &name); - printf("tag %s\n", name); - if (mark_tags) { - mark_next_object(&tag->object); - printf("mark :%"PRIu32"\n", last_idnum); - } - if (tagged_mark) - printf("from :%d\n", tagged_mark); - else - printf("from %s\n", oid_to_hex(&tagged->oid)); - + if (starts_with(name, "refs/tags/")) + name += 10; + printf("tag %s\nfrom :%d\n", name, tagged_mark); if (show_original_ids) printf("original-oid %s\n", oid_to_hex(&tag->object.oid)); printf("%.*s%sdata %d\n%.*s\n", @@ -1068,16 +1047,11 @@ static void export_marks(char *file) error("Unable to write marks file %s.", file); } -static void import_marks(char *input_file, int check_exists) +static void import_marks(char *input_file) { char line[512]; - FILE *f; - struct stat sb; - - if (check_exists && stat(input_file, &sb)) - return; + FILE *f = xfopen(input_file, "r"); - f = xfopen(input_file, "r"); while (fgets(line, sizeof(line), f)) { uint32_t mark; char *line_end, *mark_end; @@ -1141,9 +1115,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) struct rev_info revs; struct object_array commits = OBJECT_ARRAY_INIT; struct commit *commit; - char *export_filename = NULL, - *import_filename = NULL, - *import_filename_if_exists = NULL; + char *export_filename = NULL, *import_filename = NULL; uint32_t lastimportid; struct string_list refspecs_list = STRING_LIST_INIT_NODUP; struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP; @@ -1163,10 +1135,6 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) N_("Dump marks to this file")), OPT_STRING(0, "import-marks", &import_filename, N_("file"), N_("Import marks from this file")), - OPT_STRING(0, "import-marks-if-exists", - &import_filename_if_exists, - N_("file"), - N_("Import marks from this file if it exists")), OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger, N_("Fake a tagger when tags lack one")), OPT_BOOL(0, "full-tree", &full_tree, @@ -1181,8 +1149,6 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) &reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")), OPT_BOOL(0, "show-original-ids", &show_original_ids, N_("Show original object ids of blobs/commits")), - OPT_BOOL(0, "mark-tags", &mark_tags, - N_("Label tags with mark ids")), OPT_END() }; @@ -1216,12 +1182,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) if (use_done_feature) printf("feature done\n"); - if (import_filename && import_filename_if_exists) - die(_("Cannot pass both --import-marks and --import-marks-if-exists")); if (import_filename) - import_marks(import_filename, 0); - else if (import_filename_if_exists) - import_marks(import_filename_if_exists, 1); + import_marks(import_filename); lastimportid = last_idnum; if (import_filename && revs.prune_data.nr) diff --git a/third_party/git/builtin/fetch.c b/third_party/git/builtin/fetch.c index bf6bab80fab9..717dd14e8961 100644 --- a/third_party/git/builtin/fetch.c +++ b/third_party/git/builtin/fetch.c @@ -7,7 +7,6 @@ #include "refs.h" #include "refspec.h" #include "object-store.h" -#include "oidset.h" #include "commit.h" #include "builtin.h" #include "string-list.h" @@ -24,9 +23,6 @@ #include "packfile.h" #include "list-objects-filter-options.h" #include "commit-reach.h" -#include "branch.h" -#include "promisor-remote.h" -#include "commit-graph.h" #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000) @@ -54,13 +50,11 @@ 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 verbosity, deepen_relative, set_upstream; +static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative; 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 max_children = 1; static enum transport_family family; static const char *depth; static const char *deepen_since; @@ -77,7 +71,6 @@ static struct refspec refmap = REFSPEC_INIT_FETCH; static struct list_objects_filter_options filter_options; 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 git_fetch_config(const char *k, const char *v, void *cb) { @@ -103,20 +96,13 @@ static int git_fetch_config(const char *k, const char *v, void *cb) } if (!strcmp(k, "submodule.fetchjobs")) { - submodule_fetch_jobs_config = parse_submodule_fetchjobs(k, v); + max_children = parse_submodule_fetchjobs(k, v); return 0; } else if (!strcmp(k, "fetch.recursesubmodules")) { 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) - die(_("fetch.parallel cannot be negative")); - return 0; - } - return git_default_config(k, v, cb); } @@ -137,8 +123,6 @@ 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_STRING(0, "upload-pack", &upload_pack, N_("path"), @@ -150,7 +134,7 @@ static struct option builtin_fetch_options[] = { 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, + OPT_INTEGER('j', "jobs", &max_children, N_("number of submodules fetched in parallel")), OPT_BOOL('p', "prune", &prune, N_("prune remote-tracking branches no longer on remote")), @@ -199,8 +183,6 @@ static struct option builtin_fetch_options[] = { N_("run 'gc --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_END() }; @@ -257,31 +239,32 @@ static void add_merge_config(struct ref **head, } } -static void create_fetch_oidset(struct ref **head, struct oidset *out) +static int will_fetch(struct ref **head, const unsigned char *sha1) { struct ref *rm = *head; while (rm) { - oidset_insert(out, &rm->old_oid); + if (hasheq(rm->old_oid.hash, sha1)) + return 1; rm = rm->next; } + return 0; } struct refname_hash_entry { - struct hashmap_entry ent; + struct hashmap_entry ent; /* must be the first member */ struct object_id oid; int ignore; char refname[FLEX_ARRAY]; }; static int refname_hash_entry_cmp(const void *hashmap_cmp_fn_data, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, + const void *e1_, + const void *e2_, const void *keydata) { - const struct refname_hash_entry *e1, *e2; + const struct refname_hash_entry *e1 = e1_; + const struct refname_hash_entry *e2 = e2_; - e1 = container_of(eptr, const struct refname_hash_entry, ent); - e2 = container_of(entry_or_key, const struct refname_hash_entry, ent); return strcmp(e1->refname, keydata ? keydata : e2->refname); } @@ -293,9 +276,9 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map, size_t len = strlen(refname); FLEX_ALLOC_MEM(ent, refname, refname, len); - hashmap_entry_init(&ent->ent, strhash(refname)); + hashmap_entry_init(ent, strhash(refname)); oidcpy(&ent->oid, oid); - hashmap_add(map, &ent->ent); + hashmap_add(map, ent); return ent; } @@ -330,16 +313,13 @@ static void find_non_local_tags(const struct ref *refs, { struct hashmap existing_refs; struct hashmap remote_refs; - struct oidset fetch_oids = OIDSET_INIT; struct string_list remote_refs_list = STRING_LIST_INIT_NODUP; struct string_list_item *remote_ref_item; const struct ref *ref; struct refname_hash_entry *item = NULL; - const int quick_flags = OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT; refname_hash_init(&existing_refs); refname_hash_init(&remote_refs); - create_fetch_oidset(head, &fetch_oids); for_each_ref(add_one_refname, &existing_refs); for (ref = refs; ref; ref = ref->next) { @@ -354,10 +334,11 @@ static void find_non_local_tags(const struct ref *refs, */ if (ends_with(ref->name, "^{}")) { if (item && - !has_object_file_with_flags(&ref->old_oid, quick_flags) && - !oidset_contains(&fetch_oids, &ref->old_oid) && - !has_object_file_with_flags(&item->oid, quick_flags) && - !oidset_contains(&fetch_oids, &item->oid)) + !has_object_file_with_flags(&ref->old_oid, + OBJECT_INFO_QUICK) && + !will_fetch(head, ref->old_oid.hash) && + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && + !will_fetch(head, item->oid.hash)) clear_item(item); item = NULL; continue; @@ -370,8 +351,8 @@ static void find_non_local_tags(const struct ref *refs, * fetch. */ if (item && - !has_object_file_with_flags(&item->oid, quick_flags) && - !oidset_contains(&fetch_oids, &item->oid)) + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && + !will_fetch(head, item->oid.hash)) clear_item(item); item = NULL; @@ -384,15 +365,15 @@ static void find_non_local_tags(const struct ref *refs, item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid); string_list_insert(&remote_refs_list, ref->name); } - hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent); + hashmap_free(&existing_refs, 1); /* * We may have a final lightweight tag that needs to be * checked to see if it needs fetching. */ if (item && - !has_object_file_with_flags(&item->oid, quick_flags) && - !oidset_contains(&fetch_oids, &item->oid)) + !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && + !will_fetch(head, item->oid.hash)) clear_item(item); /* @@ -402,10 +383,8 @@ static void find_non_local_tags(const struct ref *refs, for_each_string_list_item(remote_ref_item, &remote_refs_list) { const char *refname = remote_ref_item->string; struct ref *rm; - unsigned int hash = strhash(refname); - item = hashmap_get_entry_from_hash(&remote_refs, hash, refname, - struct refname_hash_entry, ent); + item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname); if (!item) BUG("unseen remote ref?"); @@ -419,9 +398,8 @@ static void find_non_local_tags(const struct ref *refs, **tail = rm; *tail = &rm->next; } - hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent); + hashmap_free(&remote_refs, 1); string_list_clear(&remote_refs_list, 0); - oidset_clear(&fetch_oids); } static struct ref *get_ref_map(struct remote *remote, @@ -538,18 +516,17 @@ static struct ref *get_ref_map(struct remote *remote, if (rm->peer_ref) { const char *refname = rm->peer_ref->name; struct refname_hash_entry *peer_item; - unsigned int hash = strhash(refname); - peer_item = hashmap_get_entry_from_hash(&existing_refs, - hash, refname, - struct refname_hash_entry, ent); + peer_item = hashmap_get_from_hash(&existing_refs, + strhash(refname), + refname); if (peer_item) { struct object_id *old_oid = &peer_item->oid; oidcpy(&rm->peer_ref->old_oid, old_oid); } } } - hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent); + hashmap_free(&existing_refs, 1); return ref_map; } @@ -906,17 +883,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, url = xstrdup("foreign"); if (!connectivity_checked) { - struct check_connected_options opt = CHECK_CONNECTED_INIT; - - if (filter_options.choice) - /* - * Since a filter is specified, objects indirectly - * referenced by refs are allowed to be absent. - */ - opt.check_refs_are_promisor_objects_only = 1; - rm = ref_map; - if (check_connected(iterate_ref_map, &rm, &opt)) { + if (check_connected(iterate_ref_map, &rm, NULL)) { rc = error(_("%s did not send all necessary objects\n"), url); goto abort; } @@ -966,12 +934,18 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, kind = ""; what = ""; } - else if (skip_prefix(rm->name, "refs/heads/", &what)) + else if (starts_with(rm->name, "refs/heads/")) { kind = "branch"; - else if (skip_prefix(rm->name, "refs/tags/", &what)) + what = rm->name + 11; + } + else if (starts_with(rm->name, "refs/tags/")) { kind = "tag"; - else if (skip_prefix(rm->name, "refs/remotes/", &what)) + what = rm->name + 10; + } + else if (starts_with(rm->name, "refs/remotes/")) { kind = "remote-tracking branch"; + what = rm->name + 13; + } else { kind = ""; what = rm->name; @@ -1080,8 +1054,7 @@ static int check_exist_and_connected(struct ref *ref_map) * we need all direct targets to exist. */ for (r = rm; r; r = r->next) { - if (!has_object_file_with_flags(&r->old_oid, - OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (!has_object_file(&r->old_oid)) return -1; } @@ -1092,11 +1065,8 @@ static int check_exist_and_connected(struct ref *ref_map) static int fetch_refs(struct transport *transport, struct ref *ref_map) { int ret = check_exist_and_connected(ref_map); - if (ret) { - trace2_region_enter("fetch", "fetch_refs", the_repository); + if (ret) ret = transport_fetch_refs(transport, ref_map); - trace2_region_leave("fetch", "fetch_refs", the_repository); - } if (!ret) /* * Keep the new pack's ".keep" file around to allow the caller @@ -1112,14 +1082,11 @@ static int consume_refs(struct transport *transport, struct ref *ref_map) { int connectivity_checked = transport->smart_options ? transport->smart_options->connectivity_checked : 0; - int ret; - trace2_region_enter("fetch", "consume_refs", the_repository); - ret = store_updated_refs(transport->url, - transport->remote->name, - connectivity_checked, - ref_map); + int ret = store_updated_refs(transport->url, + transport->remote->name, + connectivity_checked, + ref_map); transport_unlock_pack(transport); - trace2_region_leave("fetch", "consume_refs", the_repository); return ret; } @@ -1271,10 +1238,13 @@ static struct transport *prepare_transport(struct remote *remote, int deepen) if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); if (filter_options.choice) { - const char *spec = - expand_list_objects_filter_spec(&filter_options); - set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, spec); + struct strbuf expanded_filter_spec = STRBUF_INIT; + expand_list_objects_filter_spec(&filter_options, + &expanded_filter_spec); + set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, + expanded_filter_spec.buf); set_option(transport, TRANS_OPT_FROM_PROMISOR, "1"); + strbuf_release(&expanded_filter_spec); } if (negotiation_tip.nr) { if (transport->smart_options) @@ -1364,11 +1334,9 @@ static int do_fetch(struct transport *transport, argv_array_push(&ref_prefixes, "refs/tags/"); } - if (must_list_refs) { - trace2_region_enter("fetch", "remote_refs", the_repository); + if (must_list_refs) remote_refs = transport_get_remote_refs(transport, &ref_prefixes); - trace2_region_leave("fetch", "remote_refs", the_repository); - } else + else remote_refs = NULL; argv_array_clear(&ref_prefixes); @@ -1399,51 +1367,6 @@ static int do_fetch(struct transport *transport, retcode = 1; goto cleanup; } - - if (set_upstream) { - struct branch *branch = branch_get("HEAD"); - struct ref *rm; - struct ref *source_ref = NULL; - - /* - * We're setting the upstream configuration for the - * current branch. The relevant upstream is the - * fetched branch that is meant to be merged with the - * current one, i.e. the one fetched to FETCH_HEAD. - * - * When there are several such branches, consider the - * request ambiguous and err on the safe side by doing - * nothing and just emit a warning. - */ - for (rm = ref_map; rm; rm = rm->next) { - if (!rm->peer_ref) { - if (source_ref) { - warning(_("multiple branches detected, incompatible with --set-upstream")); - goto skip; - } else { - source_ref = rm; - } - } - } - if (source_ref) { - if (!strcmp(source_ref->name, "HEAD") || - starts_with(source_ref->name, "refs/heads/")) - install_branch_config(0, - branch->name, - transport->remote->name, - source_ref->name); - else if (starts_with(source_ref->name, "refs/remotes/")) - warning(_("not setting upstream for a remote remote-tracking branch")); - else if (starts_with(source_ref->name, "refs/tags/")) - warning(_("not setting upstream for a remote tag")); - else - warning(_("unknown branch type")); - } else { - warning(_("no source branch found.\n" - "you need to specify exactly one branch with the --set-upstream option.")); - } - } - skip: free_refs(ref_map); /* if neither --no-tags nor --tags was specified, do automated tag @@ -1540,62 +1463,7 @@ static void add_options_to_argv(struct argv_array *argv) } -/* Fetch multiple remotes in parallel */ - -struct parallel_fetch_state { - const char **argv; - struct string_list *remotes; - int next, result; -}; - -static int fetch_next_remote(struct child_process *cp, struct strbuf *out, - void *cb, void **task_cb) -{ - struct parallel_fetch_state *state = cb; - char *remote; - - if (state->next < 0 || state->next >= state->remotes->nr) - return 0; - - remote = state->remotes->items[state->next++].string; - *task_cb = remote; - - argv_array_pushv(&cp->args, state->argv); - argv_array_push(&cp->args, remote); - cp->git_cmd = 1; - - if (verbosity >= 0) - printf(_("Fetching %s\n"), remote); - - return 1; -} - -static int fetch_failed_to_start(struct strbuf *out, void *cb, void *task_cb) -{ - struct parallel_fetch_state *state = cb; - const char *remote = task_cb; - - state->result = error(_("Could not fetch %s"), remote); - - return 0; -} - -static int fetch_finished(int result, struct strbuf *out, - void *cb, void *task_cb) -{ - struct parallel_fetch_state *state = cb; - const char *remote = task_cb; - - if (result) { - strbuf_addf(out, _("could not fetch '%s' (exit code: %d)\n"), - remote, result); - state->result = -1; - } - - return 0; -} - -static int fetch_multiple(struct string_list *list, int max_children) +static int fetch_multiple(struct string_list *list) { int i, result = 0; struct argv_array argv = ARGV_ARRAY_INIT; @@ -1606,38 +1474,23 @@ static int fetch_multiple(struct string_list *list, int max_children) return errcode; } - argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc", - "--no-write-commit-graph", NULL); + argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc", NULL); add_options_to_argv(&argv); - if (max_children != 1 && list->nr != 1) { - struct parallel_fetch_state state = { argv.argv, list, 0, 0 }; - - argv_array_push(&argv, "--end-of-options"); - result = run_processes_parallel_tr2(max_children, - &fetch_next_remote, - &fetch_failed_to_start, - &fetch_finished, - &state, - "fetch", "parallel/fetch"); - - if (!result) - result = state.result; - } else - for (i = 0; i < list->nr; i++) { - const char *name = list->items[i].string; - argv_array_push(&argv, name); - if (verbosity >= 0) - printf(_("Fetching %s\n"), name); - if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { - error(_("Could not fetch %s"), name); - result = 1; - } - argv_array_pop(&argv); + for (i = 0; i < list->nr; i++) { + const char *name = list->items[i].string; + argv_array_push(&argv, name); + if (verbosity >= 0) + printf(_("Fetching %s\n"), name); + if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { + error(_("Could not fetch %s"), name); + result = 1; } + argv_array_pop(&argv); + } argv_array_clear(&argv); - return !!result; + return result; } /* @@ -1657,27 +1510,37 @@ static inline void fetch_one_setup_partial(struct remote *remote) * If no prior partial clone/fetch and the current fetch DID NOT * request a partial-fetch, do a normal fetch. */ - if (!has_promisor_remote() && !filter_options.choice) + if (!repository_format_partial_clone && !filter_options.choice) return; /* - * If this is a partial-fetch request, we enable partial on - * this repo if not already enabled and remember the given - * filter-spec as the default for subsequent fetches to this - * remote. + * If this is the FIRST partial-fetch request, we enable partial + * on this repo and remember the given filter-spec as the default + * for subsequent fetches to this remote. */ - if (filter_options.choice) { + if (!repository_format_partial_clone && filter_options.choice) { partial_clone_register(remote->name, &filter_options); return; } /* + * We are currently limited to only ONE promisor remote and only + * allow partial-fetches from the promisor remote. + */ + if (strcmp(remote->name, repository_format_partial_clone)) { + if (filter_options.choice) + die(_("--filter can only be used with the remote " + "configured in extensions.partialClone")); + return; + } + + /* * Do a partial-fetch from the promisor remote using either the * explicitly given filter-spec or inherit the filter-spec from * the config. */ if (!filter_options.choice) - partial_clone_get_default_filter_spec(&filter_options, remote->name); + partial_clone_get_default_filter_spec(&filter_options); return; } @@ -1763,13 +1626,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) packet_trace_identity("fetch"); + fetch_if_missing = 0; + /* Record the command line for the reflog */ strbuf_addstr(&default_rla, "fetch"); for (i = 1; i < argc; i++) strbuf_addf(&default_rla, " %s", argv[i]); - fetch_config_from_gitmodules(&submodule_fetch_jobs_config, - &recurse_submodules); + fetch_config_from_gitmodules(&max_children, &recurse_submodules); git_config(git_fetch_config, NULL); argc = parse_options(argc, argv, prefix, @@ -1797,7 +1661,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (depth || deepen_since || deepen_not.nr) deepen = 1; - if (filter_options.choice && !has_promisor_remote()) + if (filter_options.choice && !repository_format_partial_clone) die("--filter can only be used when extensions.partialClone is set"); if (all) { @@ -1831,31 +1695,19 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } if (remote) { - if (filter_options.choice || has_promisor_remote()) + if (filter_options.choice || repository_format_partial_clone) fetch_one_setup_partial(remote); result = fetch_one(remote, argc, argv, prune_tags_ok); } else { - int max_children = max_jobs; - if (filter_options.choice) die(_("--filter can only be used with the remote " "configured in extensions.partialclone")); - - if (max_children < 0) - max_children = fetch_parallel_config; - /* TODO should this also die if we have a previous partial-clone? */ - result = fetch_multiple(&list, max_children); + result = fetch_multiple(&list); } if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { struct argv_array options = ARGV_ARRAY_INIT; - int max_children = max_jobs; - - if (max_children < 0) - max_children = submodule_fetch_jobs_config; - if (max_children < 0) - max_children = fetch_parallel_config; add_options_to_argv(&options); result = fetch_populated_submodules(the_repository, @@ -1870,20 +1722,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) string_list_clear(&list, 0); - prepare_repo_settings(the_repository); - if (fetch_write_commit_graph > 0 || - (fetch_write_commit_graph < 0 && - the_repository->settings.fetch_write_commit_graph)) { - int commit_graph_flags = COMMIT_GRAPH_WRITE_SPLIT; - - if (progress) - commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS; - - write_commit_graph_reachable(the_repository->objects->odb, - commit_graph_flags, - NULL); - } - close_object_store(the_repository->objects); if (enable_auto_gc) { diff --git a/third_party/git/builtin/fmt-merge-msg.c b/third_party/git/builtin/fmt-merge-msg.c index 736f666f644c..a4615587fd79 100644 --- a/third_party/git/builtin/fmt-merge-msg.c +++ b/third_party/git/builtin/fmt-merge-msg.c @@ -106,7 +106,7 @@ static int handle_line(char *line, struct merge_parents *merge_parents) int i, len = strlen(line); struct origin_data *origin_data; char *src; - const char *origin, *tag_name; + const char *origin; struct src_data *src_data; struct string_list_item *item; int pulling_head = 0; @@ -162,13 +162,14 @@ static int handle_line(char *line, struct merge_parents *merge_parents) if (pulling_head) { origin = src; src_data->head_status |= 1; - } else if (skip_prefix(line, "branch ", &origin)) { + } else if (starts_with(line, "branch ")) { origin_data->is_local_branch = 1; + origin = line + 7; string_list_append(&src_data->branch, origin); src_data->head_status |= 2; - } else if (skip_prefix(line, "tag ", &tag_name)) { + } else if (starts_with(line, "tag ")) { origin = line; - string_list_append(&src_data->tag, tag_name); + string_list_append(&src_data->tag, origin + 4); src_data->head_status |= 2; } else if (skip_prefix(line, "remote-tracking branch ", &origin)) { string_list_append(&src_data->r_branch, origin); diff --git a/third_party/git/builtin/fsck.c b/third_party/git/builtin/fsck.c index 8d13794b1412..18403a94fa42 100644 --- a/third_party/git/builtin/fsck.c +++ b/third_party/git/builtin/fsck.c @@ -50,20 +50,40 @@ static int name_objects; #define ERROR_REFS 010 #define ERROR_COMMIT_GRAPH 020 -static const char *describe_object(const struct object_id *oid) +static const char *describe_object(struct object *obj) { - return fsck_describe_object(&fsck_walk_options, oid); + static struct strbuf bufs[] = { + STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT + }; + static int b = 0; + struct strbuf *buf; + char *name = NULL; + + if (name_objects) + name = lookup_decoration(fsck_walk_options.object_names, obj); + + buf = bufs + b; + b = (b + 1) % ARRAY_SIZE(bufs); + strbuf_reset(buf); + strbuf_addstr(buf, oid_to_hex(&obj->oid)); + if (name) + strbuf_addf(buf, " (%s)", name); + + return buf->buf; } -static const char *printable_type(const struct object_id *oid, - enum object_type type) +static const char *printable_type(struct object *obj) { const char *ret; - if (type == OBJ_NONE) - type = oid_object_info(the_repository, oid, NULL); + if (obj->type == OBJ_NONE) { + enum object_type type = oid_object_info(the_repository, + &obj->oid, NULL); + if (type > 0) + object_as_type(the_repository, obj, type, 0); + } - ret = type_name(type); + ret = type_name(obj->type); if (!ret) ret = _("unknown"); @@ -98,32 +118,26 @@ static int objerror(struct object *obj, const char *err) errors_found |= ERROR_OBJECT; /* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */ fprintf_ln(stderr, _("error in %s %s: %s"), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid), err); + printable_type(obj), describe_object(obj), err); return -1; } static int fsck_error_func(struct fsck_options *o, - const struct object_id *oid, - enum object_type object_type, - int msg_type, const char *message) + struct object *obj, int type, const char *message) { - switch (msg_type) { + switch (type) { case FSCK_WARN: /* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */ fprintf_ln(stderr, _("warning in %s %s: %s"), - printable_type(oid, object_type), - describe_object(oid), message); + printable_type(obj), describe_object(obj), message); return 0; case FSCK_ERROR: /* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */ fprintf_ln(stderr, _("error in %s %s: %s"), - printable_type(oid, object_type), - describe_object(oid), message); + printable_type(obj), describe_object(obj), message); return 1; default: - BUG("%d (FSCK_IGNORE?) should never trigger this callback", - msg_type); + BUG("%d (FSCK_IGNORE?) should never trigger this callback", type); } } @@ -141,8 +155,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (!obj) { /* ... these references to parent->fld are safe here */ printf_ln(_("broken link from %7s %s"), - printable_type(&parent->oid, parent->type), - describe_object(&parent->oid)); + printable_type(parent), describe_object(parent)); printf_ln(_("broken link from %7s %s"), (type == OBJ_ANY ? _("unknown") : type_name(type)), _("unknown")); @@ -170,10 +183,10 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt if (parent && !has_object_file(&obj->oid)) { printf_ln(_("broken link from %7s %s\n" " to %7s %s"), - printable_type(&parent->oid, parent->type), - describe_object(&parent->oid), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid)); + printable_type(parent), + describe_object(parent), + printable_type(obj), + describe_object(obj)); errors_found |= ERROR_REACHABLE; } return 1; @@ -279,9 +292,8 @@ static void check_reachable_object(struct object *obj) return; if (has_object_pack(&obj->oid)) return; /* it is in pack - forget about it */ - printf_ln(_("missing %s %s"), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid)); + printf_ln(_("missing %s %s"), printable_type(obj), + describe_object(obj)); errors_found |= ERROR_REACHABLE; return; } @@ -306,9 +318,8 @@ static void check_unreachable_object(struct object *obj) * since this is something that is prunable. */ if (show_unreachable) { - printf_ln(_("unreachable %s %s"), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid)); + printf_ln(_("unreachable %s %s"), printable_type(obj), + describe_object(obj)); return; } @@ -326,13 +337,12 @@ static void check_unreachable_object(struct object *obj) */ if (!(obj->flags & USED)) { if (show_dangling) - printf_ln(_("dangling %s %s"), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid)); + printf_ln(_("dangling %s %s"), printable_type(obj), + describe_object(obj)); if (write_lost_and_found) { char *filename = git_pathdup("lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", - describe_object(&obj->oid)); + describe_object(obj)); FILE *f; if (safe_create_leading_directories_const(filename)) { @@ -345,7 +355,7 @@ static void check_unreachable_object(struct object *obj) if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1)) die_errno(_("could not write '%s'"), filename); } else - fprintf(f, "%s\n", describe_object(&obj->oid)); + fprintf(f, "%s\n", describe_object(obj)); if (fclose(f)) die_errno(_("could not finish '%s'"), filename); @@ -364,7 +374,7 @@ static void check_unreachable_object(struct object *obj) static void check_object(struct object *obj) { if (verbose) - fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid)); + fprintf_ln(stderr, _("Checking %s"), describe_object(obj)); if (obj->flags & REACHABLE) check_reachable_object(obj); @@ -422,8 +432,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size) if (verbose) fprintf_ln(stderr, _("Checking %s %s"), - printable_type(&obj->oid, obj->type), - describe_object(&obj->oid)); + printable_type(obj), describe_object(obj)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, _("broken links")); @@ -436,7 +445,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size) if (!commit->parents && show_root) printf_ln(_("root %s"), - describe_object(&commit->object.oid)); + describe_object(&commit->object)); } if (obj->type == OBJ_TAG) { @@ -444,10 +453,10 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size) if (show_tags && tag->tagged) { printf_ln(_("tagged %s %s (%s) in %s"), - printable_type(&tag->tagged->oid, tag->tagged->type), - describe_object(&tag->tagged->oid), + printable_type(tag->tagged), + describe_object(tag->tagged), tag->tag, - describe_object(&tag->object.oid)); + describe_object(&tag->object)); } } @@ -490,10 +499,10 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, if (!is_null_oid(oid)) { obj = lookup_object(the_repository, oid); if (obj && (obj->flags & HAS_OBJ)) { - if (timestamp) - fsck_put_object_name(&fsck_walk_options, oid, - "%s@{%"PRItime"}", - refname, timestamp); + if (timestamp && name_objects) + add_decoration(fsck_walk_options.object_names, + obj, + xstrfmt("%s@{%"PRItime"}", refname, timestamp)); obj->flags |= USED; mark_object_reachable(obj); } else if (!is_promisor_object(oid)) { @@ -557,8 +566,9 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid, } default_refs++; obj->flags |= USED; - fsck_put_object_name(&fsck_walk_options, - oid, "%s", refname); + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(refname)); mark_object_reachable(obj); return 0; @@ -732,7 +742,9 @@ static int fsck_cache_tree(struct cache_tree *it) return 1; } obj->flags |= USED; - fsck_put_object_name(&fsck_walk_options, &it->oid, ":"); + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(":")); mark_object_reachable(obj); if (obj->type != OBJ_TREE) err |= objerror(obj, _("non-tree in cache-tree")); @@ -818,7 +830,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } if (name_objects) - fsck_enable_object_names(&fsck_walk_options); + fsck_walk_options.object_names = + xcalloc(1, sizeof(struct decoration)); git_config(fsck_config, NULL); @@ -877,8 +890,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } obj->flags |= USED; - fsck_put_object_name(&fsck_walk_options, &oid, - "%s", arg); + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, xstrdup(arg)); mark_object_reachable(obj); continue; } @@ -914,8 +928,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) continue; obj = &blob->object; obj->flags |= USED; - fsck_put_object_name(&fsck_walk_options, &obj->oid, - ":%s", active_cache[i]->name); + if (name_objects) + add_decoration(fsck_walk_options.object_names, + obj, + xstrfmt(":%s", active_cache[i]->name)); mark_object_reachable(obj); } if (active_cache_tree) diff --git a/third_party/git/builtin/gc.c b/third_party/git/builtin/gc.c index 8e0b9cf41b3d..c18efadda53e 100644 --- a/third_party/git/builtin/gc.c +++ b/third_party/git/builtin/gc.c @@ -27,7 +27,6 @@ #include "pack-objects.h" #include "blob.h" #include "tree.h" -#include "promisor-remote.h" #define FAILED_RUN "failed to run %s" @@ -42,6 +41,7 @@ static int aggressive_depth = 50; static int aggressive_window = 250; static int gc_auto_threshold = 6700; static int gc_auto_pack_limit = 50; +static int gc_write_commit_graph; static int detach_auto = 1; static timestamp_t gc_log_expire_time; static const char *gc_log_expire = "1.day.ago"; @@ -148,6 +148,7 @@ static void gc_config(void) git_config_get_int("gc.aggressivedepth", &aggressive_depth); git_config_get_int("gc.auto", &gc_auto_threshold); git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); + git_config_get_bool("gc.writecommitgraph", &gc_write_commit_graph); git_config_get_bool("gc.autodetach", &detach_auto); git_config_get_expiry("gc.pruneexpire", &prune_expire); git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire); @@ -458,7 +459,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) /* * Returns 0 if there was no previous error and gc can proceed, 1 if * gc should not proceed due to an error in the last run. Prints a - * message and returns -1 if an error occurred while reading gc.log + * message and returns -1 if an error occured while reading gc.log */ static int report_last_gc_error(void) { @@ -601,7 +602,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (detach_auto) { int ret = report_last_gc_error(); if (ret < 0) - /* an I/O error occurred, already reported */ + /* an I/O error occured, already reported */ exit(128); if (ret == 1) /* Last gc --auto failed. Skip this one. */ @@ -660,7 +661,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) argv_array_push(&prune, prune_expire); if (quiet) argv_array_push(&prune, "--no-progress"); - if (has_promisor_remote()) + if (repository_format_partial_clone) argv_array_push(&prune, "--exclude-promisor-objects"); if (run_command_v_opt(prune.argv, RUN_GIT_CMD)) @@ -684,11 +685,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix) clean_pack_garbage(); } - prepare_repo_settings(the_repository); - if (the_repository->settings.gc_write_commit_graph == 1) - write_commit_graph_reachable(the_repository->objects->odb, - !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0, - NULL); + if (gc_write_commit_graph && + write_commit_graph_reachable(get_object_directory(), + !quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0, + NULL)) + return 1; if (auto_gc && too_many_loose_objects()) warning(_("There are too many unreachable loose objects; " diff --git a/third_party/git/builtin/grep.c b/third_party/git/builtin/grep.c index 99e26850907b..560051784ef7 100644 --- a/third_party/git/builtin/grep.c +++ b/third_party/git/builtin/grep.c @@ -24,7 +24,6 @@ #include "submodule.h" #include "submodule-config.h" #include "object-store.h" -#include "packfile.h" static char const * const grep_usage[] = { N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"), @@ -33,6 +32,7 @@ static char const * const grep_usage[] = { static int recurse_submodules; +#define GREP_NUM_THREADS_DEFAULT 8 static int num_threads; static pthread_t *threads; @@ -91,11 +91,8 @@ static pthread_cond_t cond_result; static int skip_first_line; -static void add_work(struct grep_opt *opt, struct grep_source *gs) +static void add_work(struct grep_opt *opt, const struct grep_source *gs) { - if (opt->binary != GREP_BINARY_TEXT) - grep_source_load_driver(gs, opt->repo->index); - grep_lock(); while ((todo_end+1) % ARRAY_SIZE(todo) == todo_done) { @@ -103,6 +100,9 @@ static void add_work(struct grep_opt *opt, struct grep_source *gs) } todo[todo_end].source = *gs; + if (opt->binary != GREP_BINARY_TEXT) + grep_source_load_driver(&todo[todo_end].source, + opt->repo->index); todo[todo_end].done = 0; strbuf_reset(&todo[todo_end].out); todo_end = (todo_end + 1) % ARRAY_SIZE(todo); @@ -200,12 +200,12 @@ static void start_threads(struct grep_opt *opt) int i; pthread_mutex_init(&grep_mutex, NULL); + pthread_mutex_init(&grep_read_mutex, NULL); pthread_mutex_init(&grep_attr_mutex, NULL); pthread_cond_init(&cond_add, NULL); pthread_cond_init(&cond_write, NULL); pthread_cond_init(&cond_result, NULL); grep_use_locks = 1; - enable_obj_read_lock(); for (i = 0; i < ARRAY_SIZE(todo); i++) { strbuf_init(&todo[i].out, 0); @@ -257,12 +257,12 @@ static int wait_all(void) free(threads); pthread_mutex_destroy(&grep_mutex); + pthread_mutex_destroy(&grep_read_mutex); pthread_mutex_destroy(&grep_attr_mutex); pthread_cond_destroy(&cond_add); pthread_cond_destroy(&cond_write); pthread_cond_destroy(&cond_result); grep_use_locks = 0; - disable_obj_read_lock(); return hit; } @@ -295,6 +295,16 @@ static int grep_cmd_config(const char *var, const char *value, void *cb) return st; } +static void *lock_and_read_oid_file(const struct object_id *oid, enum object_type *type, unsigned long *size) +{ + void *data; + + grep_read_lock(); + data = read_object_file(oid, type, size); + grep_read_unlock(); + return data; +} + static int grep_oid(struct grep_opt *opt, const struct object_id *oid, const char *filename, int tree_name_len, const char *path) @@ -393,32 +403,34 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, static int grep_submodule(struct grep_opt *opt, const struct pathspec *pathspec, const struct object_id *oid, - const char *filename, const char *path, int cached) + const char *filename, const char *path) { struct repository subrepo; struct repository *superproject = opt->repo; - const struct submodule *sub; + const struct submodule *sub = submodule_from_path(superproject, + &null_oid, path); struct grep_opt subopt; int hit; - sub = submodule_from_path(superproject, &null_oid, path); + /* + * NEEDSWORK: submodules functions need to be protected because they + * access the object store via config_from_gitmodules(): the latter + * uses get_oid() which, for now, relies on the global the_repository + * object. + */ + grep_read_lock(); - if (!is_submodule_active(superproject, path)) + if (!is_submodule_active(superproject, path)) { + grep_read_unlock(); return 0; + } - if (repo_submodule_init(&subrepo, superproject, sub)) + if (repo_submodule_init(&subrepo, superproject, sub)) { + grep_read_unlock(); return 0; + } - /* - * NEEDSWORK: repo_read_gitmodules() might call - * add_to_alternates_memory() via config_from_gitmodules(). This - * operation causes a race condition with concurrent object readings - * performed by the worker threads. That's why we need obj_read_lock() - * here. It should be removed once it's no longer necessary to add the - * subrepo's odbs to the in-memory alternates list. - */ - obj_read_lock(); - repo_read_gitmodules(&subrepo, 0); + repo_read_gitmodules(&subrepo); /* * NEEDSWORK: This adds the submodule's object directory to the list of @@ -431,7 +443,7 @@ static int grep_submodule(struct grep_opt *opt, * object. */ add_to_alternates_memory(subrepo.objects->odb->path); - obj_read_unlock(); + grep_read_unlock(); memcpy(&subopt, opt, sizeof(subopt)); subopt.repo = &subrepo; @@ -443,12 +455,14 @@ static int grep_submodule(struct grep_opt *opt, unsigned long size; struct strbuf base = STRBUF_INIT; - obj_read_lock(); object = parse_object_or_die(oid, oid_to_hex(oid)); - obj_read_unlock(); + + grep_read_lock(); data = read_object_with_reference(&subrepo, &object->oid, tree_type, &size, NULL); + grep_read_unlock(); + if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&object->oid)); @@ -461,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt, strbuf_release(&base); free(data); } else { - hit = grep_cache(&subopt, pathspec, cached); + hit = grep_cache(&subopt, pathspec, 1); } repo_clear(&subrepo); @@ -509,8 +523,7 @@ static int grep_cache(struct grep_opt *opt, } } else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && submodule_path_match(repo->index, pathspec, name.buf, NULL)) { - hit |= grep_submodule(opt, pathspec, NULL, ce->name, - ce->name, cached); + hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name); } else { continue; } @@ -573,7 +586,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, void *data; unsigned long size; - data = read_object_file(&entry.oid, &type, &size); + data = lock_and_read_oid_file(&entry.oid, &type, &size); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&entry.oid)); @@ -585,8 +598,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, free(data); } else if (recurse_submodules && S_ISGITLINK(entry.mode)) { hit |= grep_submodule(opt, pathspec, &entry.oid, - base->buf, base->buf + tn_len, - 1); /* ignored */ + base->buf, base->buf + tn_len); } strbuf_setlen(base, old_baselen); @@ -611,9 +623,12 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, struct strbuf base; int hit, len; + grep_read_lock(); data = read_object_with_reference(opt->repo, &obj->oid, tree_type, &size, NULL); + grep_read_unlock(); + if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); @@ -642,18 +657,13 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, for (i = 0; i < nr; i++) { struct object *real_obj; - - obj_read_lock(); real_obj = deref_tag(opt->repo, list->objects[i].item, NULL, 0); - obj_read_unlock(); /* load the gitmodules file for this rev */ if (recurse_submodules) { submodule_free(opt->repo); - obj_read_lock(); gitmodules_config_oid(&real_obj->oid); - obj_read_unlock(); } if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path)) { @@ -946,9 +956,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) /* die the same way as if we did it at the beginning */ setup_git_directory(); } - /* Ignore --recurse-submodules if --no-index is given or implied */ - if (!use_index) - recurse_submodules = 0; /* * skip a -- separator; we know it cannot be @@ -1053,10 +1060,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) pathspec.recursive = 1; pathspec.recurse_submodules = !!recurse_submodules; - if (recurse_submodules && untracked) - die(_("--untracked not supported with --recurse-submodules")); - - if (show_in_pager) { + if (list.nr || cached || show_in_pager) { if (num_threads > 1) warning(_("invalid option combination, ignoring --threads")); num_threads = 1; @@ -1066,7 +1070,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } else if (num_threads < 0) die(_("invalid number of threads specified (%d)"), num_threads); else if (num_threads == 0) - num_threads = HAVE_THREADS ? online_cpus() : 1; + num_threads = HAVE_THREADS ? GREP_NUM_THREADS_DEFAULT : 1; if (num_threads > 1) { if (!HAVE_THREADS) @@ -1075,17 +1079,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) && (opt.pre_context || opt.post_context || opt.file_break || opt.funcbody)) skip_first_line = 1; - - /* - * Pre-read gitmodules (if not read already) and force eager - * initialization of packed_git to prevent racy lazy - * reading/initialization once worker threads are started. - */ - if (recurse_submodules) - repo_read_gitmodules(the_repository, 1); - if (startup_info->have_repository) - (void)get_packed_git(the_repository); - start_threads(&opt); } else { /* @@ -1115,11 +1108,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix) strbuf_addf(&buf, "+/%s%s", strcmp("less", pager) ? "" : "*", opt.pattern_list->pattern); - string_list_append(&path_list, - strbuf_detach(&buf, NULL)); + string_list_append(&path_list, buf.buf); + strbuf_detach(&buf, NULL); } } + if (recurse_submodules && (!use_index || untracked)) + die(_("option not supported with --recurse-submodules")); + if (!show_in_pager && !opt.status_only) setup_pager(); @@ -1149,6 +1145,5 @@ int cmd_grep(int argc, const char **argv, const char *prefix) run_pager(&opt, prefix); clear_pathspec(&pathspec); free_grep_patterns(&opt); - grep_destroy(); return !hit; } diff --git a/third_party/git/builtin/index-pack.c b/third_party/git/builtin/index-pack.c index d967d188a307..0d55f73b0b44 100644 --- a/third_party/git/builtin/index-pack.c +++ b/third_party/git/builtin/index-pack.c @@ -14,7 +14,7 @@ #include "thread-utils.h" #include "packfile.h" #include "object-store.h" -#include "promisor-remote.h" +#include "fetch-object.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>])"; @@ -757,8 +757,7 @@ static int check_collison(struct object_entry *entry) memset(&data, 0, sizeof(data)); data.entry = entry; - data.st = open_istream(the_repository, &entry->idx.oid, &type, &size, - NULL); + data.st = open_istream(&entry->idx.oid, &type, &size, NULL); if (!data.st) return -1; if (size != entry->size || type != entry->type) @@ -949,7 +948,7 @@ static void resolve_delta(struct object_entry *delta_obj, free(delta_data); if (!result->data) bad_object(delta_obj->idx.offset, _("failed to apply delta")); - hash_object_file(the_hash_algo, result->data, result->size, + hash_object_file(result->data, result->size, type_name(delta_obj->real_type), &delta_obj->idx.oid); sha1_object(result->data, NULL, result->size, delta_obj->real_type, &delta_obj->idx.oid); @@ -1004,9 +1003,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base, if (!compare_and_swap_type(&child->real_type, OBJ_REF_DELTA, base->obj->real_type)) - die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)", - (uintmax_t)child->idx.offset, - oid_to_hex(&base->obj->idx.oid)); + BUG("child->real_type != OBJ_REF_DELTA"); resolve_delta(child, base, result); if (base->ref_first == base->ref_last && base->ofs_last == -1) @@ -1355,7 +1352,7 @@ static void fix_unresolved_deltas(struct hashfile *f) sorted_by_pos[i] = &ref_deltas[i]; QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare); - if (has_promisor_remote()) { + if (repository_format_partial_clone) { /* * Prefetch the delta bases. */ @@ -1369,8 +1366,8 @@ static void fix_unresolved_deltas(struct hashfile *f) oid_array_append(&to_fetch, &d->oid); } if (to_fetch.nr) - promisor_remote_get_direct(the_repository, - to_fetch.oid, to_fetch.nr); + fetch_objects(repository_format_partial_clone, + to_fetch.oid, to_fetch.nr); oid_array_clear(&to_fetch); } @@ -1386,9 +1383,8 @@ static void fix_unresolved_deltas(struct hashfile *f) if (!base_obj->data) continue; - if (check_object_signature(the_repository, &d->oid, - base_obj->data, base_obj->size, - type_name(type))) + if (check_object_signature(&d->oid, base_obj->data, + base_obj->size, type_name(type))) die(_("local object %s is corrupt"), oid_to_hex(&d->oid)); base_obj->obj = append_obj_to_pack(f, d->oid.hash, base_obj->data, base_obj->size, type); @@ -1494,11 +1490,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name, } if (!from_stdin) { - printf("%s\n", hash_to_hex(hash)); + printf("%s\n", sha1_to_hex(hash)); } else { struct strbuf buf = STRBUF_INIT; - strbuf_addf(&buf, "%s\t%s\n", report, hash_to_hex(hash)); + strbuf_addf(&buf, "%s\t%s\n", report, sha1_to_hex(hash)); write_or_die(1, buf.buf, buf.len); strbuf_release(&buf); diff --git a/third_party/git/builtin/log.c b/third_party/git/builtin/log.c index 83a4a6188e22..44b10b341541 100644 --- a/third_party/git/builtin/log.c +++ b/third_party/git/builtin/log.c @@ -37,7 +37,6 @@ #include "range-diff.h" #define MAIL_DEFAULT_WRAP 72 -#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100 /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -208,7 +207,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, if (!rev->show_notes_given && (!rev->pretty_given || w.notes)) rev->show_notes = 1; if (rev->show_notes) - load_display_notes(&rev->notes_opt); + init_display_notes(&rev->notes_opt); if ((rev->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) || rev->diffopt.filter || rev->diffopt.flags.follow_renames) @@ -628,7 +627,6 @@ int cmd_show(int argc, const char **argv, const char *prefix) break; case OBJ_TAG: { struct tag *t = (struct tag *)o; - struct object_id *oid = get_tagged_oid(t); if (rev.shown_one) putchar('\n'); @@ -640,10 +638,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.shown_one = 1; if (ret) break; - o = parse_object(the_repository, oid); + o = parse_object(the_repository, &t->tagged->oid); if (!o) ret = error(_("could not read object %s"), - oid_to_hex(oid)); + oid_to_hex(&t->tagged->oid)); objects[i].item = o; i--; break; @@ -766,56 +764,28 @@ static void add_header(const char *value) item->string[len] = '\0'; } -enum cover_setting { - COVER_UNSET, - COVER_OFF, - COVER_ON, - COVER_AUTO -}; - -enum thread_level { - THREAD_UNSET, - THREAD_SHALLOW, - THREAD_DEEP -}; - -enum cover_from_description { - COVER_FROM_NONE, - COVER_FROM_MESSAGE, - COVER_FROM_SUBJECT, - COVER_FROM_AUTO -}; - -static enum thread_level thread; +#define THREAD_SHALLOW 1 +#define THREAD_DEEP 2 +static int thread; static int do_signoff; static int base_auto; static char *from; static const char *signature = git_version_string; static const char *signature_file; -static enum cover_setting config_cover_letter; +static int config_cover_letter; static const char *config_output_directory; -static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE; -static int show_notes; -static struct display_notes_opt notes_opt; -static enum cover_from_description parse_cover_from_description(const char *arg) -{ - if (!arg || !strcmp(arg, "default")) - return COVER_FROM_MESSAGE; - else if (!strcmp(arg, "none")) - return COVER_FROM_NONE; - else if (!strcmp(arg, "message")) - return COVER_FROM_MESSAGE; - else if (!strcmp(arg, "subject")) - return COVER_FROM_SUBJECT; - else if (!strcmp(arg, "auto")) - return COVER_FROM_AUTO; - else - die(_("%s: invalid cover from description mode"), arg); -} +enum { + COVER_UNSET, + COVER_OFF, + COVER_ON, + COVER_AUTO +}; static int git_format_config(const char *var, const char *value, void *cb) { + struct rev_info *rev = cb; + if (!strcmp(var, "format.headers")) { if (!value) die(_("format.headers without value")); @@ -865,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb) thread = THREAD_SHALLOW; return 0; } - thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET; + thread = git_config_bool(var, value) && THREAD_SHALLOW; return 0; } if (!strcmp(var, "format.signoff")) { @@ -902,17 +872,19 @@ static int git_format_config(const char *var, const char *value, void *cb) return 0; } if (!strcmp(var, "format.notes")) { + struct strbuf buf = STRBUF_INIT; int b = git_parse_maybe_bool(value); - if (b < 0) - enable_ref_display_notes(¬es_opt, &show_notes, value); - else if (b) - enable_default_display_notes(¬es_opt, &show_notes); - else - disable_display_notes(¬es_opt, &show_notes); - return 0; - } - if (!strcmp(var, "format.coverfromdescription")) { - cover_from_description_mode = parse_cover_from_description(value); + if (!b) + return 0; + rev->show_notes = 1; + if (b < 0) { + strbuf_addstr(&buf, value); + expand_notes_ref(&buf); + string_list_append(&rev->notes_opt.extra_notes_refs, + strbuf_detach(&buf, NULL)); + } else { + rev->notes_opt.use_default_notes = 1; + } return 0; } @@ -1021,6 +993,20 @@ static void print_signature(FILE *file) putc('\n', file); } +static void add_branch_description(struct strbuf *buf, const char *branch_name) +{ + struct strbuf desc = STRBUF_INIT; + if (!branch_name || !*branch_name) + return; + read_branch_desc(&desc, branch_name); + if (desc.len) { + strbuf_addch(buf, '\n'); + strbuf_addbuf(buf, &desc); + strbuf_addch(buf, '\n'); + } + strbuf_release(&desc); +} + static char *find_branch_name(struct rev_info *rev) { int i, positive = -1; @@ -1067,63 +1053,6 @@ static void show_diffstat(struct rev_info *rev, fprintf(rev->diffopt.file, "\n"); } -static void prepare_cover_text(struct pretty_print_context *pp, - const char *branch_name, - struct strbuf *sb, - const char *encoding, - int need_8bit_cte) -{ - const char *subject = "*** SUBJECT HERE ***"; - const char *body = "*** BLURB HERE ***"; - struct strbuf description_sb = STRBUF_INIT; - struct strbuf subject_sb = STRBUF_INIT; - - if (cover_from_description_mode == COVER_FROM_NONE) - goto do_pp; - - if (branch_name && *branch_name) - read_branch_desc(&description_sb, branch_name); - if (!description_sb.len) - goto do_pp; - - if (cover_from_description_mode == COVER_FROM_SUBJECT || - cover_from_description_mode == COVER_FROM_AUTO) - body = format_subject(&subject_sb, description_sb.buf, " "); - - if (cover_from_description_mode == COVER_FROM_MESSAGE || - (cover_from_description_mode == COVER_FROM_AUTO && - subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN)) - body = description_sb.buf; - else - subject = subject_sb.buf; - -do_pp: - pp_title_line(pp, &subject, sb, encoding, need_8bit_cte); - pp_remainder(pp, &body, sb, 0); - - strbuf_release(&description_sb); - strbuf_release(&subject_sb); -} - -static int get_notes_refs(struct string_list_item *item, void *arg) -{ - argv_array_pushf(arg, "--notes=%s", item->string); - return 0; -} - -static void get_notes_args(struct argv_array *arg, struct rev_info *rev) -{ - if (!rev->show_notes) { - argv_array_push(arg, "--no-notes"); - } else if (rev->notes_opt.use_default_notes > 0 || - (rev->notes_opt.use_default_notes == -1 && - !rev->notes_opt.extra_notes_refs.nr)) { - argv_array_push(arg, "--notes"); - } else { - for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg); - } -} - static void make_cover_letter(struct rev_info *rev, int use_stdout, struct commit *origin, int nr, struct commit **list, @@ -1131,6 +1060,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, int quiet) { const char *committer; + const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n"; + const char *msg; struct shortlog log; struct strbuf sb = STRBUF_INIT; int i; @@ -1160,12 +1091,15 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, if (!branch_name) branch_name = find_branch_name(rev); + msg = body; pp.fmt = CMIT_FMT_EMAIL; pp.date_mode.type = DATE_RFC2822; pp.rev = rev; pp.print_email_subject = 1; pp_user_info(&pp, NULL, &sb, committer, encoding); - prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte); + pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte); + pp_remainder(&pp, &msg, &sb, 0); + add_branch_description(&sb, branch_name); fprintf(rev->diffopt.file, "%s\n", sb.buf); strbuf_release(&sb); @@ -1196,16 +1130,13 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, * can be added later if deemed desirable. */ struct diff_options opts; - struct argv_array other_arg = ARGV_ARRAY_INIT; 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); - argv_array_clear(&other_arg); + rev->creation_factor, 1, &opts); } } @@ -1317,9 +1248,9 @@ static int output_directory_callback(const struct option *opt, const char *arg, static int thread_callback(const struct option *opt, const char *arg, int unset) { - enum thread_level *thread = (enum thread_level *)opt->value; + int *thread = (int *)opt->value; if (unset) - *thread = THREAD_UNSET; + *thread = 0; else if (!arg || !strcmp(arg, "shallow")) *thread = THREAD_SHALLOW; else if (!strcmp(arg, "deep")) @@ -1366,7 +1297,7 @@ static int header_callback(const struct option *opt, const char *arg, int unset) string_list_clear(&extra_to, 0); string_list_clear(&extra_cc, 0); } else { - add_header(arg); + add_header(arg); } return 0; } @@ -1422,7 +1353,7 @@ static struct commit *get_base_commit(const char *base_commit, base = lookup_commit_reference_by_name(base_commit); if (!base) die(_("unknown commit %s"), base_commit); - } else if ((base_commit && !strcmp(base_commit, "auto"))) { + } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) { struct branch *curr_branch = branch_get(NULL); const char *upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1610,7 +1541,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int use_patch_format = 0; int quiet = 0; int reroll_count = -1; - char *cover_from_description_arg = NULL; char *branch_name = NULL; char *base_commit = NULL; struct base_tree_info bases; @@ -1647,9 +1577,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "rfc", &rev, NULL, N_("Use [RFC PATCH] instead of [PATCH]"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback }, - OPT_STRING(0, "cover-from-description", &cover_from_description_arg, - N_("cover-from-description-mode"), - N_("generate parts of a cover letter based on a branch's description")), { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"), N_("Use [<prefix>] instead of [PATCH]"), PARSE_OPT_NONEG, subject_prefix_callback }, @@ -1713,11 +1640,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) extra_to.strdup_strings = 1; extra_cc.strdup_strings = 1; init_log_defaults(); - init_display_notes(¬es_opt); - git_config(git_format_config, NULL); repo_init_revisions(the_repository, &rev, prefix); - rev.show_notes = show_notes; - memcpy(&rev.notes_opt, ¬es_opt, sizeof(notes_opt)); + git_config(git_format_config, &rev); rev.commit_format = CMIT_FMT_EMAIL; rev.expand_tabs_in_log_default = 0; rev.verbose_header = 1; @@ -1729,9 +1653,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) s_r_opt.def = "HEAD"; s_r_opt.revarg_opt = REVARG_COMMITTISH; - if (base_auto) - base_commit = "auto"; - if (default_attach) { rev.mime_boundary = default_attach; rev.no_inline = 1; @@ -1747,9 +1668,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH); - if (cover_from_description_arg) - cover_from_description_mode = parse_cover_from_description(cover_from_description_arg); - if (0 < reroll_count) { struct strbuf sprefix = STRBUF_INIT; strbuf_addf(&sprefix, "%s v%d", @@ -1836,7 +1754,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diffopt.flags.binary = 1; if (rev.show_notes) - load_display_notes(&rev.notes_opt); + init_display_notes(&rev.notes_opt); if (!output_directory && !use_stdout) output_directory = config_output_directory; @@ -1847,26 +1765,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) setup_pager(); if (output_directory) { - int saved; if (rev.diffopt.use_color != GIT_COLOR_ALWAYS) rev.diffopt.use_color = GIT_COLOR_NEVER; if (use_stdout) die(_("standard output, or directory, which one?")); - /* - * We consider <outdir> as 'outside of gitdir', therefore avoid - * applying adjust_shared_perm in s-c-l-d. - */ - saved = get_shared_repository(); - set_shared_repository(0); - switch (safe_create_leading_directories_const(output_directory)) { - case SCLD_OK: - case SCLD_EXISTS: - break; - default: - die(_("could not create leading directories " - "of '%s'"), output_directory); - } - set_shared_repository(saved); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) die_errno(_("could not create directory '%s'"), output_directory); @@ -1995,7 +1897,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } memset(&bases, 0, sizeof(bases)); - if (base_commit) { + if (base_commit || base_auto) { struct commit *base = get_base_commit(base_commit, list, nr); reset_revision_walk(); clear_object_flags(UNINTERESTING); diff --git a/third_party/git/builtin/ls-files.c b/third_party/git/builtin/ls-files.c index f069a028cea1..670e8fb93c93 100644 --- a/third_party/git/builtin/ls-files.c +++ b/third_party/git/builtin/ls-files.c @@ -492,7 +492,7 @@ static int option_parse_exclude_from(const struct option *opt, BUG_ON_OPT_NEG(unset); exc_given = 1; - add_patterns_from_file(dir, arg); + add_excludes_from_file(dir, arg); return 0; } @@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) int require_work_tree = 0, show_tag = 0, i; const char *max_prefix; struct dir_struct dir; - struct pattern_list *pl; + struct exclude_list *el; struct string_list exclude_list = STRING_LIST_INIT_NODUP; struct option builtin_ls_files_options[] = { /* Think twice before adding "--nul" synonym to this */ @@ -594,9 +594,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) argc = parse_options(argc, argv, prefix, builtin_ls_files_options, ls_files_usage, 0); - pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); + el = add_exclude_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) { - add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args); + add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args); } if (show_tag || show_valid_bit || show_fsmonitor_bit) { tag_cached = "H "; diff --git a/third_party/git/builtin/merge-recursive.c b/third_party/git/builtin/merge-recursive.c index a4bfd8fc51d6..5b910e351e4d 100644 --- a/third_party/git/builtin/merge-recursive.c +++ b/third_party/git/builtin/merge-recursive.c @@ -1,4 +1,3 @@ -#include "cache.h" #include "builtin.h" #include "commit.h" #include "tag.h" @@ -64,9 +63,6 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (argc - i != 3) /* "--" "<head>" "<remote>" */ die(_("not handling anything other than two heads merge.")); - if (repo_read_index_unmerged(the_repository)) - die_resolve_conflict("merge"); - o.branch1 = argv[++i]; o.branch2 = argv[++i]; diff --git a/third_party/git/builtin/merge-tree.c b/third_party/git/builtin/merge-tree.c index e72714a5a87d..97b54caeb900 100644 --- a/third_party/git/builtin/merge-tree.c +++ b/third_party/git/builtin/merge-tree.c @@ -180,9 +180,8 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru static char *traverse_path(const struct traverse_info *info, const struct name_entry *n) { - struct strbuf buf = STRBUF_INIT; - strbuf_make_traverse_path(&buf, info, n->path, n->pathlen); - return strbuf_detach(&buf, NULL); + char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz); + return make_traverse_path(path, info, n); } static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result) diff --git a/third_party/git/builtin/merge.c b/third_party/git/builtin/merge.c index d127d2225f89..e2ccbc44e204 100644 --- a/third_party/git/builtin/merge.c +++ b/third_party/git/builtin/merge.c @@ -62,7 +62,6 @@ static int show_diffstat = 1, shortlog_len = -1, squash; static int option_commit = -1; static int option_edit = -1; static int allow_trivial = 1, have_message, verify_signatures; -static int check_trust_level = 1; static int overwrite_ignore = 1; static struct strbuf merge_msg = STRBUF_INIT; static struct strategy **use_strategies; @@ -82,7 +81,7 @@ static int show_progress = -1; static int default_to_upstream = 1; static int signoff; static const char *sign_commit; -static int no_verify; +static int verify_msg = 1; static struct strategy all_strategy[] = { { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, @@ -288,7 +287,7 @@ static struct option builtin_merge_options[] = { N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")), OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")), - OPT_BOOL(0, "no-verify", &no_verify, N_("bypass pre-merge-commit and commit-msg hooks")), + OPT_BOOL(0, "verify", &verify_msg, N_("verify commit-msg hook")), OPT_END() }; @@ -632,8 +631,6 @@ static int git_merge_config(const char *k, const char *v, void *cb) } else if (!strcmp(k, "commit.gpgsign")) { sign_commit = git_config_bool(k, v) ? "" : NULL; return 0; - } else if (!strcmp(k, "gpg.mintrustlevel")) { - check_trust_level = 0; } status = fmt_merge_msg_config(k, v, cb); @@ -691,13 +688,16 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, struct commit_list *remoteheads, struct commit *head) { + struct lock_file lock = LOCK_INIT; const char *head_arg = "HEAD"; - if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0) + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); + refresh_cache(REFRESH_QUIET); + if (write_locked_index(&the_index, &lock, + COMMIT_LOCK | SKIP_IF_UNCHANGED)) return error(_("Unable to write index.")); if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) { - struct lock_file lock = LOCK_INIT; int clean, x; struct commit *result; struct commit_list *reversed = NULL; @@ -816,18 +816,6 @@ static void write_merge_heads(struct commit_list *); static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; - const char *index_file = get_index_file(); - - if (!no_verify && run_commit_hook(0 < option_edit, index_file, "pre-merge-commit", NULL)) - abort_commit(remoteheads, NULL); - /* - * Re-read the index as pre-merge-commit hook could have updated it, - * and write it out as a tree. We must do this before we invoke - * the editor and after we invoke run_status above. - */ - if (find_hook("pre-merge-commit")) - discard_cache(); - read_cache_from(index_file); strbuf_addbuf(&msg, &merge_msg); if (squash) BUG("the control must not reach here under --squash"); @@ -854,7 +842,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) abort_commit(remoteheads, NULL); } - if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), + if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(), "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); @@ -872,8 +860,12 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads) { struct object_id result_tree, result_commit; struct commit_list *parents, **pptr = &parents; + struct lock_file lock = LOCK_INIT; - if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0) + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); + refresh_cache(REFRESH_QUIET); + if (write_locked_index(&the_index, &lock, + COMMIT_LOCK | SKIP_IF_UNCHANGED)) return error(_("Unable to write index.")); write_tree_trivial(&result_tree); @@ -1400,8 +1392,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) die(_("Can merge only exactly one commit into empty head")); if (verify_signatures) - verify_merge_signature(remoteheads->item, verbosity, - check_trust_level); + verify_merge_signature(remoteheads->item, verbosity); remote_head_oid = &remoteheads->item->object.oid; read_empty(remote_head_oid, 0); @@ -1424,8 +1415,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) if (verify_signatures) { for (p = remoteheads; p; p = p->next) { - verify_merge_signature(p->item, verbosity, - check_trust_level); + verify_merge_signature(p->item, verbosity); } } diff --git a/third_party/git/builtin/mktag.c b/third_party/git/builtin/mktag.c index 4982d3a93efb..6fb7dc8578d6 100644 --- a/third_party/git/builtin/mktag.c +++ b/third_party/git/builtin/mktag.c @@ -29,11 +29,8 @@ static int verify_object(const struct object_id *oid, const char *expected_type) const struct object_id *repl = lookup_replace_object(the_repository, oid); if (buffer) { - if (type == type_from_string(expected_type)) { - ret = check_object_signature(the_repository, repl, - buffer, size, - expected_type); - } + if (type == type_from_string(expected_type)) + ret = check_object_signature(repl, buffer, size, expected_type); free(buffer); } return ret; diff --git a/third_party/git/builtin/multi-pack-index.c b/third_party/git/builtin/multi-pack-index.c index 5bf88cd2a8e2..b1ea1a6aa177 100644 --- a/third_party/git/builtin/multi-pack-index.c +++ b/third_party/git/builtin/multi-pack-index.c @@ -6,25 +6,21 @@ #include "trace2.h" static char const * const builtin_multi_pack_index_usage[] = { - N_("git multi-pack-index [<options>] (write|verify|expire|repack --batch-size=<size>)"), + N_("git multi-pack-index [--object-dir=<dir>] (write|verify|expire|repack --batch-size=<size>)"), NULL }; static struct opts_multi_pack_index { const char *object_dir; unsigned long batch_size; - int progress; } opts; int cmd_multi_pack_index(int argc, const char **argv, const char *prefix) { - unsigned flags = 0; - static struct option builtin_multi_pack_index_options[] = { OPT_FILENAME(0, "object-dir", &opts.object_dir, N_("object directory containing set of packfile and pack-index pairs")), - OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")), OPT_MAGNITUDE(0, "batch-size", &opts.batch_size, N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")), OPT_END(), @@ -32,15 +28,12 @@ int cmd_multi_pack_index(int argc, const char **argv, git_config(git_default_config, NULL); - opts.progress = isatty(2); argc = parse_options(argc, argv, prefix, builtin_multi_pack_index_options, builtin_multi_pack_index_usage, 0); if (!opts.object_dir) opts.object_dir = get_object_directory(); - if (opts.progress) - flags |= MIDX_PROGRESS; if (argc == 0) usage_with_options(builtin_multi_pack_index_usage, @@ -54,17 +47,16 @@ int cmd_multi_pack_index(int argc, const char **argv, trace2_cmd_mode(argv[0]); if (!strcmp(argv[0], "repack")) - return midx_repack(the_repository, opts.object_dir, - (size_t)opts.batch_size, flags); + return midx_repack(the_repository, opts.object_dir, (size_t)opts.batch_size); if (opts.batch_size) die(_("--batch-size option is only for 'repack' subcommand")); if (!strcmp(argv[0], "write")) - return write_midx_file(opts.object_dir, flags); + return write_midx_file(opts.object_dir); if (!strcmp(argv[0], "verify")) - return verify_midx_file(the_repository, opts.object_dir, flags); + return verify_midx_file(the_repository, opts.object_dir); if (!strcmp(argv[0], "expire")) - return expire_midx_packs(the_repository, opts.object_dir, flags); + return expire_midx_packs(the_repository, opts.object_dir); die(_("unrecognized subcommand: %s"), argv[0]); } diff --git a/third_party/git/builtin/name-rev.c b/third_party/git/builtin/name-rev.c index a9dcd25e4647..c785fe16bade 100644 --- a/third_party/git/builtin/name-rev.c +++ b/third_party/git/builtin/name-rev.c @@ -6,25 +6,20 @@ #include "tag.h" #include "refs.h" #include "parse-options.h" -#include "prio-queue.h" #include "sha1-lookup.h" #include "commit-slab.h" -/* - * One day. See the 'name a rev shortly after epoch' test in t6120 when - * changing this value - */ -#define CUTOFF_DATE_SLOP 86400 +#define CUTOFF_DATE_SLOP 86400 /* one day */ -struct rev_name { - char *tip_name; +typedef struct rev_name { + const char *tip_name; timestamp_t taggerdate; int generation; int distance; int from_tag; -}; +} rev_name; -define_commit_slab(commit_rev_name, struct rev_name); +define_commit_slab(commit_rev_name, struct rev_name *); static timestamp_t cutoff = TIME_MAX; static struct commit_rev_name rev_names; @@ -32,16 +27,16 @@ static struct commit_rev_name rev_names; /* How many generations are maximally preferred over _one_ merge traversal? */ #define MERGE_TRAVERSAL_WEIGHT 65535 -static int is_valid_rev_name(const struct rev_name *name) +static struct rev_name *get_commit_rev_name(struct commit *commit) { - return name && (name->generation || name->tip_name); + struct rev_name **slot = commit_rev_name_peek(&rev_names, commit); + + return slot ? *slot : NULL; } -static struct rev_name *get_commit_rev_name(const struct commit *commit) +static void set_commit_rev_name(struct commit *commit, struct rev_name *name) { - struct rev_name *name = commit_rev_name_peek(&rev_names, commit); - - return is_valid_rev_name(name) ? name : NULL; + *commit_rev_name_at(&rev_names, commit) = name; } static int is_better_name(struct rev_name *name, @@ -80,135 +75,68 @@ static int is_better_name(struct rev_name *name, return 0; } -static struct rev_name *create_or_update_name(struct commit *commit, - timestamp_t taggerdate, - int generation, int distance, - int from_tag) -{ - struct rev_name *name = commit_rev_name_at(&rev_names, commit); - - if (is_valid_rev_name(name)) { - if (!is_better_name(name, taggerdate, distance, from_tag)) - return NULL; - - /* - * This string might still be shared with ancestors - * (generation > 0). We can release it here regardless, - * because the new name that has just won will be better - * for them as well, so name_rev() will replace these - * stale pointers when it processes the parents. - */ - if (!name->generation) - free(name->tip_name); - } - - name->taggerdate = taggerdate; - name->generation = generation; - name->distance = distance; - name->from_tag = from_tag; - - return name; -} - -static char *get_parent_name(const struct rev_name *name, int parent_number) -{ - struct strbuf sb = STRBUF_INIT; - size_t len; - - strip_suffix(name->tip_name, "^0", &len); - if (name->generation > 0) { - strbuf_grow(&sb, len + - 1 + decimal_width(name->generation) + - 1 + decimal_width(parent_number)); - strbuf_addf(&sb, "%.*s~%d^%d", (int)len, name->tip_name, - name->generation, parent_number); - } else { - strbuf_grow(&sb, len + - 1 + decimal_width(parent_number)); - strbuf_addf(&sb, "%.*s^%d", (int)len, name->tip_name, - parent_number); - } - return strbuf_detach(&sb, NULL); -} - -static void name_rev(struct commit *start_commit, +static void name_rev(struct commit *commit, const char *tip_name, timestamp_t taggerdate, - int from_tag, int deref) + int generation, int distance, int from_tag, + int deref) { - struct prio_queue queue; - struct commit *commit; - struct commit **parents_to_queue = NULL; - size_t parents_to_queue_nr, parents_to_queue_alloc = 0; - struct rev_name *start_name; - - parse_commit(start_commit); - if (start_commit->date < cutoff) - return; + struct rev_name *name = get_commit_rev_name(commit); + struct commit_list *parents; + int parent_number = 1; + char *to_free = NULL; - start_name = create_or_update_name(start_commit, taggerdate, 0, 0, - from_tag); - if (!start_name) - return; - if (deref) - start_name->tip_name = xstrfmt("%s^0", tip_name); - else - start_name->tip_name = xstrdup(tip_name); + parse_commit(commit); - memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */ - prio_queue_put(&queue, start_commit); - - while ((commit = prio_queue_get(&queue))) { - struct rev_name *name = get_commit_rev_name(commit); - struct commit_list *parents; - int parent_number = 1; - - parents_to_queue_nr = 0; + if (commit->date < cutoff) + return; - for (parents = commit->parents; - parents; - parents = parents->next, parent_number++) { - struct commit *parent = parents->item; - struct rev_name *parent_name; - int generation, distance; + if (deref) { + tip_name = to_free = xstrfmt("%s^0", tip_name); - parse_commit(parent); - if (parent->date < cutoff) - continue; + if (generation) + die("generation: %d, but deref?", generation); + } - if (parent_number > 1) { - generation = 0; - distance = name->distance + MERGE_TRAVERSAL_WEIGHT; - } else { - generation = name->generation + 1; - distance = name->distance + 1; - } + if (name == NULL) { + name = xmalloc(sizeof(rev_name)); + set_commit_rev_name(commit, name); + goto copy_data; + } else if (is_better_name(name, taggerdate, distance, from_tag)) { +copy_data: + name->tip_name = tip_name; + name->taggerdate = taggerdate; + name->generation = generation; + name->distance = distance; + name->from_tag = from_tag; + } else { + free(to_free); + return; + } - parent_name = create_or_update_name(parent, taggerdate, - generation, - distance, from_tag); - if (parent_name) { - if (parent_number > 1) - parent_name->tip_name = - get_parent_name(name, - parent_number); - else - parent_name->tip_name = name->tip_name; - ALLOC_GROW(parents_to_queue, - parents_to_queue_nr + 1, - parents_to_queue_alloc); - parents_to_queue[parents_to_queue_nr] = parent; - parents_to_queue_nr++; - } + for (parents = commit->parents; + parents; + parents = parents->next, parent_number++) { + if (parent_number > 1) { + size_t len; + char *new_name; + + strip_suffix(tip_name, "^0", &len); + if (generation > 0) + new_name = xstrfmt("%.*s~%d^%d", (int)len, tip_name, + generation, parent_number); + else + new_name = xstrfmt("%.*s^%d", (int)len, tip_name, + parent_number); + + name_rev(parents->item, new_name, taggerdate, 0, + distance + MERGE_TRAVERSAL_WEIGHT, + from_tag, 0); + } else { + name_rev(parents->item, tip_name, taggerdate, + generation + 1, distance + 1, + from_tag, 0); } - - /* The first parent must come out first from the prio_queue */ - while (parents_to_queue_nr) - prio_queue_put(&queue, - parents_to_queue[--parents_to_queue_nr]); } - - clear_prio_queue(&queue); - free(parents_to_queue); } static int subpath_matches(const char *path, const char *filter) @@ -229,10 +157,10 @@ static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous) { if (shorten_unambiguous) refname = shorten_unambiguous_ref(refname, 0); - else if (skip_prefix(refname, "refs/heads/", &refname)) - ; /* refname already advanced */ - else - skip_prefix(refname, "refs/", &refname); + else if (starts_with(refname, "refs/heads/")) + refname = refname + 11; + else if (starts_with(refname, "refs/")) + refname = refname + 5; return refname; } @@ -247,10 +175,6 @@ static struct tip_table { struct tip_table_entry { struct object_id oid; const char *refname; - struct commit *commit; - timestamp_t taggerdate; - unsigned int from_tag:1; - unsigned int deref:1; } *table; int nr; int alloc; @@ -258,18 +182,13 @@ static struct tip_table { } tip_table; static void add_to_tip_table(const struct object_id *oid, const char *refname, - int shorten_unambiguous, struct commit *commit, - timestamp_t taggerdate, int from_tag, int deref) + int shorten_unambiguous) { refname = name_ref_abbrev(refname, shorten_unambiguous); ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc); oidcpy(&tip_table.table[tip_table.nr].oid, oid); tip_table.table[tip_table.nr].refname = xstrdup(refname); - tip_table.table[tip_table.nr].commit = commit; - tip_table.table[tip_table.nr].taggerdate = taggerdate; - tip_table.table[tip_table.nr].from_tag = from_tag; - tip_table.table[tip_table.nr].deref = deref; tip_table.nr++; tip_table.sorted = 0; } @@ -280,30 +199,12 @@ static int tipcmp(const void *a_, const void *b_) return oidcmp(&a->oid, &b->oid); } -static int cmp_by_tag_and_age(const void *a_, const void *b_) -{ - const struct tip_table_entry *a = a_, *b = b_; - int cmp; - - /* Prefer tags. */ - cmp = b->from_tag - a->from_tag; - if (cmp) - return cmp; - - /* Older is better. */ - if (a->taggerdate < b->taggerdate) - return -1; - return a->taggerdate != b->taggerdate; -} - static int name_ref(const char *path, const struct object_id *oid, int flags, void *cb_data) { struct object *o = parse_object(the_repository, oid); struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; - int from_tag = 0; - struct commit *commit = NULL; timestamp_t taggerdate = TIME_MAX; if (data->tags_only && !starts_with(path, "refs/tags/")) @@ -352,6 +253,8 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo return 0; } + add_to_tip_table(oid, path, can_abbreviate_output); + while (o && o->type == OBJ_TAG) { struct tag *t = (struct tag *) o; if (!t->tagged) @@ -361,33 +264,16 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo taggerdate = t->date; } if (o && o->type == OBJ_COMMIT) { - commit = (struct commit *)o; - from_tag = starts_with(path, "refs/tags/"); - if (taggerdate == TIME_MAX) - taggerdate = commit->date; - } + struct commit *commit = (struct commit *)o; + int from_tag = starts_with(path, "refs/tags/"); - add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate, + if (taggerdate == TIME_MAX) + taggerdate = ((struct commit *)o)->date; + path = name_ref_abbrev(path, can_abbreviate_output); + name_rev(commit, xstrdup(path), taggerdate, 0, 0, from_tag, deref); - return 0; -} - -static void name_tips(void) -{ - int i; - - /* - * Try to set better names first, so that worse ones spread - * less. - */ - QSORT(tip_table.table, tip_table.nr, cmp_by_tag_and_age); - for (i = 0; i < tip_table.nr; i++) { - struct tip_table_entry *e = &tip_table.table[i]; - if (e->commit) { - name_rev(e->commit, e->refname, e->taggerdate, - e->from_tag, e->deref); - } } + return 0; } static const unsigned char *nth_tip_table_ent(size_t ix, void *table_) @@ -419,11 +305,11 @@ static const char *get_exact_ref_match(const struct object *o) static const char *get_rev_name(const struct object *o, struct strbuf *buf) { struct rev_name *n; - const struct commit *c; + struct commit *c; if (o->type != OBJ_COMMIT) return get_exact_ref_match(o); - c = (const struct commit *) o; + c = (struct commit *) o; n = get_commit_rev_name(c); if (!n) return NULL; @@ -431,10 +317,11 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf) if (!n->generation) return n->tip_name; else { + int len = strlen(n->tip_name); + if (len > 2 && !strcmp(n->tip_name + len - 2, "^0")) + len -= 2; strbuf_reset(buf); - strbuf_addstr(buf, n->tip_name); - strbuf_strip_suffix(buf, "^0"); - strbuf_addf(buf, "~%d", n->generation); + strbuf_addf(buf, "%.*s~%d", len, n->tip_name, n->generation); return buf->buf; } } @@ -594,15 +481,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) add_object_array(object, *argv, &revs); } - if (cutoff) { - /* check for undeflow */ - if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP) - cutoff = cutoff - CUTOFF_DATE_SLOP; - else - cutoff = TIME_MIN; - } + if (cutoff) + cutoff = cutoff - CUTOFF_DATE_SLOP; for_each_ref(name_ref, &data); - name_tips(); if (transform_stdin) { char buffer[2048]; diff --git a/third_party/git/builtin/notes.c b/third_party/git/builtin/notes.c index 35e468ea2d2f..02e97f55c5a0 100644 --- a/third_party/git/builtin/notes.c +++ b/third_party/git/builtin/notes.c @@ -513,7 +513,7 @@ static int copy(int argc, const char **argv, const char *prefix) } } - if (argc < 1) { + if (argc < 2) { error(_("too few parameters")); usage_with_options(git_notes_copy_usage, options); } @@ -622,7 +622,7 @@ static int append_edit(int argc, const char **argv, const char *prefix) strbuf_grow(&d.buf, size + 1); if (d.buf.len && prev_buf && size) - strbuf_insertstr(&d.buf, 0, "\n"); + strbuf_insert(&d.buf, 0, "\n", 1); if (prev_buf && size) strbuf_insert(&d.buf, 0, prev_buf, size); free(prev_buf); @@ -745,7 +745,7 @@ static int merge_commit(struct notes_merge_options *o) memset(&pretty_ctx, 0, sizeof(pretty_ctx)); format_commit_message(partial, "%s", &msg, &pretty_ctx); strbuf_trim(&msg); - strbuf_insertstr(&msg, 0, "notes: "); + strbuf_insert(&msg, 0, "notes: ", 7); update_ref(msg.buf, o->local_ref, &oid, is_null_oid(&parent_oid) ? NULL : &parent_oid, 0, UPDATE_REFS_DIE_ON_ERR); diff --git a/third_party/git/builtin/pack-objects.c b/third_party/git/builtin/pack-objects.c index 02aa6ee4808a..76ce9069467e 100644 --- a/third_party/git/builtin/pack-objects.c +++ b/third_party/git/builtin/pack-objects.c @@ -92,11 +92,10 @@ static struct progress *progress_state; static struct packed_git *reuse_packfile; static uint32_t reuse_packfile_objects; -static struct bitmap *reuse_packfile_bitmap; +static off_t reuse_packfile_offset; static int use_bitmap_index_default = 1; static int use_bitmap_index = -1; -static int allow_pack_reuse = 1; static enum { WRITE_BITMAP_FALSE = 0, WRITE_BITMAP_QUIET, @@ -164,7 +163,7 @@ static void *get_delta(struct object_entry *entry) delta_buf = diff_delta(base_buf, base_size, buf, size, &delta_size, 0); /* - * We successfully computed this delta once but dropped it for + * We succesfully computed this delta once but dropped it for * memory reasons. Something is very wrong if this time we * recompute and create a different delta. */ @@ -304,8 +303,7 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent if (!usable_delta) { if (oe_type(entry) == OBJ_BLOB && oe_size_greater_than(&to_pack, entry, big_file_threshold) && - (st = open_istream(the_repository, &entry->idx.oid, &type, - &size, NULL)) != NULL) + (st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL) buf = NULL; else { buf = read_object_file(&entry->idx.oid, &type, &size); @@ -612,12 +610,12 @@ static int mark_tagged(const char *path, const struct object_id *oid, int flag, void *cb_data) { struct object_id peeled; - struct object_entry *entry = packlist_find(&to_pack, oid); + struct object_entry *entry = packlist_find(&to_pack, oid, NULL); if (entry) entry->tagged = 1; if (!peel_ref(path, &peeled)) { - entry = packlist_find(&to_pack, &peeled); + entry = packlist_find(&to_pack, &peeled, NULL); if (entry) entry->tagged = 1; } @@ -786,186 +784,57 @@ static struct object_entry **compute_write_order(void) return wo; } - -/* - * A reused set of objects. All objects in a chunk have the same - * relative position in the original packfile and the generated - * packfile. - */ - -static struct reused_chunk { - /* The offset of the first object of this chunk in the original - * packfile. */ - off_t original; - /* The offset of the first object of this chunk in the generated - * packfile minus "original". */ - off_t difference; -} *reused_chunks; -static int reused_chunks_nr; -static int reused_chunks_alloc; - -static void record_reused_object(off_t where, off_t offset) +static off_t write_reused_pack(struct hashfile *f) { - if (reused_chunks_nr && reused_chunks[reused_chunks_nr-1].difference == offset) - return; + unsigned char buffer[8192]; + off_t to_write, total; + int fd; - ALLOC_GROW(reused_chunks, reused_chunks_nr + 1, - reused_chunks_alloc); - reused_chunks[reused_chunks_nr].original = where; - reused_chunks[reused_chunks_nr].difference = offset; - reused_chunks_nr++; -} + if (!is_pack_valid(reuse_packfile)) + die(_("packfile is invalid: %s"), reuse_packfile->pack_name); -/* - * Binary search to find the chunk that "where" is in. Note - * that we're not looking for an exact match, just the first - * chunk that contains it (which implicitly ends at the start - * of the next chunk. - */ -static off_t find_reused_offset(off_t where) -{ - int lo = 0, hi = reused_chunks_nr; - while (lo < hi) { - int mi = lo + ((hi - lo) / 2); - if (where == reused_chunks[mi].original) - return reused_chunks[mi].difference; - if (where < reused_chunks[mi].original) - hi = mi; - else - lo = mi + 1; - } + fd = git_open(reuse_packfile->pack_name); + if (fd < 0) + die_errno(_("unable to open packfile for reuse: %s"), + reuse_packfile->pack_name); - /* - * The first chunk starts at zero, so we can't have gone below - * there. - */ - assert(lo); - return reused_chunks[lo-1].difference; -} + if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1) + die_errno(_("unable to seek in reused packfile")); -static void write_reused_pack_one(size_t pos, struct hashfile *out, - struct pack_window **w_curs) -{ - off_t offset, next, cur; - enum object_type type; - unsigned long size; + if (reuse_packfile_offset < 0) + reuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz; - offset = reuse_packfile->revindex[pos].offset; - next = reuse_packfile->revindex[pos + 1].offset; + total = to_write = reuse_packfile_offset - sizeof(struct pack_header); - record_reused_object(offset, offset - hashfile_total(out)); + while (to_write) { + int read_pack = xread(fd, buffer, sizeof(buffer)); - cur = offset; - type = unpack_object_header(reuse_packfile, w_curs, &cur, &size); - assert(type >= 0); + if (read_pack <= 0) + die_errno(_("unable to read from reused packfile")); - if (type == OBJ_OFS_DELTA) { - off_t base_offset; - off_t fixup; - - unsigned char header[MAX_PACK_OBJECT_HEADER]; - unsigned len; - - base_offset = get_delta_base(reuse_packfile, w_curs, &cur, type, offset); - assert(base_offset != 0); - - /* Convert to REF_DELTA if we must... */ - if (!allow_ofs_delta) { - int base_pos = find_revindex_position(reuse_packfile, base_offset); - struct object_id base_oid; - - nth_packed_object_id(&base_oid, reuse_packfile, - reuse_packfile->revindex[base_pos].nr); - - len = encode_in_pack_object_header(header, sizeof(header), - OBJ_REF_DELTA, size); - hashwrite(out, header, len); - hashwrite(out, base_oid.hash, 20); - copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur); - return; - } - - /* Otherwise see if we need to rewrite the offset... */ - fixup = find_reused_offset(offset) - - find_reused_offset(base_offset); - if (fixup) { - unsigned char ofs_header[10]; - unsigned i, ofs_len; - off_t ofs = offset - base_offset - fixup; - - len = encode_in_pack_object_header(header, sizeof(header), - OBJ_OFS_DELTA, size); + if (read_pack > to_write) + read_pack = to_write; - i = sizeof(ofs_header) - 1; - ofs_header[i] = ofs & 127; - while (ofs >>= 7) - ofs_header[--i] = 128 | (--ofs & 127); - - ofs_len = sizeof(ofs_header) - i; - - hashwrite(out, header, len); - hashwrite(out, ofs_header + sizeof(ofs_header) - ofs_len, ofs_len); - copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur); - return; - } - - /* ...otherwise we have no fixup, and can write it verbatim */ - } - - copy_pack_data(out, reuse_packfile, w_curs, offset, next - offset); -} - -static size_t write_reused_pack_verbatim(struct hashfile *out, - struct pack_window **w_curs) -{ - size_t pos = 0; - - while (pos < reuse_packfile_bitmap->word_alloc && - reuse_packfile_bitmap->words[pos] == (eword_t)~0) - pos++; - - if (pos) { - off_t to_write; - - written = (pos * BITS_IN_EWORD); - to_write = reuse_packfile->revindex[written].offset - - sizeof(struct pack_header); - - /* We're recording one chunk, not one object. */ - record_reused_object(sizeof(struct pack_header), 0); - hashflush(out); - copy_pack_data(out, reuse_packfile, w_curs, - sizeof(struct pack_header), to_write); + hashwrite(f, buffer, read_pack); + to_write -= read_pack; + /* + * We don't know the actual number of objects written, + * only how many bytes written, how many bytes total, and + * how many objects total. So we can fake it by pretending all + * objects we are writing are the same size. This gives us a + * smooth progress meter, and at the end it matches the true + * answer. + */ + written = reuse_packfile_objects * + (((double)(total - to_write)) / total); display_progress(progress_state, written); } - return pos; -} - -static void write_reused_pack(struct hashfile *f) -{ - size_t i = 0; - uint32_t offset; - struct pack_window *w_curs = NULL; - - if (allow_ofs_delta) - i = write_reused_pack_verbatim(f, &w_curs); - - for (; i < reuse_packfile_bitmap->word_alloc; ++i) { - eword_t word = reuse_packfile_bitmap->words[i]; - size_t pos = (i * BITS_IN_EWORD); - - for (offset = 0; offset < BITS_IN_EWORD; ++offset) { - if ((word >> offset) == 0) - break; - - offset += ewah_bit_ctz64(word >> offset); - write_reused_pack_one(pos + offset, f, &w_curs); - display_progress(progress_state, ++written); - } - } - unuse_pack(&w_curs); + close(fd); + written = reuse_packfile_objects; + display_progress(progress_state, written); + return reuse_packfile_offset - sizeof(struct pack_header); } static const char no_split_warning[] = N_( @@ -998,9 +867,11 @@ static void write_pack_file(void) offset = write_pack_header(f, nr_remaining); if (reuse_packfile) { + off_t packfile_size; assert(pack_to_stdout); - write_reused_pack(f); - offset = hashfile_total(f); + + packfile_size = write_reused_pack(f); + offset += packfile_size; } nr_written = 0; @@ -1125,15 +996,12 @@ static int no_try_delta(const char *path) * few lines later when we want to add the new entry. */ static int have_duplicate_entry(const struct object_id *oid, - int exclude) + int exclude, + uint32_t *index_pos) { struct object_entry *entry; - if (reuse_packfile_bitmap && - bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid)) - return 1; - - entry = packlist_find(&to_pack, oid); + entry = packlist_find(&to_pack, oid, index_pos); if (!entry) return 0; @@ -1273,12 +1141,13 @@ static void create_object_entry(const struct object_id *oid, uint32_t hash, int exclude, int no_try_delta, + uint32_t index_pos, struct packed_git *found_pack, off_t found_offset) { struct object_entry *entry; - entry = packlist_alloc(&to_pack, oid); + entry = packlist_alloc(&to_pack, oid->hash, index_pos); entry->hash = hash; oe_set_type(entry, type); if (exclude) @@ -1302,10 +1171,11 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, { struct packed_git *found_pack = NULL; off_t found_offset = 0; + uint32_t index_pos; display_progress(progress_state, ++nr_seen); - if (have_duplicate_entry(oid, exclude)) + if (have_duplicate_entry(oid, exclude, &index_pos)) return 0; if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { @@ -1320,7 +1190,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, create_object_entry(oid, type, pack_name_hash(name), exclude, name && no_try_delta(name), - found_pack, found_offset); + index_pos, found_pack, found_offset); return 1; } @@ -1329,15 +1199,17 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, int flags, uint32_t name_hash, struct packed_git *pack, off_t offset) { + uint32_t index_pos; + display_progress(progress_state, ++nr_seen); - if (have_duplicate_entry(oid, 0)) + if (have_duplicate_entry(oid, 0, &index_pos)) return 0; if (!want_object_in_pack(oid, 0, &pack, &offset)) return 0; - create_object_entry(oid, type, name_hash, 0, 0, pack, offset); + create_object_entry(oid, type, name_hash, 0, 0, index_pos, pack, offset); return 1; } @@ -1619,17 +1491,23 @@ static void cleanup_preferred_base(void) * deltify other objects against, in order to avoid * circular deltas. */ -static int can_reuse_delta(const struct object_id *base_oid, +static int can_reuse_delta(const unsigned char *base_sha1, struct object_entry *delta, struct object_entry **base_out) { struct object_entry *base; + struct object_id base_oid; + + if (!base_sha1) + return 0; + + oidread(&base_oid, base_sha1); /* * First see if we're already sending the base (or it's explicitly in * our "excluded" list). */ - base = packlist_find(&to_pack, base_oid); + base = packlist_find(&to_pack, &base_oid, NULL); if (base) { if (!in_same_island(&delta->idx.oid, &base->idx.oid)) return 0; @@ -1642,9 +1520,9 @@ static int can_reuse_delta(const struct object_id *base_oid, * even if it was buried too deep in history to make it into the * packing list. */ - if (thin && bitmap_has_oid_in_uninteresting(bitmap_git, base_oid)) { + if (thin && bitmap_has_oid_in_uninteresting(bitmap_git, &base_oid)) { if (use_delta_islands) { - if (!in_same_island(&delta->idx.oid, base_oid)) + if (!in_same_island(&delta->idx.oid, &base_oid)) return 0; } *base_out = NULL; @@ -1661,8 +1539,7 @@ static void check_object(struct object_entry *entry) if (IN_PACK(entry)) { struct packed_git *p = IN_PACK(entry); struct pack_window *w_curs = NULL; - int have_base = 0; - struct object_id base_ref; + const unsigned char *base_ref = NULL; struct object_entry *base_entry; unsigned long used, used_0; unsigned long avail; @@ -1703,13 +1580,9 @@ static void check_object(struct object_entry *entry) unuse_pack(&w_curs); return; case OBJ_REF_DELTA: - if (reuse_delta && !entry->preferred_base) { - oidread(&base_ref, - use_pack(p, &w_curs, - entry->in_pack_offset + used, - NULL)); - have_base = 1; - } + if (reuse_delta && !entry->preferred_base) + base_ref = use_pack(p, &w_curs, + entry->in_pack_offset + used, NULL); entry->in_pack_header_size = used + the_hash_algo->rawsz; break; case OBJ_OFS_DELTA: @@ -1739,15 +1612,13 @@ static void check_object(struct object_entry *entry) revidx = find_pack_revindex(p, ofs); if (!revidx) goto give_up; - if (!nth_packed_object_id(&base_ref, p, revidx->nr)) - have_base = 1; + base_ref = nth_packed_object_sha1(p, revidx->nr); } entry->in_pack_header_size = used + used_0; break; } - if (have_base && - can_reuse_delta(&base_ref, entry, &base_entry)) { + if (can_reuse_delta(base_ref, entry, &base_entry)) { oe_set_type(entry, entry->in_pack_type); SET_SIZE(entry, in_pack_size); /* delta size */ SET_DELTA_SIZE(entry, in_pack_size); @@ -1757,7 +1628,7 @@ static void check_object(struct object_entry *entry) entry->delta_sibling_idx = base_entry->delta_child_idx; SET_DELTA_CHILD(base_entry, entry); } else { - SET_DELTA_EXT(entry, &base_ref); + SET_DELTA_EXT(entry, base_ref); } unuse_pack(&w_curs); @@ -2471,6 +2342,15 @@ static void find_deltas(struct object_entry **list, unsigned *list_size, free(array); } +static void try_to_free_from_threads(size_t size) +{ + packing_data_lock(&to_pack); + release_pack_memory(size); + packing_data_unlock(&to_pack); +} + +static try_to_free_t old_try_to_free_routine; + /* * The main object list is split into smaller lists, each is handed to * one worker. @@ -2511,10 +2391,12 @@ static void init_threaded_search(void) pthread_mutex_init(&cache_mutex, NULL); pthread_mutex_init(&progress_mutex, NULL); pthread_cond_init(&progress_cond, NULL); + old_try_to_free_routine = set_try_to_free_routine(try_to_free_from_threads); } static void cleanup_threaded_search(void) { + set_try_to_free_routine(old_try_to_free_routine); pthread_cond_destroy(&progress_cond); pthread_mutex_destroy(&cache_mutex); pthread_mutex_destroy(&progress_mutex); @@ -2686,13 +2568,6 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size, free(p); } -static int obj_is_packed(const struct object_id *oid) -{ - return packlist_find(&to_pack, oid) || - (reuse_packfile_bitmap && - bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid)); -} - static void add_tag_chain(const struct object_id *oid) { struct tag *tag; @@ -2704,7 +2579,7 @@ static void add_tag_chain(const struct object_id *oid) * it was included via bitmaps, we would not have parsed it * previously). */ - if (obj_is_packed(oid)) + if (packlist_find(&to_pack, oid, NULL)) return; tag = lookup_tag(the_repository, oid); @@ -2728,7 +2603,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag, if (starts_with(path, "refs/tags/") && /* is a tag? */ !peel_ref(path, &peeled) && /* peelable? */ - obj_is_packed(&peeled)) /* object packed? */ + packlist_find(&to_pack, &peeled, NULL)) /* object packed? */ add_tag_chain(oid); return 0; } @@ -2796,7 +2671,6 @@ static void prepare_pack(int window, int depth) if (nr_deltas && n > 1) { unsigned nr_done = 0; - if (progress) progress_state = start_progress(_("Compressing objects"), nr_deltas); @@ -2841,8 +2715,8 @@ static int git_pack_config(const char *k, const char *v, void *cb) use_bitmap_index_default = git_config_bool(k, v); return 0; } - if (!strcmp(k, "pack.allowpackreuse")) { - allow_pack_reuse = git_config_bool(k, v); + if (!strcmp(k, "pack.usesparse")) { + sparse = git_config_bool(k, v); return 0; } if (!strcmp(k, "pack.threads")) { @@ -2929,7 +2803,7 @@ static void show_object(struct object *obj, const char *name, void *data) for (p = strchr(name, '/'); p; p = strchr(p + 1, '/')) depth++; - ent = packlist_find(&to_pack, &obj->oid); + ent = packlist_find(&to_pack, &obj->oid, NULL); if (ent && depth > oe_tree_depth(&to_pack, ent)) oe_set_tree_depth(&to_pack, ent, depth); } @@ -3055,7 +2929,7 @@ static void add_objects_in_unpacked_packs(void) in_pack.alloc); for (i = 0; i < p->num_objects; i++) { - nth_packed_object_id(&oid, p, i); + nth_packed_object_oid(&oid, p, i); o = lookup_unknown_object(&oid); if (!(o->flags & OBJECT_ADDED)) mark_in_pack_object(o, p, &in_pack); @@ -3159,8 +3033,8 @@ static void loosen_unused_packed_objects(void) die(_("cannot open pack index")); for (i = 0; i < p->num_objects; i++) { - nth_packed_object_id(&oid, p, i); - if (!packlist_find(&to_pack, &oid) && + nth_packed_object_oid(&oid, p, i); + if (!packlist_find(&to_pack, &oid, NULL) && !has_sha1_pack_kept_or_nonlocal(&oid) && !loosened_object_can_be_discarded(&oid, p->mtime)) if (force_object_loose(&oid, p->mtime)) @@ -3176,8 +3050,8 @@ static void loosen_unused_packed_objects(void) */ static int pack_options_allow_reuse(void) { - return allow_pack_reuse && - pack_to_stdout && + return pack_to_stdout && + allow_ofs_delta && !ignore_packed_keep_on_disk && !ignore_packed_keep_in_core && (!local || !have_non_local_packs) && @@ -3186,7 +3060,7 @@ static int pack_options_allow_reuse(void) static int get_object_list_from_bitmap(struct rev_info *revs) { - if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options))) + if (!(bitmap_git = prepare_bitmap_walk(revs))) return -1; if (pack_options_allow_reuse() && @@ -3194,14 +3068,13 @@ static int get_object_list_from_bitmap(struct rev_info *revs) bitmap_git, &reuse_packfile, &reuse_packfile_objects, - &reuse_packfile_bitmap)) { + &reuse_packfile_offset)) { assert(reuse_packfile_objects); nr_result += reuse_packfile_objects; display_progress(progress_state, nr_result); } - traverse_bitmap_commit_list(bitmap_git, revs, - &add_object_entry_from_bitmap); + traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap); return 0; } @@ -3470,10 +3343,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) read_replace_refs = 0; sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0); - prepare_repo_settings(the_repository); - if (!sparse && the_repository->settings.pack_use_sparse != -1) - sparse = the_repository->settings.pack_use_sparse; - reset_pack_idx_option(&pack_idx_opts); git_config(git_pack_config, NULL); @@ -3565,6 +3434,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (filter_options.choice) { if (!pack_to_stdout) die(_("cannot use --filter without --stdout")); + use_bitmap_index = 0; } /* @@ -3655,9 +3525,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (progress) fprintf_ln(stderr, _("Total %"PRIu32" (delta %"PRIu32")," - " reused %"PRIu32" (delta %"PRIu32")," - " pack-reused %"PRIu32), - written, written_delta, reused, reused_delta, - reuse_packfile_objects); + " reused %"PRIu32" (delta %"PRIu32")"), + written, written_delta, reused, reused_delta); return 0; } diff --git a/third_party/git/builtin/patch-id.c b/third_party/git/builtin/patch-id.c index 822ffff51fbd..bd28b80b2d0f 100644 --- a/third_party/git/builtin/patch-id.c +++ b/third_party/git/builtin/patch-id.c @@ -1,12 +1,16 @@ -#include "cache.h" #include "builtin.h" #include "config.h" #include "diff.h" static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result) { - if (patchlen) - printf("%s %s\n", oid_to_hex(result), oid_to_hex(id)); + char name[50]; + + if (!patchlen) + return; + + memcpy(name, oid_to_hex(id), GIT_SHA1_HEXSZ + 1); + printf("%s %s\n", oid_to_hex(result), name); } static int remove_space(char *line) @@ -56,9 +60,9 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result, { int patchlen = 0, found_next = 0; int before = -1, after = -1; - git_hash_ctx ctx; + git_SHA_CTX ctx; - the_hash_algo->init_fn(&ctx); + git_SHA1_Init(&ctx); oidclr(result); while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) { @@ -118,7 +122,7 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result, /* Compute the sha without whitespace */ len = remove_space(line); patchlen += len; - the_hash_algo->update_fn(&ctx, line, len); + git_SHA1_Update(&ctx, line, len); } if (!found_next) diff --git a/third_party/git/builtin/pull.c b/third_party/git/builtin/pull.c index 3e624d1e0085..f1eaf6e6edb1 100644 --- a/third_party/git/builtin/pull.c +++ b/third_party/git/builtin/pull.c @@ -15,7 +15,6 @@ #include "sha1-array.h" #include "remote.h" #include "dir.h" -#include "rebase.h" #include "refs.h" #include "refspec.h" #include "revision.h" @@ -27,6 +26,15 @@ #include "commit-reach.h" #include "sequencer.h" +enum rebase_type { + REBASE_INVALID = -1, + REBASE_FALSE = 0, + REBASE_TRUE, + REBASE_PRESERVE, + REBASE_MERGES, + REBASE_INTERACTIVE +}; + /** * Parses the value of --rebase. If value is a false value, returns * REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is @@ -37,9 +45,22 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value, int fatal) { - enum rebase_type v = rebase_parse_value(value); - if (v != REBASE_INVALID) - return v; + int v = git_parse_maybe_bool(value); + + if (!v) + return REBASE_FALSE; + else if (v > 0) + return REBASE_TRUE; + else if (!strcmp(value, "preserve") || !strcmp(value, "p")) + return REBASE_PRESERVE; + else if (!strcmp(value, "merges") || !strcmp(value, "m")) + return REBASE_MERGES; + else if (!strcmp(value, "interactive") || !strcmp(value, "i")) + return REBASE_INTERACTIVE; + /* + * Please update _git_config() in git-completion.bash when you + * add new rebase modes. + */ if (fatal) die(_("Invalid value for %s: %s"), key, value); @@ -86,7 +107,6 @@ static char *opt_ff; static char *opt_verify_signatures; static int opt_autostash = -1; static int config_autostash; -static int check_trust_level = 1; static struct argv_array opt_strategies = ARGV_ARRAY_INIT; static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT; static char *opt_gpg_sign; @@ -109,7 +129,6 @@ static char *opt_refmap; static char *opt_ipv4; static char *opt_ipv6; static int opt_show_forced_updates = -1; -static char *set_upstream; static struct option pull_options[] = { /* Shared options */ @@ -224,9 +243,6 @@ static struct option pull_options[] = { PARSE_OPT_NOARG), OPT_BOOL(0, "show-forced-updates", &opt_show_forced_updates, N_("check for forced-updates on all updated branches")), - OPT_PASSTHRU(0, "set-upstream", &set_upstream, NULL, - N_("set upstream for git pull/fetch"), - PARSE_OPT_NOARG), OPT_END() }; @@ -335,8 +351,6 @@ static enum rebase_type config_get_rebase(void) */ static int git_pull_config(const char *var, const char *value, void *cb) { - int status; - if (!strcmp(var, "rebase.autostash")) { config_autostash = git_config_bool(var, value); return 0; @@ -344,14 +358,7 @@ static int git_pull_config(const char *var, const char *value, void *cb) recurse_submodules = git_config_bool(var, value) ? RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; return 0; - } else if (!strcmp(var, "gpg.mintrustlevel")) { - check_trust_level = 0; } - - status = git_gpg_config(var, value, cb); - if (status) - return status; - return git_default_config(var, value, cb); } @@ -549,8 +556,6 @@ static int run_fetch(const char *repo, const char **refspecs) argv_array_push(&args, "--show-forced-updates"); else if (opt_show_forced_updates == 0) argv_array_push(&args, "--no-show-forced-updates"); - if (set_upstream) - argv_array_push(&args, set_upstream); if (repo) { argv_array_push(&args, repo); @@ -576,8 +581,7 @@ static int pull_into_void(const struct object_id *merge_head, die(_("unable to access commit %s"), oid_to_hex(merge_head)); - verify_merge_signature(commit, opt_verbosity, - check_trust_level); + verify_merge_signature(commit, opt_verbosity); } /* diff --git a/third_party/git/builtin/push.c b/third_party/git/builtin/push.c index 6dbf0f0bb713..021dd3b1e489 100644 --- a/third_party/git/builtin/push.c +++ b/third_party/git/builtin/push.c @@ -64,7 +64,6 @@ static struct string_list push_options_config = STRING_LIST_INIT_DUP; static const char *map_refspec(const char *ref, struct remote *remote, struct ref *local_refs) { - const char *branch_name; struct ref *matched = NULL; /* Does "ref" uniquely name our ref? */ @@ -85,8 +84,8 @@ static const char *map_refspec(const char *ref, } if (push_default == PUSH_DEFAULT_UPSTREAM && - skip_prefix(matched->name, "refs/heads/", &branch_name)) { - struct branch *branch = branch_get(branch_name); + starts_with(matched->name, "refs/heads/")) { + struct branch *branch = branch_get(matched->name + 11); if (branch->merge_nr == 1 && branch->merge[0]->src) { struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "%s:%s", @@ -144,8 +143,8 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p) return remote->url_nr; } -static NORETURN void die_push_simple(struct branch *branch, - struct remote *remote) +static NORETURN int die_push_simple(struct branch *branch, + struct remote *remote) { /* * There's no point in using shorten_unambiguous_ref here, @@ -358,10 +357,8 @@ static int push_with_options(struct transport *transport, struct refspec *rs, if (verbosity > 0) fprintf(stderr, _("Pushing to %s\n"), transport->url); - trace2_region_enter("push", "transport_push", the_repository); err = transport_push(the_repository, transport, rs, flags, &reject_reasons); - trace2_region_leave("push", "transport_push", the_repository); if (err != 0) { fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR)); error(_("failed to push some refs to '%s'"), transport->url); @@ -388,14 +385,30 @@ static int push_with_options(struct transport *transport, struct refspec *rs, } static int do_push(const char *repo, int flags, - const struct string_list *push_options, - struct remote *remote) + const struct string_list *push_options) { int i, errs; + struct remote *remote = pushremote_get(repo); const char **url; int url_nr; struct refspec *push_refspec = &rs; + if (!remote) { + if (repo) + die(_("bad repository '%s'"), repo); + die(_("No configured push destination.\n" + "Either specify the URL from the command-line or configure a remote repository using\n" + "\n" + " git remote add <name> <url>\n" + "\n" + "and then push using the remote name\n" + "\n" + " git push <name>\n")); + } + + if (remote->mirror) + flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); + if (push_options->nr) flags |= TRANSPORT_PUSH_OPTIONS; @@ -535,7 +548,6 @@ int cmd_push(int argc, const char **argv, const char *prefix) struct string_list push_options_cmdline = STRING_LIST_INIT_DUP; struct string_list *push_options; const struct string_list_item *item; - struct remote *remote; struct option options[] = { OPT__VERBOSITY(&verbosity), @@ -590,6 +602,20 @@ int cmd_push(int argc, const char **argv, const char *prefix) die(_("--delete is incompatible with --all, --mirror and --tags")); if (deleterefs && argc < 2) die(_("--delete doesn't make sense without any refs")); + if (flags & TRANSPORT_PUSH_ALL) { + if (tags) + die(_("--all and --tags are incompatible")); + if (argc >= 2) + die(_("--all can't be combined with refspecs")); + } + if (flags & TRANSPORT_PUSH_MIRROR) { + if (tags) + die(_("--mirror and --tags are incompatible")); + if (argc >= 2) + die(_("--mirror can't be combined with refspecs")); + } + if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR)) + die(_("--all and --mirror are incompatible")); if (recurse_submodules == RECURSE_SUBMODULES_CHECK) flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK; @@ -606,43 +632,11 @@ int cmd_push(int argc, const char **argv, const char *prefix) set_refspecs(argv + 1, argc - 1, repo); } - remote = pushremote_get(repo); - if (!remote) { - if (repo) - die(_("bad repository '%s'"), repo); - die(_("No configured push destination.\n" - "Either specify the URL from the command-line or configure a remote repository using\n" - "\n" - " git remote add <name> <url>\n" - "\n" - "and then push using the remote name\n" - "\n" - " git push <name>\n")); - } - - if (remote->mirror) - flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE); - - if (flags & TRANSPORT_PUSH_ALL) { - if (tags) - die(_("--all and --tags are incompatible")); - if (argc >= 2) - die(_("--all can't be combined with refspecs")); - } - if (flags & TRANSPORT_PUSH_MIRROR) { - if (tags) - die(_("--mirror and --tags are incompatible")); - if (argc >= 2) - die(_("--mirror can't be combined with refspecs")); - } - if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR)) - die(_("--all and --mirror are incompatible")); - for_each_string_list_item(item, push_options) if (strchr(item->string, '\n')) die(_("push options must not have new line characters")); - rc = do_push(repo, flags, push_options, remote); + rc = do_push(repo, flags, push_options); string_list_clear(&push_options_cmdline, 0); string_list_clear(&push_options_config, 0); if (rc == -1) diff --git a/third_party/git/builtin/range-diff.c b/third_party/git/builtin/range-diff.c index d8a467062990..9202e7554476 100644 --- a/third_party/git/builtin/range-diff.c +++ b/third_party/git/builtin/range-diff.c @@ -15,16 +15,12 @@ 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 argv_array other_arg = ARGV_ARRAY_INIT; int simple_color = -1; struct option range_diff_options[] = { OPT_INTEGER(0, "creation-factor", &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_END() }; struct option *options; @@ -82,9 +78,8 @@ 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); + simple_color < 1, &diffopt); - argv_array_clear(&other_arg); strbuf_release(&range1); strbuf_release(&range2); diff --git a/third_party/git/builtin/read-tree.c b/third_party/git/builtin/read-tree.c index af7424b94c8e..ca5e655d2f8b 100644 --- a/third_party/git/builtin/read-tree.c +++ b/third_party/git/builtin/read-tree.c @@ -185,7 +185,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (opts.reset || opts.merge || opts.prefix) { if (read_cache_unmerged() && (opts.prefix || opts.merge)) - die(_("You need to resolve your current index first")); + die("You need to resolve your current index first"); stage = opts.merge = 1; } resolve_undo_clear(); diff --git a/third_party/git/builtin/rebase.c b/third_party/git/builtin/rebase.c index bff53d5d167e..670096c065f5 100644 --- a/third_party/git/builtin/rebase.c +++ b/third_party/git/builtin/rebase.c @@ -29,8 +29,8 @@ #include "rebase-interactive.h" static char const * const builtin_rebase_usage[] = { - N_("git rebase [-i] [options] [--exec <cmd>] " - "[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"), + N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] " + "[<upstream>] [<branch>]"), N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] " "--root [<branch>]"), N_("git rebase --continue | --abort | --skip | --edit-todo"), @@ -44,22 +44,14 @@ static GIT_PATH_FUNC(merge_dir, "rebase-merge") enum rebase_type { REBASE_UNSPECIFIED = -1, - REBASE_APPLY, + REBASE_AM, REBASE_MERGE, + REBASE_INTERACTIVE, REBASE_PRESERVE_MERGES }; -enum empty_type { - EMPTY_UNSPECIFIED = -1, - EMPTY_DROP, - EMPTY_KEEP, - EMPTY_ASK -}; - struct rebase_options { enum rebase_type type; - enum empty_type empty; - const char *default_backend; const char *state_dir; struct commit *upstream; const char *upstream_name; @@ -70,7 +62,7 @@ struct rebase_options { const char *onto_name; const char *revisions; const char *switch_to; - int root, root_with_onto; + int root; struct object_id *squash_onto; struct commit *restrict_revision; int dont_finish_rebase; @@ -85,6 +77,7 @@ struct rebase_options { const char *action; int signoff; int allow_rerere_autoupdate; + int keep_empty; int autosquash; char *gpg_sign_opt; int autostash; @@ -99,8 +92,6 @@ struct rebase_options { #define REBASE_OPTIONS_INIT { \ .type = REBASE_UNSPECIFIED, \ - .empty = EMPTY_UNSPECIFIED, \ - .default_backend = "merge", \ .flags = REBASE_NO_QUIET, \ .git_am_opts = ARGV_ARRAY_INIT, \ .git_format_patch_opt = STRBUF_INIT \ @@ -119,9 +110,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) replay.allow_rerere_auto = opts->allow_rerere_autoupdate; replay.allow_empty = 1; replay.allow_empty_message = opts->allow_empty_message; - replay.drop_redundant_commits = (opts->empty == EMPTY_DROP); - replay.keep_redundant_commits = (opts->empty == EMPTY_KEEP); - replay.quiet = !(opts->flags & REBASE_NO_QUIET); replay.verbose = opts->flags & REBASE_VERBOSE; replay.reschedule_failed_exec = opts->reschedule_failed_exec; replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt); @@ -129,11 +117,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) if (opts->strategy_opts) parse_strategy_opts(&replay, opts->strategy_opts); - if (opts->squash_onto) { - oidcpy(&replay.squash_onto, opts->squash_onto); - replay.have_squash_onto = 1; - } - return replay; } @@ -258,17 +241,21 @@ static int edit_todo_file(unsigned flags) } static int get_revision_ranges(struct commit *upstream, struct commit *onto, - struct object_id *orig_head, const char **head_hash, + const char **head_hash, char **revisions, char **shortrevisions) { struct commit *base_rev = upstream ? upstream : onto; const char *shorthead; + struct object_id orig_head; - *head_hash = find_unique_abbrev(orig_head, GIT_MAX_HEXSZ); + if (get_oid("HEAD", &orig_head)) + return error(_("no HEAD?")); + + *head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ); *revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid), *head_hash); - shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV); + shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV); if (upstream) { const char *shortrev; @@ -322,8 +309,12 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) struct replay_opts replay = get_replay_opts(opts); struct string_list commands = STRING_LIST_INIT_DUP; - if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head, - &head_hash, &revisions, &shortrevisions)) + if (prepare_branch_to_be_rebased(the_repository, &replay, + opts->switch_to)) + return -1; + + if (get_revision_ranges(opts->upstream, opts->onto, &head_hash, + &revisions, &shortrevisions)) return -1; if (init_basic_state(&replay, @@ -341,8 +332,8 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) argv_array_pushl(&make_script_args, "", revisions, NULL); if (opts->restrict_revision) - argv_array_pushf(&make_script_args, "^%s", - oid_to_hex(&opts->restrict_revision->object.oid)); + argv_array_push(&make_script_args, + oid_to_hex(&opts->restrict_revision->object.oid)); ret = sequencer_make_script(the_repository, &todo_list.buf, make_script_args.argc, make_script_args.argv, @@ -371,7 +362,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) return ret; } -static int run_sequencer_rebase(struct rebase_options *opts, +static int run_rebase_interactive(struct rebase_options *opts, enum action command) { unsigned flags = 0; @@ -379,10 +370,10 @@ static int run_sequencer_rebase(struct rebase_options *opts, git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands); + flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0; flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0; flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0; flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0; - flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0; flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0; switch (command) { @@ -442,21 +433,6 @@ static int run_sequencer_rebase(struct rebase_options *opts, return ret; } -static int parse_opt_keep_empty(const struct option *opt, const char *arg, - int unset) -{ - struct rebase_options *opts = opt->value; - - BUG_ON_OPT_ARG(arg); - - /* - * If we ever want to remap --keep-empty to --empty=keep, insert: - * opts->empty = unset ? EMPTY_UNSPECIFIED : EMPTY_KEEP; - */ - opts->type = REBASE_MERGE; - return 0; -} - static const char * const builtin_rebase_interactive_usage[] = { N_("git rebase--interactive [<options>]"), NULL @@ -470,13 +446,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"), REBASE_FORCE), - { OPTION_CALLBACK, 'k', "keep-empty", &options, NULL, - N_("(DEPRECATED) keep empty commits"), - PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, - parse_opt_keep_empty }, - OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message, - N_("allow commits with empty messages"), - PARSE_OPT_HIDDEN), + OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")), + OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message, + N_("allow commits with empty messages")), OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")), OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins, N_("keep original branch points of cousins")), @@ -546,26 +518,28 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) warning(_("--[no-]rebase-cousins has no effect without " "--rebase-merges")); - return !!run_sequencer_rebase(&opts, command); + return !!run_rebase_interactive(&opts, command); } -static int is_merge(struct rebase_options *opts) +static int is_interactive(struct rebase_options *opts) { - return opts->type == REBASE_MERGE || + return opts->type == REBASE_INTERACTIVE || opts->type == REBASE_PRESERVE_MERGES; } -static void imply_merge(struct rebase_options *opts, const char *option) +static void imply_interactive(struct rebase_options *opts, const char *option) { switch (opts->type) { - case REBASE_APPLY: + case REBASE_AM: die(_("%s requires an interactive rebase"), option); break; - case REBASE_MERGE: + case REBASE_INTERACTIVE: case REBASE_PRESERVE_MERGES: break; + case REBASE_MERGE: + /* we now implement --merge via --interactive */ default: - opts->type = REBASE_MERGE; /* implied */ + opts->type = REBASE_INTERACTIVE; /* implied */ break; } } @@ -691,8 +665,8 @@ static int rebase_write_basic_state(struct rebase_options *opts) opts->onto ? oid_to_hex(&opts->onto->object.oid) : ""); write_file(state_dir_path("orig-head", opts), "%s", oid_to_hex(&opts->orig_head)); - if (!(opts->flags & REBASE_NO_QUIET)) - write_file(state_dir_path("quiet", opts), "%s", ""); + write_file(state_dir_path("quiet", opts), "%s", + opts->flags & REBASE_NO_QUIET ? "" : "t"); if (opts->flags & REBASE_VERBOSE) write_file(state_dir_path("verbose", opts), "%s", ""); if (opts->strategy) @@ -710,7 +684,7 @@ static int rebase_write_basic_state(struct rebase_options *opts) write_file(state_dir_path("gpg_sign_opt", opts), "%s", opts->gpg_sign_opt); if (opts->signoff) - write_file(state_dir_path("signoff", opts), "--signoff"); + write_file(state_dir_path("strategy", opts), "--signoff"); return 0; } @@ -774,7 +748,7 @@ static int finish_rebase(struct rebase_options *opts) * user should see them. */ run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); - if (opts->type == REBASE_MERGE) { + if (opts->type == REBASE_INTERACTIVE) { struct replay_opts replay = REPLAY_OPTS_INIT; replay.action = REPLAY_INTERACTIVE_REBASE; @@ -1037,8 +1011,7 @@ static int run_am(struct rebase_options *opts) argv_array_pushl(&format_patch.args, "format-patch", "-k", "--stdout", "--full-index", "--cherry-pick", "--right-only", "--src-prefix=a/", "--dst-prefix=b/", "--no-renames", - "--no-cover-letter", "--pretty=mboxrd", "--topo-order", - "--no-base", NULL); + "--no-cover-letter", "--pretty=mboxrd", "--topo-order", NULL); if (opts->git_format_patch_opt.len) argv_array_split(&format_patch.args, opts->git_format_patch_opt.buf); @@ -1107,8 +1080,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) int status; const char *backend, *backend_func; - if (opts->type == REBASE_MERGE) { - /* Run sequencer-based rebase */ + if (opts->type == REBASE_INTERACTIVE) { + /* Run builtin interactive rebase */ setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1); if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) { setenv("GIT_SEQUENCE_EDITOR", ":", 1); @@ -1121,11 +1094,11 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) opts->gpg_sign_opt = tmp; } - status = run_sequencer_rebase(opts, action); + status = run_rebase_interactive(opts, action); goto finished_rebase; } - if (opts->type == REBASE_APPLY) { + if (opts->type == REBASE_AM) { status = run_am(opts); goto finished_rebase; } @@ -1145,6 +1118,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) add_var(&script_snippet, "revisions", opts->revisions); add_var(&script_snippet, "restrict_revision", opts->restrict_revision ? oid_to_hex(&opts->restrict_revision->object.oid) : NULL); + add_var(&script_snippet, "GIT_QUIET", + opts->flags & REBASE_NO_QUIET ? "" : "t"); sq_quote_argv_pretty(&buf, opts->git_am_opts.argv); add_var(&script_snippet, "git_am_opt", buf.buf); strbuf_release(&buf); @@ -1162,6 +1137,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) opts->allow_rerere_autoupdate ? opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ? "--rerere-autoupdate" : "--no-rerere-autoupdate" : ""); + add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : ""); add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : ""); add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt); add_var(&script_snippet, "cmd", opts->cmd); @@ -1179,7 +1155,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) add_var(&script_snippet, "git_format_patch_opt", opts->git_format_patch_opt.buf); - if (is_merge(opts) && + if (is_interactive(opts) && !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) { strbuf_addstr(&script_snippet, "GIT_SEQUENCE_EDITOR=:; export GIT_SEQUENCE_EDITOR; "); @@ -1204,8 +1180,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action) finished_rebase: if (opts->dont_finish_rebase) ; /* do nothing */ - else if (opts->type == REBASE_MERGE) - ; /* merge backend cleans up after itself */ + else if (opts->type == REBASE_INTERACTIVE) + ; /* interactive rebase cleans up after itself */ else if (status == 0) { if (!file_exists(state_dir_path("stopped-sha", opts))) finish_rebase(opts); @@ -1263,10 +1239,6 @@ static int rebase_config(const char *var, const char *value, void *data) return 0; } - if (!strcmp(var, "rebase.backend")) { - return git_config_string(&opts->default_backend, var, value); - } - return git_default_config(var, value, data); } @@ -1288,60 +1260,28 @@ static int is_linear_history(struct commit *from, struct commit *to) return 1; } -static int can_fast_forward(struct commit *onto, struct commit *upstream, - struct commit *restrict_revision, - struct object_id *head_oid, struct object_id *merge_base) +static int can_fast_forward(struct commit *onto, struct object_id *head_oid, + struct object_id *merge_base) { struct commit *head = lookup_commit(the_repository, head_oid); - struct commit_list *merge_bases = NULL; - int res = 0; + struct commit_list *merge_bases; + int res; if (!head) - goto done; + return 0; merge_bases = get_merge_bases(onto, head); - if (!merge_bases || merge_bases->next) { + if (merge_bases && !merge_bases->next) { + oidcpy(merge_base, &merge_bases->item->object.oid); + res = oideq(merge_base, &onto->object.oid); + } else { oidcpy(merge_base, &null_oid); - goto done; + res = 0; } - - oidcpy(merge_base, &merge_bases->item->object.oid); - if (!oideq(merge_base, &onto->object.oid)) - goto done; - - if (restrict_revision && !oideq(&restrict_revision->object.oid, merge_base)) - goto done; - - if (!upstream) - goto done; - - free_commit_list(merge_bases); - merge_bases = get_merge_bases(upstream, head); - if (!merge_bases || merge_bases->next) - goto done; - - if (!oideq(&onto->object.oid, &merge_bases->item->object.oid)) - goto done; - - res = 1; - -done: free_commit_list(merge_bases); return res && is_linear_history(onto, head); } -static int parse_opt_am(const struct option *opt, const char *arg, int unset) -{ - struct rebase_options *opts = opt->value; - - BUG_ON_OPT_NEG(unset); - BUG_ON_OPT_ARG(arg); - - opts->type = REBASE_APPLY; - - return 0; -} - /* -i followed by -m is still -i */ static int parse_opt_merge(const struct option *opt, const char *arg, int unset) { @@ -1350,7 +1290,7 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset) BUG_ON_OPT_NEG(unset); BUG_ON_OPT_ARG(arg); - if (!is_merge(opts)) + if (!is_interactive(opts)) opts->type = REBASE_MERGE; return 0; @@ -1365,35 +1305,12 @@ static int parse_opt_interactive(const struct option *opt, const char *arg, BUG_ON_OPT_NEG(unset); BUG_ON_OPT_ARG(arg); - opts->type = REBASE_MERGE; + opts->type = REBASE_INTERACTIVE; opts->flags |= REBASE_INTERACTIVE_EXPLICIT; return 0; } -static enum empty_type parse_empty_value(const char *value) -{ - if (!strcasecmp(value, "drop")) - return EMPTY_DROP; - else if (!strcasecmp(value, "keep")) - return EMPTY_KEEP; - else if (!strcasecmp(value, "ask")) - return EMPTY_ASK; - - die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value); -} - -static int parse_opt_empty(const struct option *opt, const char *arg, int unset) -{ - struct rebase_options *options = opt->value; - enum empty_type value = parse_empty_value(arg); - - BUG_ON_OPT_NEG(unset); - - options->empty = value; - return 0; -} - static void NORETURN error_on_missing_default_upstream(void) { struct branch *current_branch = branch_get(NULL); @@ -1429,14 +1346,14 @@ static void set_reflog_action(struct rebase_options *options) const char *env; struct strbuf buf = STRBUF_INIT; - if (!is_merge(options)) + if (!is_interactive(options)) return; env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT); if (env && strcmp("rebase", env)) return; /* only override it if it is "rebase" */ - strbuf_addf(&buf, "rebase (%s)", options->action); + strbuf_addf(&buf, "rebase -i (%s)", options->action); setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1); strbuf_release(&buf); } @@ -1459,7 +1376,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) struct rebase_options options = REBASE_OPTIONS_INIT; const char *branch_name; int ret, flags, total_argc, in_progress = 0; - int keep_base = 0; int ok_to_skip_pre_rebase = 0; struct strbuf msg = STRBUF_INIT; struct strbuf revisions = STRBUF_INIT; @@ -1474,18 +1390,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) struct object_id squash_onto; char *squash_onto_name = NULL; int reschedule_failed_exec = -1; - int allow_preemptive_ff = 1; struct option builtin_rebase_options[] = { OPT_STRING(0, "onto", &options.onto_name, N_("revision"), N_("rebase onto given branch instead of upstream")), - OPT_BOOL(0, "keep-base", &keep_base, - N_("use the merge-base of upstream and branch as the current base")), OPT_BOOL(0, "no-verify", &ok_to_skip_pre_rebase, N_("allow pre-rebase hook to run")), OPT_NEGBIT('q', "quiet", &options.flags, N_("be quiet. implies --no-stat"), - REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT), + REBASE_NO_QUIET| REBASE_VERBOSE | REBASE_DIFFSTAT), OPT_BIT('v', "verbose", &options.flags, N_("display a diffstat of what changed upstream"), REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT), @@ -1526,10 +1439,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_CMDMODE(0, "show-current-patch", &action, N_("show the patch file being applied or merged"), ACTION_SHOW_CURRENT_PATCH), - { OPTION_CALLBACK, 0, "apply", &options, NULL, - N_("use apply strategies to rebase"), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, - parse_opt_am }, { OPTION_CALLBACK, 'm', "merge", &options, NULL, N_("use merging strategies to rebase"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, @@ -1538,18 +1447,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) N_("let the user edit the list of commits to rebase"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_interactive }, - OPT_SET_INT_F('p', "preserve-merges", &options.type, - N_("(DEPRECATED) try to recreate merges instead of " - "ignoring them"), - REBASE_PRESERVE_MERGES, PARSE_OPT_HIDDEN), + OPT_SET_INT('p', "preserve-merges", &options.type, + N_("(DEPRECATED) try to recreate merges instead of " + "ignoring them"), REBASE_PRESERVE_MERGES), OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate), - OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}", - N_("how to handle commits that become empty"), - PARSE_OPT_NONEG, parse_opt_empty), - { OPTION_CALLBACK, 'k', "keep-empty", &options, NULL, - N_("(DEPRECATED) keep empty commits"), - PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, - parse_opt_keep_empty }, + OPT_BOOL('k', "keep-empty", &options.keep_empty, + N_("preserve empty commits during rebase")), OPT_BOOL(0, "autosquash", &options.autosquash, N_("move commits that begin with " "squash!/fixup! under -i")), @@ -1561,10 +1464,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_STRING_LIST('x', "exec", &exec, N_("exec"), N_("add exec lines after each commit of the " "editable list")), - OPT_BOOL_F(0, "allow-empty-message", - &options.allow_empty_message, - N_("allow rebasing commits with empty messages"), - PARSE_OPT_HIDDEN), + OPT_BOOL(0, "allow-empty-message", + &options.allow_empty_message, + N_("allow rebasing commits with empty messages")), {OPTION_STRING, 'r', "rebase-merges", &rebase_merges, N_("mode"), N_("try to rebase merges instead of skipping them"), @@ -1604,7 +1506,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) die(_("It looks like 'git am' is in progress. Cannot rebase.")); if (is_directory(apply_dir())) { - options.type = REBASE_APPLY; + options.type = REBASE_AM; options.state_dir = apply_dir(); } else if (is_directory(merge_dir())) { strbuf_reset(&buf); @@ -1616,7 +1518,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) strbuf_reset(&buf); strbuf_addf(&buf, "%s/interactive", merge_dir()); if(file_exists(buf.buf)) { - options.type = REBASE_MERGE; + options.type = REBASE_INTERACTIVE; options.flags |= REBASE_INTERACTIVE_EXPLICIT; } else options.type = REBASE_MERGE; @@ -1645,23 +1547,16 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) warning(_("git rebase --preserve-merges is deprecated. " "Use --rebase-merges instead.")); - if (keep_base) { - if (options.onto_name) - die(_("cannot combine '--keep-base' with '--onto'")); - if (options.root) - die(_("cannot combine '--keep-base' with '--root'")); - } - if (action != ACTION_NONE && !in_progress) die(_("No rebase in progress?")); setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0); - if (action == ACTION_EDIT_TODO && !is_merge(&options)) + if (action == ACTION_EDIT_TODO && !is_interactive(&options)) die(_("The --edit-todo action can only be used during " "interactive rebase.")); if (trace2_is_enabled()) { - if (is_merge(&options)) + if (is_interactive(&options)) trace2_cmd_mode("interactive"); else if (exec.nr) trace2_cmd_mode("interactive-exec"); @@ -1737,7 +1632,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) goto cleanup; } case ACTION_QUIT: { - if (options.type == REBASE_MERGE) { + if (options.type == REBASE_INTERACTIVE) { struct replay_opts replay = REPLAY_OPTS_INIT; replay.action = REPLAY_INTERACTIVE_REBASE; @@ -1786,20 +1681,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) state_dir_base, cmd_live_rebase, buf.buf); } - if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) || - (action != ACTION_NONE) || - (exec.nr > 0) || - options.autosquash) { - allow_preemptive_ff = 0; - } - for (i = 0; i < options.git_am_opts.argc; i++) { const char *option = options.git_am_opts.argv[i], *p; if (!strcmp(option, "--committer-date-is-author-date") || !strcmp(option, "--ignore-date") || !strcmp(option, "--whitespace=fix") || !strcmp(option, "--whitespace=strip")) - allow_preemptive_ff = 0; + options.flags |= REBASE_FORCE; else if (skip_prefix(option, "-C", &p)) { while (*p) if (!isdigit(*(p++))) @@ -1819,8 +1707,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (!(options.flags & REBASE_NO_QUIET)) argv_array_push(&options.git_am_opts, "-q"); - if (options.empty != EMPTY_UNSPECIFIED) - imply_merge(&options, "--empty"); + if (options.keep_empty) + imply_interactive(&options, "--keep-empty"); if (gpg_sign) { free(options.gpg_sign_opt); @@ -1830,7 +1718,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (exec.nr) { int i; - imply_merge(&options, "--exec"); + imply_interactive(&options, "--exec"); strbuf_reset(&buf); for (i = 0; i < exec.nr; i++) @@ -1846,7 +1734,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) else if (strcmp("no-rebase-cousins", rebase_merges)) die(_("Unknown mode: %s"), rebase_merges); options.rebase_merges = 1; - imply_merge(&options, "--rebase-merges"); + imply_interactive(&options, "--rebase-merges"); } if (strategy_options.nr) { @@ -1865,9 +1753,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (options.strategy) { options.strategy = xstrdup(options.strategy); switch (options.type) { - case REBASE_APPLY: + case REBASE_AM: die(_("--strategy requires --merge or --interactive")); case REBASE_MERGE: + case REBASE_INTERACTIVE: case REBASE_PRESERVE_MERGES: /* compatible */ break; @@ -1880,65 +1769,47 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) } if (options.type == REBASE_MERGE) - imply_merge(&options, "--merge"); + imply_interactive(&options, "--merge"); if (options.root && !options.onto_name) - imply_merge(&options, "--root without --onto"); + imply_interactive(&options, "--root without --onto"); if (isatty(2) && options.flags & REBASE_NO_QUIET) strbuf_addstr(&options.git_format_patch_opt, " --progress"); - if (options.git_am_opts.argc || options.type == REBASE_APPLY) { - /* all am options except -q are compatible only with --apply */ - for (i = options.git_am_opts.argc - 1; i >= 0; i--) - if (strcmp(options.git_am_opts.argv[i], "-q")) - break; - - if (i >= 0) { - if (is_merge(&options)) - die(_("cannot combine apply options with " - "merge options")); - else - options.type = REBASE_APPLY; - } - } - - if (options.type == REBASE_UNSPECIFIED) { - if (!strcmp(options.default_backend, "merge")) - imply_merge(&options, "--merge"); - else if (!strcmp(options.default_backend, "apply")) - options.type = REBASE_APPLY; - else - die(_("Unknown rebase backend: %s"), - options.default_backend); - } - switch (options.type) { case REBASE_MERGE: + case REBASE_INTERACTIVE: case REBASE_PRESERVE_MERGES: options.state_dir = merge_dir(); break; - case REBASE_APPLY: + case REBASE_AM: options.state_dir = apply_dir(); break; default: - BUG("options.type was just set above; should be unreachable."); + /* the default rebase backend is `--am` */ + options.type = REBASE_AM; + options.state_dir = apply_dir(); + break; } - if (options.empty == EMPTY_UNSPECIFIED) { - if (options.flags & REBASE_INTERACTIVE_EXPLICIT) - options.empty = EMPTY_ASK; - else if (exec.nr > 0) - options.empty = EMPTY_KEEP; - else - options.empty = EMPTY_DROP; - } - if (reschedule_failed_exec > 0 && !is_merge(&options)) + if (reschedule_failed_exec > 0 && !is_interactive(&options)) die(_("--reschedule-failed-exec requires " "--exec or --interactive")); if (reschedule_failed_exec >= 0) options.reschedule_failed_exec = reschedule_failed_exec; + if (options.git_am_opts.argc) { + /* all am options except -q are compatible only with --am */ + for (i = options.git_am_opts.argc - 1; i >= 0; i--) + if (strcmp(options.git_am_opts.argv[i], "-q")) + break; + + if (is_interactive(&options) && i >= 0) + die(_("cannot combine am options with either " + "interactive or merge options")); + } + if (options.signoff) { if (options.type == REBASE_PRESERVE_MERGES) die("cannot combine '--signoff' with " @@ -1962,6 +1833,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) "'--reschedule-failed-exec'")); } + if (options.rebase_merges) { + if (strategy_options.nr) + die(_("cannot combine '--rebase-merges' with " + "'--strategy-option'")); + if (options.strategy) + die(_("cannot combine '--rebase-merges' with " + "'--strategy'")); + } + if (!options.root) { if (argc < 1) { struct branch *branch; @@ -1992,9 +1872,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) options.squash_onto = &squash_onto; options.onto_name = squash_onto_name = xstrdup(oid_to_hex(&squash_onto)); - } else - options.root_with_onto = 1; - + } options.upstream_name = NULL; options.upstream = NULL; if (argc > 1) @@ -2004,22 +1882,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) } /* Make sure the branch to rebase onto is valid. */ - if (keep_base) { - strbuf_reset(&buf); - strbuf_addstr(&buf, options.upstream_name); - strbuf_addstr(&buf, "..."); - options.onto_name = xstrdup(buf.buf); - } else if (!options.onto_name) + if (!options.onto_name) options.onto_name = options.upstream_name; if (strstr(options.onto_name, "...")) { - if (get_oid_mb(options.onto_name, &merge_base) < 0) { - if (keep_base) - die(_("'%s': need exactly one merge base with branch"), - options.upstream_name); - else - die(_("'%s': need exactly one merge base"), - options.onto_name); - } + if (get_oid_mb(options.onto_name, &merge_base) < 0) + die(_("'%s': need exactly one merge base"), + options.onto_name); options.onto = lookup_commit_or_die(&merge_base, options.onto_name); } else { @@ -2044,11 +1912,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) /* Is it a local branch? */ strbuf_reset(&buf); strbuf_addf(&buf, "refs/heads/%s", branch_name); - if (!read_ref(buf.buf, &options.orig_head)) { - die_if_checked_out(buf.buf, 1); + if (!read_ref(buf.buf, &options.orig_head)) options.head_name = xstrdup(buf.buf); /* If not is it a valid ref (branch or commit)? */ - } else if (!get_oid(branch_name, &options.orig_head)) + else if (!get_oid(branch_name, &options.orig_head)) options.head_name = NULL; else die(_("fatal: no such branch/commit '%s'"), @@ -2101,6 +1968,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) state_dir_path("autostash", &options); struct child_process stash = CHILD_PROCESS_INIT; struct object_id oid; + struct commit *head = + lookup_commit_reference(the_repository, + &options.orig_head); argv_array_pushl(&stash.args, "stash", "create", "autostash", NULL); @@ -2121,9 +1991,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) options.state_dir); write_file(autostash, "%s", oid_to_hex(&oid)); printf(_("Created autostash: %s\n"), buf.buf); - if (reset_head(NULL, "reset --hard", + if (reset_head(&head->object.oid, "reset --hard", NULL, RESET_HEAD_HARD, NULL, NULL) < 0) die(_("could not reset --hard")); + printf(_("HEAD is now at %s"), + find_unique_abbrev(&head->object.oid, + DEFAULT_ABBREV)); + strbuf_reset(&buf); + pp_commit_easy(CMIT_FMT_ONELINE, head, &buf); + if (buf.len > 0) + printf(" %s", buf.buf); + putchar('\n'); if (discard_index(the_repository->index) < 0 || repo_read_index(the_repository) < 0) @@ -2144,25 +2022,31 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) /* * Check if we are already based on onto with linear history, - * in which case we could fast-forward without replacing the commits - * with new commits recreated by replaying their changes. - * - * Note that can_fast_forward() initializes merge_base, so we have to - * call it before checking allow_preemptive_ff. + * but this should be done only when upstream and onto are the same + * and if this is not an interactive rebase. */ - if (can_fast_forward(options.onto, options.upstream, options.restrict_revision, - &options.orig_head, &merge_base) && - allow_preemptive_ff) { + if (can_fast_forward(options.onto, &options.orig_head, &merge_base) && + !is_interactive(&options) && !options.restrict_revision && + options.upstream && + !oidcmp(&options.upstream->object.oid, &options.onto->object.oid)) { int flag; if (!(options.flags & REBASE_FORCE)) { /* Lazily switch to the target branch if needed... */ if (options.switch_to) { + struct object_id oid; + + if (get_oid(options.switch_to, &oid) < 0) { + ret = !!error(_("could not parse '%s'"), + options.switch_to); + goto cleanup; + } + strbuf_reset(&buf); strbuf_addf(&buf, "%s: checkout %s", getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.switch_to); - if (reset_head(&options.orig_head, "checkout", + if (reset_head(&oid, "checkout", options.head_name, RESET_HEAD_RUN_POST_CHECKOUT_HOOK, NULL, buf.buf) < 0) { @@ -2227,7 +2111,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) diff_flush(&opts); } - if (is_merge(&options)) + if (is_interactive(&options)) goto run_rebase; /* Detach HEAD and reset the tree */ diff --git a/third_party/git/builtin/receive-pack.c b/third_party/git/builtin/receive-pack.c index 2cc18bbffdcf..dcf385511f07 100644 --- a/third_party/git/builtin/receive-pack.c +++ b/third_party/git/builtin/receive-pack.c @@ -27,7 +27,6 @@ #include "object-store.h" #include "protocol.h" #include "commit-reach.h" -#include "worktree.h" static const char * const receive_pack_usage[] = { N_("git receive-pack <git-dir>"), @@ -418,22 +417,24 @@ static int copy_to_sideband(int in, int out, void *arg) return 0; } -static void hmac(unsigned char *out, +#define HMAC_BLOCK_SIZE 64 + +static void hmac_sha1(unsigned char *out, const char *key_in, size_t key_len, const char *text, size_t text_len) { - unsigned char key[GIT_MAX_BLKSZ]; - unsigned char k_ipad[GIT_MAX_BLKSZ]; - unsigned char k_opad[GIT_MAX_BLKSZ]; + unsigned char key[HMAC_BLOCK_SIZE]; + unsigned char k_ipad[HMAC_BLOCK_SIZE]; + unsigned char k_opad[HMAC_BLOCK_SIZE]; int i; - git_hash_ctx ctx; + git_SHA_CTX ctx; /* RFC 2104 2. (1) */ - memset(key, '\0', GIT_MAX_BLKSZ); - if (the_hash_algo->blksz < key_len) { - the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, key_in, key_len); - the_hash_algo->final_fn(key, &ctx); + memset(key, '\0', HMAC_BLOCK_SIZE); + if (HMAC_BLOCK_SIZE < key_len) { + git_SHA1_Init(&ctx); + git_SHA1_Update(&ctx, key_in, key_len); + git_SHA1_Final(key, &ctx); } else { memcpy(key, key_in, key_len); } @@ -445,29 +446,29 @@ static void hmac(unsigned char *out, } /* RFC 2104 2. (3) & (4) */ - the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, k_ipad, sizeof(k_ipad)); - the_hash_algo->update_fn(&ctx, text, text_len); - the_hash_algo->final_fn(out, &ctx); + git_SHA1_Init(&ctx); + git_SHA1_Update(&ctx, k_ipad, sizeof(k_ipad)); + git_SHA1_Update(&ctx, text, text_len); + git_SHA1_Final(out, &ctx); /* RFC 2104 2. (6) & (7) */ - the_hash_algo->init_fn(&ctx); - the_hash_algo->update_fn(&ctx, k_opad, sizeof(k_opad)); - the_hash_algo->update_fn(&ctx, out, the_hash_algo->rawsz); - the_hash_algo->final_fn(out, &ctx); + git_SHA1_Init(&ctx); + git_SHA1_Update(&ctx, k_opad, sizeof(k_opad)); + git_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ); + git_SHA1_Final(out, &ctx); } static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp) { struct strbuf buf = STRBUF_INIT; - unsigned char hash[GIT_MAX_RAWSZ]; + unsigned char sha1[GIT_SHA1_RAWSZ]; strbuf_addf(&buf, "%s:%"PRItime, path, stamp); - hmac(hash, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed)); + hmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed)); strbuf_release(&buf); /* RFC 2104 5. HMAC-SHA1-80 */ - strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, (int)the_hash_algo->hexsz, hash_to_hex(hash)); + strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, GIT_SHA1_HEXSZ, sha1_to_hex(sha1)); return strbuf_detach(&buf, NULL); } @@ -817,6 +818,16 @@ static int run_update_hook(struct command *cmd) return finish_command(&proc); } +static int is_ref_checked_out(const char *ref) +{ + if (is_bare_repository()) + return 0; + + if (!head_name) + return 0; + return !strcmp(head_name, ref); +} + static char *refuse_unconfigured_deny_msg = N_("By default, updating the current branch in a non-bare repository\n" "is denied, because it will make the index and work tree inconsistent\n" @@ -959,7 +970,7 @@ static const char *push_to_deploy(unsigned char *sha1, if (run_command(&child)) return "Working directory has staged changes"; - read_tree[3] = hash_to_hex(sha1); + read_tree[3] = sha1_to_hex(sha1); child_process_init(&child); child.argv = read_tree; child.env = env->argv; @@ -976,38 +987,28 @@ static const char *push_to_deploy(unsigned char *sha1, static const char *push_to_checkout_hook = "push-to-checkout"; -static const char *push_to_checkout(unsigned char *hash, +static const char *push_to_checkout(unsigned char *sha1, struct argv_array *env, const char *work_tree) { argv_array_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree)); if (run_hook_le(env->argv, push_to_checkout_hook, - hash_to_hex(hash), NULL)) + sha1_to_hex(sha1), NULL)) return "push-to-checkout hook declined"; else return NULL; } -static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) +static const char *update_worktree(unsigned char *sha1) { - const char *retval, *work_tree, *git_dir = NULL; + const char *retval; + const char *work_tree = git_work_tree_cfg ? git_work_tree_cfg : ".."; struct argv_array env = ARGV_ARRAY_INIT; - if (worktree && worktree->path) - work_tree = worktree->path; - else if (git_work_tree_cfg) - work_tree = git_work_tree_cfg; - else - work_tree = ".."; - if (is_bare_repository()) return "denyCurrentBranch = updateInstead needs a worktree"; - if (worktree) - git_dir = get_worktree_git_dir(worktree); - if (!git_dir) - git_dir = get_git_dir(); - argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir)); + argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(get_git_dir())); if (!find_hook(push_to_checkout_hook)) retval = push_to_deploy(sha1, &env, work_tree); @@ -1027,7 +1028,6 @@ static const char *update(struct command *cmd, struct shallow_info *si) struct object_id *old_oid = &cmd->old_oid; struct object_id *new_oid = &cmd->new_oid; int do_update_worktree = 0; - const struct worktree *worktree = is_bare_repository() ? NULL : find_shared_symref("HEAD", name); /* only refs/... are allowed */ if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) { @@ -1039,7 +1039,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) free(namespaced_name); namespaced_name = strbuf_detach(&namespaced_name_buf, NULL); - if (worktree) { + if (is_ref_checked_out(namespaced_name)) { switch (deny_current_branch) { case DENY_IGNORE: break; @@ -1071,7 +1071,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) return "deletion prohibited"; } - if (worktree || (head_name && !strcmp(namespaced_name, head_name))) { + if (head_name && !strcmp(namespaced_name, head_name)) { switch (deny_delete_current) { case DENY_IGNORE: break; @@ -1120,7 +1120,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) } if (do_update_worktree) { - ret = update_worktree(new_oid->hash, find_shared_symref("HEAD", name)); + ret = update_worktree(new_oid->hash); if (ret) return ret; } diff --git a/third_party/git/builtin/reflog.c b/third_party/git/builtin/reflog.c index 81dfd563c0d9..4d3430900d06 100644 --- a/third_party/git/builtin/reflog.c +++ b/third_party/git/builtin/reflog.c @@ -560,16 +560,15 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) { const char *arg = argv[i]; - if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) flags |= EXPIRE_REFLOGS_DRY_RUN; - else if (skip_prefix(arg, "--expire=", &arg)) { - if (parse_expiry_date(arg, &cb.cmd.expire_total)) + else if (starts_with(arg, "--expire=")) { + if (parse_expiry_date(arg + 9, &cb.cmd.expire_total)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_TOTAL; } - else if (skip_prefix(arg, "--expire-unreachable=", &arg)) { - if (parse_expiry_date(arg, &cb.cmd.expire_unreachable)) + else if (starts_with(arg, "--expire-unreachable=")) { + if (parse_expiry_date(arg + 21, &cb.cmd.expire_unreachable)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_UNREACH; } diff --git a/third_party/git/builtin/remote.c b/third_party/git/builtin/remote.c index 555d4c896c5f..5591cef77543 100644 --- a/third_party/git/builtin/remote.c +++ b/third_party/git/builtin/remote.c @@ -6,7 +6,6 @@ #include "string-list.h" #include "strbuf.h" #include "run-command.h" -#include "rebase.h" #include "refs.h" #include "refspec.h" #include "object-store.h" @@ -249,8 +248,9 @@ static int add(int argc, const char **argv) struct branch_info { char *remote_name; struct string_list merge; - enum rebase_type rebase; - char *push_remote_name; + enum { + NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE, REBASE_MERGES + } rebase; }; static struct string_list branch_list = STRING_LIST_INIT_NODUP; @@ -264,69 +264,59 @@ static const char *abbrev_ref(const char *name, const char *prefix) static int config_read_branches(const char *key, const char *value, void *cb) { - const char *orig_key = key; - char *name; - struct string_list_item *item; - struct branch_info *info; - enum { REMOTE, MERGE, REBASE, PUSH_REMOTE } type; - size_t key_len; + if (starts_with(key, "branch.")) { + const char *orig_key = key; + char *name; + struct string_list_item *item; + struct branch_info *info; + enum { REMOTE, MERGE, REBASE } type; + size_t key_len; + + key += 7; + if (strip_suffix(key, ".remote", &key_len)) { + name = xmemdupz(key, key_len); + type = REMOTE; + } else if (strip_suffix(key, ".merge", &key_len)) { + name = xmemdupz(key, key_len); + type = MERGE; + } else if (strip_suffix(key, ".rebase", &key_len)) { + name = xmemdupz(key, key_len); + type = REBASE; + } else + return 0; - if (!starts_with(key, "branch.")) - return 0; + item = string_list_insert(&branch_list, name); - key += strlen("branch."); - if (strip_suffix(key, ".remote", &key_len)) - type = REMOTE; - else if (strip_suffix(key, ".merge", &key_len)) - type = MERGE; - else if (strip_suffix(key, ".rebase", &key_len)) - type = REBASE; - else if (strip_suffix(key, ".pushremote", &key_len)) - type = PUSH_REMOTE; - else - return 0; - name = xmemdupz(key, key_len); - - item = string_list_insert(&branch_list, name); - - if (!item->util) - item->util = xcalloc(1, sizeof(struct branch_info)); - info = item->util; - switch (type) { - case REMOTE: - if (info->remote_name) - warning(_("more than one %s"), orig_key); - info->remote_name = xstrdup(value); - break; - case MERGE: { - char *space = strchr(value, ' '); - value = abbrev_branch(value); - while (space) { - char *merge; - merge = xstrndup(value, space - value); - string_list_append(&info->merge, merge); - value = abbrev_branch(space + 1); - space = strchr(value, ' '); + if (!item->util) + item->util = xcalloc(1, sizeof(struct branch_info)); + info = item->util; + if (type == REMOTE) { + if (info->remote_name) + warning(_("more than one %s"), orig_key); + info->remote_name = xstrdup(value); + } else if (type == MERGE) { + char *space = strchr(value, ' '); + value = abbrev_branch(value); + while (space) { + char *merge; + merge = xstrndup(value, space - value); + string_list_append(&info->merge, merge); + value = abbrev_branch(space + 1); + space = strchr(value, ' '); + } + string_list_append(&info->merge, xstrdup(value)); + } else { + int v = git_parse_maybe_bool(value); + if (v >= 0) + info->rebase = v; + else if (!strcmp(value, "preserve")) + info->rebase = NORMAL_REBASE; + else if (!strcmp(value, "merges")) + info->rebase = REBASE_MERGES; + else if (!strcmp(value, "interactive")) + info->rebase = INTERACTIVE_REBASE; } - string_list_append(&info->merge, xstrdup(value)); - break; - } - case REBASE: - /* - * Consider invalid values as false and check the - * truth value with >= REBASE_TRUE. - */ - info->rebase = rebase_parse_value(value); - break; - case PUSH_REMOTE: - if (info->push_remote_name) - warning(_("more than one %s"), orig_key); - info->push_remote_name = xstrdup(value); - break; - default: - BUG("unexpected type=%d", type); } - return 0; } @@ -615,56 +605,6 @@ static int migrate_file(struct remote *remote) return 0; } -struct push_default_info -{ - const char *old_name; - enum config_scope scope; - struct strbuf origin; - int linenr; -}; - -static int config_read_push_default(const char *key, const char *value, - void *cb) -{ - struct push_default_info* info = cb; - if (strcmp(key, "remote.pushdefault") || - !value || strcmp(value, info->old_name)) - return 0; - - info->scope = current_config_scope(); - strbuf_reset(&info->origin); - strbuf_addstr(&info->origin, current_config_name()); - info->linenr = current_config_line(); - - return 0; -} - -static void handle_push_default(const char* old_name, const char* new_name) -{ - struct push_default_info push_default = { - old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 }; - git_config(config_read_push_default, &push_default); - if (push_default.scope >= CONFIG_SCOPE_COMMAND) - ; /* pass */ - else if (push_default.scope >= CONFIG_SCOPE_LOCAL) { - int result = git_config_set_gently("remote.pushDefault", - new_name); - if (new_name && result && result != CONFIG_NOTHING_SET) - die(_("could not set '%s'"), "remote.pushDefault"); - else if (!new_name && result && result != CONFIG_NOTHING_SET) - die(_("could not unset '%s'"), "remote.pushDefault"); - } else if (push_default.scope >= CONFIG_SCOPE_SYSTEM) { - /* warn */ - warning(_("The %s configuration remote.pushDefault in:\n" - "\t%s:%d\n" - "now names the non-existent remote '%s'"), - config_scope_name(push_default.scope), - push_default.origin.buf, push_default.linenr, - old_name); - } -} - - static int mv(int argc, const char **argv) { struct option options[] = { @@ -740,11 +680,6 @@ static int mv(int argc, const char **argv) strbuf_addf(&buf, "branch.%s.remote", item->string); git_config_set(buf.buf, rename.new_name); } - if (info->push_remote_name && !strcmp(info->push_remote_name, rename.old_name)) { - strbuf_reset(&buf); - strbuf_addf(&buf, "branch.%s.pushremote", item->string); - git_config_set(buf.buf, rename.new_name); - } } if (!refspec_updated) @@ -758,8 +693,9 @@ static int mv(int argc, const char **argv) for (i = 0; i < remote_branches.nr; i++) { struct string_list_item *item = remote_branches.items + i; int flag = 0; + struct object_id oid; - read_ref_full(item->string, RESOLVE_REF_READING, NULL, &flag); + read_ref_full(item->string, RESOLVE_REF_READING, &oid, &flag); if (!(flag & REF_ISSYMREF)) continue; if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF)) @@ -800,9 +736,6 @@ static int mv(int argc, const char **argv) die(_("creating '%s' failed"), buf.buf); } string_list_clear(&remote_branches, 1); - - handle_push_default(rename.old_name, rename.new_name); - return 0; } @@ -849,13 +782,6 @@ static int rm(int argc, const char **argv) die(_("could not unset '%s'"), buf.buf); } } - if (info->push_remote_name && !strcmp(info->push_remote_name, remote->name)) { - strbuf_reset(&buf); - strbuf_addf(&buf, "branch.%s.pushremote", item->string); - result = git_config_set_gently(buf.buf, NULL); - if (result && result != CONFIG_NOTHING_SET) - die(_("could not unset '%s'"), buf.buf); - } } /* @@ -888,8 +814,6 @@ static int rm(int argc, const char **argv) strbuf_addf(&buf, "remote.%s", remote->name); if (git_config_rename_section(buf.buf, NULL) < 1) return error(_("Could not remove config section '%s'"), buf.buf); - - handle_push_default(remote->name, NULL); } return result; @@ -1020,7 +944,7 @@ static int add_local_to_show_info(struct string_list_item *branch_item, void *cb return 0; if ((n = strlen(branch_item->string)) > show_info->width) show_info->width = n; - if (branch_info->rebase >= REBASE_TRUE) + if (branch_info->rebase) show_info->any_rebase = 1; item = string_list_insert(show_info->list, branch_item->string); @@ -1037,16 +961,16 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data) int width = show_info->width + 4; int i; - if (branch_info->rebase >= REBASE_TRUE && branch_info->merge.nr > 1) { + if (branch_info->rebase && branch_info->merge.nr > 1) { error(_("invalid branch.%s.merge; cannot rebase onto > 1 branch"), item->string); return 0; } printf(" %-*s ", show_info->width, item->string); - if (branch_info->rebase >= REBASE_TRUE) { + if (branch_info->rebase) { const char *msg; - if (branch_info->rebase == REBASE_INTERACTIVE) + if (branch_info->rebase == INTERACTIVE_REBASE) msg = _("rebases interactively onto remote %s"); else if (branch_info->rebase == REBASE_MERGES) msg = _("rebases interactively (with merges) onto " diff --git a/third_party/git/builtin/repack.c b/third_party/git/builtin/repack.c index 0781763b06e8..632c0c0a7942 100644 --- a/third_party/git/builtin/repack.c +++ b/third_party/git/builtin/repack.c @@ -11,7 +11,6 @@ #include "midx.h" #include "packfile.h" #include "object-store.h" -#include "promisor-remote.h" static int delta_base_offset = 1; static int pack_kept_objects = -1; @@ -191,7 +190,7 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack, die(_("could not start pack-objects to repack promisor objects")); } - xwrite(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz); + xwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ); xwrite(cmd->in, "\n", 1); return 0; } @@ -233,13 +232,6 @@ static void repack_promisor_objects(const struct pack_objects_args *args, /* * pack-objects creates the .pack and .idx files, but not the * .promisor file. Create the .promisor file, which is empty. - * - * NEEDSWORK: fetch-pack sometimes generates non-empty - * .promisor files containing the ref names and associated - * hashes at the point of generation of the corresponding - * packfile, but this would not preserve their contents. Maybe - * concatenate the contents of all .promisor files instead of - * just creating a new empty file. */ promisor_name = mkpathdup("%s-%s.promisor", packtmp, line.buf); @@ -369,7 +361,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argv_array_push(&cmd.args, "--all"); argv_array_push(&cmd.args, "--reflog"); argv_array_push(&cmd.args, "--indexed-objects"); - if (has_promisor_remote()) + if (repository_format_partial_clone) argv_array_push(&cmd.args, "--exclude-promisor-objects"); if (write_bitmaps > 0) argv_array_push(&cmd.args, "--write-bitmap-index"); @@ -569,7 +561,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) remove_temporary_files(); if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) - write_midx_file(get_object_directory(), 0); + write_midx_file(get_object_directory()); string_list_clear(&names, 0); string_list_clear(&rollback, 0); diff --git a/third_party/git/builtin/replace.c b/third_party/git/builtin/replace.c index b36d17a657f3..644b21ca8d57 100644 --- a/third_party/git/builtin/replace.c +++ b/third_party/git/builtin/replace.c @@ -272,7 +272,7 @@ static int import_object(struct object_id *oid, enum object_type type, return error(_("unable to spawn mktree")); } - if (strbuf_read(&result, cmd.out, the_hash_algo->hexsz + 1) < 0) { + if (strbuf_read(&result, cmd.out, 41) < 0) { error_errno(_("unable to read from mktree")); close(fd); close(cmd.out); @@ -358,15 +358,14 @@ static int replace_parents(struct strbuf *buf, int argc, const char **argv) struct strbuf new_parents = STRBUF_INIT; const char *parent_start, *parent_end; int i; - const unsigned hexsz = the_hash_algo->hexsz; /* find existing parents */ parent_start = buf->buf; - parent_start += hexsz + 6; /* "tree " + "hex sha1" + "\n" */ + parent_start += GIT_SHA1_HEXSZ + 6; /* "tree " + "hex sha1" + "\n" */ parent_end = parent_start; while (starts_with(parent_end, "parent ")) - parent_end += hexsz + 8; /* "parent " + "hex sha1" + "\n" */ + parent_end += 48; /* "parent " + "hex sha1" + "\n" */ /* prepare new parents */ for (i = 0; i < argc; i++) { @@ -409,8 +408,7 @@ static int check_one_mergetag(struct commit *commit, struct tag *tag; int i; - hash_object_file(the_hash_algo, extra->value, extra->len, - type_name(OBJ_TAG), &tag_oid); + hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &tag_oid); tag = lookup_tag(the_repository, &tag_oid); if (!tag) return error(_("bad mergetag in commit '%s'"), ref); @@ -423,7 +421,7 @@ static int check_one_mergetag(struct commit *commit, if (get_oid(mergetag_data->argv[i], &oid) < 0) return error(_("not a valid object name: '%s'"), mergetag_data->argv[i]); - if (oideq(get_tagged_oid(tag), &oid)) + if (oideq(&tag->tagged->oid, &oid)) return 0; /* found */ } diff --git a/third_party/git/builtin/reset.c b/third_party/git/builtin/reset.c index 18228c312ea0..fdd572168b51 100644 --- a/third_party/git/builtin/reset.c +++ b/third_party/git/builtin/reset.c @@ -30,9 +30,8 @@ static const char * const git_reset_usage[] = { N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"), - N_("git reset [-q] [<tree-ish>] [--] <pathspec>..."), - N_("git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"), - N_("git reset --patch [<tree-ish>] [--] [<pathspec>...]"), + N_("git reset [-q] [<tree-ish>] [--] <paths>..."), + N_("git reset --patch [<tree-ish>] [--] [<paths>...]"), NULL }; @@ -285,8 +284,8 @@ static int git_reset_config(const char *var, const char *value, void *cb) int cmd_reset(int argc, const char **argv, const char *prefix) { int reset_type = NONE, update_ref_status = 0, quiet = 0; - int patch_mode = 0, pathspec_file_nul = 0, unborn; - const char *rev, *pathspec_from_file = NULL; + int patch_mode = 0, unborn; + const char *rev; struct object_id oid; struct pathspec pathspec; int intent_to_add = 0; @@ -307,8 +306,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix) OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")), OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that removed paths will be added later")), - OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), OPT_END() }; @@ -319,25 +316,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH); parse_args(&pathspec, argv, prefix, patch_mode, &rev); - if (pathspec_from_file) { - if (patch_mode) - die(_("--pathspec-from-file is incompatible with --patch")); - - if (pathspec.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - parse_pathspec_file(&pathspec, 0, - PATHSPEC_PREFER_FULL, - prefix, pathspec_from_file, pathspec_file_nul); - } else if (pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ oidcpy(&oid, the_hash_algo->empty_tree); - } else if (!pathspec.nr && !patch_mode) { + } else if (!pathspec.nr) { struct commit *commit; if (get_oid_committish(rev, &oid)) die(_("Failed to resolve '%s' as a valid revision."), rev); diff --git a/third_party/git/builtin/rev-list.c b/third_party/git/builtin/rev-list.c index f520111eda09..301ccb970bb3 100644 --- a/third_party/git/builtin/rev-list.c +++ b/third_party/git/builtin/rev-list.c @@ -18,6 +18,7 @@ #include "reflog-walk.h" #include "oidset.h" #include "packfile.h" +#include "object-store.h" static const char rev_list_usage[] = "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n" @@ -253,26 +254,11 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) static void show_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; - struct rev_info *revs = info->revs; - if (finish_object(obj, name, cb_data)) return; display_progress(progress, ++progress_counter); if (info->flags & REV_LIST_QUIET) return; - - if (revs->count) { - /* - * The object count is always accumulated in the .count_right - * field for traversal that is not a left-right traversal, - * and cmd_rev_list() made sure that a .count request that - * wants to count non-commit objects, which is handled by - * the show_object() callback, does not ask for .left_right. - */ - revs->count_right++; - return; - } - if (arg_show_object_names) show_object_with_name(stdout, obj, name); else @@ -379,79 +365,6 @@ static inline int parse_missing_action_value(const char *value) return 0; } -static int try_bitmap_count(struct rev_info *revs, - struct list_objects_filter_options *filter) -{ - uint32_t commit_count = 0, - tag_count = 0, - tree_count = 0, - blob_count = 0; - int max_count; - struct bitmap_index *bitmap_git; - - /* This function only handles counting, not general traversal. */ - if (!revs->count) - return -1; - - /* - * A bitmap result can't know left/right, etc, because we don't - * actually traverse. - */ - if (revs->left_right || revs->cherry_mark) - return -1; - - /* - * If we're counting reachable objects, we can't handle a max count of - * commits to traverse, since we don't know which objects go with which - * commit. - */ - if (revs->max_count >= 0 && - (revs->tag_objects || revs->tree_objects || revs->blob_objects)) - return -1; - - /* - * This must be saved before doing any walking, since the revision - * machinery will count it down to zero while traversing. - */ - max_count = revs->max_count; - - bitmap_git = prepare_bitmap_walk(revs, filter); - if (!bitmap_git) - return -1; - - count_bitmap_commit_list(bitmap_git, &commit_count, - revs->tree_objects ? &tree_count : NULL, - revs->blob_objects ? &blob_count : NULL, - revs->tag_objects ? &tag_count : NULL); - if (max_count >= 0 && max_count < commit_count) - commit_count = max_count; - - printf("%d\n", commit_count + tree_count + blob_count + tag_count); - free_bitmap_index(bitmap_git); - return 0; -} - -static int try_bitmap_traversal(struct rev_info *revs, - struct list_objects_filter_options *filter) -{ - struct bitmap_index *bitmap_git; - - /* - * We can't use a bitmap result with a traversal limit, since the set - * of commits we'd get would be essentially random. - */ - if (revs->max_count >= 0) - return -1; - - bitmap_git = prepare_bitmap_walk(revs, filter); - if (!bitmap_git) - return -1; - - traverse_bitmap_commit_list(bitmap_git, revs, &show_object_fast); - free_bitmap_index(bitmap_git); - return 0; -} - int cmd_rev_list(int argc, const char **argv, const char *prefix) { struct rev_info revs; @@ -558,6 +471,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) parse_list_objects_filter(&filter_options, arg); if (filter_options.choice && !revs.blob_objects) die(_("object filtering requires --objects")); + if (filter_options.choice == LOFC_SPARSE_OID && + !filter_options.sparse_oid_value) + die(_("invalid sparse value '%s'"), + filter_options.filter_spec); continue; } if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) { @@ -609,10 +526,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (revs.show_notes) die(_("rev-list does not support display of notes")); - if (revs.count && - (revs.tag_objects || revs.tree_objects || revs.blob_objects) && - (revs.left_right || revs.cherry_mark)) - die(_("marked counting is incompatible with --objects")); + if (filter_options.choice && use_bitmap_index) + die(_("cannot combine --use-bitmap-index with object filtering")); save_commit_buffer = (revs.verbose_header || revs.grep_filter.pattern_list || @@ -623,11 +538,28 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (show_progress) progress = start_delayed_progress(show_progress, 0); - if (use_bitmap_index) { - if (!try_bitmap_count(&revs, &filter_options)) - return 0; - if (!try_bitmap_traversal(&revs, &filter_options)) - return 0; + if (use_bitmap_index && !revs.prune) { + if (revs.count && !revs.left_right && !revs.cherry_mark) { + uint32_t commit_count; + int max_count = revs.max_count; + struct bitmap_index *bitmap_git; + if ((bitmap_git = prepare_bitmap_walk(&revs))) { + count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL); + if (max_count >= 0 && max_count < commit_count) + commit_count = max_count; + printf("%d\n", commit_count); + free_bitmap_index(bitmap_git); + return 0; + } + } else if (revs.max_count < 0 && + revs.tag_objects && revs.tree_objects && revs.blob_objects) { + struct bitmap_index *bitmap_git; + if ((bitmap_git = prepare_bitmap_walk(&revs))) { + traverse_bitmap_commit_list(bitmap_git, &show_object_fast); + free_bitmap_index(bitmap_git); + return 0; + } + } } if (prepare_revision_walk(&revs)) diff --git a/third_party/git/builtin/rev-parse.c b/third_party/git/builtin/rev-parse.c index 7a00da820355..f8bbe6d47ec3 100644 --- a/third_party/git/builtin/rev-parse.c +++ b/third_party/git/builtin/rev-parse.c @@ -593,7 +593,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) const char *name = NULL; struct object_context unused; struct strbuf buf = STRBUF_INIT; - const int hexsz = the_hash_algo->hexsz; if (argc > 1 && !strcmp("--parseopt", argv[1])) return cmd_parseopt(argc - 1, argv + 1, prefix); @@ -731,8 +730,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) abbrev = strtoul(arg, NULL, 10); if (abbrev < MINIMUM_ABBREV) abbrev = MINIMUM_ABBREV; - else if (hexsz <= abbrev) - abbrev = hexsz; + else if (40 <= abbrev) + abbrev = 40; continue; } if (!strcmp(arg, "--sq")) { @@ -803,8 +802,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) const char *work_tree = get_git_work_tree(); if (work_tree) puts(work_tree); - else - die("this operation must be run in a work tree"); continue; } if (!strcmp(arg, "--show-superproject-working-tree")) { @@ -921,17 +918,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) show_datestring("--min-age=", arg); continue; } - if (opt_with_value(arg, "--show-object-format", &arg)) { - const char *val = arg ? arg : "storage"; - - if (strcmp(val, "storage") && - strcmp(val, "input") && - strcmp(val, "output")) - die("unknown mode for --show-object-format: %s", - arg); - puts(the_hash_algo->name); - continue; - } if (show_flag(arg) && verify) die_no_single_rev(quiet); continue; diff --git a/third_party/git/builtin/rm.c b/third_party/git/builtin/rm.c index 4858631e0f02..19ce95a901bc 100644 --- a/third_party/git/builtin/rm.c +++ b/third_party/git/builtin/rm.c @@ -235,8 +235,7 @@ static int check_local_mod(struct object_id *head, int index_only) } static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0; -static int ignore_unmatch = 0, pathspec_file_nul; -static char *pathspec_from_file; +static int ignore_unmatch = 0; static struct option builtin_rm_options[] = { OPT__DRY_RUN(&show_only, N_("dry run")), @@ -246,8 +245,6 @@ static struct option builtin_rm_options[] = { OPT_BOOL('r', NULL, &recursive, N_("allow recursive removal")), OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch, N_("exit with a zero status even if nothing matched")), - OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), OPT_END(), }; @@ -262,24 +259,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_rm_options, builtin_rm_usage, 0); - - parse_pathspec(&pathspec, 0, - PATHSPEC_PREFER_CWD, - prefix, argv); - - if (pathspec_from_file) { - if (pathspec.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - parse_pathspec_file(&pathspec, 0, - PATHSPEC_PREFER_CWD, - prefix, pathspec_from_file, pathspec_file_nul); - } else if (pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - - if (!pathspec.nr) - die(_("No pathspec was given. Which files should I remove?")); + if (!argc) + usage_with_options(builtin_rm_usage, builtin_rm_options); if (!index_only) setup_work_tree(); @@ -289,6 +270,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (read_cache() < 0) die(_("index file corrupt")); + parse_pathspec(&pathspec, 0, + PATHSPEC_PREFER_CWD, + prefix, argv); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL); seen = xcalloc(pathspec.nr, 1); diff --git a/third_party/git/builtin/show-branch.c b/third_party/git/builtin/show-branch.c index 8c90cbb18f07..35d7f51c236d 100644 --- a/third_party/git/builtin/show-branch.c +++ b/third_party/git/builtin/show-branch.c @@ -536,7 +536,7 @@ static void append_one_rev(const char *av) append_ref(av, &revkey, 0); return; } - if (strpbrk(av, "*?[")) { + if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) { /* glob style match */ int saved_matches = ref_name_cnt; diff --git a/third_party/git/builtin/show-index.c b/third_party/git/builtin/show-index.c index 0826f6a5a2c2..a6e678809efe 100644 --- a/third_party/git/builtin/show-index.c +++ b/third_party/git/builtin/show-index.c @@ -11,7 +11,6 @@ int cmd_show_index(int argc, const char **argv, const char *prefix) unsigned nr; unsigned int version; static unsigned int top_index[256]; - const unsigned hashsz = the_hash_algo->rawsz; if (argc != 1) usage(show_index_usage); @@ -37,23 +36,23 @@ int cmd_show_index(int argc, const char **argv, const char *prefix) } if (version == 1) { for (i = 0; i < nr; i++) { - unsigned int offset, entry[(GIT_MAX_RAWSZ + 4) / sizeof(unsigned int)]; + unsigned int offset, entry[6]; - if (fread(entry, 4 + hashsz, 1, stdin) != 1) + if (fread(entry, 4 + 20, 1, stdin) != 1) die("unable to read entry %u/%u", i, nr); offset = ntohl(entry[0]); - printf("%u %s\n", offset, hash_to_hex((void *)(entry+1))); + printf("%u %s\n", offset, sha1_to_hex((void *)(entry+1))); } } else { unsigned off64_nr = 0; struct { - struct object_id oid; + unsigned char sha1[20]; uint32_t crc; uint32_t off; } *entries; ALLOC_ARRAY(entries, nr); for (i = 0; i < nr; i++) - if (fread(entries[i].oid.hash, hashsz, 1, stdin) != 1) + if (fread(entries[i].sha1, 20, 1, stdin) != 1) die("unable to read sha1 %u/%u", i, nr); for (i = 0; i < nr; i++) if (fread(&entries[i].crc, 4, 1, stdin) != 1) @@ -78,7 +77,7 @@ int cmd_show_index(int argc, const char **argv, const char *prefix) } printf("%" PRIuMAX " %s (%08"PRIx32")\n", (uintmax_t) offset, - oid_to_hex(&entries[i].oid), + sha1_to_hex(entries[i].sha1), ntohl(entries[i].crc)); } free(entries); diff --git a/third_party/git/builtin/sparse-checkout.c b/third_party/git/builtin/sparse-checkout.c deleted file mode 100644 index 740da4b6d54a..000000000000 --- a/third_party/git/builtin/sparse-checkout.c +++ /dev/null @@ -1,631 +0,0 @@ -#include "builtin.h" -#include "config.h" -#include "dir.h" -#include "parse-options.h" -#include "pathspec.h" -#include "repository.h" -#include "run-command.h" -#include "strbuf.h" -#include "string-list.h" -#include "cache.h" -#include "cache-tree.h" -#include "lockfile.h" -#include "resolve-undo.h" -#include "unpack-trees.h" -#include "wt-status.h" -#include "quote.h" - -static const char *empty_base = ""; - -static char const * const builtin_sparse_checkout_usage[] = { - N_("git sparse-checkout (init|list|set|add|disable) <options>"), - 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; - - for (i = 0; i < pl->nr; i++) { - struct path_pattern *p = pl->patterns[i]; - - if (p->flags & PATTERN_FLAG_NEGATIVE) - fprintf(fp, "!"); - - fprintf(fp, "%s", p->pattern); - - if (p->flags & PATTERN_FLAG_MUSTBEDIR) - fprintf(fp, "/"); - - fprintf(fp, "\n"); - } -} - -static int sparse_checkout_list(int argc, const char **argv) -{ - struct pattern_list pl; - char *sparse_filename; - int res; - - memset(&pl, 0, sizeof(pl)); - - 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); - free(sparse_filename); - - if (res < 0) { - warning(_("this worktree is not sparse (sparse-checkout file may not exist)")); - return 0; - } - - if (pl.use_cone_patterns) { - int i; - struct pattern_entry *pe; - struct hashmap_iter iter; - struct string_list sl = STRING_LIST_INIT_DUP; - - hashmap_for_each_entry(&pl.recursive_hashmap, &iter, pe, ent) { - /* pe->pattern starts with "/", skip it */ - string_list_insert(&sl, pe->pattern + 1); - } - - string_list_sort(&sl); - - for (i = 0; i < sl.nr; i++) { - quote_c_style(sl.items[i].string, NULL, stdout, 0); - printf("\n"); - } - - return 0; - } - - write_patterns_to_file(stdout, &pl); - clear_pattern_list(&pl); - - return 0; -} - -static int update_working_directory(struct pattern_list *pl) -{ - int result = 0; - struct unpack_trees_options o; - struct lock_file lock_file = LOCK_INIT; - struct object_id oid; - struct tree *tree; - struct tree_desc t; - struct repository *r = the_repository; - - if (repo_read_index_unmerged(r)) - die(_("you need to resolve your current index first")); - - if (get_oid("HEAD", &oid)) - return 0; - - tree = parse_tree_indirect(&oid); - parse_tree(tree); - init_tree_desc(&t, tree->buffer, tree->size); - - memset(&o, 0, sizeof(o)); - o.verbose_update = isatty(2); - o.merge = 1; - o.update = 1; - o.fn = oneway_merge; - o.head_idx = -1; - o.src_index = r->index; - o.dst_index = r->index; - o.skip_sparse_checkout = 0; - o.pl = pl; - o.keep_pattern_list = !!pl; - - resolve_undo_clear_index(r->index); - setup_work_tree(); - - cache_tree_free(&r->index->cache_tree); - - repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR); - - core_apply_sparse_checkout = 1; - result = unpack_trees(1, &t, &o); - - if (!result) { - prime_cache_tree(r, r->index, tree); - write_locked_index(r->index, &lock_file, COMMIT_LOCK); - } else - rollback_lock_file(&lock_file); - - return result; -} - -static char *escaped_pattern(char *pattern) -{ - char *p = pattern; - struct strbuf final = STRBUF_INIT; - - while (*p) { - if (is_glob_special(*p)) - strbuf_addch(&final, '\\'); - - strbuf_addch(&final, *p); - p++; - } - - return strbuf_detach(&final, NULL); -} - -static void write_cone_to_file(FILE *fp, struct pattern_list *pl) -{ - int i; - struct pattern_entry *pe; - struct hashmap_iter iter; - struct string_list sl = STRING_LIST_INIT_DUP; - struct strbuf parent_pattern = STRBUF_INIT; - - hashmap_for_each_entry(&pl->parent_hashmap, &iter, pe, ent) { - if (hashmap_get_entry(&pl->recursive_hashmap, pe, ent, NULL)) - continue; - - if (!hashmap_contains_parent(&pl->recursive_hashmap, - pe->pattern, - &parent_pattern)) - string_list_insert(&sl, pe->pattern); - } - - string_list_sort(&sl); - string_list_remove_duplicates(&sl, 0); - - fprintf(fp, "/*\n!/*/\n"); - - for (i = 0; i < sl.nr; i++) { - char *pattern = escaped_pattern(sl.items[i].string); - - if (strlen(pattern)) - fprintf(fp, "%s/\n!%s/*/\n", pattern, pattern); - free(pattern); - } - - string_list_clear(&sl, 0); - - hashmap_for_each_entry(&pl->recursive_hashmap, &iter, pe, ent) { - if (!hashmap_contains_parent(&pl->recursive_hashmap, - pe->pattern, - &parent_pattern)) - string_list_insert(&sl, pe->pattern); - } - - strbuf_release(&parent_pattern); - - string_list_sort(&sl); - string_list_remove_duplicates(&sl, 0); - - for (i = 0; i < sl.nr; i++) { - char *pattern = escaped_pattern(sl.items[i].string); - fprintf(fp, "%s/\n", pattern); - free(pattern); - } -} - -static int write_patterns_and_update(struct pattern_list *pl) -{ - char *sparse_filename; - FILE *fp; - int fd; - struct lock_file lk = LOCK_INIT; - int result; - - sparse_filename = get_sparse_checkout_filename(); - - if (safe_create_leading_directories(sparse_filename)) - die(_("failed to create directory for sparse-checkout file")); - - fd = hold_lock_file_for_update(&lk, sparse_filename, - LOCK_DIE_ON_ERROR); - - result = update_working_directory(pl); - if (result) { - rollback_lock_file(&lk); - free(sparse_filename); - clear_pattern_list(pl); - update_working_directory(NULL); - return result; - } - - fp = xfdopen(fd, "w"); - - if (core_sparse_checkout_cone) - write_cone_to_file(fp, pl); - else - write_patterns_to_file(fp, pl); - - fflush(fp); - commit_lock_file(&lk); - - free(sparse_filename); - clear_pattern_list(pl); - - return 0; -} - -enum sparse_checkout_mode { - MODE_NO_PATTERNS = 0, - MODE_ALL_PATTERNS = 1, - MODE_CONE_PATTERNS = 2, -}; - -static int set_config(enum sparse_checkout_mode mode) -{ - const char *config_path; - - if (git_config_set_gently("extensions.worktreeConfig", "true")) { - error(_("failed to set extensions.worktreeConfig setting")); - return 1; - } - - config_path = git_path("config.worktree"); - git_config_set_in_file_gently(config_path, - "core.sparseCheckout", - mode ? "true" : NULL); - - git_config_set_in_file_gently(config_path, - "core.sparseCheckoutCone", - mode == MODE_CONE_PATTERNS ? "true" : NULL); - - return 0; -} - -static char const * const builtin_sparse_checkout_init_usage[] = { - N_("git sparse-checkout init [--cone]"), - NULL -}; - -static struct sparse_checkout_init_opts { - int cone_mode; -} init_opts; - -static int sparse_checkout_init(int argc, const char **argv) -{ - struct pattern_list pl; - char *sparse_filename; - int res; - struct object_id oid; - int mode; - struct strbuf pattern = STRBUF_INIT; - - static struct option builtin_sparse_checkout_init_options[] = { - OPT_BOOL(0, "cone", &init_opts.cone_mode, - N_("initialize the sparse-checkout in cone mode")), - OPT_END(), - }; - - repo_read_index(the_repository); - require_clean_work_tree(the_repository, - N_("initialize sparse-checkout"), NULL, 1, 0); - - argc = parse_options(argc, argv, NULL, - builtin_sparse_checkout_init_options, - builtin_sparse_checkout_init_usage, 0); - - if (init_opts.cone_mode) { - mode = MODE_CONE_PATTERNS; - core_sparse_checkout_cone = 1; - } else - mode = MODE_ALL_PATTERNS; - - if (set_config(mode)) - return 1; - - memset(&pl, 0, sizeof(pl)); - - sparse_filename = get_sparse_checkout_filename(); - res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL); - - /* If we already have a sparse-checkout file, use it. */ - if (res >= 0) { - free(sparse_filename); - core_apply_sparse_checkout = 1; - return update_working_directory(NULL); - } - - if (get_oid("HEAD", &oid)) { - FILE *fp; - - /* assume we are in a fresh repo, but update the sparse-checkout file */ - fp = xfopen(sparse_filename, "w"); - if (!fp) - die(_("failed to open '%s'"), sparse_filename); - - free(sparse_filename); - fprintf(fp, "/*\n!/*/\n"); - fclose(fp); - return 0; - } - - strbuf_addstr(&pattern, "/*"); - add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0); - strbuf_addstr(&pattern, "!/*/"); - add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0); - - return write_patterns_and_update(&pl); -} - -static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path) -{ - struct pattern_entry *e = xmalloc(sizeof(*e)); - e->patternlen = path->len; - e->pattern = strbuf_detach(path, NULL); - hashmap_entry_init(&e->ent, - ignore_case ? - strihash(e->pattern) : - strhash(e->pattern)); - - hashmap_add(&pl->recursive_hashmap, &e->ent); - - while (e->patternlen) { - char *slash = strrchr(e->pattern, '/'); - char *oldpattern = e->pattern; - size_t newlen; - - if (slash == e->pattern) - break; - - newlen = slash - e->pattern; - e = xmalloc(sizeof(struct pattern_entry)); - e->patternlen = newlen; - e->pattern = xstrndup(oldpattern, newlen); - hashmap_entry_init(&e->ent, - ignore_case ? - strihash(e->pattern) : - strhash(e->pattern)); - - if (!hashmap_get_entry(&pl->parent_hashmap, e, ent, NULL)) - hashmap_add(&pl->parent_hashmap, &e->ent); - } -} - -static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl) -{ - strbuf_trim(line); - - strbuf_trim_trailing_dir_sep(line); - - if (strbuf_normalize_path(line)) - die(_("could not normalize path %s"), line->buf); - - if (!line->len) - return; - - if (line->buf[0] != '/') - strbuf_insertstr(line, 0, "/"); - - insert_recursive_pattern(pl, line); -} - -static char const * const builtin_sparse_checkout_set_usage[] = { - N_("git sparse-checkout (set|add) (--stdin | <patterns>)"), - NULL -}; - -static struct sparse_checkout_set_opts { - int use_stdin; -} set_opts; - -static void add_patterns_from_input(struct pattern_list *pl, - int argc, const char **argv) -{ - int i; - if (core_sparse_checkout_cone) { - struct strbuf line = STRBUF_INIT; - - hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0); - hashmap_init(&pl->parent_hashmap, pl_hashmap_cmp, NULL, 0); - pl->use_cone_patterns = 1; - - if (set_opts.use_stdin) { - struct strbuf unquoted = STRBUF_INIT; - while (!strbuf_getline(&line, stdin)) { - if (line.buf[0] == '"') { - strbuf_reset(&unquoted); - if (unquote_c_style(&unquoted, line.buf, NULL)) - die(_("unable to unquote C-style string '%s'"), - line.buf); - - strbuf_swap(&unquoted, &line); - } - - strbuf_to_cone_pattern(&line, pl); - } - - strbuf_release(&unquoted); - } else { - for (i = 0; i < argc; i++) { - strbuf_setlen(&line, 0); - strbuf_addstr(&line, argv[i]); - strbuf_to_cone_pattern(&line, pl); - } - } - } else { - if (set_opts.use_stdin) { - struct strbuf line = STRBUF_INIT; - - while (!strbuf_getline(&line, stdin)) { - size_t len; - char *buf = strbuf_detach(&line, &len); - add_pattern(buf, empty_base, 0, pl, 0); - } - } else { - for (i = 0; i < argc; i++) - add_pattern(argv[i], empty_base, 0, pl, 0); - } - } -} - -enum modify_type { - REPLACE, - ADD, -}; - -static void add_patterns_cone_mode(int argc, const char **argv, - struct pattern_list *pl) -{ - struct strbuf buffer = STRBUF_INIT; - struct pattern_entry *pe; - struct hashmap_iter iter; - struct pattern_list existing; - char *sparse_filename = get_sparse_checkout_filename(); - - add_patterns_from_input(pl, argc, argv); - - memset(&existing, 0, sizeof(existing)); - existing.use_cone_patterns = core_sparse_checkout_cone; - - if (add_patterns_from_file_to_list(sparse_filename, "", 0, - &existing, NULL)) - die(_("unable to load existing sparse-checkout patterns")); - free(sparse_filename); - - hashmap_for_each_entry(&existing.recursive_hashmap, &iter, pe, ent) { - if (!hashmap_contains_parent(&pl->recursive_hashmap, - pe->pattern, &buffer) || - !hashmap_contains_parent(&pl->parent_hashmap, - pe->pattern, &buffer)) { - strbuf_reset(&buffer); - strbuf_addstr(&buffer, pe->pattern); - insert_recursive_pattern(pl, &buffer); - } - } - - clear_pattern_list(&existing); - strbuf_release(&buffer); -} - -static void add_patterns_literal(int argc, const char **argv, - struct pattern_list *pl) -{ - char *sparse_filename = get_sparse_checkout_filename(); - if (add_patterns_from_file_to_list(sparse_filename, "", 0, - pl, NULL)) - die(_("unable to load existing sparse-checkout patterns")); - free(sparse_filename); - add_patterns_from_input(pl, argc, argv); -} - -static int modify_pattern_list(int argc, const char **argv, enum modify_type m) -{ - int result; - int changed_config = 0; - struct pattern_list pl; - memset(&pl, 0, sizeof(pl)); - - switch (m) { - case ADD: - if (core_sparse_checkout_cone) - add_patterns_cone_mode(argc, argv, &pl); - else - add_patterns_literal(argc, argv, &pl); - break; - - case REPLACE: - add_patterns_from_input(&pl, argc, argv); - break; - } - - if (!core_apply_sparse_checkout) { - set_config(MODE_ALL_PATTERNS); - core_apply_sparse_checkout = 1; - changed_config = 1; - } - - result = write_patterns_and_update(&pl); - - if (result && changed_config) - set_config(MODE_NO_PATTERNS); - - clear_pattern_list(&pl); - return result; -} - -static int sparse_checkout_set(int argc, const char **argv, const char *prefix, - enum modify_type m) -{ - static struct option builtin_sparse_checkout_set_options[] = { - OPT_BOOL(0, "stdin", &set_opts.use_stdin, - N_("read patterns from standard in")), - OPT_END(), - }; - - repo_read_index(the_repository); - require_clean_work_tree(the_repository, - N_("set sparse-checkout patterns"), NULL, 1, 0); - - argc = parse_options(argc, argv, prefix, - builtin_sparse_checkout_set_options, - builtin_sparse_checkout_set_usage, - PARSE_OPT_KEEP_UNKNOWN); - - return modify_pattern_list(argc, argv, m); -} - -static int sparse_checkout_disable(int argc, const char **argv) -{ - struct pattern_list pl; - struct strbuf match_all = STRBUF_INIT; - - repo_read_index(the_repository); - require_clean_work_tree(the_repository, - N_("disable sparse-checkout"), NULL, 1, 0); - - memset(&pl, 0, sizeof(pl)); - hashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0); - hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0); - pl.use_cone_patterns = 0; - core_apply_sparse_checkout = 1; - - strbuf_addstr(&match_all, "/*"); - add_pattern(strbuf_detach(&match_all, NULL), empty_base, 0, &pl, 0); - - if (update_working_directory(&pl)) - die(_("error while refreshing working directory")); - - clear_pattern_list(&pl); - return set_config(MODE_NO_PATTERNS); -} - -int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) -{ - static struct option builtin_sparse_checkout_options[] = { - OPT_END(), - }; - - if (argc == 2 && !strcmp(argv[1], "-h")) - usage_with_options(builtin_sparse_checkout_usage, - builtin_sparse_checkout_options); - - argc = parse_options(argc, argv, prefix, - builtin_sparse_checkout_options, - builtin_sparse_checkout_usage, - PARSE_OPT_STOP_AT_NON_OPTION); - - git_config(git_default_config, NULL); - - if (argc > 0) { - if (!strcmp(argv[0], "list")) - return sparse_checkout_list(argc, argv); - if (!strcmp(argv[0], "init")) - return sparse_checkout_init(argc, argv); - if (!strcmp(argv[0], "set")) - return sparse_checkout_set(argc, argv, prefix, REPLACE); - if (!strcmp(argv[0], "add")) - return sparse_checkout_set(argc, argv, prefix, ADD); - if (!strcmp(argv[0], "disable")) - return sparse_checkout_disable(argc, argv); - } - - usage_with_options(builtin_sparse_checkout_usage, - builtin_sparse_checkout_options); -} diff --git a/third_party/git/builtin/stash.c b/third_party/git/builtin/stash.c index 78af6ce56431..b5a301f24d7a 100644 --- a/third_party/git/builtin/stash.c +++ b/third_party/git/builtin/stash.c @@ -27,7 +27,6 @@ static const char * const git_stash_usage[] = { N_("git stash clear"), N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" " [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n" - " [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" " [--] [<pathspec>...]]"), N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" " [-u|--include-untracked] [-a|--all] [<message>]"), @@ -397,7 +396,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, const struct object_id *bases[1]; read_cache_preload(NULL); - if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) + if (refresh_cache(REFRESH_QUIET)) return -1; if (write_cache_as_tree(&c_tree, 0, NULL)) @@ -428,8 +427,6 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, return error(_("could not save index tree")); reset_head(); - discard_cache(); - read_cache(); } } @@ -484,12 +481,13 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, if (ret) return -1; - /* read back the result of update_index() back from the disk */ discard_cache(); - read_cache(); } - if (!quiet) { + if (quiet) { + if (refresh_cache(REFRESH_QUIET)) + warning("could not refresh index"); + } else { struct child_process cp = CHILD_PROCESS_INIT; /* @@ -499,10 +497,6 @@ static int do_apply_stash(const char *prefix, struct stash_info *info, */ cp.git_cmd = 1; cp.dir = prefix; - argv_array_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s", - absolute_path(get_git_work_tree())); - argv_array_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s", - absolute_path(get_git_dir())); argv_array_push(&cp.args, "status"); run_command(&cp); } @@ -999,9 +993,9 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps, { int ret = 0; struct child_process cp_read_tree = CHILD_PROCESS_INIT; + struct child_process cp_add_i = CHILD_PROCESS_INIT; struct child_process cp_diff_tree = CHILD_PROCESS_INIT; struct index_state istate = { NULL }; - char *old_index_env = NULL, *old_repo_index_file; remove_path(stash_index_path.buf); @@ -1015,19 +1009,16 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps, } /* Find out what the user wants. */ - old_repo_index_file = the_repository->index_file; - the_repository->index_file = stash_index_path.buf; - old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT)); - setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1); - - ret = run_add_interactive(NULL, "--patch=stash", ps); - - the_repository->index_file = old_repo_index_file; - if (old_index_env && *old_index_env) - setenv(INDEX_ENVIRONMENT, old_index_env, 1); - else - unsetenv(INDEX_ENVIRONMENT); - FREE_AND_NULL(old_index_env); + cp_add_i.git_cmd = 1; + argv_array_pushl(&cp_add_i.args, "add--interactive", "--patch=stash", + "--", NULL); + add_pathspecs(&cp_add_i.args, ps); + argv_array_pushf(&cp_add_i.env_array, "GIT_INDEX_FILE=%s", + stash_index_path.buf); + if (run_command(&cp_add_i)) { + ret = -1; + goto done; + } /* State of the working tree. */ if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0, @@ -1091,9 +1082,8 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps } cp_upd_index.git_cmd = 1; - argv_array_pushl(&cp_upd_index.args, "update-index", - "--ignore-skip-worktree-entries", - "-z", "--add", "--remove", "--stdin", NULL); + argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", + "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); @@ -1139,10 +1129,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b prepare_fallback_ident("git stash", "git@stash"); read_cache_preload(NULL); - if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) { - ret = -1; - goto done; - } + refresh_cache(REFRESH_QUIET); if (get_oid("HEAD", &info->b_commit)) { if (!quiet) @@ -1303,7 +1290,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q free(ps_matched); } - if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) { + if (refresh_cache(REFRESH_QUIET)) { ret = -1; goto done; } @@ -1396,7 +1383,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "--hard", "-q", - "--no-recurse-submodules", NULL); + NULL); if (run_command(&cp)) { ret = -1; goto done; @@ -1452,17 +1439,13 @@ done: return ret; } -static int push_stash(int argc, const char **argv, const char *prefix, - int push_assumed) +static int push_stash(int argc, const char **argv, const char *prefix) { - int force_assume = 0; int keep_index = -1; int patch_mode = 0; int include_untracked = 0; int quiet = 0; - int pathspec_file_nul = 0; const char *stash_msg = NULL; - const char *pathspec_from_file = NULL; struct pathspec ps; struct option options[] = { OPT_BOOL('k', "keep-index", &keep_index, @@ -1476,45 +1459,16 @@ static int push_stash(int argc, const char **argv, const char *prefix, N_("include ignore files"), 2), OPT_STRING('m', "message", &stash_msg, N_("message"), N_("stash message")), - OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), - OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), OPT_END() }; - if (argc) { - force_assume = !strcmp(argv[0], "-p"); + if (argc) argc = parse_options(argc, argv, prefix, options, git_stash_push_usage, - PARSE_OPT_KEEP_DASHDASH); - } - - if (argc) { - if (!strcmp(argv[0], "--")) { - argc--; - argv++; - } else if (push_assumed && !force_assume) { - die("subcommand wasn't specified; 'push' can't be assumed due to unexpected token '%s'", - argv[0]); - } - } + 0); parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN, prefix, argv); - - if (pathspec_from_file) { - if (patch_mode) - die(_("--pathspec-from-file is incompatible with --patch")); - - if (ps.nr) - die(_("--pathspec-from-file is incompatible with pathspec arguments")); - - parse_pathspec_file(&ps, 0, - PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN, - prefix, pathspec_from_file, pathspec_file_nul); - } else if (pathspec_file_nul) { - die(_("--pathspec-file-nul requires --pathspec-from-file")); - } - return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, include_untracked); } @@ -1584,6 +1538,7 @@ static int use_builtin_stash(void) int cmd_stash(int argc, const char **argv, const char *prefix) { + int i = -1; pid_t pid = getpid(); const char *index_file; struct argv_array args = ARGV_ARRAY_INIT; @@ -1616,7 +1571,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix) (uintmax_t)pid); if (!argc) - return !!push_stash(0, NULL, prefix, 0); + return !!push_stash(0, NULL, prefix); else if (!strcmp(argv[0], "apply")) return !!apply_stash(argc, argv, prefix); else if (!strcmp(argv[0], "clear")) @@ -1636,15 +1591,45 @@ int cmd_stash(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[0], "create")) return !!create_stash(argc, argv, prefix); else if (!strcmp(argv[0], "push")) - return !!push_stash(argc, argv, prefix, 0); + return !!push_stash(argc, argv, prefix); else if (!strcmp(argv[0], "save")) return !!save_stash(argc, argv, prefix); else if (*argv[0] != '-') usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]), git_stash_usage, options); - /* Assume 'stash push' */ + if (strcmp(argv[0], "-p")) { + while (++i < argc && strcmp(argv[i], "--")) { + /* + * `akpqu` is a string which contains all short options, + * except `-m` which is verified separately. + */ + if ((strlen(argv[i]) == 2) && *argv[i] == '-' && + strchr("akpqu", argv[i][1])) + continue; + + if (!strcmp(argv[i], "--all") || + !strcmp(argv[i], "--keep-index") || + !strcmp(argv[i], "--no-keep-index") || + !strcmp(argv[i], "--patch") || + !strcmp(argv[i], "--quiet") || + !strcmp(argv[i], "--include-untracked")) + continue; + + /* + * `-m` and `--message=` are verified separately because + * they need to be immediately followed by a string + * (i.e.`-m"foobar"` or `--message="foobar"`). + */ + if (starts_with(argv[i], "-m") || + starts_with(argv[i], "--message=")) + continue; + + usage_with_options(git_stash_usage, options); + } + } + argv_array_push(&args, "push"); argv_array_pushv(&args, argv); - return !!push_stash(args.argc, args.argv, prefix, 1); + return !!push_stash(args.argc, args.argv, prefix); } diff --git a/third_party/git/builtin/submodule--helper.c b/third_party/git/builtin/submodule--helper.c index 86a608eec114..909e77e802d3 100644 --- a/third_party/git/builtin/submodule--helper.c +++ b/third_party/git/builtin/submodule--helper.c @@ -19,8 +19,6 @@ #include "diffcore.h" #include "diff.h" #include "object-store.h" -#include "dir.h" -#include "advice.h" #define OPT_QUIET (1 << 0) #define OPT_CACHED (1 << 1) @@ -426,7 +424,7 @@ static int module_list(int argc, const char **argv, const char *prefix) const struct cache_entry *ce = list.entries[i]; if (ce_stage(ce)) - printf("%06o %s U\t", ce->ce_mode, oid_to_hex(&null_oid)); + printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1)); else printf("%06o %s %d\t", ce->ce_mode, oid_to_hex(&ce->oid), ce_stage(ce)); @@ -782,8 +780,6 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, struct argv_array diff_files_args = ARGV_ARRAY_INIT; struct rev_info rev; int diff_files_result; - struct strbuf buf = STRBUF_INIT; - const char *git_dir; if (!submodule_from_path(the_repository, &null_oid, path)) die(_("no submodule mapping found in .gitmodules for path '%s'"), @@ -796,26 +792,17 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, goto cleanup; } - strbuf_addf(&buf, "%s/.git", path); - git_dir = read_gitfile(buf.buf); - if (!git_dir) - git_dir = buf.buf; - - if (!is_submodule_active(the_repository, path) || - !is_git_directory(git_dir)) { + if (!is_submodule_active(the_repository, path)) { print_status(flags, '-', path, ce_oid, displaypath); - strbuf_release(&buf); goto cleanup; } - strbuf_release(&buf); argv_array_pushl(&diff_files_args, "diff-files", "--ignore-submodules=dirty", "--quiet", "--", path, NULL); git_config(git_diff_basic_config, NULL); - - repo_init_revisions(the_repository, &rev, NULL); + repo_init_revisions(the_repository, &rev, prefix); rev.abbrev = 0; diff_files_args.argc = setup_revisions(diff_files_args.argc, diff_files_args.argv, @@ -1235,7 +1222,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix) static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, struct string_list *reference, int dissociate, - int quiet, int progress, int single_branch) + int quiet, int progress) { struct child_process cp = CHILD_PROCESS_INIT; @@ -1257,10 +1244,6 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url argv_array_push(&cp.args, "--dissociate"); if (gitdir && *gitdir) argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL); - if (single_branch >= 0) - argv_array_push(&cp.args, single_branch ? - "--single-branch" : - "--no-single-branch"); argv_array_push(&cp.args, "--"); argv_array_push(&cp.args, url); @@ -1285,13 +1268,6 @@ struct submodule_alternate_setup { #define SUBMODULE_ALTERNATE_SETUP_INIT { NULL, \ SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL } -static const char alternate_error_advice[] = N_( -"An alternate computed from a superproject's alternate is invalid.\n" -"To allow Git to clone without an alternate in such a case, set\n" -"submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n" -"'--reference-if-able' instead of '--reference'." -); - static int add_possible_reference_from_superproject( struct object_directory *odb, void *sas_cb) { @@ -1323,8 +1299,6 @@ static int add_possible_reference_from_superproject( } else { switch (sas->error_mode) { case SUBMODULE_ALTERNATE_ERROR_DIE: - if (advice_submodule_alternate_error_strategy_die) - advise(_(alternate_error_advice)); die(_("submodule '%s' cannot add alternate: %s"), sas->submodule_name, err.buf); case SUBMODULE_ALTERNATE_ERROR_INFO: @@ -1385,9 +1359,8 @@ static int module_clone(int argc, const char **argv, const char *prefix) char *p, *path = NULL, *sm_gitdir; struct strbuf sb = STRBUF_INIT; struct string_list reference = STRING_LIST_INIT_NODUP; - int dissociate = 0, require_init = 0; + int dissociate = 0; char *sm_alternate = NULL, *error_strategy = NULL; - int single_branch = -1; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &prefix, @@ -1413,17 +1386,12 @@ static int module_clone(int argc, const char **argv, const char *prefix) OPT__QUIET(&quiet, "Suppress output for cloning a submodule"), OPT_BOOL(0, "progress", &progress, N_("force cloning progress")), - OPT_BOOL(0, "require-init", &require_init, - N_("disallow cloning into non-empty directory")), - OPT_BOOL(0, "single-branch", &single_branch, - N_("clone only one branch, HEAD or --branch")), OPT_END() }; const char *const git_submodule_helper_usage[] = { N_("git submodule--helper clone [--prefix=<path>] [--quiet] " "[--reference <repository>] [--name <name>] [--depth <depth>] " - "[--single-branch] " "--url <url> --path <path>"), NULL }; @@ -1445,10 +1413,6 @@ static int module_clone(int argc, const char **argv, const char *prefix) } else path = xstrdup(path); - if (validate_submodule_git_dir(sm_gitdir, name) < 0) - die(_("refusing to create/use '%s' in another submodule's " - "git dir"), sm_gitdir); - if (!file_exists(sm_gitdir)) { if (safe_create_leading_directories_const(sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); @@ -1456,12 +1420,10 @@ static int module_clone(int argc, const char **argv, const char *prefix) prepare_possible_alternates(name, &reference); if (clone_submodule(path, sm_gitdir, url, depth, &reference, dissociate, - quiet, progress, single_branch)) + quiet, progress)) die(_("clone of '%s' into submodule path '%s' failed"), url, path); } else { - if (require_init && !access(path, X_OK) && !is_empty_dir(path)) - die(_("directory not empty: '%s'"), path); if (safe_create_leading_directories_const(path) < 0) die(_("could not create directory '%s'"), path); strbuf_addf(&sb, "%s/index", sm_gitdir); @@ -1516,8 +1478,6 @@ static void determine_submodule_update_strategy(struct repository *r, die(_("Invalid update mode '%s' configured for submodule path '%s'"), val, path); } else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) { - if (sub->update_strategy.type == SM_UPDATE_COMMAND) - BUG("how did we read update = !command from .gitmodules?"); out->type = sub->update_strategy.type; out->command = sub->update_strategy.command; } else @@ -1576,11 +1536,9 @@ struct submodule_update_clone { int recommend_shallow; struct string_list references; int dissociate; - unsigned require_init; const char *depth; const char *recursive_prefix; const char *prefix; - int single_branch; /* to be consumed by git-submodule.sh */ struct update_clone_data *update_clone; @@ -1595,14 +1553,10 @@ struct submodule_update_clone { int max_jobs; }; -#define SUBMODULE_UPDATE_CLONE_INIT { \ - .list = MODULE_LIST_INIT, \ - .update = SUBMODULE_UPDATE_STRATEGY_INIT, \ - .recommend_shallow = -1, \ - .references = STRING_LIST_INIT_DUP, \ - .single_branch = -1, \ - .max_jobs = 1, \ -} +#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ + SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \ + NULL, NULL, NULL, \ + NULL, 0, 0, 0, NULL, 0, 0, 1} static void next_submodule_warn_missing(struct submodule_update_clone *suc, @@ -1727,8 +1681,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL); if (suc->recommend_shallow && sub->recommend_shallow == 1) argv_array_push(&child->args, "--depth=1"); - if (suc->require_init) - argv_array_push(&child->args, "--require-init"); argv_array_pushl(&child->args, "--path", sub->path, NULL); argv_array_pushl(&child->args, "--name", sub->name, NULL); argv_array_pushl(&child->args, "--url", url, NULL); @@ -1741,10 +1693,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, argv_array_push(&child->args, "--dissociate"); if (suc->depth) argv_array_push(&child->args, suc->depth); - if (suc->single_branch >= 0) - argv_array_push(&child->args, suc->single_branch ? - "--single-branch" : - "--no-single-branch"); cleanup: strbuf_reset(&displaypath_sb); @@ -1922,15 +1870,11 @@ static int update_clone(int argc, const char **argv, const char *prefix) OPT__QUIET(&suc.quiet, N_("don't print cloning progress")), OPT_BOOL(0, "progress", &suc.progress, N_("force cloning progress")), - OPT_BOOL(0, "require-init", &suc.require_init, - N_("disallow cloning into non-empty directory")), - OPT_BOOL(0, "single-branch", &suc.single_branch, - N_("clone only one branch, HEAD or --branch")), OPT_END() }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper update-clone [--prefix=<path>] [<path>...]"), + N_("git submodule--helper update_clone [--prefix=<path>] [<path>...]"), NULL }; suc.prefix = prefix; diff --git a/third_party/git/builtin/unpack-objects.c b/third_party/git/builtin/unpack-objects.c index dd4a75e030d2..a87a4bfd2c55 100644 --- a/third_party/git/builtin/unpack-objects.c +++ b/third_party/git/builtin/unpack-objects.c @@ -24,7 +24,6 @@ static off_t consumed_bytes; static off_t max_input_size; static git_hash_ctx ctx; static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; -static struct progress *progress; /* * When running under --strict mode, objects whose reachability are @@ -93,7 +92,6 @@ static void use(int bytes) consumed_bytes += bytes; if (max_input_size && consumed_bytes > max_input_size) die(_("pack exceeds maximum allowed size")); - display_throughput(progress, consumed_bytes); } static void *get_data(unsigned long size) @@ -265,8 +263,7 @@ static void write_object(unsigned nr, enum object_type type, } else { struct object *obj; int eaten; - hash_object_file(the_hash_algo, buf, size, type_name(type), - &obj_list[nr].oid); + hash_object_file(buf, size, type_name(type), &obj_list[nr].oid); added_object(nr, type, buf, size); obj = parse_object_buffer(the_repository, &obj_list[nr].oid, type, size, buf, @@ -487,6 +484,7 @@ static void unpack_one(unsigned nr) static void unpack_all(void) { int i; + struct progress *progress = NULL; struct pack_header *hdr = fill(sizeof(struct pack_header)); nr_objects = ntohl(hdr->hdr_entries); diff --git a/third_party/git/builtin/update-index.c b/third_party/git/builtin/update-index.c index d527b8f10668..dff2f4b83720 100644 --- a/third_party/git/builtin/update-index.c +++ b/third_party/git/builtin/update-index.c @@ -35,7 +35,6 @@ static int verbose; static int mark_valid_only; static int mark_skip_worktree_only; static int mark_fsmonitor_only; -static int ignore_skip_worktree_entries; #define MARK_FLAG 1 #define UNMARK_FLAG 2 static struct strbuf mtime_dir = STRBUF_INIT; @@ -382,8 +381,7 @@ static int process_path(const char *path, struct stat *st, int stat_errno) * so updating it does not make sense. * On the other hand, removing it from index should work */ - if (!ignore_skip_worktree_entries && allow_remove && - remove_file_from_cache(path)) + if (allow_remove && remove_file_from_cache(path)) return error("%s: cannot remove from the index", path); return 0; } @@ -968,7 +966,6 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) struct parse_opt_ctx_t ctx; strbuf_getline_fn getline_fn; int parseopt_state = PARSE_OPT_UNKNOWN; - struct repository *r = the_repository; struct option options[] = { OPT_BIT('q', NULL, &refresh_args.flags, N_("continue refresh even when index needs update"), @@ -1016,8 +1013,6 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, N_("clear skip-worktree bit"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, - OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries, - N_("do not touch index-only entries")), OPT_SET_INT(0, "info-only", &info_only, N_("add to index only; do not add content to object database"), 1), OPT_SET_INT(0, "force-remove", &force_remove, @@ -1185,12 +1180,11 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) remove_split_index(&the_index); } - prepare_repo_settings(r); switch (untracked_cache) { case UC_UNSPECIFIED: break; case UC_DISABLE: - if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE) + if (git_config_get_untracked_cache() == 1) warning(_("core.untrackedCache is set to true; " "remove or change it, if you really want to " "disable the untracked cache")); @@ -1202,7 +1196,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) return !test_if_untracked_cache_is_supported(); case UC_ENABLE: case UC_FORCE: - if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE) + if (git_config_get_untracked_cache() == 0) warning(_("core.untrackedCache is set to false; " "remove or change it, if you really want to " "enable the untracked cache")); diff --git a/third_party/git/builtin/worktree.c b/third_party/git/builtin/worktree.c index 24f22800f38c..a5bb02b2076a 100644 --- a/third_party/git/builtin/worktree.c +++ b/third_party/git/builtin/worktree.c @@ -10,6 +10,7 @@ #include "run-command.h" #include "sigchain.h" #include "submodule.h" +#include "refs.h" #include "utf8.h" #include "worktree.h" @@ -234,7 +235,14 @@ static void validate_worktree_add(const char *path, const struct add_opts *opts) die(_("'%s' already exists"), path); worktrees = get_worktrees(0); - wt = find_worktree_by_path(worktrees, path); + /* + * find_worktree()'s suffix matching may undesirably find the main + * rather than a linked worktree (for instance, when the basenames + * of the main worktree and the one being created are the same). + * We're only interested in linked worktrees, so skip the main + * worktree with +1. + */ + wt = find_worktree(worktrees + 1, NULL, path); if (!wt) goto done; @@ -342,7 +350,7 @@ static int add_worktree(const char *path, const char *refname, */ strbuf_reset(&sb); strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); - write_file(sb.buf, "%s", oid_to_hex(&null_oid)); + write_file(sb.buf, "%s", sha1_to_hex(null_sha1)); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -369,7 +377,7 @@ static int add_worktree(const char *path, const char *refname, if (opts->checkout) { cp.argv = NULL; argv_array_clear(&cp.args); - argv_array_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL); + argv_array_pushl(&cp.args, "reset", "--hard", NULL); if (opts->quiet) argv_array_push(&cp.args, "--quiet"); cp.env = child_env.argv; @@ -872,7 +880,7 @@ static void check_clean_worktree(struct worktree *wt, original_path); ret = xread(cp.out, buf, sizeof(buf)); if (ret) - die(_("'%s' contains modified or untracked files, use --force to delete it"), + die(_("'%s' is dirty, use --force to delete it"), original_path); close(cp.out); ret = finish_command(&cp); |