From: Junio C Hamano Date: Wed, 15 Aug 2018 22:08:23 +0000 (-0700) Subject: Merge branch 'nd/i18n' X-Git-Tag: v2.19.0-rc0~74 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/4bea8485e395769951c6b9eddfba1081ea7ef47f?hp=-c Merge branch 'nd/i18n' Many more strings are prepared for l10n. * nd/i18n: (23 commits) transport-helper.c: mark more strings for translation transport.c: mark more strings for translation sha1-file.c: mark more strings for translation sequencer.c: mark more strings for translation replace-object.c: mark more strings for translation refspec.c: mark more strings for translation refs.c: mark more strings for translation pkt-line.c: mark more strings for translation object.c: mark more strings for translation exec-cmd.c: mark more strings for translation environment.c: mark more strings for translation dir.c: mark more strings for translation convert.c: mark more strings for translation connect.c: mark more strings for translation config.c: mark more strings for translation commit-graph.c: mark more strings for translation builtin/replace.c: mark more strings for translation builtin/pack-objects.c: mark more strings for translation builtin/grep.c: mark strings for translation builtin/config.c: mark more strings for translation ... --- 4bea8485e395769951c6b9eddfba1081ea7ef47f diff --combined archive-tar.c index 7df8565246,68e72d9176..0bc50f6e89 --- a/archive-tar.c +++ b/archive-tar.c @@@ -5,7 -5,6 +5,7 @@@ #include "config.h" #include "tar.h" #include "archive.h" +#include "object-store.h" #include "streaming.h" #include "run-command.h" @@@ -122,7 -121,7 +122,7 @@@ static int stream_blocked(const struct st = open_istream(oid, &type, &sz, NULL); if (!st) - return error("cannot stream blob %s", oid_to_hex(oid)); + return error(_("cannot stream blob %s"), oid_to_hex(oid)); for (;;) { readlen = read_istream(st, buf, sizeof(buf)); if (readlen <= 0) @@@ -257,7 -256,7 +257,7 @@@ static int write_tar_entry(struct archi *header.typeflag = TYPEFLAG_REG; mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask; } else { - return error("unsupported file mode: 0%o (SHA1: %s)", + return error(_("unsupported file mode: 0%o (SHA1: %s)"), mode, oid_to_hex(oid)); } if (pathlen > sizeof(header.name)) { @@@ -284,7 -283,7 +284,7 @@@ enum object_type type; buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size); if (!buffer) - return error("cannot read %s", oid_to_hex(oid)); + return error(_("cannot read %s"), oid_to_hex(oid)); } else { buffer = NULL; size = 0; @@@ -455,17 -454,17 +455,17 @@@ static int write_tar_filter_archive(con filter.in = -1; if (start_command(&filter) < 0) - die_errno("unable to start '%s' filter", argv[0]); + die_errno(_("unable to start '%s' filter"), argv[0]); close(1); if (dup2(filter.in, 1) < 0) - die_errno("unable to redirect descriptor"); + die_errno(_("unable to redirect descriptor")); close(filter.in); r = write_tar_archive(ar, args); close(1); if (finish_command(&filter) != 0) - die("'%s' filter reported error", argv[0]); + die(_("'%s' filter reported error"), argv[0]); strbuf_release(&cmd); return r; diff --combined archive-zip.c index abc556e5a7,7ad46d8854..024267ff0f --- a/archive-zip.c +++ b/archive-zip.c @@@ -6,7 -6,6 +6,7 @@@ #include "archive.h" #include "streaming.h" #include "utf8.h" +#include "object-store.h" #include "userdiff.h" #include "xdiff-interface.h" @@@ -310,11 -309,11 +310,11 @@@ static int write_zip_entry(struct archi if (is_utf8(path)) flags |= ZIP_UTF8; else - warning("Path is not valid UTF-8: %s", path); + warning(_("path is not valid UTF-8: %s"), path); } if (pathlen > 0xffff) { - return error("path too long (%d chars, SHA1: %s): %s", + return error(_("path too long (%d chars, SHA1: %s): %s"), (int)pathlen, oid_to_hex(oid), path); } @@@ -341,7 -340,7 +341,7 @@@ size > big_file_threshold) { stream = open_istream(oid, &type, &size, NULL); if (!stream) - return error("cannot stream blob %s", + return error(_("cannot stream blob %s"), oid_to_hex(oid)); flags |= ZIP_STREAM; out = buffer = NULL; @@@ -349,7 -348,7 +349,7 @@@ buffer = object_file_to_archive(args, path, oid, mode, &type, &size); if (!buffer) - return error("cannot read %s", + return error(_("cannot read %s"), oid_to_hex(oid)); crc = crc32(crc, buffer, size); is_binary = entry_is_binary(path_without_prefix, @@@ -358,7 -357,7 +358,7 @@@ } compressed_size = (method == 0) ? size : 0; } else { - return error("unsupported file mode: 0%o (SHA1: %s)", mode, + return error(_("unsupported file mode: 0%o (SHA1: %s)"), mode, oid_to_hex(oid)); } @@@ -467,7 -466,7 +467,7 @@@ zstream.avail_in = readlen; result = git_deflate(&zstream, 0); if (result != Z_OK) - die("deflate error (%d)", result); + die(_("deflate error (%d)"), result); out_len = zstream.next_out - compressed; if (out_len > 0) { @@@ -602,7 -601,7 +602,7 @@@ static void dos_time(timestamp_t *times struct tm *t; if (date_overflows(*timestamp)) - die("timestamp too large for this system: %"PRItime, + die(_("timestamp too large for this system: %"PRItime), *timestamp); time = (time_t)*timestamp; t = localtime(&time); diff --combined builtin/blame.c index 5c93d169dd,b77ba6ae82..97f6ecaf37 --- a/builtin/blame.c +++ b/builtin/blame.c @@@ -9,7 -9,6 +9,7 @@@ #include "config.h" #include "color.h" #include "builtin.h" +#include "repository.h" #include "commit.h" #include "diff.h" #include "revision.h" @@@ -24,7 -23,6 +24,7 @@@ #include "line-log.h" #include "dir.h" #include "progress.h" +#include "object-store.h" #include "blame.h" #include "string-list.h" @@@ -410,7 -408,7 +410,7 @@@ static void parse_color_fields(const ch } if (next == EXPECT_COLOR) - die (_("must end with a color")); + die(_("must end with a color")); colorfield[colorfield_nr].hop = TIME_MAX; string_list_clear(&l, 0); @@@ -578,7 -576,7 +578,7 @@@ static int read_ancestry(const char *gr /* The format is just "Commit Parent1 Parent2 ...\n" */ struct commit_graft *graft = read_graft_line(&buf); if (graft) - register_commit_graft(graft, 0); + register_commit_graft(the_repository, graft, 0); } fclose(fp); strbuf_release(&buf); @@@ -1002,13 -1000,13 +1002,13 @@@ parse_done nth_line_cb, &sb, lno, anchor, &bottom, &top, sb.path)) usage(blame_usage); - if (lno < top || ((lno || bottom) && lno < bottom)) + if ((!lno && (top || bottom)) || lno < bottom) die(Q_("file %s has only %lu line", "file %s has only %lu lines", lno), path, lno); if (bottom < 1) bottom = 1; - if (top < 1) + if (top < 1 || lno < top) top = lno; bottom--; range_set_append_unsafe(&ranges, bottom, top); @@@ -1071,9 -1069,7 +1071,9 @@@ find_alignment(&sb, &output_option); if (!*repeated_meta_color && (output_option & OUTPUT_COLOR_LINE)) - strcpy(repeated_meta_color, GIT_COLOR_CYAN); + xsnprintf(repeated_meta_color, + sizeof(repeated_meta_color), + "%s", GIT_COLOR_CYAN); } if (output_option & OUTPUT_ANNOTATE_COMPAT) output_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR); diff --combined builtin/checkout.c index 516136a23a,626868637a..cb6bb76312 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@@ -4,7 -4,6 +4,7 @@@ #include "lockfile.h" #include "parse-options.h" #include "refs.h" +#include "object-store.h" #include "commit.h" #include "tree.h" #include "tree-walk.h" @@@ -23,7 -22,6 +23,7 @@@ #include "resolve-undo.h" #include "submodule-config.h" #include "submodule.h" +#include "advice.h" static const char * const checkout_usage[] = { N_("git checkout [] "), @@@ -79,7 -77,7 +79,7 @@@ static int update_some(const struct obj return READ_TREE_RECURSIVE; len = base->len + strlen(pathname); - ce = xcalloc(1, cache_entry_size(len)); + ce = make_empty_cache_entry(&the_index, len); oidcpy(&ce->oid, oid); memcpy(ce->name, base->buf, base->len); memcpy(ce->name + base->len, pathname, len - base->len); @@@ -98,7 -96,7 +98,7 @@@ if (ce->ce_mode == old->ce_mode && !oidcmp(&ce->oid, &old->oid)) { old->ce_flags |= CE_UPDATE; - free(ce); + discard_cache_entry(ce); return 0; } } @@@ -232,11 -230,11 +232,11 @@@ static int checkout_merged(int pos, con if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid)) die(_("Unable to add merge result for '%s'"), path); free(result_buf.ptr); - ce = make_cache_entry(mode, oid.hash, path, 2, 0); + ce = make_transient_cache_entry(mode, &oid, path, 2); if (!ce) die(_("make_cache_entry failed for path '%s'"), path); status = checkout_entry(ce, state, NULL); - free(ce); + discard_cache_entry(ce); return status; } @@@ -380,7 -378,7 +380,7 @@@ static int checkout_paths(const struct die(_("unable to write new index file")); read_ref_full("HEAD", 0, &rev, NULL); - head = lookup_commit_reference_gently(&rev, 1); + head = lookup_commit_reference_gently(the_repository, &rev, 1); errs |= post_checkout_hook(head, head, 0); return errs; @@@ -831,7 -829,7 +831,7 @@@ static int switch_branches(const struc memset(&old_branch_info, 0, sizeof(old_branch_info)); old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag); if (old_branch_info.path) - old_branch_info.commit = lookup_commit_reference_gently(&rev, 1); + old_branch_info.commit = lookup_commit_reference_gently(the_repository, &rev, 1); if (!(flag & REF_ISSYMREF)) old_branch_info.path = NULL; @@@ -880,8 -878,7 +880,8 @@@ static int parse_branchname_arg(int arg 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) { struct tree **source_tree = &opts->source_tree; const char **new_branch = &opts->new_branch; @@@ -913,10 -910,8 +913,10 @@@ * (b) If is _not_ a commit, either "--" is present * or is not a path, no -t or -b was given, and * and there is a tracking branch whose name is - * in one and only one remote, then this is a short-hand to - * fork local from that remote-tracking branch. + * in one and only one remote (or if the branch exists on the + * remote named in checkout.defaultRemote), then this is a + * short-hand to fork local from that + * remote-tracking branch. * * (c) Otherwise, if "--" is present, treat it like case (1). * @@@ -977,8 -972,7 +977,8 @@@ recover_with_dwim = 0; if (recover_with_dwim) { - const char *remote = unique_tracking_name(arg, rev); + const char *remote = unique_tracking_name(arg, rev, + dwim_remotes_matched); if (remote) { *new_branch = arg; arg = remote; @@@ -1009,7 -1003,7 +1009,7 @@@ else new_branch_info->path = NULL; /* not an existing branch */ - new_branch_info->commit = lookup_commit_reference_gently(rev, 1); + new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1); if (!new_branch_info->commit) { /* not a commit */ *source_tree = parse_tree_indirect(rev); @@@ -1115,7 -1109,6 +1115,7 @@@ int cmd_checkout(int argc, const char * struct branch_info new_branch_info; char *conflict_style = NULL; int dwim_new_local_branch = 1; + int dwim_remotes_matched = 0; struct option options[] = { OPT__QUIET(&opts.quiet, N_("suppress progress reporting")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@@ -1198,12 -1191,12 +1198,12 @@@ if (opts.track != BRANCH_TRACK_UNSPECIFIED && !opts.new_branch) { const char *argv0 = argv[0]; if (!argc || !strcmp(argv0, "--")) - die (_("--track needs a branch name")); + die(_("--track needs a branch name")); skip_prefix(argv0, "refs/", &argv0); skip_prefix(argv0, "remotes/", &argv0); argv0 = strchr(argv0, '/'); if (!argv0 || !argv0[1]) - die (_("Missing branch name; try -b")); + die(_("missing branch name; try -b")); opts.new_branch = argv0 + 1; } @@@ -1228,8 -1221,7 +1228,8 @@@ 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; } @@@ -1271,26 -1263,8 +1271,26 @@@ } 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/\n" + "\n" + "If you'd like to always have checkouts of an ambiguous 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); + } } diff --combined builtin/commit.c index 158e3f843a,d3276a10b2..213fca2d8e --- a/builtin/commit.c +++ b/builtin/commit.c @@@ -168,9 -168,9 +168,9 @@@ static int opt_parse_rename_score(cons static void determine_whence(struct wt_status *s) { - if (file_exists(git_path_merge_head())) + if (file_exists(git_path_merge_head(the_repository))) whence = FROM_MERGE; - else if (file_exists(git_path_cherry_pick_head())) { + else if (file_exists(git_path_cherry_pick_head(the_repository))) { whence = FROM_CHERRY_PICK; if (file_exists(git_path_seq_dir())) sequencer_in_use = 1; @@@ -718,21 -718,21 +718,21 @@@ static int prepare_to_commit(const cha if (have_option_m) strbuf_addbuf(&sb, &message); hook_arg1 = "message"; - } else if (!stat(git_path_merge_msg(), &statbuf)) { + } else if (!stat(git_path_merge_msg(the_repository), &statbuf)) { /* * prepend SQUASH_MSG here if it exists and a * "merge --squash" was originally performed */ - if (!stat(git_path_squash_msg(), &statbuf)) { - if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0) + if (!stat(git_path_squash_msg(the_repository), &statbuf)) { + if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0) die_errno(_("could not read SQUASH_MSG")); hook_arg1 = "squash"; } else hook_arg1 = "merge"; - if (strbuf_read_file(&sb, git_path_merge_msg(), 0) < 0) + if (strbuf_read_file(&sb, git_path_merge_msg(the_repository), 0) < 0) die_errno(_("could not read MERGE_MSG")); - } else if (!stat(git_path_squash_msg(), &statbuf)) { - if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0) + } else if (!stat(git_path_squash_msg(the_repository), &statbuf)) { + if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0) die_errno(_("could not read SQUASH_MSG")); hook_arg1 = "squash"; } else if (template_file) { @@@ -813,8 -813,8 +813,8 @@@ " %s\n" "and try again.\n"), whence == FROM_MERGE ? - git_path_merge_head() : - git_path_cherry_pick_head()); + git_path_merge_head(the_repository) : + git_path_cherry_pick_head(the_repository)); } fprintf(s->fp, "\n"); @@@ -1564,7 -1564,7 +1564,7 @@@ int cmd_commit(int argc, const char **a if (!reflog_msg) reflog_msg = "commit (merge)"; pptr = commit_list_append(current_head, pptr); - fp = xfopen(git_path_merge_head(), "r"); + fp = xfopen(git_path_merge_head(the_repository), "r"); while (strbuf_getline_lf(&m, fp) != EOF) { struct commit *parent; @@@ -1575,8 -1575,8 +1575,8 @@@ } fclose(fp); strbuf_release(&m); - if (!stat(git_path_merge_mode(), &statbuf)) { - if (strbuf_read_file(&sb, git_path_merge_mode(), 0) < 0) + if (!stat(git_path_merge_mode(the_repository), &statbuf)) { + if (strbuf_read_file(&sb, git_path_merge_mode(the_repository), 0) < 0) die_errno(_("could not read MERGE_MODE")); if (!strcmp(sb.buf, "no-ff")) allow_fast_forward = 0; @@@ -1639,17 -1639,17 +1639,17 @@@ die("%s", err.buf); } - unlink(git_path_cherry_pick_head()); - unlink(git_path_revert_head()); - unlink(git_path_merge_head()); - unlink(git_path_merge_msg()); - unlink(git_path_merge_mode()); - unlink(git_path_squash_msg()); + unlink(git_path_cherry_pick_head(the_repository)); + unlink(git_path_revert_head(the_repository)); + unlink(git_path_merge_head(the_repository)); + unlink(git_path_merge_msg(the_repository)); + unlink(git_path_merge_mode(the_repository)); + unlink(git_path_squash_msg(the_repository)); if (commit_index_files()) - die (_("Repository has been updated, but unable to write\n" - "new_index file. Check that disk is not full and quota is\n" - "not exceeded, and then \"git reset HEAD\" to recover.")); + die(_("repository has been updated, but unable to write\n" + "new_index file. Check that disk is not full and quota is\n" + "not exceeded, and then \"git reset HEAD\" to recover.")); rerere(0); run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); diff --combined builtin/config.c index 2c93a289a7,5761a2c4ac..97b58c4aea --- a/builtin/config.c +++ b/builtin/config.c @@@ -67,7 -67,7 +67,7 @@@ static int show_origin { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \ PARSE_OPT_NONEG, option_parse_type, (i) } -static struct option builtin_config_options[]; +static NORETURN void usage_builtin_config(void); static int option_parse_type(const struct option *opt, const char *arg, int unset) @@@ -110,8 -110,9 +110,8 @@@ * --int' and '--type=bool * --type=int'. */ - error("only one type at a time."); + error(_("only one type at a time")); - usage_with_options(builtin_config_usage, - builtin_config_options); + usage_builtin_config(); } *to_type = new_type; @@@ -156,16 -157,15 +156,20 @@@ static struct option builtin_config_opt OPT_END(), }; +static NORETURN void usage_builtin_config(void) +{ + usage_with_options(builtin_config_usage, builtin_config_options); +} + static void check_argc(int argc, int min, int max) { if (argc >= min && argc <= max) return; - error("wrong number of arguments"); + if (min == max) + error(_("wrong number of arguments, should be %d"), min); + else + error(_("wrong number of arguments, should be from %d to %d"), + min, max); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } static void show_config_origin(struct strbuf *buf) @@@ -297,7 -297,7 +301,7 @@@ static int get_value(const char *key_, key_regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(key_regexp, key, REG_EXTENDED)) { - error("invalid key pattern: %s", key_); + error(_("invalid key pattern: %s"), key_); FREE_AND_NULL(key_regexp); ret = CONFIG_INVALID_PATTERN; goto free_strings; @@@ -317,7 -317,7 +321,7 @@@ regexp = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(regexp, regex_, REG_EXTENDED)) { - error("invalid pattern: %s", regex_); + error(_("invalid pattern: %s"), regex_); FREE_AND_NULL(regexp); ret = CONFIG_INVALID_PATTERN; goto free_strings; @@@ -390,7 -390,7 +394,7 @@@ static char *normalize_value(const cha if (type == TYPE_COLOR) { char v[COLOR_MAXLEN]; if (git_config_color(v, key, value)) - die("cannot parse color '%s'", value); + die(_("cannot parse color '%s'"), value); /* * The contents of `v` now contain an ANSI escape @@@ -485,13 -485,13 +489,13 @@@ static int get_colorbool(const char *va static void check_write(void) { if (!given_config_source.file && !startup_info->have_repository) - die("not in a git directory"); + die(_("not in a git directory")); if (given_config_source.use_stdin) - die("writing to stdin is not supported"); + die(_("writing to stdin is not supported")); if (given_config_source.blob) - die("writing config blobs is not supported"); + die(_("writing config blobs is not supported")); } struct urlmatch_current_candidate_value { @@@ -599,8 -599,8 +603,8 @@@ int cmd_config(int argc, const char **a if (use_global_config + use_system_config + use_local_config + !!given_config_source.file + !!given_config_source.blob > 1) { - error("only one config file at a time."); + error(_("only one config file at a time")); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (use_local_config && nongit) @@@ -626,7 -626,7 +630,7 @@@ * location; error out even if XDG_CONFIG_HOME * is set and points at a sane location. */ - die("$HOME not set"); + die(_("$HOME not set")); if (access_or_warn(user_config, R_OK, 0) && xdg_config && !access_or_warn(xdg_config, R_OK, 0)) { @@@ -663,13 -663,13 +667,13 @@@ } if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) { - error("--get-color and variable type are incoherent"); + error(_("--get-color and variable type are incoherent")); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (HAS_MULTI_BITS(actions)) { - error("only one action at a time."); + error(_("only one action at a time")); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (actions == 0) switch (argc) { @@@ -677,24 -677,25 +681,24 @@@ case 2: actions = ACTION_SET; break; case 3: actions = ACTION_SET_ALL; break; default: - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (omit_values && !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) { - error("--name-only is only applicable to --list or --get-regexp"); + error(_("--name-only is only applicable to --list or --get-regexp")); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (show_origin && !(actions & (ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) { - error("--show-origin is only applicable to --get, --get-all, " - "--get-regexp, and --list."); + error(_("--show-origin is only applicable to --get, --get-all, " + "--get-regexp, and --list")); - usage_with_options(builtin_config_usage, builtin_config_options); + usage_builtin_config(); } if (default_value && !(actions & ACTION_GET)) { - error("--default is only applicable to --get"); + error(_("--default is only applicable to --get")); - usage_with_options(builtin_config_usage, - builtin_config_options); + usage_builtin_config(); } if (actions & PAGING_ACTIONS) @@@ -706,10 -707,10 +710,10 @@@ &given_config_source, &config_options) < 0) { if (given_config_source.file) - die_errno("unable to read config file '%s'", + die_errno(_("unable to read config file '%s'"), given_config_source.file); else - die("error processing config file(s)"); + die(_("error processing config file(s)")); } } else if (actions == ACTION_EDIT) { @@@ -717,11 -718,11 +721,11 @@@ check_argc(argc, 0, 0); if (!given_config_source.file && nongit) - die("not in a git directory"); + die(_("not in a git directory")); if (given_config_source.use_stdin) - die("editing stdin is not supported"); + die(_("editing stdin is not supported")); if (given_config_source.blob) - die("editing blobs is not supported"); + die(_("editing blobs is not supported")); git_config(git_default_config, NULL); config_file = given_config_source.file ? xstrdup(given_config_source.file) : @@@ -822,7 -823,7 +826,7 @@@ if (ret < 0) return ret; if (ret == 0) - die("No such section!"); + die(_("no such section: %s"), argv[0]); } else if (actions == ACTION_REMOVE_SECTION) { int ret; @@@ -833,7 -834,7 +837,7 @@@ if (ret < 0) return ret; if (ret == 0) - die("No such section!"); + die(_("no such section: %s"), argv[0]); } else if (actions == ACTION_GET_COLOR) { check_argc(argc, 1, 2); diff --combined builtin/fast-export.c index 223499d7ca,83c482581b..9bd8a14b57 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@@ -8,7 -8,6 +8,7 @@@ #include "config.h" #include "refs.h" #include "refspec.h" +#include "object-store.h" #include "commit.h" #include "object.h" #include "tag.h" @@@ -230,22 -229,21 +230,22 @@@ static void export_blob(const struct ob if (is_null_oid(oid)) return; - object = lookup_object(oid->hash); + object = lookup_object(the_repository, oid->hash); if (object && object->flags & SHOWN) return; if (anonymize) { buf = anonymize_blob(&size); - object = (struct object *)lookup_blob(oid); + object = (struct object *)lookup_blob(the_repository, oid); eaten = 0; } else { buf = read_object_file(oid, &type, &size); if (!buf) - die ("Could not read blob %s", oid_to_hex(oid)); + die("could not read blob %s", oid_to_hex(oid)); if (check_object_signature(oid, buf, size, type_name(type)) < 0) die("sha1 mismatch in blob %s", oid_to_hex(oid)); - object = parse_object_buffer(oid, type, size, buf, &eaten); + object = parse_object_buffer(the_repository, oid, type, + size, buf, &eaten); } if (!object) @@@ -255,7 -253,7 +255,7 @@@ printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size); if (size && fwrite(buf, size, 1, stdout) != 1) - die_errno ("Could not write blob '%s'", oid_to_hex(oid)); + die_errno("could not write blob '%s'", oid_to_hex(oid)); printf("\n"); show_progress(); @@@ -403,8 -401,7 +403,8 @@@ static void show_filemodify(struct diff anonymize_sha1(&spec->oid) : spec->oid.hash)); else { - struct object *object = lookup_object(spec->oid.hash); + struct object *object = lookup_object(the_repository, + spec->oid.hash); printf("M %06o :%d ", spec->mode, get_object_mark(object)); } @@@ -563,14 -560,14 +563,14 @@@ static void handle_commit(struct commi commit_buffer = get_commit_buffer(commit, NULL); author = strstr(commit_buffer, "\nauthor "); if (!author) - die ("Could not find author in commit %s", - oid_to_hex(&commit->object.oid)); + die("could not find author in commit %s", + oid_to_hex(&commit->object.oid)); author++; author_end = strchrnul(author, '\n'); committer = strstr(author_end, "\ncommitter "); if (!committer) - die ("Could not find committer in commit %s", - oid_to_hex(&commit->object.oid)); + die("could not find committer in commit %s", + oid_to_hex(&commit->object.oid)); committer++; committer_end = strchrnul(committer, '\n'); message = strstr(committer_end, "\n\n"); @@@ -691,7 -688,7 +691,7 @@@ static void handle_tag(const char *name buf = read_object_file(&tag->object.oid, &type, &size); if (!buf) - die ("Could not read tag %s", oid_to_hex(&tag->object.oid)); + die("could not read tag %s", oid_to_hex(&tag->object.oid)); message = memmem(buf, size, "\n\n", 2); if (message) { message += 2; @@@ -728,18 -725,18 +728,18 @@@ if (signature) switch(signed_tag_mode) { case ABORT: - die ("Encountered signed tag %s; use " - "--signed-tags= to handle it.", - oid_to_hex(&tag->object.oid)); + die("encountered signed tag %s; use " + "--signed-tags= to handle it", + oid_to_hex(&tag->object.oid)); case WARN: - warning ("Exporting signed tag %s", - oid_to_hex(&tag->object.oid)); + warning("exporting signed tag %s", + oid_to_hex(&tag->object.oid)); /* fallthru */ case VERBATIM: break; case WARN_STRIP: - warning ("Stripping signature from tag %s", - oid_to_hex(&tag->object.oid)); + warning("stripping signature from tag %s", + oid_to_hex(&tag->object.oid)); /* fallthru */ case STRIP: message_size = signature + 1 - message; @@@ -753,18 -750,18 +753,18 @@@ if (!tagged_mark) { switch(tag_of_filtered_mode) { case ABORT: - die ("Tag %s tags unexported object; use " - "--tag-of-filtered-object= to handle it.", - oid_to_hex(&tag->object.oid)); + die("tag %s tags unexported object; use " + "--tag-of-filtered-object= to handle it", + oid_to_hex(&tag->object.oid)); case DROP: /* Ignore this tag altogether */ free(buf); return; case REWRITE: if (tagged->type != OBJ_COMMIT) { - die ("Tag %s tags unexported %s!", - oid_to_hex(&tag->object.oid), - type_name(tagged->type)); + die("tag %s tags unexported %s!", + oid_to_hex(&tag->object.oid), + type_name(tagged->type)); } p = (struct commit *)tagged; for (;;) { @@@ -775,7 -772,7 +775,7 @@@ if (!(p->object.flags & TREESAME)) break; if (!p->parents) - die ("Can't find replacement commit for tag %s\n", + die("can't find replacement commit for tag %s", oid_to_hex(&tag->object.oid)); p = p->parents->item; } @@@ -803,7 -800,7 +803,7 @@@ static struct commit *get_commit(struc /* handle nested tags */ while (tag && tag->object.type == OBJ_TAG) { - parse_object(&tag->object.oid); + parse_object(the_repository, &tag->object.oid); string_list_append(&extra_refs, full_name)->util = tag; tag = (struct tag *)tag->tagged; } @@@ -963,7 -960,7 +963,7 @@@ static void import_marks(char *input_fi /* only commits */ continue; - commit = lookup_commit(&oid); + commit = lookup_commit(the_repository, &oid); if (!commit) die("not a commit? can't happen: %s", oid_to_hex(&oid)); diff --combined builtin/fmt-merge-msg.c index ca9206fbbe,a08f239e00..f35ff1612b --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@@ -2,7 -2,6 +2,7 @@@ #include "cache.h" #include "config.h" #include "refs.h" +#include "object-store.h" #include "commit.h" #include "diff.h" #include "revision.h" @@@ -11,7 -10,6 +11,7 @@@ #include "branch.h" #include "fmt-merge-msg.h" #include "gpg-interface.h" +#include "repository.h" static const char * const fmt_merge_msg_usage[] = { N_("git fmt-merge-msg [-m ] [--log[=] | --no-log] [--file ]"), @@@ -110,15 -108,14 +110,15 @@@ static int handle_line(char *line, stru struct string_list_item *item; int pulling_head = 0; struct object_id oid; + const unsigned hexsz = the_hash_algo->hexsz; - if (len < GIT_SHA1_HEXSZ + 3 || line[GIT_SHA1_HEXSZ] != '\t') + if (len < hexsz + 3 || line[hexsz] != '\t') return 1; - if (starts_with(line + GIT_SHA1_HEXSZ + 1, "not-for-merge")) + if (starts_with(line + hexsz + 1, "not-for-merge")) return 0; - if (line[GIT_SHA1_HEXSZ + 1] != '\t') + if (line[hexsz + 1] != '\t') return 2; i = get_oid_hex(line, &oid); @@@ -133,7 -130,7 +133,7 @@@ if (line[len - 1] == '\n') line[len - 1] = 0; - line += GIT_SHA1_HEXSZ + 2; + line += hexsz + 2; /* * At this point, line points at the beginning of comment e.g. @@@ -345,9 -342,7 +345,9 @@@ static void shortlog(const char *name const struct object_id *oid = &origin_data->oid; int limit = opts->shortlog_len; - branch = deref_tag(parse_object(oid), oid_to_hex(oid), GIT_SHA1_HEXSZ); + branch = deref_tag(the_repository, parse_object(the_repository, oid), + oid_to_hex(oid), + the_hash_algo->hexsz); if (!branch || branch->type != OBJ_COMMIT) return; @@@ -550,7 -545,6 +550,7 @@@ static void find_merge_parents(struct m int len; char *p = in->buf + pos; char *newline = strchr(p, '\n'); + const char *q; struct object_id oid; struct commit *parent; struct object *obj; @@@ -558,23 -552,24 +558,23 @@@ len = newline ? newline - p : strlen(p); pos += len + !!newline; - if (len < GIT_SHA1_HEXSZ + 3 || - get_oid_hex(p, &oid) || - p[GIT_SHA1_HEXSZ] != '\t' || - p[GIT_SHA1_HEXSZ + 1] != '\t') + if (parse_oid_hex(p, &oid, &q) || + q[0] != '\t' || + q[1] != '\t') continue; /* skip not-for-merge */ /* * Do not use get_merge_parent() here; we do not have * "name" here and we do not want to contaminate its * util field yet. */ - obj = parse_object(&oid); + obj = parse_object(the_repository, &oid); parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT); if (!parent) continue; commit_list_insert(parent, &parents); add_merge_parent(result, &obj->oid, &parent->object.oid); } - head_commit = lookup_commit(head); + head_commit = lookup_commit(the_repository, head); if (head_commit) commit_list_insert(head_commit, &parents); reduce_heads_replace(&parents); @@@ -628,7 -623,7 +628,7 @@@ int fmt_merge_msg(struct strbuf *in, st i++; p[len] = 0; if (handle_line(p, &merge_parents)) - die ("Error in line %d: %.*s", i, len, p); + die("error in line %d: %.*s", i, len, p); } if (opts->add_title && srcs.nr) diff --combined builtin/grep.c index 056161f0f8,58f941e951..ee5a1bd355 --- a/builtin/grep.c +++ b/builtin/grep.c @@@ -489,7 -489,7 +489,7 @@@ static int grep_cache(struct grep_opt * } if (repo_read_index(repo) < 0) - die("index file corrupt"); + die(_("index file corrupt")); for (nr = 0; nr < repo->index->cache_nr; nr++) { const struct cache_entry *ce = repo->index->cache[nr]; @@@ -647,8 -647,7 +647,8 @@@ static int grep_objects(struct grep_op for (i = 0; i < nr; i++) { struct object *real_obj; - real_obj = deref_tag(list->objects[i].item, NULL, 0); + real_obj = deref_tag(the_repository, list->objects[i].item, + NULL, 0); /* load the gitmodules file for this rev */ if (recurse_submodules) { @@@ -829,7 -828,6 +829,7 @@@ int cmd_grep(int argc, const char **arg GREP_PATTERN_TYPE_PCRE), OPT_GROUP(""), OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")), + OPT_BOOL(0, "column", &opt.columnnum, N_("show column number of first match")), OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1), OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1), OPT_NEGBIT(0, "full-name", &opt.relative, @@@ -844,8 -842,6 +844,8 @@@ OPT_BOOL_F('z', "null", &opt.null_following_name, N_("print NUL after filenames"), PARSE_OPT_NOCOMPLETE), + OPT_BOOL('o', "only-matching", &opt.only_matching, + N_("show only matching parts of a line")), OPT_BOOL('c', "count", &opt.count, N_("show the number of matches instead of matching lines")), OPT__COLOR(&opt.color, N_("highlight matches")), @@@ -963,12 -959,8 +963,12 @@@ } if (!opt.pattern_list) - die(_("no pattern given.")); + die(_("no pattern given")); + /* --only-matching has no effect with --invert. */ + if (opt.invert) + opt.only_matching = 0; + /* * We have to find "--" in a separate pass, because its presence * influences how we will parse arguments that come before it. @@@ -1093,19 -1085,19 +1093,19 @@@ } if (recurse_submodules && (!use_index || untracked)) - die(_("option not supported with --recurse-submodules.")); + die(_("option not supported with --recurse-submodules")); if (!show_in_pager && !opt.status_only) setup_pager(); if (!use_index && (untracked || cached)) - die(_("--cached or --untracked cannot be used with --no-index.")); + die(_("--cached or --untracked cannot be used with --no-index")); if (!use_index || untracked) { int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude; hit = grep_directory(&opt, &pathspec, use_exclude, use_index); } else if (0 <= opt_exclude) { - die(_("--[no-]exclude-standard cannot be used for tracked contents.")); + die(_("--[no-]exclude-standard cannot be used for tracked contents")); } else if (!list.nr) { if (!cached) setup_work_tree(); @@@ -1113,7 -1105,7 +1113,7 @@@ hit = grep_cache(&opt, the_repository, &pathspec, cached); } else { if (cached) - die(_("both --cached and trees are given.")); + die(_("both --cached and trees are given")); hit = grep_objects(&opt, &pathspec, &list); } diff --combined builtin/log.c index 574595132a,99d4c6996e..e094560d9a --- a/builtin/log.c +++ b/builtin/log.c @@@ -7,7 -7,6 +7,7 @@@ #include "cache.h" #include "config.h" #include "refs.h" +#include "object-store.h" #include "color.h" #include "commit.h" #include "diff.h" @@@ -30,7 -29,6 +30,7 @@@ #include "gpg-interface.h" #include "progress.h" #include "commit-slab.h" +#include "repository.h" #define MAIL_DEFAULT_WRAP 72 @@@ -620,7 -618,7 +620,7 @@@ int cmd_show(int argc, const char **arg rev.shown_one = 1; if (ret) break; - o = parse_object(&t->tagged->oid); + o = parse_object(the_repository, &t->tagged->oid); if (!o) ret = error(_("Could not read object %s"), oid_to_hex(&t->tagged->oid)); @@@ -907,8 -905,8 +907,8 @@@ static void get_patch_ids(struct rev_in o2 = rev->pending.objects[1].item; flags1 = o1->flags; flags2 = o2->flags; - c1 = lookup_commit_reference(&o1->oid); - c2 = lookup_commit_reference(&o2->oid); + c1 = lookup_commit_reference(the_repository, &o1->oid); + c2 = lookup_commit_reference(the_repository, &o2->oid); if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die(_("Not a range.")); @@@ -1608,14 -1606,14 +1608,14 @@@ int cmd_format_patch(int argc, const ch numbered = 0; if (numbered && keep_subject) - die (_("-n and -k are mutually exclusive.")); + die(_("-n and -k are mutually exclusive")); if (keep_subject && subject_prefix) - die (_("--subject-prefix/--rfc and -k are mutually exclusive.")); + die(_("--subject-prefix/--rfc and -k are mutually exclusive")); rev.preserve_subject = keep_subject; argc = setup_revisions(argc, argv, &rev, &s_r_opt); if (argc > 1) - die (_("unrecognized argument: %s"), argv[1]); + die(_("unrecognized argument: %s"), argv[1]); if (rev.diffopt.output_format & DIFF_FORMAT_NAME) die(_("--name-only does not make sense")); @@@ -1757,7 -1755,6 +1757,7 @@@ if (base_commit || base_auto) { struct commit *base = get_base_commit(base_commit, list, nr); reset_revision_walk(); + clear_object_flags(UNINTERESTING); prepare_bases(&bases, base, list, nr); } @@@ -1865,8 -1862,7 +1865,8 @@@ static int add_pending_commit(const cha { struct object_id oid; if (get_oid(arg, &oid) == 0) { - struct commit *commit = lookup_commit_reference(&oid); + struct commit *commit = lookup_commit_reference(the_repository, + &oid); if (commit) { commit->object.flags |= flags; add_pending_object(revs, &commit->object, arg); diff --combined builtin/merge.c index 77e1694a78,f553f89a48..8f4a5065c2 --- a/builtin/merge.c +++ b/builtin/merge.c @@@ -111,35 -111,6 +111,35 @@@ static int option_parse_message(const s return 0; } +static int option_read_message(struct parse_opt_ctx_t *ctx, + const struct option *opt, int unset) +{ + struct strbuf *buf = opt->value; + const char *arg; + + if (unset) + BUG("-F cannot be negated"); + + if (ctx->opt) { + arg = ctx->opt; + ctx->opt = NULL; + } else if (ctx->argc > 1) { + ctx->argc--; + arg = *++ctx->argv; + } else + return opterror(opt, "requires a value", 0); + + if (buf->len) + strbuf_addch(buf, '\n'); + if (ctx->prefix && !is_absolute_path(arg)) + arg = prefix_filename(ctx->prefix, arg); + if (strbuf_read_file(buf, arg, 0) < 0) + return error(_("could not read file '%s'"), arg); + have_message = 1; + + return 0; +} + static struct strategy *get_strategy(const char *name) { int i; @@@ -257,9 -228,6 +257,9 @@@ static struct option builtin_merge_opti OPT_CALLBACK('m', "message", &merge_msg, N_("message"), N_("merge commit message (for a non-fast-forward merge)"), option_parse_message), + { OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"), + N_("read message from file"), PARSE_OPT_NONEG, + (parse_opt_cb *) option_read_message }, OPT__VERBOSITY(&verbosity), OPT_BOOL(0, "abort", &abort_current_merge, N_("abort the current in-progress merge")), @@@ -279,9 -247,9 +279,9 @@@ /* Cleans up metadata that is uninteresting after a succeeded merge. */ static void drop_save(void) { - unlink(git_path_merge_head()); - unlink(git_path_merge_msg()); - unlink(git_path_merge_mode()); + unlink(git_path_merge_head(the_repository)); + unlink(git_path_merge_msg(the_repository)); + unlink(git_path_merge_mode(the_repository)); } static int save_state(struct object_id *stash) @@@ -414,7 -382,7 +414,7 @@@ static void squash_message(struct commi oid_to_hex(&commit->object.oid)); pretty_print_commit(&ctx, commit, &out); } - write_file_buf(git_path_squash_msg(), out.buf, out.len); + write_file_buf(git_path_squash_msg(the_repository), out.buf, out.len); strbuf_release(&out); } @@@ -725,7 -693,7 +725,7 @@@ static int try_merge_strategy(const cha exit(128); if (write_locked_index(&the_index, &lock, COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die (_("unable to write %s"), get_index_file()); + die(_("unable to write %s"), get_index_file()); return clean ? 0 : 1; } else { return try_merge_command(strategy, xopts_nr, xopts, @@@ -773,7 -741,7 +773,7 @@@ static void add_strategies(const char * static void read_merge_msg(struct strbuf *msg) { - const char *filename = git_path_merge_msg(); + const char *filename = git_path_merge_msg(the_repository); strbuf_reset(msg); if (strbuf_read_file(msg, filename, 0) < 0) die_errno(_("Could not read from '%s'"), filename); @@@ -810,18 -778,18 +810,18 @@@ static void prepare_to_commit(struct co if (signoff) append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); write_merge_heads(remoteheads); - write_file_buf(git_path_merge_msg(), msg.buf, msg.len); + write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", - git_path_merge_msg(), "merge", NULL)) + git_path_merge_msg(the_repository), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { - if (launch_editor(git_path_merge_msg(), NULL, NULL)) + if (launch_editor(git_path_merge_msg(the_repository), NULL, NULL)) abort_commit(remoteheads, NULL); } if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(), "commit-msg", - git_path_merge_msg(), NULL)) + git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); read_merge_msg(&msg); @@@ -891,7 -859,7 +891,7 @@@ static int suggest_conflicts(void FILE *fp; struct strbuf msgbuf = STRBUF_INIT; - filename = git_path_merge_msg(); + filename = git_path_merge_msg(the_repository); fp = xfopen(filename, "a"); append_conflicts_hint(&msgbuf); @@@ -974,12 -942,12 +974,12 @@@ static void write_merge_heads(struct co } strbuf_addf(&buf, "%s\n", oid_to_hex(oid)); } - write_file_buf(git_path_merge_head(), buf.buf, buf.len); + write_file_buf(git_path_merge_head(the_repository), buf.buf, buf.len); strbuf_reset(&buf); if (fast_forward == FF_NO) strbuf_addstr(&buf, "no-ff"); - write_file_buf(git_path_merge_mode(), buf.buf, buf.len); + write_file_buf(git_path_merge_mode(the_repository), buf.buf, buf.len); strbuf_release(&buf); } @@@ -987,8 -955,7 +987,8 @@@ static void write_merge_state(struct co { write_merge_heads(remoteheads); strbuf_addch(&merge_msg, '\n'); - write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len); + write_file_buf(git_path_merge_msg(the_repository), merge_msg.buf, + merge_msg.len); } static int default_edit_option(void) @@@ -1067,12 -1034,11 +1067,12 @@@ static void handle_fetch_head(struct co const char *filename; int fd, pos, npos; struct strbuf fetch_head_file = STRBUF_INIT; + const unsigned hexsz = the_hash_algo->hexsz; if (!merge_names) merge_names = &fetch_head_file; - filename = git_path_fetch_head(); + filename = git_path_fetch_head(the_repository); fd = open(filename, O_RDONLY); if (fd < 0) die_errno(_("could not open '%s' for reading"), filename); @@@ -1093,16 -1059,16 +1093,16 @@@ else npos = merge_names->len; - if (npos - pos < GIT_SHA1_HEXSZ + 2 || + if (npos - pos < hexsz + 2 || get_oid_hex(merge_names->buf + pos, &oid)) commit = NULL; /* bad */ - else if (memcmp(merge_names->buf + pos + GIT_SHA1_HEXSZ, "\t\t", 2)) + else if (memcmp(merge_names->buf + pos + hexsz, "\t\t", 2)) continue; /* not-for-merge */ else { - char saved = merge_names->buf[pos + GIT_SHA1_HEXSZ]; - merge_names->buf[pos + GIT_SHA1_HEXSZ] = '\0'; + char saved = merge_names->buf[pos + hexsz]; + merge_names->buf[pos + hexsz] = '\0'; commit = get_merge_parent(merge_names->buf + pos); - merge_names->buf[pos + GIT_SHA1_HEXSZ] = saved; + merge_names->buf[pos + hexsz] = saved; } if (!commit) { if (ptr) @@@ -1247,7 -1213,7 +1247,7 @@@ int cmd_merge(int argc, const char **ar usage_msg_opt(_("--abort expects no arguments"), builtin_merge_usage, builtin_merge_options); - if (!file_exists(git_path_merge_head())) + if (!file_exists(git_path_merge_head(the_repository))) die(_("There is no merge to abort (MERGE_HEAD missing).")); /* Invoke 'git reset --merge' */ @@@ -1263,7 -1229,7 +1263,7 @@@ usage_msg_opt(_("--continue expects no arguments"), builtin_merge_usage, builtin_merge_options); - if (!file_exists(git_path_merge_head())) + if (!file_exists(git_path_merge_head(the_repository))) die(_("There is no merge in progress (MERGE_HEAD missing).")); /* Invoke 'git commit' */ @@@ -1274,7 -1240,7 +1274,7 @@@ if (read_cache_unmerged()) die_resolve_conflict("merge"); - if (file_exists(git_path_merge_head())) { + if (file_exists(git_path_merge_head(the_repository))) { /* * There is no unmerged entry, don't advise 'git * add/rm ', just 'git commit'. @@@ -1285,7 -1251,7 +1285,7 @@@ else die(_("You have not concluded your merge (MERGE_HEAD exists).")); } - if (file_exists(git_path_cherry_pick_head())) { + if (file_exists(git_path_cherry_pick_head(the_repository))) { if (advice_resolve_conflict) die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" "Please, commit your changes before you merge.")); diff --combined builtin/pack-objects.c index 33f23f99ce,37d63f6721..3848f3782d --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -140,7 -140,7 +140,7 @@@ static void *get_delta(struct object_en buf = read_object_file(&entry->idx.oid, &type, &size); if (!buf) - die("unable to read %s", oid_to_hex(&entry->idx.oid)); + die(_("unable to read %s"), oid_to_hex(&entry->idx.oid)); base_buf = read_object_file(&DELTA(entry)->idx.oid, &type, &base_size); if (!base_buf) @@@ -148,8 -148,13 +148,13 @@@ oid_to_hex(&DELTA(entry)->idx.oid)); delta_buf = diff_delta(base_buf, base_size, buf, size, &delta_size, 0); + /* + * 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. + */ if (!delta_buf || delta_size != DELTA_SIZE(entry)) - die("delta size changed"); + BUG("delta size changed"); free(buf); free(base_buf); return delta_buf; @@@ -406,7 -411,7 +411,7 @@@ static off_t write_reuse_object(struct datalen = revidx[1].offset - offset; if (!pack_to_stdout && p->index_version > 1 && check_pack_crc(p, &w_curs, offset, datalen, revidx->nr)) { - error("bad packed object CRC for %s", + error(_("bad packed object CRC for %s"), oid_to_hex(&entry->idx.oid)); unuse_pack(&w_curs); return write_no_reuse_object(f, entry, limit, usable_delta); @@@ -417,7 -422,7 +422,7 @@@ if (!pack_to_stdout && p->index_version == 1 && check_pack_inflate(p, &w_curs, offset, datalen, entry_size)) { - error("corrupt packed object for %s", + error(_("corrupt packed object for %s"), oid_to_hex(&entry->idx.oid)); unuse_pack(&w_curs); return write_no_reuse_object(f, entry, limit, usable_delta); @@@ -548,7 -553,7 +553,7 @@@ static enum write_one_status write_one( */ recursing = (e->idx.offset == 1); if (recursing) { - warning("recursive delta detected for object %s", + warning(_("recursive delta detected for object %s"), oid_to_hex(&e->idx.oid)); return WRITE_ONE_RECURSIVE; } else if (e->idx.offset || e->preferred_base) { @@@ -582,7 -587,7 +587,7 @@@ /* make sure off_t is sufficiently large not to wrap */ if (signed_add_overflows(*offset, size)) - die("pack too large for current definition of off_t"); + die(_("pack too large for current definition of off_t")); *offset += size; return WRITE_ONE_WRITTEN; } @@@ -748,7 -753,8 +753,8 @@@ static struct object_entry **compute_wr } if (wo_end != to_pack.nr_objects) - die("ordered %u objects, expected %"PRIu32, wo_end, to_pack.nr_objects); + die(_("ordered %u objects, expected %"PRIu32), + wo_end, to_pack.nr_objects); return wo; } @@@ -760,15 -766,15 +766,15 @@@ static off_t write_reused_pack(struct h int fd; if (!is_pack_valid(reuse_packfile)) - die("packfile is invalid: %s", reuse_packfile->pack_name); + die(_("packfile is invalid: %s"), reuse_packfile->pack_name); fd = git_open(reuse_packfile->pack_name); if (fd < 0) - die_errno("unable to open packfile for reuse: %s", + die_errno(_("unable to open packfile for reuse: %s"), reuse_packfile->pack_name); if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1) - die_errno("unable to seek in reused packfile"); + die_errno(_("unable to seek in reused packfile")); if (reuse_packfile_offset < 0) reuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz; @@@ -779,7 -785,7 +785,7 @@@ int read_pack = xread(fd, buffer, sizeof(buffer)); if (read_pack <= 0) - die_errno("unable to read from reused packfile"); + die_errno(_("unable to read from reused packfile")); if (read_pack > to_write) read_pack = to_write; @@@ -882,7 -888,7 +888,7 @@@ static void write_pack_file(void * to preserve this property. */ if (stat(pack_tmp_name, &st) < 0) { - warning_errno("failed to stat %s", pack_tmp_name); + warning_errno(_("failed to stat %s"), pack_tmp_name); } else if (!last_mtime) { last_mtime = st.st_mtime; } else { @@@ -890,7 -896,7 +896,7 @@@ utb.actime = st.st_atime; utb.modtime = --last_mtime; if (utime(pack_tmp_name, &utb) < 0) - warning_errno("failed utime() on %s", pack_tmp_name); + warning_errno(_("failed utime() on %s"), pack_tmp_name); } strbuf_addf(&tmpname, "%s-", base_name); @@@ -935,8 -941,8 +941,8 @@@ free(write_order); stop_progress(&progress_state); if (written != nr_result) - die("wrote %"PRIu32" objects while expecting %"PRIu32, - written, nr_result); + die(_("wrote %"PRIu32" objects while expecting %"PRIu32), + written, nr_result); } static int no_try_delta(const char *path) @@@ -1480,7 -1486,7 +1486,7 @@@ static void check_object(struct object_ while (c & 128) { ofs += 1; if (!ofs || MSB(ofs, 7)) { - error("delta base offset overflow in pack for %s", + error(_("delta base offset overflow in pack for %s"), oid_to_hex(&entry->idx.oid)); goto give_up; } @@@ -1489,7 -1495,7 +1495,7 @@@ } ofs = entry->in_pack_offset - ofs; if (ofs <= 0 || ofs >= entry->in_pack_offset) { - error("delta base offset out of bound for %s", + error(_("delta base offset out of bound for %s"), oid_to_hex(&entry->idx.oid)); goto give_up; } @@@ -1974,10 -1980,10 +1980,10 @@@ static int try_delta(struct unpacked *t trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz); read_unlock(); if (!trg->data) - die("object %s cannot be read", + die(_("object %s cannot be read"), oid_to_hex(&trg_entry->idx.oid)); if (sz != trg_size) - die("object %s inconsistent object length (%lu vs %lu)", + die(_("object %s inconsistent object length (%lu vs %lu)"), oid_to_hex(&trg_entry->idx.oid), sz, trg_size); *mem_usage += sz; @@@ -1990,7 -1996,7 +1996,7 @@@ if (src_entry->preferred_base) { static int warned = 0; if (!warned++) - warning("object %s cannot be read", + warning(_("object %s cannot be read"), oid_to_hex(&src_entry->idx.oid)); /* * Those objects are not included in the @@@ -2000,11 -2006,11 +2006,11 @@@ */ return 0; } - die("object %s cannot be read", + die(_("object %s cannot be read"), oid_to_hex(&src_entry->idx.oid)); } if (sz != src_size) - die("object %s inconsistent object length (%lu vs %lu)", + die(_("object %s inconsistent object length (%lu vs %lu)"), oid_to_hex(&src_entry->idx.oid), sz, src_size); *mem_usage += sz; @@@ -2014,7 -2020,7 +2020,7 @@@ if (!src->index) { static int warned = 0; if (!warned++) - warning("suboptimal pack - out of memory"); + warning(_("suboptimal pack - out of memory")); return 0; } *mem_usage += sizeof_delta_index(src->index); @@@ -2341,8 -2347,8 +2347,8 @@@ static void ll_find_deltas(struct objec return; } if (progress > pack_to_stdout) - fprintf(stderr, "Delta compression using up to %d threads.\n", - delta_search_threads); + fprintf_ln(stderr, _("Delta compression using up to %d threads"), + delta_search_threads); p = xcalloc(delta_search_threads, sizeof(*p)); /* Partition the work amongst work threads. */ @@@ -2382,7 -2388,7 +2388,7 @@@ ret = pthread_create(&p[i].thread, NULL, threaded_find_deltas, &p[i]); if (ret) - die("unable to create thread: %s", strerror(ret)); + die(_("unable to create thread: %s"), strerror(ret)); active_threads++; } @@@ -2474,10 -2480,10 +2480,10 @@@ static void add_tag_chain(const struct if (packlist_find(&to_pack, oid->hash, NULL)) return; - tag = lookup_tag(oid); + tag = lookup_tag(the_repository, oid); while (1) { if (!tag || parse_tag(tag) || !tag->tagged) - die("unable to pack objects reachable from tag %s", + die(_("unable to pack objects reachable from tag %s"), oid_to_hex(oid)); add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); @@@ -2543,7 -2549,7 +2549,7 @@@ static void prepare_pack(int window, in if (!entry->preferred_base) { nr_deltas++; if (oe_type(entry) < 0) - die("unable to get type of object %s", + die(_("unable to get type of object %s"), oid_to_hex(&entry->idx.oid)); } else { if (oe_type(entry) < 0) { @@@ -2567,7 -2573,7 +2573,7 @@@ ll_find_deltas(delta_list, n, window+1, depth, &nr_done); stop_progress(&progress_state); if (nr_done != nr_deltas) - die("inconsistency with delta count"); + die(_("inconsistency with delta count")); } free(delta_list); } @@@ -2607,11 -2613,11 +2613,11 @@@ static int git_pack_config(const char * if (!strcmp(k, "pack.threads")) { delta_search_threads = git_config_int(k, v); if (delta_search_threads < 0) - die("invalid number of threads specified (%d)", + die(_("invalid number of threads specified (%d)"), delta_search_threads); #ifdef NO_PTHREADS if (delta_search_threads != 1) { - warning("no threads support, ignoring %s", k); + warning(_("no threads support, ignoring %s"), k); delta_search_threads = 0; } #endif @@@ -2620,7 -2626,7 +2626,7 @@@ if (!strcmp(k, "pack.indexversion")) { pack_idx_opts.version = git_config_int(k, v); if (pack_idx_opts.version > 2) - die("bad pack.indexversion=%"PRIu32, + die(_("bad pack.indexversion=%"PRIu32), pack_idx_opts.version); return 0; } @@@ -2638,7 -2644,7 +2644,7 @@@ static void read_object_list_from_stdin if (feof(stdin)) break; if (!ferror(stdin)) - die("fgets returned NULL, not EOF, not error!"); + die("BUG: fgets returned NULL, not EOF, not error!"); if (errno != EINTR) die_errno("fgets"); clearerr(stdin); @@@ -2646,13 -2652,13 +2652,13 @@@ } if (line[0] == '-') { if (get_oid_hex(line+1, &oid)) - die("expected edge object ID, got garbage:\n %s", + die(_("expected edge object ID, got garbage:\n %s"), line); add_preferred_base(&oid); continue; } if (parse_oid_hex(line, &oid, &p)) - die("expected object ID, got garbage:\n %s", line); + die(_("expected object ID, got garbage:\n %s"), line); add_preferred_base_object(p + 1); add_object_entry(&oid, OBJ_NONE, p + 1, 0); @@@ -2791,7 -2797,7 +2797,7 @@@ static void add_objects_in_unpacked_pac if (!p->pack_local || p->pack_keep || p->pack_keep_in_core) continue; if (open_pack_index(p)) - die("cannot open pack index"); + die(_("cannot open pack index")); ALLOC_GROW(in_pack.array, in_pack.nr + p->num_objects, @@@ -2822,7 -2828,7 +2828,7 @@@ static int add_loose_object(const struc enum object_type type = oid_object_info(the_repository, oid, NULL); if (type < 0) { - warning("loose object at %s could not be examined", path); + warning(_("loose object at %s could not be examined"), path); return 0; } @@@ -2899,7 -2905,7 +2905,7 @@@ static void loosen_unused_packed_object continue; if (open_pack_index(p)) - die("cannot open pack index"); + die(_("cannot open pack index")); for (i = 0; i < p->num_objects; i++) { nth_packed_object_oid(&oid, p, i); @@@ -2907,7 -2913,7 +2913,7 @@@ !has_sha1_pack_kept_or_nonlocal(&oid) && !loosened_object_can_be_discarded(&oid, p->mtime)) if (force_object_loose(&oid, p->mtime)) - die("unable to force loose object"); + die(_("unable to force loose object")); } } } @@@ -2929,13 -2935,11 +2935,13 @@@ static int pack_options_allow_reuse(voi static int get_object_list_from_bitmap(struct rev_info *revs) { - if (prepare_bitmap_walk(revs) < 0) + struct bitmap_index *bitmap_git; + if (!(bitmap_git = prepare_bitmap_walk(revs))) return -1; if (pack_options_allow_reuse() && !reuse_partial_packfile_from_bitmap( + bitmap_git, &reuse_packfile, &reuse_packfile_objects, &reuse_packfile_offset)) { @@@ -2944,8 -2948,7 +2950,8 @@@ display_progress(progress_state, nr_result); } - traverse_bitmap_commit_list(&add_object_entry_from_bitmap); + traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap); + free_bitmap_index(bitmap_git); return 0; } @@@ -2972,7 -2975,7 +2978,7 @@@ static void get_object_list(int ac, con setup_revisions(ac, av, &revs, NULL); /* make sure shallows are read */ - is_repository_shallow(); + is_repository_shallow(the_repository); while (fgets(line, sizeof(line), stdin) != NULL) { int len = strlen(line); @@@ -2990,21 -2993,21 +2996,21 @@@ struct object_id oid; if (get_oid_hex(line + 10, &oid)) die("not an SHA-1 '%s'", line + 10); - register_shallow(&oid); + register_shallow(the_repository, &oid); use_bitmap_index = 0; continue; } - die("not a rev '%s'", line); + die(_("not a rev '%s'"), line); } if (handle_revision_arg(line, &revs, flags, REVARG_CANNOT_BE_FILENAME)) - die("bad revision '%s'", line); + die(_("bad revision '%s'"), line); } if (use_bitmap_index && !get_object_list_from_bitmap(&revs)) return; if (prepare_revision_walk(&revs)) - die("revision walk setup failed"); + die(_("revision walk setup failed")); mark_edges_uninteresting(&revs, show_edge); if (!fn_show_object) @@@ -3017,9 -3020,9 +3023,9 @@@ revs.ignore_missing_links = 1; if (add_unseen_recent_objects_to_traversal(&revs, unpack_unreachable_expiration)) - die("unable to add recent objects"); + die(_("unable to add recent objects")); if (prepare_revision_walk(&revs)) - die("revision walk setup failed"); + die(_("revision walk setup failed")); traverse_commit_list(&revs, record_recent_commit, record_recent_object, NULL); } @@@ -3188,7 -3191,7 +3194,7 @@@ int cmd_pack_objects(int argc, const ch if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS)) BUG("too many dfs states, increase OE_DFS_STATE_BITS"); - check_replace_refs = 0; + read_replace_refs = 0; reset_pack_idx_option(&pack_idx_opts); git_config(git_pack_config, NULL); @@@ -3254,35 -3257,35 +3260,35 @@@ if (pack_compression_level == -1) pack_compression_level = Z_DEFAULT_COMPRESSION; else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION) - die("bad pack compression level %d", pack_compression_level); + die(_("bad pack compression level %d"), pack_compression_level); if (!delta_search_threads) /* --threads=0 means autodetect */ delta_search_threads = online_cpus(); #ifdef NO_PTHREADS if (delta_search_threads != 1) - warning("no threads support, ignoring --threads"); + warning(_("no threads support, ignoring --threads")); #endif if (!pack_to_stdout && !pack_size_limit) pack_size_limit = pack_size_limit_cfg; if (pack_to_stdout && pack_size_limit) - die("--max-pack-size cannot be used to build a pack for transfer."); + die(_("--max-pack-size cannot be used to build a pack for transfer")); if (pack_size_limit && pack_size_limit < 1024*1024) { - warning("minimum pack size limit is 1 MiB"); + warning(_("minimum pack size limit is 1 MiB")); pack_size_limit = 1024*1024; } if (!pack_to_stdout && thin) - die("--thin cannot be used to build an indexable pack."); + die(_("--thin cannot be used to build an indexable pack")); if (keep_unreachable && unpack_unreachable) - die("--keep-unreachable and --unpack-unreachable are incompatible."); + die(_("--keep-unreachable and --unpack-unreachable are incompatible")); if (!rev_list_all || !rev_list_reflog || !rev_list_index) unpack_unreachable_expiration = 0; if (filter_options.choice) { if (!pack_to_stdout) - die("cannot use --filter without --stdout."); + die(_("cannot use --filter without --stdout")); use_bitmap_index = 0; } @@@ -3302,7 -3305,7 +3308,7 @@@ use_bitmap_index = use_bitmap_index_default; /* "hard" reasons not to use bitmaps; these just won't work at all */ - if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow()) + if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow(the_repository)) use_bitmap_index = 0; if (pack_to_stdout || !rev_list_all) @@@ -3356,8 -3359,9 +3362,9 @@@ prepare_pack(window, depth); write_pack_file(); if (progress) - fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32")," - " reused %"PRIu32" (delta %"PRIu32")\n", - written, written_delta, reused, reused_delta); + fprintf_ln(stderr, + _("Total %"PRIu32" (delta %"PRIu32")," + " reused %"PRIu32" (delta %"PRIu32")"), + written, written_delta, reused, reused_delta); return 0; } diff --combined builtin/replace.c index e997a562f0,e879ace277..4f05791f3e --- a/builtin/replace.c +++ b/builtin/replace.c @@@ -54,7 -54,7 +54,7 @@@ static int show_reference(const char *r enum object_type obj_type, repl_type; if (get_oid(refname, &object)) - return error("Failed to resolve '%s' as a valid ref.", refname); + return error(_("failed to resolve '%s' as a valid ref"), refname); obj_type = oid_object_info(the_repository, &object, NULL); @@@ -83,8 -83,8 +83,8 @@@ static int list_replace_refs(const cha else if (!strcmp(format, "long")) data.format = REPLACE_FORMAT_LONG; else - return error("invalid replace format '%s'\n" - "valid formats are 'short', 'medium' and 'long'\n", + return error(_("invalid replace format '%s'\n" + "valid formats are 'short', 'medium' and 'long'"), format); for_each_replace_ref(the_repository, show_reference, (void *)&data); @@@ -108,7 -108,7 +108,7 @@@ static int for_each_replace_name(const for (p = argv; *p; p++) { if (get_oid(*p, &oid)) { - error("Failed to resolve '%s' as a valid ref.", *p); + error("failed to resolve '%s' as a valid ref", *p); had_error = 1; continue; } @@@ -118,7 -118,7 +118,7 @@@ full_hex = ref.buf + base_len; if (read_ref(ref.buf, &oid)) { - error("replace ref '%s' not found.", full_hex); + error(_("replace ref '%s' not found"), full_hex); had_error = 1; continue; } @@@ -134,7 -134,7 +134,7 @@@ static int delete_replace_ref(const cha { if (delete_ref(NULL, ref, oid, 0)) return 1; - printf("Deleted replace ref '%s'\n", name); + printf_ln(_("Deleted replace ref '%s'"), name); return 0; } @@@ -146,12 -146,12 +146,12 @@@ static int check_ref_valid(struct objec strbuf_reset(ref); strbuf_addf(ref, "%s%s", git_replace_ref_base, oid_to_hex(object)); if (check_refname_format(ref->buf, 0)) - return error("'%s' is not a valid ref name.", ref->buf); + return error(_("'%s' is not a valid ref name"), ref->buf); if (read_ref(ref->buf, prev)) oidclr(prev); else if (!force) - return error("replace ref '%s' already exists", ref->buf); + return error(_("replace ref '%s' already exists"), ref->buf); return 0; } @@@ -171,10 -171,10 +171,10 @@@ static int replace_object_oid(const cha obj_type = oid_object_info(the_repository, object, NULL); repl_type = oid_object_info(the_repository, repl, NULL); if (!force && obj_type != repl_type) - return error("Objects must be of the same type.\n" - "'%s' points to a replaced object of type '%s'\n" - "while '%s' points to a replacement object of " - "type '%s'.", + return error(_("Objects must be of the same type.\n" + "'%s' points to a replaced object of type '%s'\n" + "while '%s' points to a replacement object of " + "type '%s'."), object_ref, type_name(obj_type), replace_ref, type_name(repl_type)); @@@ -200,10 -200,10 +200,10 @@@ static int replace_object(const char *o struct object_id object, repl; if (get_oid(object_ref, &object)) - return error("Failed to resolve '%s' as a valid ref.", + return error(_("failed to resolve '%s' as a valid ref"), object_ref); if (get_oid(replace_ref, &repl)) - return error("Failed to resolve '%s' as a valid ref.", + return error(_("failed to resolve '%s' as a valid ref"), replace_ref); return replace_object_oid(object_ref, &object, replace_ref, &repl, force); @@@ -222,7 -222,7 +222,7 @@@ static int export_object(const struct o fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) - return error_errno("unable to open %s for writing", filename); + return error_errno(_("unable to open %s for writing"), filename); argv_array_push(&cmd.args, "--no-replace-objects"); argv_array_push(&cmd.args, "cat-file"); @@@ -235,7 -235,7 +235,7 @@@ cmd.out = fd; if (run_command(&cmd)) - return error("cat-file reported failure"); + return error(_("cat-file reported failure")); return 0; } @@@ -251,7 -251,7 +251,7 @@@ static int import_object(struct object_ fd = open(filename, O_RDONLY); if (fd < 0) - return error_errno("unable to open %s for reading", filename); + return error_errno(_("unable to open %s for reading"), filename); if (!raw && type == OBJ_TREE) { const char *argv[] = { "mktree", NULL }; @@@ -265,11 -265,11 +265,11 @@@ if (start_command(&cmd)) { close(fd); - return error("unable to spawn mktree"); + return error(_("unable to spawn mktree")); } if (strbuf_read(&result, cmd.out, 41) < 0) { - error_errno("unable to read from mktree"); + error_errno(_("unable to read from mktree")); close(fd); close(cmd.out); return -1; @@@ -278,11 -278,11 +278,11 @@@ if (finish_command(&cmd)) { strbuf_release(&result); - return error("mktree reported failure"); + return error(_("mktree reported failure")); } if (get_oid_hex(result.buf, oid) < 0) { strbuf_release(&result); - return error("mktree did not return an object name"); + return error(_("mktree did not return an object name")); } strbuf_release(&result); @@@ -291,12 -291,12 +291,12 @@@ int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT; if (fstat(fd, &st) < 0) { - error_errno("unable to fstat %s", filename); + error_errno(_("unable to fstat %s"), filename); close(fd); return -1; } if (index_fd(oid, fd, &st, type, NULL, flags) < 0) - return error("unable to write object to database"); + return error(_("unable to write object to database")); /* index_fd close()s fd for us */ } @@@ -315,11 -315,11 +315,11 @@@ static int edit_and_replace(const char struct strbuf ref = STRBUF_INIT; if (get_oid(object_ref, &old_oid) < 0) - return error("Not a valid object name: '%s'", object_ref); + return error(_("not a valid object name: '%s'"), object_ref); type = oid_object_info(the_repository, &old_oid, NULL); if (type < 0) - return error("unable to get object type for %s", + return error(_("unable to get object type for %s"), oid_to_hex(&old_oid)); if (check_ref_valid(&old_oid, &prev, &ref, force)) { @@@ -335,7 -335,7 +335,7 @@@ } if (launch_editor(tmpfile, NULL, NULL) < 0) { free(tmpfile); - return error("editing object file failed"); + return error(_("editing object file failed")); } if (import_object(&new_oid, type, raw, tmpfile)) { free(tmpfile); @@@ -344,7 -344,7 +344,7 @@@ free(tmpfile); if (!oidcmp(&old_oid, &new_oid)) - return error("new object is the same as the old one: '%s'", oid_to_hex(&old_oid)); + return error(_("new object is the same as the old one: '%s'"), oid_to_hex(&old_oid)); return replace_object_oid(object_ref, &old_oid, "replacement", &new_oid, force); } @@@ -368,10 -368,10 +368,10 @@@ static int replace_parents(struct strbu struct object_id oid; if (get_oid(argv[i], &oid) < 0) { strbuf_release(&new_parents); - return error(_("Not a valid object name: '%s'"), + return error(_("not a valid object name: '%s'"), argv[i]); } - if (!lookup_commit_reference(&oid)) { + if (!lookup_commit_reference(the_repository, &oid)) { strbuf_release(&new_parents); return error(_("could not parse %s"), argv[i]); } @@@ -402,17 -402,17 +402,17 @@@ static int check_one_mergetag(struct co int i; hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &tag_oid); - tag = lookup_tag(&tag_oid); + tag = lookup_tag(the_repository, &tag_oid); if (!tag) return error(_("bad mergetag in commit '%s'"), ref); - if (parse_tag_buffer(tag, extra->value, extra->len)) + if (parse_tag_buffer(the_repository, tag, extra->value, extra->len)) return error(_("malformed mergetag in commit '%s'"), ref); /* iterate over new parents */ for (i = 1; i < mergetag_data->argc; i++) { struct object_id oid; if (get_oid(mergetag_data->argv[i], &oid) < 0) - return error(_("Not a valid object name: '%s'"), + return error(_("not a valid object name: '%s'"), mergetag_data->argv[i]); if (!oidcmp(&tag->tagged->oid, &oid)) return 0; /* found */ @@@ -442,8 -442,8 +442,8 @@@ static int create_graft(int argc, cons unsigned long size; if (get_oid(old_ref, &old_oid) < 0) - return error(_("Not a valid object name: '%s'"), old_ref); + return error(_("not a valid object name: '%s'"), old_ref); - commit = lookup_commit_reference(&old_oid); + commit = lookup_commit_reference(the_repository, &old_oid); if (!commit) return error(_("could not parse %s"), old_ref); @@@ -457,7 -457,7 +457,7 @@@ } if (remove_signature(&buf)) { - warning(_("the original commit '%s' has a gpg signature."), old_ref); + warning(_("the original commit '%s' has a gpg signature"), old_ref); warning(_("the signature will be removed in the replacement commit!")); } @@@ -476,10 -476,10 +476,10 @@@ if (!oidcmp(&old_oid, &new_oid)) { if (gentle) { - warning("graft for '%s' unnecessary", oid_to_hex(&old_oid)); + warning(_("graft for '%s' unnecessary"), oid_to_hex(&old_oid)); return 0; } - return error("new commit is the same as the old one: '%s'", oid_to_hex(&old_oid)); + return error(_("new commit is the same as the old one: '%s'"), oid_to_hex(&old_oid)); } return replace_object_oid(old_ref, &old_oid, "replacement", &new_oid, force); @@@ -487,7 -487,7 +487,7 @@@ static int convert_graft_file(int force) { - const char *graft_file = get_graft_file(); + const char *graft_file = get_graft_file(the_repository); FILE *fp = fopen_or_warn(graft_file, "r"); struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT; struct argv_array args = ARGV_ARRAY_INIT; @@@ -544,7 -544,7 +544,7 @@@ int cmd_replace(int argc, const char ** OPT_END() }; - check_replace_refs = 0; + read_replace_refs = 0; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0); @@@ -553,7 -553,7 +553,7 @@@ cmdmode = argc ? MODE_REPLACE : MODE_LIST; if (format && cmdmode != MODE_LIST) - usage_msg_opt("--format cannot be used when not listing", + usage_msg_opt(_("--format cannot be used when not listing"), git_replace_usage, options); if (force && @@@ -561,47 -561,47 +561,47 @@@ cmdmode != MODE_EDIT && cmdmode != MODE_GRAFT && cmdmode != MODE_CONVERT_GRAFT_FILE) - usage_msg_opt("-f only makes sense when writing a replacement", + usage_msg_opt(_("-f only makes sense when writing a replacement"), git_replace_usage, options); if (raw && cmdmode != MODE_EDIT) - usage_msg_opt("--raw only makes sense with --edit", + usage_msg_opt(_("--raw only makes sense with --edit"), git_replace_usage, options); switch (cmdmode) { case MODE_DELETE: if (argc < 1) - usage_msg_opt("-d needs at least one argument", + usage_msg_opt(_("-d needs at least one argument"), git_replace_usage, options); return for_each_replace_name(argv, delete_replace_ref); case MODE_REPLACE: if (argc != 2) - usage_msg_opt("bad number of arguments", + usage_msg_opt(_("bad number of arguments"), git_replace_usage, options); return replace_object(argv[0], argv[1], force); case MODE_EDIT: if (argc != 1) - usage_msg_opt("-e needs exactly one argument", + usage_msg_opt(_("-e needs exactly one argument"), git_replace_usage, options); return edit_and_replace(argv[0], force, raw); case MODE_GRAFT: if (argc < 1) - usage_msg_opt("-g needs at least one argument", + usage_msg_opt(_("-g needs at least one argument"), git_replace_usage, options); return create_graft(argc, argv, force, 0); case MODE_CONVERT_GRAFT_FILE: if (argc != 0) - usage_msg_opt("--convert-graft-file takes no argument", + usage_msg_opt(_("--convert-graft-file takes no argument"), git_replace_usage, options); return !!convert_graft_file(force); case MODE_LIST: if (argc > 1) - usage_msg_opt("only one pattern can be given with -l", + usage_msg_opt(_("only one pattern can be given with -l"), git_replace_usage, options); return list_replace_refs(argv[0], format); diff --combined commit-graph.c index b0a55ad128,c8d521923c..0034740c26 --- a/commit-graph.c +++ b/commit-graph.c @@@ -7,12 -7,10 +7,12 @@@ #include "packfile.h" #include "commit.h" #include "object.h" +#include "refs.h" #include "revision.h" #include "sha1-lookup.h" #include "commit-graph.h" #include "object-store.h" +#include "alloc.h" #define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */ #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */ @@@ -37,11 -35,10 +37,11 @@@ #define GRAPH_LAST_EDGE 0x80000000 +#define GRAPH_HEADER_SIZE 8 #define GRAPH_FANOUT_SIZE (4 * 256) #define GRAPH_CHUNKLOOKUP_WIDTH 12 -#define GRAPH_MIN_SIZE (5 * GRAPH_CHUNKLOOKUP_WIDTH + GRAPH_FANOUT_SIZE + \ - GRAPH_OID_LEN + 8) +#define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \ + + GRAPH_FANOUT_SIZE + GRAPH_OID_LEN) char *get_commit_graph_filename(const char *obj_dir) { @@@ -80,28 -77,28 +80,28 @@@ struct commit_graph *load_commit_graph_ if (graph_size < GRAPH_MIN_SIZE) { close(fd); - die("graph file %s is too small", graph_file); + die(_("graph file %s is too small"), graph_file); } graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0); data = (const unsigned char *)graph_map; graph_signature = get_be32(data); if (graph_signature != GRAPH_SIGNATURE) { - error("graph signature %X does not match signature %X", + error(_("graph signature %X does not match signature %X"), graph_signature, GRAPH_SIGNATURE); goto cleanup_fail; } graph_version = *(unsigned char*)(data + 4); if (graph_version != GRAPH_VERSION) { - error("graph version %X does not match version %X", + error(_("graph version %X does not match version %X"), graph_version, GRAPH_VERSION); goto cleanup_fail; } hash_version = *(unsigned char*)(data + 5); if (hash_version != GRAPH_OID_VERSION) { - error("hash version %X does not match version %X", + error(_("hash version %X does not match version %X"), hash_version, GRAPH_OID_VERSION); goto cleanup_fail; } @@@ -125,7 -122,7 +125,7 @@@ chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH; if (chunk_offset > graph_size - GIT_MAX_RAWSZ) { - error("improper chunk offset %08x%08x", (uint32_t)(chunk_offset >> 32), + error(_("improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32), (uint32_t)chunk_offset); goto cleanup_fail; } @@@ -161,7 -158,7 +161,7 @@@ } if (chunk_repeated) { - error("chunk id %08x appears multiple times", chunk_id); + error(_("chunk id %08x appears multiple times"), chunk_id); goto cleanup_fail; } @@@ -183,60 -180,53 +183,60 @@@ cleanup_fail exit(1); } -/* global storage */ -static struct commit_graph *commit_graph = NULL; - -static void prepare_commit_graph_one(const char *obj_dir) +static void prepare_commit_graph_one(struct repository *r, const char *obj_dir) { char *graph_name; - if (commit_graph) + if (r->objects->commit_graph) return; graph_name = get_commit_graph_filename(obj_dir); - commit_graph = load_commit_graph_one(graph_name); + r->objects->commit_graph = + load_commit_graph_one(graph_name); FREE_AND_NULL(graph_name); } -static int prepare_commit_graph_run_once = 0; -static void prepare_commit_graph(void) +/* + * Return 1 if commit_graph is non-NULL, and 0 otherwise. + * + * On the first invocation, this function attemps to load the commit + * graph if the_repository is configured to have one. + */ +static int prepare_commit_graph(struct repository *r) { struct alternate_object_database *alt; char *obj_dir; + int config_value; + + if (r->objects->commit_graph_attempted) + return !!r->objects->commit_graph; + r->objects->commit_graph_attempted = 1; + + if (repo_config_get_bool(r, "core.commitgraph", &config_value) || + !config_value) + /* + * This repository is not configured to use commit graphs, so + * do not load one. (But report commit_graph_attempted anyway + * so that commit graph loading is not attempted again for this + * repository.) + */ + return 0; - if (prepare_commit_graph_run_once) - return; - prepare_commit_graph_run_once = 1; - - obj_dir = get_object_directory(); - prepare_commit_graph_one(obj_dir); - prepare_alt_odb(the_repository); - for (alt = the_repository->objects->alt_odb_list; - !commit_graph && alt; + obj_dir = r->objects->objectdir; + prepare_commit_graph_one(r, obj_dir); + prepare_alt_odb(r); + for (alt = r->objects->alt_odb_list; + !r->objects->commit_graph && alt; alt = alt->next) - prepare_commit_graph_one(alt->path); + prepare_commit_graph_one(r, alt->path); + return !!r->objects->commit_graph; } static void close_commit_graph(void) { - if (!commit_graph) - return; - - if (commit_graph->graph_fd >= 0) { - munmap((void *)commit_graph->data, commit_graph->data_len); - commit_graph->data = NULL; - close(commit_graph->graph_fd); - } - - FREE_AND_NULL(commit_graph); + free_commit_graph(the_repository->objects->commit_graph); + the_repository->objects->commit_graph = NULL; } static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t *pos) @@@ -251,14 -241,10 +251,14 @@@ static struct commit_list **insert_pare { struct commit *c; struct object_id oid; + + if (pos >= g->num_commits) + die("invalid parent position %"PRIu64, pos); + hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos); - c = lookup_commit(&oid); + c = lookup_commit(the_repository, &oid); if (!c) - die("could not find commit %s", oid_to_hex(&oid)); + die(_("could not find commit %s"), oid_to_hex(&oid)); c->graph_pos = pos; return &commit_list_insert(c, pptr)->next; } @@@ -327,33 -313,28 +327,33 @@@ static int find_commit_in_graph(struct } } -int parse_commit_in_graph(struct commit *item) +static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item) { uint32_t pos; - if (!core_commit_graph) - return 0; if (item->object.parsed) return 1; - prepare_commit_graph(); - if (commit_graph && find_commit_in_graph(item, commit_graph, &pos)) - return fill_commit_in_graph(item, commit_graph, pos); + + if (find_commit_in_graph(item, g, &pos)) + return fill_commit_in_graph(item, g, pos); + return 0; } -void load_commit_graph_info(struct commit *item) +int parse_commit_in_graph(struct repository *r, struct commit *item) +{ + if (!prepare_commit_graph(r)) + return 0; + return parse_commit_in_graph_one(r->objects->commit_graph, item); +} + +void load_commit_graph_info(struct repository *r, struct commit *item) { uint32_t pos; - if (!core_commit_graph) + if (!prepare_commit_graph(r)) return; - prepare_commit_graph(); - if (commit_graph && find_commit_in_graph(item, commit_graph, &pos)) - fill_commit_graph_info(item, commit_graph, pos); + if (find_commit_in_graph(item, r->objects->commit_graph, &pos)) + fill_commit_graph_info(item, r->objects->commit_graph, pos); } static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c) @@@ -363,25 -344,19 +363,25 @@@ GRAPH_DATA_WIDTH * (c->graph_pos); hashcpy(oid.hash, commit_data); - c->maybe_tree = lookup_tree(&oid); + c->maybe_tree = lookup_tree(the_repository, &oid); return c->maybe_tree; } -struct tree *get_commit_tree_in_graph(const struct commit *c) +static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g, + const struct commit *c) { if (c->maybe_tree) return c->maybe_tree; if (c->graph_pos == COMMIT_NOT_FROM_GRAPH) - BUG("get_commit_tree_in_graph called from non-commit-graph commit"); + BUG("get_commit_tree_in_graph_one called from non-commit-graph commit"); - return load_tree_for_commit(commit_graph, (struct commit *)c); + return load_tree_for_commit(g, (struct commit *)c); +} + +struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c) +{ + return get_commit_tree_in_graph_one(r->objects->commit_graph, c); } static void write_graph_chunk_fanout(struct hashfile *f, @@@ -562,7 -537,7 +562,7 @@@ static int add_packed_commits(const str oi.typep = &type; if (packed_object_info(the_repository, pack, offset, &oi) < 0) - die("unable to get type of object %s", oid_to_hex(oid)); + die(_("unable to get type of object %s"), oid_to_hex(oid)); if (type != OBJ_COMMIT) return 0; @@@ -593,7 -568,7 +593,7 @@@ static void close_reachable(struct pack struct commit *commit; for (i = 0; i < oids->nr; i++) { - commit = lookup_commit(&oids->list[i]); + commit = lookup_commit(the_repository, &oids->list[i]); if (commit) commit->object.flags |= UNINTERESTING; } @@@ -604,14 -579,14 +604,14 @@@ * closure. */ for (i = 0; i < oids->nr; i++) { - commit = lookup_commit(&oids->list[i]); + commit = lookup_commit(the_repository, &oids->list[i]); if (commit && !parse_commit(commit)) add_missing_parents(oids, commit); } for (i = 0; i < oids->nr; i++) { - commit = lookup_commit(&oids->list[i]); + commit = lookup_commit(the_repository, &oids->list[i]); if (commit) commit->object.flags &= ~UNINTERESTING; @@@ -657,28 -632,11 +657,28 @@@ static void compute_generation_numbers( } } +static int add_ref_to_list(const char *refname, + const struct object_id *oid, + int flags, void *cb_data) +{ + struct string_list *list = (struct string_list *)cb_data; + + string_list_append(list, oid_to_hex(oid)); + return 0; +} + +void write_commit_graph_reachable(const char *obj_dir, int append) +{ + struct string_list list; + + string_list_init(&list, 1); + for_each_ref(add_ref_to_list, &list); + write_commit_graph(obj_dir, NULL, &list, append); +} + void write_commit_graph(const char *obj_dir, - const char **pack_indexes, - int nr_packs, - const char **commit_hex, - int nr_commits, + struct string_list *pack_indexes, + struct string_list *commit_hex, int append) { struct packed_oid_list oids; @@@ -697,18 -655,16 +697,18 @@@ oids.alloc = approximate_object_count() / 4; if (append) { - prepare_commit_graph_one(obj_dir); - if (commit_graph) - oids.alloc += commit_graph->num_commits; + prepare_commit_graph_one(the_repository, obj_dir); + if (the_repository->objects->commit_graph) + oids.alloc += the_repository->objects->commit_graph->num_commits; } if (oids.alloc < 1024) oids.alloc = 1024; ALLOC_ARRAY(oids.list, oids.alloc); - if (append && commit_graph) { + if (append && the_repository->objects->commit_graph) { + struct commit_graph *commit_graph = + the_repository->objects->commit_graph; for (i = 0; i < commit_graph->num_commits; i++) { const unsigned char *hash = commit_graph->chunk_oid_lookup + commit_graph->hash_len * i; @@@ -721,15 -677,15 +721,15 @@@ int dirlen; strbuf_addf(&packname, "%s/pack/", obj_dir); dirlen = packname.len; - for (i = 0; i < nr_packs; i++) { + for (i = 0; i < pack_indexes->nr; i++) { struct packed_git *p; strbuf_setlen(&packname, dirlen); - strbuf_addstr(&packname, pack_indexes[i]); + strbuf_addstr(&packname, pack_indexes->items[i].string); p = add_packed_git(packname.buf, packname.len, 1); if (!p) - die("error adding pack %s", packname.buf); + die(_("error adding pack %s"), packname.buf); if (open_pack_index(p)) - die("error opening index for %s", packname.buf); + die(_("error opening index for %s"), packname.buf); for_each_object_in_pack(p, add_packed_commits, &oids); close_pack(p); } @@@ -737,16 -693,15 +737,16 @@@ } if (commit_hex) { - for (i = 0; i < nr_commits; i++) { + for (i = 0; i < commit_hex->nr; i++) { const char *end; struct object_id oid; struct commit *result; - if (commit_hex[i] && parse_oid_hex(commit_hex[i], &oid, &end)) + if (commit_hex->items[i].string && + parse_oid_hex(commit_hex->items[i].string, &oid, &end)) continue; - result = lookup_commit_reference_gently(&oid, 1); + result = lookup_commit_reference_gently(the_repository, &oid, 1); if (result) { ALLOC_GROW(oids.list, oids.nr + 1, oids.alloc); @@@ -782,7 -737,7 +782,7 @@@ if (i > 0 && !oidcmp(&oids.list[i-1], &oids.list[i])) continue; - commits.list[commits.nr] = lookup_commit(&oids.list[i]); + commits.list[commits.nr] = lookup_commit(the_repository, &oids.list[i]); parse_commit(commits.list[commits.nr]); for (parent = commits.list[commits.nr]->parents; @@@ -853,191 -808,3 +853,191 @@@ oids.alloc = 0; oids.nr = 0; } + +#define VERIFY_COMMIT_GRAPH_ERROR_HASH 2 +static int verify_commit_graph_error; + +static void graph_report(const char *fmt, ...) +{ + va_list ap; + + verify_commit_graph_error = 1; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#define GENERATION_ZERO_EXISTS 1 +#define GENERATION_NUMBER_EXISTS 2 + +int verify_commit_graph(struct repository *r, struct commit_graph *g) +{ + uint32_t i, cur_fanout_pos = 0; + struct object_id prev_oid, cur_oid, checksum; + int generation_zero = 0; + struct hashfile *f; + int devnull; + + if (!g) { + graph_report("no commit-graph file loaded"); + return 1; + } + + verify_commit_graph_error = 0; + + if (!g->chunk_oid_fanout) + graph_report("commit-graph is missing the OID Fanout chunk"); + if (!g->chunk_oid_lookup) + graph_report("commit-graph is missing the OID Lookup chunk"); + if (!g->chunk_commit_data) + graph_report("commit-graph is missing the Commit Data chunk"); + + if (verify_commit_graph_error) + return verify_commit_graph_error; + + devnull = open("/dev/null", O_WRONLY); + f = hashfd(devnull, NULL); + hashwrite(f, g->data, g->data_len - g->hash_len); + finalize_hashfile(f, checksum.hash, CSUM_CLOSE); + if (hashcmp(checksum.hash, g->data + g->data_len - g->hash_len)) { + graph_report(_("the commit-graph file has incorrect checksum and is likely corrupt")); + verify_commit_graph_error = VERIFY_COMMIT_GRAPH_ERROR_HASH; + } + + for (i = 0; i < g->num_commits; i++) { + struct commit *graph_commit; + + hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i); + + if (i && oidcmp(&prev_oid, &cur_oid) >= 0) + graph_report("commit-graph has incorrect OID order: %s then %s", + oid_to_hex(&prev_oid), + oid_to_hex(&cur_oid)); + + oidcpy(&prev_oid, &cur_oid); + + while (cur_oid.hash[0] > cur_fanout_pos) { + uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos); + + if (i != fanout_value) + graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u", + cur_fanout_pos, fanout_value, i); + cur_fanout_pos++; + } + + graph_commit = lookup_commit(r, &cur_oid); + if (!parse_commit_in_graph_one(g, graph_commit)) + graph_report("failed to parse %s from commit-graph", + oid_to_hex(&cur_oid)); + } + + while (cur_fanout_pos < 256) { + uint32_t fanout_value = get_be32(g->chunk_oid_fanout + cur_fanout_pos); + + if (g->num_commits != fanout_value) + graph_report("commit-graph has incorrect fanout value: fanout[%d] = %u != %u", + cur_fanout_pos, fanout_value, i); + + cur_fanout_pos++; + } + + if (verify_commit_graph_error & ~VERIFY_COMMIT_GRAPH_ERROR_HASH) + return verify_commit_graph_error; + + for (i = 0; i < g->num_commits; i++) { + struct commit *graph_commit, *odb_commit; + struct commit_list *graph_parents, *odb_parents; + uint32_t max_generation = 0; + + hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i); + + graph_commit = lookup_commit(r, &cur_oid); + odb_commit = (struct commit *)create_object(r, cur_oid.hash, alloc_commit_node(r)); + if (parse_commit_internal(odb_commit, 0, 0)) { + graph_report("failed to parse %s from object database", + oid_to_hex(&cur_oid)); + continue; + } + + if (oidcmp(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid, + get_commit_tree_oid(odb_commit))) + graph_report("root tree OID for commit %s in commit-graph is %s != %s", + oid_to_hex(&cur_oid), + oid_to_hex(get_commit_tree_oid(graph_commit)), + oid_to_hex(get_commit_tree_oid(odb_commit))); + + graph_parents = graph_commit->parents; + odb_parents = odb_commit->parents; + + while (graph_parents) { + if (odb_parents == NULL) { + graph_report("commit-graph parent list for commit %s is too long", + oid_to_hex(&cur_oid)); + break; + } + + if (oidcmp(&graph_parents->item->object.oid, &odb_parents->item->object.oid)) + graph_report("commit-graph parent for %s is %s != %s", + oid_to_hex(&cur_oid), + oid_to_hex(&graph_parents->item->object.oid), + oid_to_hex(&odb_parents->item->object.oid)); + + if (graph_parents->item->generation > max_generation) + max_generation = graph_parents->item->generation; + + graph_parents = graph_parents->next; + odb_parents = odb_parents->next; + } + + if (odb_parents != NULL) + graph_report("commit-graph parent list for commit %s terminates early", + oid_to_hex(&cur_oid)); + + if (!graph_commit->generation) { + if (generation_zero == GENERATION_NUMBER_EXISTS) + graph_report("commit-graph has generation number zero for commit %s, but non-zero elsewhere", + oid_to_hex(&cur_oid)); + generation_zero = GENERATION_ZERO_EXISTS; + } else if (generation_zero == GENERATION_ZERO_EXISTS) + graph_report("commit-graph has non-zero generation number for commit %s, but zero elsewhere", + oid_to_hex(&cur_oid)); + + if (generation_zero == GENERATION_ZERO_EXISTS) + continue; + + /* + * If one of our parents has generation GENERATION_NUMBER_MAX, then + * our generation is also GENERATION_NUMBER_MAX. Decrement to avoid + * extra logic in the following condition. + */ + if (max_generation == GENERATION_NUMBER_MAX) + max_generation--; + + if (graph_commit->generation != max_generation + 1) + graph_report("commit-graph generation for commit %s is %u != %u", + oid_to_hex(&cur_oid), + graph_commit->generation, + max_generation + 1); + + if (graph_commit->date != odb_commit->date) + graph_report("commit date for commit %s in commit-graph is %"PRItime" != %"PRItime, + oid_to_hex(&cur_oid), + graph_commit->date, + odb_commit->date); + } + + return verify_commit_graph_error; +} + +void free_commit_graph(struct commit_graph *g) +{ + if (!g) + return; + if (g->graph_fd >= 0) { + munmap((void *)g->data, g->data_len); + g->data = NULL; + close(g->graph_fd); + } + free(g); +} diff --combined config.c index efe27d5e52,736b9f23f7..10522f399e --- a/config.c +++ b/config.c @@@ -14,7 -14,6 +14,7 @@@ #include "quote.h" #include "hashmap.h" #include "string-list.h" +#include "object-store.h" #include "utf8.h" #include "dir.h" #include "color.h" @@@ -32,7 -31,7 +32,7 @@@ struct config_source enum config_origin_type origin_type; const char *name; const char *path; - int die_on_error; + enum config_error_action default_error_action; int linenr; int eof; struct strbuf value; @@@ -117,12 -116,12 +117,12 @@@ static long config_buf_ftell(struct con } #define MAX_INCLUDE_DEPTH 10 - static const char include_depth_advice[] = + static const char include_depth_advice[] = N_( "exceeded maximum include depth (%d) while including\n" " %s\n" "from\n" " %s\n" - "Do you have circular includes?"; + "Do you have circular includes?"); static int handle_path_include(const char *path, struct config_include_data *inc) { int ret = 0; @@@ -134,7 -133,7 +134,7 @@@ expanded = expand_user_path(path, 0); if (!expanded) - return error("could not expand include path '%s'", path); + return error(_("could not expand include path '%s'"), path); path = expanded; /* @@@ -145,7 -144,7 +145,7 @@@ char *slash; if (!cf || !cf->path) - return error("relative config includes must come from files"); + return error(_("relative config includes must come from files")); slash = find_last_dir_sep(cf->path); if (slash) @@@ -156,7 -155,7 +156,7 @@@ if (!access_or_die(path, R_OK, 0)) { if (++inc->depth > MAX_INCLUDE_DEPTH) - die(include_depth_advice, MAX_INCLUDE_DEPTH, path, + die(_(include_depth_advice), MAX_INCLUDE_DEPTH, path, !cf ? "" : cf->name ? cf->name : "the command line"); @@@ -343,13 -342,13 +343,13 @@@ static int git_config_parse_key_1(cons if (last_dot == NULL || last_dot == key) { if (!quiet) - error("key does not contain a section: %s", key); + error(_("key does not contain a section: %s"), key); return -CONFIG_NO_SECTION_OR_NAME; } if (!last_dot[1]) { if (!quiet) - error("key does not contain variable name: %s", key); + error(_("key does not contain variable name: %s"), key); return -CONFIG_NO_SECTION_OR_NAME; } @@@ -373,13 -372,13 +373,13 @@@ if (!iskeychar(c) || (i == baselen + 1 && !isalpha(c))) { if (!quiet) - error("invalid key: %s", key); + error(_("invalid key: %s"), key); goto out_free_ret_1; } c = tolower(c); } else if (c == '\n') { if (!quiet) - error("invalid key (newline): %s", key); + error(_("invalid key (newline): %s"), key); goto out_free_ret_1; } if (store_key) @@@ -415,7 -414,7 +415,7 @@@ int git_config_parse_parameter(const ch pair = strbuf_split_str(text, '=', 2); if (!pair[0]) - return error("bogus config parameter: %s", text); + return error(_("bogus config parameter: %s"), text); if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') { strbuf_setlen(pair[0], pair[0]->len - 1); @@@ -427,7 -426,7 +427,7 @@@ strbuf_trim(pair[0]); if (!pair[0]->len) { strbuf_list_free(pair); - return error("bogus config parameter: %s", text); + return error(_("bogus config parameter: %s"), text); } if (git_config_parse_key(pair[0]->buf, &canonical_name, NULL)) { @@@ -462,7 -461,7 +462,7 @@@ int git_config_from_parameters(config_f envw = xstrdup(env); if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) { - ret = error("bogus format in " CONFIG_DATA_ENVIRONMENT); + ret = error(_("bogus format in %s"), CONFIG_DATA_ENVIRONMENT); goto out; } @@@ -810,21 -809,10 +810,21 @@@ static int git_parse_source(config_fn_ cf->linenr, cf->name); } - if (cf->die_on_error) + switch (opts && opts->error_action ? + opts->error_action : + cf->default_error_action) { + case CONFIG_ERROR_DIE: die("%s", error_msg); - else + break; + case CONFIG_ERROR_ERROR: error_return = error("%s", error_msg); + break; + case CONFIG_ERROR_SILENT: + error_return = -1; + break; + case CONFIG_ERROR_UNSET: + BUG("config error action unset"); + } free(error_msg); return error_return; @@@ -1166,7 -1154,7 +1166,7 @@@ static int git_default_core_config(cons else { int abbrev = git_config_int(var, value); if (abbrev < minimum_abbrev || abbrev > 40) - return error("abbrev length out of range: %d", abbrev); + return error(_("abbrev length out of range: %d"), abbrev); default_abbrev = abbrev; } return 0; @@@ -1283,7 -1271,7 +1283,7 @@@ comment_line_char = value[0]; auto_comment_line_char = 0; } else - return error("core.commentChar should only be one character"); + return error(_("core.commentChar should only be one character")); return 0; } @@@ -1320,6 -1308,11 +1320,6 @@@ return 0; } - if (!strcmp(var, "core.commitgraph")) { - core_commit_graph = git_config_bool(var, value); - return 0; - } - if (!strcmp(var, "core.sparsecheckout")) { core_apply_sparse_checkout = git_config_bool(var, value); return 0; @@@ -1353,11 -1346,6 +1353,11 @@@ var, value); } + if (!strcmp(var, "core.usereplacerefs")) { + read_replace_refs = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } @@@ -1396,7 -1384,7 +1396,7 @@@ static int git_default_branch_config(co else if (!strcmp(value, "always")) autorebase = AUTOREBASE_ALWAYS; else - return error("malformed value for %s", var); + return error(_("malformed value for %s"), var); return 0; } @@@ -1422,9 -1410,9 +1422,9 @@@ static int git_default_push_config(cons else if (!strcmp(value, "current")) push_default = PUSH_DEFAULT_CURRENT; else { - error("malformed value for %s: %s", var, value); - return error("Must be one of nothing, matching, simple, " - "upstream or current."); + error(_("malformed value for %s: %s"), var, value); + return error(_("must be one of nothing, matching, simple, " + "upstream or current")); } return 0; } @@@ -1532,7 -1520,7 +1532,7 @@@ static int do_config_from_file(config_f top.origin_type = origin_type; top.name = name; top.path = path; - top.die_on_error = 1; + top.default_error_action = CONFIG_ERROR_DIE; top.do_fgetc = config_file_fgetc; top.do_ungetc = config_file_ungetc; top.do_ftell = config_file_ftell; @@@ -1570,10 -1558,8 +1570,10 @@@ int git_config_from_file(config_fn_t fn return git_config_from_file_with_options(fn, filename, data, NULL); } -int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_type, - const char *name, const char *buf, size_t len, void *data) +int git_config_from_mem(config_fn_t fn, + const enum config_origin_type origin_type, + const char *name, const char *buf, size_t len, + void *data, const struct config_options *opts) { struct config_source top; @@@ -1583,12 -1569,12 +1583,12 @@@ top.origin_type = origin_type; top.name = name; top.path = NULL; - top.die_on_error = 0; + top.default_error_action = CONFIG_ERROR_ERROR; top.do_fgetc = config_buf_fgetc; top.do_ungetc = config_buf_ungetc; top.do_ftell = config_buf_ftell; - return do_config_from(&top, fn, data, NULL); + return do_config_from(&top, fn, data, opts); } int git_config_from_blob_oid(config_fn_t fn, @@@ -1603,14 -1589,13 +1603,14 @@@ buf = read_object_file(oid, &type, &size); if (!buf) - return error("unable to load config blob object '%s'", name); + return error(_("unable to load config blob object '%s'"), name); if (type != OBJ_BLOB) { free(buf); - return error("reference '%s' does not point to a blob", name); + return error(_("reference '%s' does not point to a blob"), name); } - ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, data); + ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, + data, NULL); free(buf); return ret; @@@ -1623,7 -1608,7 +1623,7 @@@ static int git_config_from_blob_ref(con struct object_id oid; if (get_oid(name, &oid) < 0) - return error("unable to resolve config blob '%s'", name); + return error(_("unable to resolve config blob '%s'"), name); return git_config_from_blob_oid(fn, name, &oid, data); } @@@ -1653,7 -1638,7 +1653,7 @@@ unsigned long git_env_ulong(const char { const char *v = getenv(k); if (v && !git_parse_ulong(v, &val)) - die("failed to parse %s", k); + die(_("failed to parse %s"), k); return val; } @@@ -2187,6 -2172,23 +2187,6 @@@ int git_config_get_pathname(const char return repo_config_get_pathname(the_repository, key, dest); } -/* - * Note: This function exists solely to maintain backward compatibility with - * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should - * NOT be used anywhere else. - * - * Runs the provided config function on the '.gitmodules' file found in the - * working directory. - */ -void config_from_gitmodules(config_fn_t fn, void *data) -{ - if (the_repository->worktree) { - char *file = repo_worktree_path(the_repository, GITMODULES_FILE); - git_config_from_file(fn, file, data); - free(file); - } -} - int git_config_get_expiry(const char *key, const char **output) { int ret = git_config_get_string_const(key, output); @@@ -2370,7 -2372,7 +2370,7 @@@ static int store_aux_event(enum config_ if (type == CONFIG_EVENT_SECTION) { if (cf->var.len < 2 || cf->var.buf[cf->var.len - 1] != '.') - return error("invalid section name '%s'", cf->var.buf); + return error(_("invalid section name '%s'"), cf->var.buf); /* Is this the section we were looking for? */ store->is_keys_section = @@@ -2426,7 -2428,7 +2426,7 @@@ static int store_aux(const char *key, c static int write_error(const char *filename) { - error("failed to write new configuration file %s", filename); + error(_("failed to write new configuration file %s"), filename); /* Same error code as "failed to rename". */ return 4; @@@ -2677,7 -2679,7 +2677,7 @@@ int git_config_set_multivar_in_file_gen */ fd = hold_lock_file_for_update(&lock, config_filename, 0); if (fd < 0) { - error_errno("could not lock config file %s", config_filename); + error_errno(_("could not lock config file %s"), config_filename); ret = CONFIG_NO_LOCK; goto out_free; } @@@ -2688,7 -2690,7 +2688,7 @@@ in_fd = open(config_filename, O_RDONLY); if ( in_fd < 0 ) { if ( ENOENT != errno ) { - error_errno("opening %s", config_filename); + error_errno(_("opening %s"), config_filename); ret = CONFIG_INVALID_FILE; /* same as "invalid config file" */ goto out_free; } @@@ -2723,7 -2725,7 +2723,7 @@@ store.value_regex = (regex_t*)xmalloc(sizeof(regex_t)); if (regcomp(store.value_regex, value_regex, REG_EXTENDED)) { - error("invalid pattern: %s", value_regex); + error(_("invalid pattern: %s"), value_regex); FREE_AND_NULL(store.value_regex); ret = CONFIG_INVALID_PATTERN; goto out_free; @@@ -2748,7 -2750,7 +2748,7 @@@ if (git_config_from_file_with_options(store_aux, config_filename, &store, &opts)) { - error("invalid config file %s", config_filename); + error(_("invalid config file %s"), config_filename); ret = CONFIG_INVALID_FILE; goto out_free; } @@@ -2772,7 -2774,7 +2772,7 @@@ if (contents == MAP_FAILED) { if (errno == ENODEV && S_ISDIR(st.st_mode)) errno = EISDIR; - error_errno("unable to mmap '%s'", config_filename); + error_errno(_("unable to mmap '%s'"), config_filename); ret = CONFIG_INVALID_FILE; contents = NULL; goto out_free; @@@ -2781,7 -2783,7 +2781,7 @@@ in_fd = -1; if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) { - error_errno("chmod on %s failed", get_lock_file_path(&lock)); + error_errno(_("chmod on %s failed"), get_lock_file_path(&lock)); ret = CONFIG_NO_WRITE; goto out_free; } @@@ -2866,7 -2868,7 +2866,7 @@@ } if (commit_lock_file(&lock) < 0) { - error_errno("could not write config file %s", config_filename); + error_errno(_("could not write config file %s"), config_filename); ret = CONFIG_NO_WRITE; goto out_free; } @@@ -2992,7 -2994,7 +2992,7 @@@ static int git_config_copy_or_rename_se memset(&store, 0, sizeof(store)); if (new_name && !section_name_is_ok(new_name)) { - ret = error("invalid section name: %s", new_name); + ret = error(_("invalid section name: %s"), new_name); goto out_no_rollback; } @@@ -3001,7 -3003,7 +3001,7 @@@ out_fd = hold_lock_file_for_update(&lock, config_filename, 0); if (out_fd < 0) { - ret = error("could not lock config file %s", config_filename); + ret = error(_("could not lock config file %s"), config_filename); goto out; } @@@ -3019,7 -3021,7 +3019,7 @@@ } if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) { - ret = error_errno("chmod on %s failed", + ret = error_errno(_("chmod on %s failed"), get_lock_file_path(&lock)); goto out; } @@@ -3116,7 -3118,7 +3116,7 @@@ config_file = NULL; commit_and_out: if (commit_lock_file(&lock) < 0) - ret = error_errno("could not write config file %s", + ret = error_errno(_("could not write config file %s"), config_filename); out: if (config_file) @@@ -3159,7 -3161,7 +3159,7 @@@ int git_config_copy_section(const char #undef config_error_nonbool int config_error_nonbool(const char *var) { - return error("missing value for '%s'", var); + return error(_("missing value for '%s'"), var); } int parse_config_key(const char *var, diff --combined convert.c index 7907efd16f,e53911d4f8..3ee4bc274b --- a/convert.c +++ b/convert.c @@@ -1,7 -1,6 +1,7 @@@ #define NO_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" +#include "object-store.h" #include "attr.h" #include "run-command.h" #include "quote.h" @@@ -191,7 -190,7 +191,7 @@@ static enum eol output_eol(enum crlf_ac /* fall through */ return text_eol_is_crlf() ? EOL_CRLF : EOL_LF; } - warning("Illegal crlf_action %d\n", (int)crlf_action); + warning(_("illegal crlf_action %d"), (int)crlf_action); return core_eol; } @@@ -204,11 -203,11 +204,11 @@@ static void check_global_conv_flags_eol * CRLFs would not be restored by checkout */ if (conv_flags & CONV_EOL_RNDTRP_DIE) - die(_("CRLF would be replaced by LF in %s."), path); + die(_("CRLF would be replaced by LF in %s"), path); else if (conv_flags & CONV_EOL_RNDTRP_WARN) warning(_("CRLF will be replaced by LF in %s.\n" "The file will have its original line" - " endings in your working directory."), path); + " endings in your working directory"), path); } else if (old_stats->lonelf && !new_stats->lonelf ) { /* * CRLFs would be added by checkout @@@ -218,7 -217,7 +218,7 @@@ else if (conv_flags & CONV_EOL_RNDTRP_WARN) warning(_("LF will be replaced by CRLF in %s.\n" "The file will have its original line" - " endings in your working directory."), path); + " endings in your working directory"), path); } } @@@ -335,7 -334,7 +335,7 @@@ static void trace_encoding(const char * strbuf_addf(&trace, "%s (%s, considered %s):\n", context, path, encoding); for (i = 0; i < len && buf; ++i) { strbuf_addf( - &trace,"| \e[2m%2i:\e[0m %2x \e[2m%c\e[0m%c", + &trace, "| \033[2m%2i:\033[0m %2x \033[2m%c\033[0m%c", i, (unsigned char) buf[i], (buf[i] > 32 && buf[i] < 127 ? buf[i] : ' '), @@@ -493,8 -492,8 +493,8 @@@ static int encode_to_worktree(const cha dst = reencode_string_len(src, src_len, enc, default_encoding, &dst_len); if (!dst) { - error("failed to encode '%s' from %s to %s", - path, default_encoding, enc); + error(_("failed to encode '%s' from %s to %s"), + path, default_encoding, enc); return 0; } @@@ -671,7 -670,8 +671,8 @@@ static int filter_buffer_or_fd(int in, if (start_command(&child_process)) { strbuf_release(&cmd); - return error("cannot fork to run external filter '%s'", params->cmd); + return error(_("cannot fork to run external filter '%s'"), + params->cmd); } sigchain_push(SIGPIPE, SIG_IGN); @@@ -690,13 -690,14 +691,14 @@@ if (close(child_process.in)) write_err = 1; if (write_err) - error("cannot feed the input to external filter '%s'", params->cmd); + error(_("cannot feed the input to external filter '%s'"), + params->cmd); sigchain_pop(SIGPIPE); status = finish_command(&child_process); if (status) - error("external filter '%s' failed %d", params->cmd, status); + error(_("external filter '%s' failed %d"), params->cmd, status); strbuf_release(&cmd); return (write_err || status); @@@ -731,13 -732,13 +733,13 @@@ static int apply_single_file_filter(con return 0; /* error was already reported */ if (strbuf_read(&nbuf, async.out, len) < 0) { - err = error("read from external filter '%s' failed", cmd); + err = error(_("read from external filter '%s' failed"), cmd); } if (close(async.out)) { - err = error("read from external filter '%s' failed", cmd); + err = error(_("read from external filter '%s' failed"), cmd); } if (finish_async(&async)) { - err = error("external filter '%s' failed", cmd); + err = error(_("external filter '%s' failed"), cmd); } if (!err) { @@@ -791,7 -792,7 +793,7 @@@ static void handle_filter_error(const s * Something went wrong with the protocol filter. * Force shutdown and restart if another blob requires filtering. */ - error("external filter '%s' failed", entry->subprocess.cmd); + error(_("external filter '%s' failed"), entry->subprocess.cmd); subprocess_stop(&subprocess_map, &entry->subprocess); free(entry); } @@@ -839,7 -840,7 +841,7 @@@ static int apply_multi_file_filter(cons else if (wanted_capability & CAP_SMUDGE) filter_type = "smudge"; else - die("unexpected filter type"); + die(_("unexpected filter type")); sigchain_push(SIGPIPE, SIG_IGN); @@@ -850,7 -851,7 +852,7 @@@ err = strlen(path) > LARGE_PACKET_DATA_MAX - strlen("pathname=\n"); if (err) { - error("path name too long for external filter"); + error(_("path name too long for external filter")); goto done; } @@@ -924,8 -925,8 +926,8 @@@ int async_query_available_blobs(const c assert(subprocess_map_initialized); entry = (struct cmd2process *)subprocess_find_entry(&subprocess_map, cmd); if (!entry) { - error("external filter '%s' is not available anymore although " - "not all paths have been filtered", cmd); + error(_("external filter '%s' is not available anymore although " + "not all paths have been filtered"), cmd); return 0; } process = &entry->subprocess.process; @@@ -1396,7 -1397,7 +1398,7 @@@ int convert_to_git(const struct index_s ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN, NULL); if (!ret && ca.drv && ca.drv->required) - die("%s: clean filter '%s' failed", path, ca.drv->name); + die(_("%s: clean filter '%s' failed"), path, ca.drv->name); if (ret && dst) { src = dst->buf; @@@ -1430,7 -1431,7 +1432,7 @@@ void convert_to_git_filter_fd(const str assert(ca.drv->clean || ca.drv->process); if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN, NULL)) - die("%s: clean filter '%s' failed", path, ca.drv->name); + die(_("%s: clean filter '%s' failed"), path, ca.drv->name); encode_to_git(path, dst->buf, dst->len, dst, ca.working_tree_encoding, conv_flags); crlf_to_git(istate, path, dst->buf, dst->len, dst, ca.crlf_action, conv_flags); @@@ -1473,7 -1474,7 +1475,7 @@@ static int convert_to_working_tree_inte ret_filter = apply_filter( path, src, len, -1, dst, ca.drv, CAP_SMUDGE, dco); if (!ret_filter && ca.drv && ca.drv->required) - die("%s: smudge filter %s failed", path, ca.drv->name); + die(_("%s: smudge filter %s failed"), path, ca.drv->name); return ret | ret_filter; } diff --combined diff.c index 0746d59fe6,b70eb79e47..f830afac79 --- a/diff.c +++ b/diff.c @@@ -13,7 -13,6 +13,7 @@@ #include "attr.h" #include "run-command.h" #include "utf8.h" +#include "object-store.h" #include "userdiff.h" #include "submodule-config.h" #include "submodule.h" @@@ -37,7 -36,6 +37,7 @@@ static int diff_rename_limit_default = static int diff_suppress_blank_empty; static int diff_use_color_default = -1; static int diff_color_moved_default; +static int diff_color_moved_ws_default; static int diff_context_default = 3; static int diff_interhunk_context_default; static const char *diff_word_regex_cfg; @@@ -265,54 -263,14 +265,54 @@@ static int parse_color_moved(const cha return COLOR_MOVED_NO; else if (!strcmp(arg, "plain")) return COLOR_MOVED_PLAIN; + else if (!strcmp(arg, "blocks")) + return COLOR_MOVED_BLOCKS; else if (!strcmp(arg, "zebra")) return COLOR_MOVED_ZEBRA; else if (!strcmp(arg, "default")) return COLOR_MOVED_DEFAULT; + else if (!strcmp(arg, "dimmed-zebra")) + return COLOR_MOVED_ZEBRA_DIM; else if (!strcmp(arg, "dimmed_zebra")) return COLOR_MOVED_ZEBRA_DIM; else - return error(_("color moved setting must be one of 'no', 'default', 'zebra', 'dimmed_zebra', 'plain'")); + return error(_("color moved setting must be one of 'no', 'default', 'blocks', 'zebra', 'dimmed-zebra', 'plain'")); +} + +static int parse_color_moved_ws(const char *arg) +{ + int ret = 0; + struct string_list l = STRING_LIST_INIT_DUP; + struct string_list_item *i; + + string_list_split(&l, arg, ',', -1); + + for_each_string_list_item(i, &l) { + struct strbuf sb = STRBUF_INIT; + strbuf_addstr(&sb, i->string); + strbuf_trim(&sb); + + if (!strcmp(sb.buf, "ignore-space-change")) + ret |= XDF_IGNORE_WHITESPACE_CHANGE; + else if (!strcmp(sb.buf, "ignore-space-at-eol")) + ret |= XDF_IGNORE_WHITESPACE_AT_EOL; + else if (!strcmp(sb.buf, "ignore-all-space")) + ret |= XDF_IGNORE_WHITESPACE; + else if (!strcmp(sb.buf, "allow-indentation-change")) + ret |= COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE; + else + error(_("ignoring unknown color-moved-ws mode '%s'"), sb.buf); + + strbuf_release(&sb); + } + + if ((ret & COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) && + (ret & XDF_WHITESPACE_FLAGS)) + die(_("color-moved-ws: allow-indentation-change cannot be combined with other white space modes")); + + string_list_clear(&l, 0); + + return ret; } int git_diff_ui_config(const char *var, const char *value, void *cb) @@@ -328,13 -286,6 +328,13 @@@ diff_color_moved_default = cm; return 0; } + if (!strcmp(var, "diff.colormovedws")) { + int cm = parse_color_moved_ws(value); + if (cm < 0) + return -1; + diff_color_moved_ws_default = cm; + return 0; + } if (!strcmp(var, "diff.context")) { diff_context_default = git_config_int(var, value); if (diff_context_default < 0) @@@ -746,116 -697,16 +746,116 @@@ struct moved_entry struct hashmap_entry ent; const struct emitted_diff_symbol *es; struct moved_entry *next_line; + struct ws_delta *wsd; }; -static int moved_entry_cmp(const struct diff_options *diffopt, - const struct moved_entry *a, - const struct moved_entry *b, +/** + * The struct ws_delta holds white space differences between moved lines, i.e. + * between '+' and '-' lines that have been detected to be a move. + * The string contains the difference in leading white spaces, before the + * rest of the line is compared using the white space config for move + * coloring. The current_longer indicates if the first string in the + * comparision is longer than the second. + */ +struct ws_delta { + char *string; + unsigned int current_longer : 1; +}; +#define WS_DELTA_INIT { NULL, 0 } + +static int compute_ws_delta(const struct emitted_diff_symbol *a, + const struct emitted_diff_symbol *b, + struct ws_delta *out) +{ + const struct emitted_diff_symbol *longer = a->len > b->len ? a : b; + const struct emitted_diff_symbol *shorter = a->len > b->len ? b : a; + int d = longer->len - shorter->len; + + out->string = xmemdupz(longer->line, d); + out->current_longer = (a == longer); + + return !strncmp(longer->line + d, shorter->line, shorter->len); +} + +static int cmp_in_block_with_wsd(const struct diff_options *o, + const struct moved_entry *cur, + const struct moved_entry *match, + struct moved_entry *pmb, + int n) +{ + struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n]; + int al = cur->es->len, cl = l->len; + const char *a = cur->es->line, + *b = match->es->line, + *c = l->line; + + int wslen; + + /* + * We need to check if 'cur' is equal to 'match'. + * As those are from the same (+/-) side, we do not need to adjust for + * indent changes. However these were found using fuzzy matching + * so we do have to check if they are equal. + */ + if (strcmp(a, b)) + return 1; + + if (!pmb->wsd) + /* + * No white space delta was carried forward? This can happen + * when we exit early in this function and do not carry + * forward ws. + */ + return 1; + + /* + * The indent changes of the block are known and carried forward in + * pmb->wsd; however we need to check if the indent changes of the + * current line are still the same as before. + * + * To do so we need to compare 'l' to 'cur', adjusting the + * one of them for the white spaces, depending which was longer. + */ + + wslen = strlen(pmb->wsd->string); + if (pmb->wsd->current_longer) { + c += wslen; + cl -= wslen; + } else { + a += wslen; + al -= wslen; + } + + if (strcmp(a, c)) + return 1; + + return 0; +} + +static int moved_entry_cmp(const void *hashmap_cmp_fn_data, + const void *entry, + const void *entry_or_key, const void *keydata) { + const struct diff_options *diffopt = hashmap_cmp_fn_data; + const struct moved_entry *a = entry; + const struct moved_entry *b = entry_or_key; + unsigned flags = diffopt->color_moved_ws_handling + & XDF_WHITESPACE_FLAGS; + + if (diffopt->color_moved_ws_handling & + COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) + /* + * As there is not specific white space config given, + * we'd need to check for a new block, so ignore all + * white space. The setup of the white space + * configuration for the next block is done else where + */ + flags |= XDF_IGNORE_WHITESPACE; + return !xdiff_compare_lines(a->es->line, a->es->len, b->es->line, b->es->len, - diffopt->xdl_opts); + flags); } static struct moved_entry *prepare_entry(struct diff_options *o, @@@ -863,12 -714,10 +863,12 @@@ { struct moved_entry *ret = xmalloc(sizeof(*ret)); struct emitted_diff_symbol *l = &o->emitted_symbols->buf[line_no]; + unsigned flags = o->color_moved_ws_handling & XDF_WHITESPACE_FLAGS; - ret->ent.hash = xdiff_hash_string(l->line, l->len, o->xdl_opts); + ret->ent.hash = xdiff_hash_string(l->line, l->len, flags); ret->es = l; ret->next_line = NULL; + ret->wsd = NULL; return ret; } @@@ -905,56 -754,6 +905,56 @@@ static void add_lines_to_move_detection } } +static void pmb_advance_or_null(struct diff_options *o, + struct moved_entry *match, + struct hashmap *hm, + struct moved_entry **pmb, + int pmb_nr) +{ + int i; + for (i = 0; i < pmb_nr; i++) { + struct moved_entry *prev = pmb[i]; + struct moved_entry *cur = (prev && prev->next_line) ? + prev->next_line : NULL; + if (cur && !hm->cmpfn(o, cur, match, NULL)) { + pmb[i] = cur; + } else { + pmb[i] = NULL; + } + } +} + +static void pmb_advance_or_null_multi_match(struct diff_options *o, + struct moved_entry *match, + struct hashmap *hm, + struct moved_entry **pmb, + int pmb_nr, int n) +{ + int i; + char *got_match = xcalloc(1, pmb_nr); + + for (; match; match = hashmap_get_next(hm, match)) { + for (i = 0; i < pmb_nr; i++) { + struct moved_entry *prev = pmb[i]; + struct moved_entry *cur = (prev && prev->next_line) ? + prev->next_line : NULL; + if (!cur) + continue; + if (!cmp_in_block_with_wsd(o, cur, match, pmb[i], n)) + got_match[i] |= 1; + } + } + + for (i = 0; i < pmb_nr; i++) { + if (got_match[i]) { + /* Carry the white space delta forward */ + pmb[i]->next_line->wsd = pmb[i]->wsd; + pmb[i] = pmb[i]->next_line; + } else + pmb[i] = NULL; + } +} + static int shrink_potential_moved_blocks(struct moved_entry **pmb, int pmb_nr) { @@@ -972,10 -771,6 +972,10 @@@ if (lp < pmb_nr && rp > -1 && lp < rp) { pmb[lp] = pmb[rp]; + if (pmb[rp]->wsd) { + free(pmb[rp]->wsd->string); + FREE_AND_NULL(pmb[rp]->wsd); + } pmb[rp] = NULL; rp--; lp++; @@@ -1033,18 -828,19 +1033,18 @@@ static void mark_color_as_moved(struct struct moved_entry *key; struct moved_entry *match = NULL; struct emitted_diff_symbol *l = &o->emitted_symbols->buf[n]; - int i; switch (l->s) { case DIFF_SYMBOL_PLUS: hm = del_lines; key = prepare_entry(o, n); - match = hashmap_get(hm, key, o); + match = hashmap_get(hm, key, NULL); free(key); break; case DIFF_SYMBOL_MINUS: hm = add_lines; key = prepare_entry(o, n); - match = hashmap_get(hm, key, o); + match = hashmap_get(hm, key, NULL); free(key); break; default: @@@ -1063,11 -859,17 +1063,11 @@@ if (o->color_moved == COLOR_MOVED_PLAIN) continue; - /* Check any potential block runs, advance each or nullify */ - for (i = 0; i < pmb_nr; i++) { - struct moved_entry *p = pmb[i]; - struct moved_entry *pnext = (p && p->next_line) ? - p->next_line : NULL; - if (pnext && !hm->cmpfn(o, pnext, match, NULL)) { - pmb[i] = p->next_line; - } else { - pmb[i] = NULL; - } - } + if (o->color_moved_ws_handling & + COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) + pmb_advance_or_null_multi_match(o, match, hm, pmb, pmb_nr, n); + else + pmb_advance_or_null(o, match, hm, pmb, pmb_nr); pmb_nr = shrink_potential_moved_blocks(pmb, pmb_nr); @@@ -1078,17 -880,7 +1078,17 @@@ */ for (; match; match = hashmap_get_next(hm, match)) { ALLOC_GROW(pmb, pmb_nr + 1, pmb_alloc); - pmb[pmb_nr++] = match; + if (o->color_moved_ws_handling & + COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) { + struct ws_delta *wsd = xmalloc(sizeof(*match->wsd)); + if (compute_ws_delta(l, match->es, wsd)) { + match->wsd = wsd; + pmb[pmb_nr++] = match; + } else + free(wsd); + } else { + pmb[pmb_nr++] = match; + } } flipped_block = (flipped_block + 1) % 2; @@@ -1099,7 -891,7 +1099,7 @@@ block_length++; - if (flipped_block) + if (flipped_block && o->color_moved != COLOR_MOVED_BLOCKS) l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT; } adjust_last_block(o, n, block_length); @@@ -2071,8 -1863,8 +2071,8 @@@ static void init_diff_words_data(struc if (regcomp(ecbdata->diff_words->word_regex, o->word_regex, REG_EXTENDED | REG_NEWLINE)) - die ("Invalid regular expression: %s", - o->word_regex); + die("invalid regular expression: %s", + o->word_regex); } for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) { if (o->word_diff == diff_words_styles[i].type) { @@@ -4040,7 -3832,7 +4040,7 @@@ static const char *diff_abbrev_oid(cons char *hex = oid_to_hex(oid); if (abbrev < 0) abbrev = FALLBACK_DEFAULT_ABBREV; - if (abbrev > GIT_SHA1_HEXSZ) + if (abbrev > the_hash_algo->hexsz) BUG("oid abbreviation out of range: %d", abbrev); if (abbrev) hex[abbrev] = '\0'; @@@ -4332,7 -4124,6 +4332,7 @@@ void diff_setup(struct diff_options *op } options->color_moved = diff_color_moved_default; + options->color_moved_ws_handling = diff_color_moved_ws_default; } void diff_setup_done(struct diff_options *options) @@@ -4912,8 -4703,6 +4912,8 @@@ int diff_opt_parse(struct diff_options if (cm < 0) die("bad --color-moved argument: %s", arg); options->color_moved = cm; + } else if (skip_prefix(arg, "--color-moved-ws=", &arg)) { + options->color_moved_ws_handling = parse_color_moved_ws(arg); } else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) { options->use_color = 1; options->word_diff = DIFF_WORDS_COLOR; @@@ -5158,7 -4947,7 +5158,7 @@@ const char *diff_aligned_abbrev(const s const char *abbrev; /* Do we want all 40 hex characters? */ - if (len == GIT_SHA1_HEXSZ) + if (len == the_hash_algo->hexsz) return oid_to_hex(oid); /* An abbreviated value is fine, possibly followed by an ellipsis. */ @@@ -5188,7 -4977,7 +5188,7 @@@ * the automatic sizing is supposed to give abblen that ensures * uniqueness across all objects (statistically speaking). */ - if (abblen < GIT_SHA1_HEXSZ - 3) { + if (abblen < the_hash_algo->hexsz - 3) { static char hex[GIT_MAX_HEXSZ + 1]; if (len < abblen && abblen <= len + 2) xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, ".."); @@@ -5744,12 -5533,10 +5744,12 @@@ static void diff_flush_patch_all_file_p if (o->color_moved) { struct hashmap add_lines, del_lines; - hashmap_init(&del_lines, - (hashmap_cmp_fn)moved_entry_cmp, o, 0); - hashmap_init(&add_lines, - (hashmap_cmp_fn)moved_entry_cmp, o, 0); + if (o->color_moved_ws_handling & + COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) + o->color_moved_ws_handling |= XDF_IGNORE_WHITESPACE; + + hashmap_init(&del_lines, moved_entry_cmp, o, 0); + hashmap_init(&add_lines, moved_entry_cmp, o, 0); add_lines_to_move_detection(o, &add_lines, &del_lines); mark_color_as_moved(o, &add_lines, &del_lines); diff --combined dir.c index 21e6f2520a,7c6e7a0a37..32f5f72759 --- a/dir.c +++ b/dir.c @@@ -11,7 -11,6 +11,7 @@@ #include "cache.h" #include "config.h" #include "dir.h" +#include "object-store.h" #include "attr.h" #include "refs.h" #include "wildmatch.h" @@@ -561,7 -560,7 +561,7 @@@ int report_path_error(const char *ps_ma if (found_dup) continue; - error("pathspec '%s' did not match any file(s) known to git.", + error(_("pathspec '%s' did not match any file(s) known to git"), pathspec->items[num].original); errors++; } @@@ -950,7 -949,7 +950,7 @@@ static void add_excludes_from_file_1(st dir->unmanaged_exclude_files++; el = add_exclude_list(dir, EXC_FILE, fname); if (add_excludes(fname, "", 0, el, NULL, oid_stat) < 0) - die("cannot use %s as an exclude file", fname); + die(_("cannot use %s as an exclude file"), fname); } void add_excludes_from_file(struct dir_struct *dir, const char *fname) @@@ -2231,7 -2230,7 +2231,7 @@@ static struct untracked_cache_dir *vali return NULL; if (!ident_in_untracked(dir->untracked)) { - warning(_("Untracked cache is disabled on this system or location.")); + warning(_("untracked cache is disabled on this system or location")); return NULL; } @@@ -2498,7 -2497,7 +2498,7 @@@ void setup_standard_excludes(struct dir { dir->exclude_per_dir = ".gitignore"; - /* core.excludefile defaulting to $XDG_HOME/git/ignore */ + /* core.excludesfile defaulting to $XDG_CONFIG_HOME/git/ignore */ if (!excludes_file) excludes_file = xdg_config_home("ignore"); if (excludes_file && !access_or_warn(excludes_file, R_OK, 0)) @@@ -3029,7 -3028,7 +3029,7 @@@ static void connect_wt_gitdir_in_nested return; if (repo_read_index(&subrepo) < 0) - die("index file corrupt in repo %s", subrepo.gitdir); + die(_("index file corrupt in repo %s"), subrepo.gitdir); for (i = 0; i < subrepo.index->cache_nr; i++) { const struct cache_entry *ce = subrepo.index->cache[i]; diff --combined environment.c index b9d71a7fec,d129c4adc5..68523b6b0e --- a/environment.c +++ b/environment.c @@@ -51,7 -51,7 +51,7 @@@ const char *editor_program const char *askpass_program; const char *excludes_file; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; -int check_replace_refs = 1; /* NEEDSWORK: rename to read_replace_refs */ +int read_replace_refs = 1; char *git_replace_ref_base; enum eol core_eol = EOL_UNSET; int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN; @@@ -66,6 -66,7 +66,6 @@@ enum push_default_type push_default = P enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; char *notes_ref_name; int grafts_replace_parents = 1; -int core_commit_graph; int core_apply_sparse_checkout; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ @@@ -146,7 -147,7 +146,7 @@@ static char *expand_namespace(const cha strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf); strbuf_list_free(components); if (check_refname_format(buf.buf, 0)) - die("bad git namespace path \"%s\"", raw_namespace); + die(_("bad git namespace path \"%s\""), raw_namespace); strbuf_addch(&buf, '/'); return strbuf_detach(&buf, NULL); } @@@ -182,7 -183,7 +182,7 @@@ void setup_git_env(const char *git_dir argv_array_clear(&to_free); if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) - check_replace_refs = 0; + read_replace_refs = 0; replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT); free(git_replace_ref_base); git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base @@@ -191,7 -192,7 +191,7 @@@ git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT)); shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); if (shallow_file) - set_alternate_shallow_file(shallow_file, 0); + set_alternate_shallow_file(the_repository, shallow_file, 0); } int is_bare_repository(void) @@@ -318,17 -319,17 +318,17 @@@ char *get_index_file(void return the_repository->index_file; } -char *get_graft_file(void) +char *get_graft_file(struct repository *r) { - if (!the_repository->graft_file) + if (!r->graft_file) BUG("git environment hasn't been setup"); - return the_repository->graft_file; + return r->graft_file; } static void set_git_dir_1(const char *path) { if (setenv(GIT_DIR_ENVIRONMENT, path, 1)) - die("could not set GIT_DIR to '%s'", path); + die(_("could not set GIT_DIR to '%s'"), path); setup_git_env(path); } diff --combined object.c index e2c112cc1a,477e686da7..51c4594515 --- a/object.c +++ b/object.c @@@ -1,7 -1,6 +1,7 @@@ #include "cache.h" #include "object.h" #include "replace-object.h" +#include "object-store.h" #include "blob.h" #include "tree.h" #include "commit.h" @@@ -9,7 -8,6 +9,7 @@@ #include "alloc.h" #include "object-store.h" #include "packfile.h" +#include "commit-graph.h" unsigned int get_max_object_index(void) { @@@ -51,7 -49,7 +51,7 @@@ int type_from_string_gently(const char if (gentle) return -1; - die("invalid object type \"%s\"", str); + die(_("invalid object type \"%s\""), str); } /* @@@ -85,20 -83,21 +85,20 @@@ static void insert_obj_hash(struct obje * Look up the record for the given sha1 in the hash map stored in * obj_hash. Return NULL if it was not found. */ -struct object *lookup_object(const unsigned char *sha1) +struct object *lookup_object(struct repository *r, const unsigned char *sha1) { unsigned int i, first; struct object *obj; - if (!the_repository->parsed_objects->obj_hash) + if (!r->parsed_objects->obj_hash) return NULL; - first = i = hash_obj(sha1, - the_repository->parsed_objects->obj_hash_size); - while ((obj = the_repository->parsed_objects->obj_hash[i]) != NULL) { + first = i = hash_obj(sha1, r->parsed_objects->obj_hash_size); + while ((obj = r->parsed_objects->obj_hash[i]) != NULL) { if (!hashcmp(sha1, obj->oid.hash)) break; i++; - if (i == the_repository->parsed_objects->obj_hash_size) + if (i == r->parsed_objects->obj_hash_size) i = 0; } if (obj && i != first) { @@@ -107,8 -106,8 +107,8 @@@ * that we do not need to walk the hash table the next * time we look for it. */ - SWAP(the_repository->parsed_objects->obj_hash[i], - the_repository->parsed_objects->obj_hash[first]); + SWAP(r->parsed_objects->obj_hash[i], + r->parsed_objects->obj_hash[first]); } return obj; } @@@ -158,19 -157,19 +158,19 @@@ void *create_object(struct repository * return obj; } -void *object_as_type(struct object *obj, enum object_type type, int quiet) +void *object_as_type(struct repository *r, struct object *obj, enum object_type type, int quiet) { if (obj->type == type) return obj; else if (obj->type == OBJ_NONE) { if (type == OBJ_COMMIT) - ((struct commit *)obj)->index = alloc_commit_index(the_repository); + ((struct commit *)obj)->index = alloc_commit_index(r); obj->type = type; return obj; } else { if (!quiet) - error("object %s is a %s, not a %s", + error(_("object %s is a %s, not a %s"), oid_to_hex(&obj->oid), type_name(obj->type), type_name(type)); return NULL; @@@ -179,28 -178,28 +179,28 @@@ struct object *lookup_unknown_object(const unsigned char *sha1) { - struct object *obj = lookup_object(sha1); + struct object *obj = lookup_object(the_repository, sha1); if (!obj) obj = create_object(the_repository, sha1, alloc_object_node(the_repository)); return obj; } -struct object *parse_object_buffer(const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p) +struct object *parse_object_buffer(struct repository *r, const struct object_id *oid, enum object_type type, unsigned long size, void *buffer, int *eaten_p) { struct object *obj; *eaten_p = 0; obj = NULL; if (type == OBJ_BLOB) { - struct blob *blob = lookup_blob(oid); + struct blob *blob = lookup_blob(r, oid); if (blob) { if (parse_blob_buffer(blob, buffer, size)) return NULL; obj = &blob->object; } } else if (type == OBJ_TREE) { - struct tree *tree = lookup_tree(oid); + struct tree *tree = lookup_tree(r, oid); if (tree) { obj = &tree->object; if (!tree->buffer) @@@ -212,25 -211,25 +212,25 @@@ } } } else if (type == OBJ_COMMIT) { - struct commit *commit = lookup_commit(oid); + struct commit *commit = lookup_commit(r, oid); if (commit) { - if (parse_commit_buffer(commit, buffer, size, 1)) + if (parse_commit_buffer(r, commit, buffer, size, 1)) return NULL; - if (!get_cached_commit_buffer(commit, NULL)) { - set_commit_buffer(commit, buffer, size); + if (!get_cached_commit_buffer(r, commit, NULL)) { + set_commit_buffer(r, commit, buffer, size); *eaten_p = 1; } obj = &commit->object; } } else if (type == OBJ_TAG) { - struct tag *tag = lookup_tag(oid); + struct tag *tag = lookup_tag(r, oid); if (tag) { - if (parse_tag_buffer(tag, buffer, size)) + if (parse_tag_buffer(r, tag, buffer, size)) return NULL; obj = &tag->object; } } else { - warning("object %s has unknown type id %d", oid_to_hex(oid), type); + warning(_("object %s has unknown type id %d"), oid_to_hex(oid), type); obj = NULL; } return obj; @@@ -239,47 -238,46 +239,47 @@@ struct object *parse_object_or_die(const struct object_id *oid, const char *name) { - struct object *o = parse_object(oid); + struct object *o = parse_object(the_repository, oid); if (o) return o; die(_("unable to parse object: %s"), name ? name : oid_to_hex(oid)); } -struct object *parse_object(const struct object_id *oid) +struct object *parse_object(struct repository *r, const struct object_id *oid) { unsigned long size; enum object_type type; int eaten; - const struct object_id *repl = lookup_replace_object(the_repository, oid); + const struct object_id *repl = lookup_replace_object(r, oid); void *buffer; struct object *obj; - obj = lookup_object(oid->hash); + obj = lookup_object(r, oid->hash); if (obj && obj->parsed) return obj; if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) || (!obj && has_object_file(oid) && - oid_object_info(the_repository, oid, NULL) == OBJ_BLOB)) { + oid_object_info(r, oid, NULL) == OBJ_BLOB)) { if (check_object_signature(repl, NULL, 0, NULL) < 0) { - error("sha1 mismatch %s", oid_to_hex(oid)); + error(_("sha1 mismatch %s"), oid_to_hex(oid)); return NULL; } - parse_blob_buffer(lookup_blob(oid), NULL, 0); - return lookup_object(oid->hash); + parse_blob_buffer(lookup_blob(r, oid), NULL, 0); + return lookup_object(r, oid->hash); } buffer = read_object_file(oid, &type, &size); if (buffer) { if (check_object_signature(repl, buffer, size, type_name(type)) < 0) { free(buffer); - error("sha1 mismatch %s", oid_to_hex(repl)); + error(_("sha1 mismatch %s"), oid_to_hex(repl)); return NULL; } - obj = parse_object_buffer(oid, type, size, buffer, &eaten); + obj = parse_object_buffer(r, oid, type, size, + buffer, &eaten); if (!eaten) free(buffer); return obj; @@@ -465,11 -463,6 +465,11 @@@ struct parsed_object_pool *parsed_objec o->tag_state = allocate_alloc_state(); o->object_state = allocate_alloc_state(); + o->is_shallow = -1; + o->shallow_stat = xcalloc(1, sizeof(*o->shallow_stat)); + + o->buffer_slab = allocate_commit_buffer_slab(); + return o; } @@@ -508,10 -501,6 +508,10 @@@ void raw_object_store_clear(struct raw_ oidmap_free(o->replace_map, 1); FREE_AND_NULL(o->replace_map); + free_commit_graph(o->commit_graph); + o->commit_graph = NULL; + o->commit_graph_attempted = 0; + free_alt_odbs(o); o->alt_odb_tail = NULL; @@@ -548,9 -537,6 +548,9 @@@ void parsed_object_pool_clear(struct pa FREE_AND_NULL(o->obj_hash); o->obj_hash_size = 0; + free_commit_buffer_slab(o->buffer_slab); + o->buffer_slab = NULL; + clear_alloc_state(o->blob_state); clear_alloc_state(o->tree_state); clear_alloc_state(o->commit_state); diff --combined reflog-walk.c index 3561a8b955,e0048a88d8..3a25b27d8f --- a/reflog-walk.c +++ b/reflog-walk.c @@@ -128,7 -128,7 +128,7 @@@ int add_reflog_for_walk(struct reflog_w enum selector_type selector = SELECTOR_NONE; if (commit->object.flags & UNINTERESTING) - die ("Cannot walk reflogs for %s", name); + die("cannot walk reflogs for %s", name); branch = xstrdup(name); if (at && at[1] == '{') { @@@ -153,7 -153,7 +153,7 @@@ free(branch); branch = resolve_refdup("HEAD", 0, NULL, NULL); if (!branch) - die ("No current branch"); + die("no current branch"); } reflogs = read_complete_reflog(branch); @@@ -305,8 -305,7 +305,8 @@@ static struct commit *next_reflog_commi { for (; log->recno >= 0; log->recno--) { struct reflog_info *entry = &log->reflogs->items[log->recno]; - struct object *obj = parse_object(&entry->noid); + struct object *obj = parse_object(the_repository, + &entry->noid); if (obj && obj->type == OBJ_COMMIT) return (struct commit *)obj; diff --combined refs.c index 457fb78057,becb78e441..5b412c61ef --- a/refs.c +++ b/refs.c @@@ -9,7 -9,6 +9,7 @@@ #include "iterator.h" #include "refs.h" #include "refs/refs-internal.h" +#include "object-store.h" #include "object.h" #include "tag.h" #include "submodule.h" @@@ -189,7 -188,7 +189,7 @@@ int ref_resolves_to_object(const char * if (flags & REF_ISBROKEN) return 0; if (!has_sha1_file(oid->hash)) { - error("%s does not point to a valid object!", refname); + error(_("%s does not point to a valid object!"), refname); return 0; } return 1; @@@ -305,7 -304,7 +305,7 @@@ enum peel_status peel_object(const stru if (o->type == OBJ_NONE) { int type = oid_object_info(the_repository, name, NULL); - if (type < 0 || !object_as_type(o, type, 0)) + if (type < 0 || !object_as_type(the_repository, o, type, 0)) return PEEL_INVALID; } @@@ -568,9 -567,9 +568,9 @@@ int expand_ref(const char *str, int len if (!warn_ambiguous_refs) break; } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) { - warning("ignoring dangling symref %s.", fullref.buf); + warning(_("ignoring dangling symref %s"), fullref.buf); } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) { - warning("ignoring broken ref %s.", fullref.buf); + warning(_("ignoring broken ref %s"), fullref.buf); } } strbuf_release(&fullref); @@@ -674,7 -673,7 +674,7 @@@ static int write_pseudoref(const char * fd = hold_lock_file_for_update_timeout(&lock, filename, 0, get_files_ref_lock_timeout_ms()); if (fd < 0) { - strbuf_addf(err, "could not open '%s' for writing: %s", + strbuf_addf(err, _("could not open '%s' for writing: %s"), filename, strerror(errno)); goto done; } @@@ -684,18 -683,18 +684,18 @@@ if (read_ref(pseudoref, &actual_old_oid)) { if (!is_null_oid(old_oid)) { - strbuf_addf(err, "could not read ref '%s'", + strbuf_addf(err, _("could not read ref '%s'"), pseudoref); rollback_lock_file(&lock); goto done; } } else if (is_null_oid(old_oid)) { - strbuf_addf(err, "ref '%s' already exists", + strbuf_addf(err, _("ref '%s' already exists"), pseudoref); rollback_lock_file(&lock); goto done; } else if (oidcmp(&actual_old_oid, old_oid)) { - strbuf_addf(err, "unexpected object ID when writing '%s'", + strbuf_addf(err, _("unexpected object ID when writing '%s'"), pseudoref); rollback_lock_file(&lock); goto done; @@@ -703,7 -702,7 +703,7 @@@ } if (write_in_full(fd, buf.buf, buf.len) < 0) { - strbuf_addf(err, "could not write to '%s'", filename); + strbuf_addf(err, _("could not write to '%s'"), filename); rollback_lock_file(&lock); goto done; } @@@ -735,9 -734,9 +735,9 @@@ static int delete_pseudoref(const char return -1; } if (read_ref(pseudoref, &actual_old_oid)) - die("could not read ref '%s'", pseudoref); + die(_("could not read ref '%s'"), pseudoref); if (oidcmp(&actual_old_oid, old_oid)) { - error("unexpected object ID when deleting '%s'", + error(_("unexpected object ID when deleting '%s'"), pseudoref); rollback_lock_file(&lock); return -1; @@@ -787,21 -786,25 +787,21 @@@ int delete_ref(const char *msg, const c old_oid, flags); } -int copy_reflog_msg(char *buf, const char *msg) +void copy_reflog_msg(struct strbuf *sb, const char *msg) { - char *cp = buf; char c; int wasspace = 1; - *cp++ = '\t'; + strbuf_addch(sb, '\t'); while ((c = *msg++)) { if (wasspace && isspace(c)) continue; wasspace = isspace(c); if (wasspace) c = ' '; - *cp++ = c; + strbuf_addch(sb, c); } - while (buf < cp && isspace(cp[-1])) - cp--; - *cp++ = '\n'; - return cp - buf; + strbuf_rtrim(sb); } int should_autocreate_reflog(const char *refname) @@@ -868,13 -871,13 +868,13 @@@ static int read_ref_at_ent(struct objec if (!is_null_oid(&cb->ooid)) { oidcpy(cb->oid, noid); if (oidcmp(&cb->ooid, noid)) - warning("Log for ref %s has gap after %s.", + warning(_("log for ref %s has gap after %s"), cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); } else if (cb->date == cb->at_time) oidcpy(cb->oid, noid); else if (oidcmp(noid, cb->oid)) - warning("Log for ref %s unexpectedly ended on %s.", + warning(_("log for ref %s unexpectedly ended on %s"), cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); oidcpy(&cb->ooid, ooid); @@@ -932,7 -935,7 +932,7 @@@ int read_ref_at(const char *refname, un if (flags & GET_OID_QUIETLY) exit(128); else - die("Log for %s is empty.", refname); + die(_("log for %s is empty"), refname); } if (cb.found_it) return 0; @@@ -1024,7 -1027,7 +1024,7 @@@ int ref_transaction_update(struct ref_t if ((new_oid && !is_null_oid(new_oid)) ? check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) : !refname_is_safe(refname)) { - strbuf_addf(err, "refusing to update ref with bad name '%s'", + strbuf_addf(err, _("refusing to update ref with bad name '%s'"), refname); return -1; } @@@ -1100,7 -1103,7 +1100,7 @@@ int refs_update_ref(struct ref_store *r } } if (ret) { - const char *str = "update_ref failed for ref '%s': %s"; + const char *str = _("update_ref failed for ref '%s': %s"); switch (onerr) { case UPDATE_REFS_MSG_ON_ERR: @@@ -1842,7 -1845,7 +1842,7 @@@ int ref_update_reject_duplicates(struc if (!cmp) { strbuf_addf(err, - "multiple updates for ref '%s' not allowed.", + _("multiple updates for ref '%s' not allowed"), refnames->items[i].string); return 1; } else if (cmp > 0) { @@@ -1970,13 -1973,13 +1970,13 @@@ int refs_verify_refname_available(struc continue; if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) { - strbuf_addf(err, "'%s' exists; cannot create '%s'", + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), dirname.buf, refname); goto cleanup; } if (extras && string_list_has_string(extras, dirname.buf)) { - strbuf_addf(err, "cannot process '%s' and '%s' at the same time", + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), refname, dirname.buf); goto cleanup; } @@@ -2000,7 -2003,7 +2000,7 @@@ string_list_has_string(skip, iter->refname)) continue; - strbuf_addf(err, "'%s' exists; cannot create '%s'", + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), iter->refname, refname); ref_iterator_abort(iter); goto cleanup; @@@ -2011,7 -2014,7 +2011,7 @@@ extra_refname = find_descendant_ref(dirname.buf, extras, skip); if (extra_refname) - strbuf_addf(err, "cannot process '%s' and '%s' at the same time", + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), refname, extra_refname); else ret = 0; diff --combined replace-object.c index 4162df6324,ddc1546b8c..4ec77ce418 --- a/replace-object.c +++ b/replace-object.c @@@ -17,7 -17,7 +17,7 @@@ static int register_replace_ref(const c if (get_oid_hex(hash, &repl_obj->original.oid)) { free(repl_obj); - warning("bad replace ref name: %s", refname); + warning(_("bad replace ref name: %s"), refname); return 0; } @@@ -26,7 -26,7 +26,7 @@@ /* Register new object */ if (oidmap_put(the_repository->objects->replace_map, repl_obj)) - die("duplicate replace ref: %s", refname); + die(_("duplicate replace ref: %s"), refname); return 0; } @@@ -51,7 -51,7 +51,7 @@@ static void prepare_replace_object(stru * replacement object's name (replaced recursively, if necessary). * The return value is either oid or a pointer to a * permanently-allocated value. This function always respects replace - * references, regardless of the value of check_replace_refs. + * references, regardless of the value of read_replace_refs. */ const struct object_id *do_lookup_replace_object(struct repository *r, const struct object_id *oid) @@@ -69,5 -69,5 +69,5 @@@ return cur; cur = &repl_obj->replacement; } - die("replace depth too high for object %s", oid_to_hex(oid)); + die(_("replace depth too high for object %s"), oid_to_hex(oid)); } diff --combined sequencer.c index 31038472fd,f7c2f2422d..af204d0cf1 --- a/sequencer.c +++ b/sequencer.c @@@ -2,7 -2,6 +2,7 @@@ #include "config.h" #include "lockfile.h" #include "dir.h" +#include "object-store.h" #include "object.h" #include "commit.h" #include "sequencer.h" @@@ -63,12 -62,12 +63,12 @@@ static GIT_PATH_FUNC(rebase_path_done, * The file to keep track of how many commands were already processed (e.g. * for the prompt). */ -static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum"); +static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum") /* * The file to keep track of how many commands are to be processed in total * (e.g. for the prompt). */ -static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end"); +static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end") /* * The commit message that is planned to be used for any changes that * need to be committed following a user interaction. @@@ -307,7 -306,7 +307,7 @@@ static const char *action_name(const st case REPLAY_INTERACTIVE_REBASE: return N_("rebase -i"); } - die(_("Unknown action: %d"), opts->action); + die(_("unknown action: %d"), opts->action); } struct commit_message { @@@ -358,7 -357,7 +358,7 @@@ static void print_advice(int show_hint * (typically rebase --interactive) wants to take care * of the commit itself so remove CHERRY_PICK_HEAD */ - unlink(git_path_cherry_pick_head()); + unlink(git_path_cherry_pick_head(the_repository)); return; } @@@ -433,7 -432,7 +433,7 @@@ static int read_oneliner(struct strbuf static struct tree *empty_tree(void) { - return lookup_tree(the_hash_algo->empty_tree); + return lookup_tree(the_repository, the_repository->hash_algo->empty_tree); } static int error_dirty_index(struct replay_opts *opts) @@@ -594,7 -593,7 +594,7 @@@ static int is_index_unchanged(void if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) return error(_("could not resolve HEAD commit")); - head_commit = lookup_commit(&head_oid); + head_commit = lookup_commit(the_repository, &head_oid); /* * If head_commit is NULL, check_commit, called from @@@ -717,7 -716,7 +717,7 @@@ static const char *read_author_ident(st /* dequote values and construct ident line in-place */ for (in = out = buf->buf; i < 3 && in - buf->buf < buf->len; i++) { if (!skip_prefix(in, keys[i], (const char **)&in)) { - warning("could not parse '%s' (looking for '%s'", + warning(_("could not parse '%s' (looking for '%s'"), rebase_path_author_script(), keys[i]); return NULL; } @@@ -739,7 -738,7 +739,7 @@@ } if (i < 3) { - warning("could not parse '%s' (looking for '%s')", + warning(_("could not parse '%s' (looking for '%s')"), rebase_path_author_script(), keys[i]); return NULL; } @@@ -1101,7 -1100,7 +1101,7 @@@ void print_commit_summary(const char *p struct strbuf author_ident = STRBUF_INIT; struct strbuf committer_ident = STRBUF_INIT; - commit = lookup_commit(oid); + commit = lookup_commit(the_repository, oid); if (!commit) die(_("couldn't look up newly created commit")); if (parse_commit(commit)) @@@ -1176,7 -1175,7 +1176,7 @@@ static int parse_head(struct commit **h if (get_oid("HEAD", &oid)) { current_head = NULL; } else { - current_head = lookup_commit_reference(&oid); + current_head = lookup_commit_reference(the_repository, &oid); if (!current_head) return error(_("could not parse HEAD")); if (oidcmp(&oid, ¤t_head->object.oid)) { @@@ -1325,8 -1324,8 +1325,8 @@@ static int do_commit(const char *msg_fi &oid); strbuf_release(&sb); if (!res) { - unlink(git_path_cherry_pick_head()); - unlink(git_path_merge_msg()); + unlink(git_path_cherry_pick_head(the_repository)); + unlink(git_path_merge_msg(the_repository)); if (!is_rebase_i(opts)) print_commit_summary(NULL, &oid, SUMMARY_SHOW_AUTHOR_DATE); @@@ -1445,7 -1444,7 +1445,7 @@@ static const char *command_to_string(co { if (command < TODO_COMMENT) return todo_command_info[command].str; - die("Unknown command: %d", command); + die(_("unknown command: %d"), command); } static char command_to_char(const enum todo_command command) @@@ -1511,7 -1510,7 +1511,7 @@@ static int update_squash_messages(enum if (get_oid("HEAD", &head)) return error(_("need a HEAD to fixup")); - if (!(head_commit = lookup_commit_reference(&head))) + if (!(head_commit = lookup_commit_reference(the_repository, &head))) return error(_("could not read HEAD")); if (!(head_message = get_commit_buffer(head_commit, NULL))) return error(_("could not read HEAD's commit message")); @@@ -1614,7 -1613,7 +1614,7 @@@ static int do_pick_commit(enum todo_com struct replay_opts *opts, int final_fixup) { unsigned int flags = opts->edit ? EDIT_MSG : 0; - const char *msg_file = opts->edit ? NULL : git_path_merge_msg(); + const char *msg_file = opts->edit ? NULL : git_path_merge_msg(the_repository); struct object_id head; struct commit *base, *next, *parent; const char *base_label, *next_label; @@@ -1756,12 -1755,12 +1756,12 @@@ flags |= CLEANUP_MSG; msg_file = rebase_path_fixup_msg(); } else { - const char *dest = git_path_squash_msg(); + const char *dest = git_path_squash_msg(the_repository); unlink(dest); if (copy_file(dest, rebase_path_squash_msg(), 0666)) return error(_("could not rename '%s' to '%s'"), rebase_path_squash_msg(), dest); - unlink(git_path_merge_msg()); + unlink(git_path_merge_msg(the_repository)); msg_file = dest; flags |= EDIT_MSG; } @@@ -1779,13 -1778,13 +1779,13 @@@ goto leave; res |= write_message(msgbuf.buf, msgbuf.len, - git_path_merge_msg(), 0); + git_path_merge_msg(the_repository), 0); } else { struct commit_list *common = NULL; struct commit_list *remotes = NULL; res = write_message(msgbuf.buf, msgbuf.len, - git_path_merge_msg(), 0); + git_path_merge_msg(the_repository), 0); commit_list_insert(base, &common); commit_list_insert(next, &remotes); @@@ -1864,6 -1863,8 +1864,6 @@@ static int prepare_revs(struct replay_o if (prepare_revision_walk(opts->revs)) return error(_("revision walk setup failed")); - if (!opts->revs->commits) - return error(_("empty commit set passed")); return 0; } @@@ -2007,7 -2008,7 +2007,7 @@@ static int parse_insn_line(struct todo_ if (status < 0) return -1; - item->commit = lookup_commit_reference(&commit_oid); + item->commit = lookup_commit_reference(the_repository, &commit_oid); return !item->commit; } @@@ -2205,7 -2206,6 +2205,7 @@@ static int populate_opts_cb(const char static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf) { int i; + char *strategy_opts_string; strbuf_reset(buf); if (!read_oneliner(buf, rebase_path_strategy(), 0)) @@@ -2214,11 -2214,7 +2214,11 @@@ if (!read_oneliner(buf, rebase_path_strategy_opts(), 0)) return; - opts->xopts_nr = split_cmdline(buf->buf, (const char ***)&opts->xopts); + strategy_opts_string = buf->buf; + if (*strategy_opts_string == ' ') + strategy_opts_string++; + opts->xopts_nr = split_cmdline(strategy_opts_string, + (const char ***)&opts->xopts); for (i = 0; i < opts->xopts_nr; i++) { const char *arg = opts->xopts[i]; @@@ -2321,10 -2317,6 +2321,10 @@@ static int walk_revs_populate_todo(stru short_commit_name(commit), subject_len, subject); unuse_commit_buffer(commit, commit_buffer); } + + if (!todo_list->nr) + return error(_("empty commit set passed")); + return 0; } @@@ -2402,8 -2394,8 +2402,8 @@@ static int rollback_single_pick(void { struct object_id head_oid; - if (!file_exists(git_path_cherry_pick_head()) && - !file_exists(git_path_revert_head())) + if (!file_exists(git_path_cherry_pick_head(the_repository)) && + !file_exists(git_path_revert_head(the_repository))) return error(_("no cherry-pick or revert in progress")); if (read_ref_full("HEAD", 0, &head_oid, NULL)) return error(_("cannot resolve HEAD")); @@@ -2608,15 -2600,17 +2608,17 @@@ static int error_with_patch(struct comm if (intend_to_amend()) return -1; - fprintf(stderr, "You can amend the commit now, with\n" - "\n" - " git commit --amend %s\n" - "\n" - "Once you are satisfied with your changes, run\n" - "\n" - " git rebase --continue\n", gpg_sign_opt_quoted(opts)); + fprintf(stderr, + _("You can amend the commit now, with\n" + "\n" + " git commit --amend %s\n" + "\n" + "Once you are satisfied with your changes, run\n" + "\n" + " git rebase --continue\n"), + gpg_sign_opt_quoted(opts)); } else if (exit_code) - fprintf(stderr, "Could not apply %s... %.*s\n", + fprintf_ln(stderr, _("Could not apply %s... %.*s"), short_commit_name(commit), subject_len, subject); return exit_code; @@@ -2628,11 -2622,10 +2630,11 @@@ static int error_failed_squash(struct c if (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666)) return error(_("could not copy '%s' to '%s'"), rebase_path_squash_msg(), rebase_path_message()); - unlink(git_path_merge_msg()); - if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666)) + unlink(git_path_merge_msg(the_repository)); + if (copy_file(git_path_merge_msg(the_repository), rebase_path_message(), 0666)) return error(_("could not copy '%s' to '%s'"), - rebase_path_message(), git_path_merge_msg()); + rebase_path_message(), + git_path_merge_msg(the_repository)); return error_with_patch(commit, subject, subject_len, opts, 1, 0); } @@@ -2645,8 -2638,6 +2647,8 @@@ static int do_exec(const char *command_ fprintf(stderr, "Executing: %s\n", command_line); child_argv[0] = command_line; argv_array_pushf(&child_env, "GIT_DIR=%s", absolute_path(get_git_dir())); + argv_array_pushf(&child_env, "GIT_WORK_TREE=%s", + absolute_path(get_git_work_tree())); status = run_command_v_opt_cd_env(child_argv, RUN_USING_SHELL, NULL, child_env.argv); @@@ -2730,7 -2721,7 +2732,7 @@@ static int do_label(const char *name, i struct object_id head_oid; if (len == 1 && *name == '#') - return error("Illegal label name: '%.*s'", len, name); + return error(_("illegal label name: '%.*s'"), len, name); strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name); strbuf_addf(&msg, "rebase -i (label) '%.*s'", len, name); @@@ -2852,26 -2843,6 +2854,26 @@@ static int do_reset(const char *name, i return ret; } +static struct commit *lookup_label(const char *label, int len, + struct strbuf *buf) +{ + struct commit *commit; + + strbuf_reset(buf); + strbuf_addf(buf, "refs/rewritten/%.*s", len, label); + commit = lookup_commit_reference_by_name(buf->buf); + if (!commit) { + /* fall back to non-rewritten ref or commit */ + strbuf_splice(buf, 0, strlen("refs/rewritten/"), "", 0); + commit = lookup_commit_reference_by_name(buf->buf); + } + + if (!commit) + error(_("could not resolve '%s'"), buf->buf); + + return commit; +} + static int do_merge(struct commit *commit, const char *arg, int arg_len, int flags, struct replay_opts *opts) { @@@ -2880,9 -2851,8 +2882,9 @@@ struct strbuf ref_name = STRBUF_INIT; struct commit *head_commit, *merge_commit, *i; struct commit_list *bases, *j, *reversed = NULL; + struct commit_list *to_merge = NULL, **tail = &to_merge; struct merge_options o; - int merge_arg_len, oneline_offset, can_fast_forward, ret; + int merge_arg_len, oneline_offset, can_fast_forward, ret, k; static struct lock_file lock; const char *p; @@@ -2897,34 -2867,26 +2899,34 @@@ goto leave_merge; } - oneline_offset = arg_len; - merge_arg_len = strcspn(arg, " \t\n"); - p = arg + merge_arg_len; - p += strspn(p, " \t\n"); - if (*p == '#' && (!p[1] || isspace(p[1]))) { - p += 1 + strspn(p + 1, " \t\n"); - oneline_offset = p - arg; - } else if (p - arg < arg_len) - BUG("octopus merges are not supported yet: '%s'", p); - - strbuf_addf(&ref_name, "refs/rewritten/%.*s", merge_arg_len, arg); - merge_commit = lookup_commit_reference_by_name(ref_name.buf); - if (!merge_commit) { - /* fall back to non-rewritten ref or commit */ - strbuf_splice(&ref_name, 0, strlen("refs/rewritten/"), "", 0); - merge_commit = lookup_commit_reference_by_name(ref_name.buf); + /* + * For octopus merges, the arg starts with the list of revisions to be + * merged. The list is optionally followed by '#' and the oneline. + */ + merge_arg_len = oneline_offset = arg_len; + for (p = arg; p - arg < arg_len; p += strspn(p, " \t\n")) { + if (!*p) + break; + if (*p == '#' && (!p[1] || isspace(p[1]))) { + p += 1 + strspn(p + 1, " \t\n"); + oneline_offset = p - arg; + break; + } + k = strcspn(p, " \t\n"); + if (!k) + continue; + merge_commit = lookup_label(p, k, &ref_name); + if (!merge_commit) { + ret = error(_("unable to parse '%.*s'"), k, p); + goto leave_merge; + } + tail = &commit_list_insert(merge_commit, tail)->next; + p += k; + merge_arg_len = p - arg; } - if (!merge_commit) { - ret = error(_("could not resolve '%s'"), ref_name.buf); + if (!to_merge) { + ret = error(_("nothing to merge: '%.*s'"), arg_len, arg); goto leave_merge; } @@@ -2935,13 -2897,8 +2937,13 @@@ * "[new root]", let's simply fast-forward to the merge head. */ rollback_lock_file(&lock); - ret = fast_forward_to(&merge_commit->object.oid, - &head_commit->object.oid, 0, opts); + if (to_merge->next) + ret = error(_("octopus merge cannot be executed on " + "top of a [new root]")); + else + ret = fast_forward_to(&to_merge->item->object.oid, + &head_commit->object.oid, 0, + opts); goto leave_merge; } @@@ -2958,11 -2915,11 +2960,11 @@@ write_author_script(message); find_commit_subject(message, &body); len = strlen(body); - ret = write_message(body, len, git_path_merge_msg(), 0); + ret = write_message(body, len, git_path_merge_msg(the_repository), 0); unuse_commit_buffer(commit, message); if (ret) { error_errno(_("could not write '%s'"), - git_path_merge_msg()); + git_path_merge_msg(the_repository)); goto leave_merge; } } else { @@@ -2977,18 -2934,17 +2979,18 @@@ p = arg + oneline_offset; len = arg_len - oneline_offset; } else { - strbuf_addf(&buf, "Merge branch '%.*s'", + strbuf_addf(&buf, "Merge %s '%.*s'", + to_merge->next ? "branches" : "branch", merge_arg_len, arg); p = buf.buf; len = buf.len; } - ret = write_message(p, len, git_path_merge_msg(), 0); + ret = write_message(p, len, git_path_merge_msg(the_repository), 0); strbuf_release(&buf); if (ret) { error_errno(_("could not write '%s'"), - git_path_merge_msg()); + git_path_merge_msg(the_repository)); goto leave_merge; } } @@@ -3002,79 -2958,31 +3004,79 @@@ &head_commit->object.oid); /* - * If the merge head is different from the original one, we cannot + * If any merge head is different from the original one, we cannot * fast-forward. */ if (can_fast_forward) { - struct commit_list *second_parent = commit->parents->next; + struct commit_list *p = commit->parents->next; - if (second_parent && !second_parent->next && - oidcmp(&merge_commit->object.oid, - &second_parent->item->object.oid)) + for (j = to_merge; j && p; j = j->next, p = p->next) + if (oidcmp(&j->item->object.oid, + &p->item->object.oid)) { + can_fast_forward = 0; + break; + } + /* + * If the number of merge heads differs from the original merge + * commit, we cannot fast-forward. + */ + if (j || p) can_fast_forward = 0; } - if (can_fast_forward && commit->parents->next && - !commit->parents->next->next && - !oidcmp(&commit->parents->next->item->object.oid, - &merge_commit->object.oid)) { + if (can_fast_forward) { rollback_lock_file(&lock); ret = fast_forward_to(&commit->object.oid, &head_commit->object.oid, 0, opts); goto leave_merge; } + if (to_merge->next) { + /* Octopus merge */ + struct child_process cmd = CHILD_PROCESS_INIT; + + if (read_env_script(&cmd.env_array)) { + const char *gpg_opt = gpg_sign_opt_quoted(opts); + + ret = error(_(staged_changes_advice), gpg_opt, gpg_opt); + goto leave_merge; + } + + cmd.git_cmd = 1; + argv_array_push(&cmd.args, "merge"); + argv_array_push(&cmd.args, "-s"); + argv_array_push(&cmd.args, "octopus"); + argv_array_push(&cmd.args, "--no-edit"); + argv_array_push(&cmd.args, "--no-ff"); + argv_array_push(&cmd.args, "--no-log"); + argv_array_push(&cmd.args, "--no-stat"); + argv_array_push(&cmd.args, "-F"); + argv_array_push(&cmd.args, git_path_merge_msg(the_repository)); + if (opts->gpg_sign) + argv_array_push(&cmd.args, opts->gpg_sign); + + /* Add the tips to be merged */ + for (j = to_merge; j; j = j->next) + argv_array_push(&cmd.args, + oid_to_hex(&j->item->object.oid)); + + strbuf_release(&ref_name); + unlink(git_path_cherry_pick_head(the_repository)); + rollback_lock_file(&lock); + + rollback_lock_file(&lock); + ret = run_command(&cmd); + + /* force re-reading of the cache */ + if (!ret && (discard_cache() < 0 || read_cache() < 0)) + ret = error(_("could not read index")); + goto leave_merge; + } + + merge_commit = to_merge->item; write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ, - git_path_merge_head(), 0); - write_message("no-ff", 5, git_path_merge_mode(), 0); + git_path_merge_head(the_repository), 0); + write_message("no-ff", 5, git_path_merge_mode(the_repository), 0); bases = get_merge_bases(head_commit, merge_commit); if (bases && !oidcmp(&merge_commit->object.oid, @@@ -3128,13 -3036,12 +3130,13 @@@ * value (a negative one would indicate that the `merge` * command needs to be rescheduled). */ - ret = !!run_git_commit(git_path_merge_msg(), opts, + ret = !!run_git_commit(git_path_merge_msg(the_repository), opts, run_commit_flags); leave_merge: strbuf_release(&ref_name); rollback_lock_file(&lock); + free_commit_list(to_merge); return ret; } @@@ -3312,27 -3219,10 +3314,27 @@@ static int pick_commits(struct todo_lis intend_to_amend(); return error_failed_squash(item->commit, opts, item->arg_len, item->arg); - } else if (res && is_rebase_i(opts) && item->commit) + } else if (res && is_rebase_i(opts) && item->commit) { + int to_amend = 0; + struct object_id oid; + + /* + * If we are rewording and have either + * fast-forwarded already, or are about to + * create a new root commit, we want to amend, + * otherwise we do not. + */ + if (item->command == TODO_REWORD && + !get_oid("HEAD", &oid) && + (!oidcmp(&item->commit->object.oid, &oid) || + (opts->have_squash_onto && + !oidcmp(&opts->squash_onto, &oid)))) + to_amend = 1; + return res | error_with_patch(item->commit, - item->arg, item->arg_len, opts, res, - item->command == TODO_REWORD); + item->arg, item->arg_len, opts, + res, to_amend); + } } else if (item->command == TODO_EXEC) { char *end_of_arg = (char *)(item->arg + item->arg_len); int saved = *end_of_arg; @@@ -3513,8 -3403,8 +3515,8 @@@ static int continue_single_pick(void { const char *argv[] = { "commit", NULL }; - if (!file_exists(git_path_cherry_pick_head()) && - !file_exists(git_path_revert_head())) + if (!file_exists(git_path_cherry_pick_head(the_repository)) && + !file_exists(git_path_revert_head(the_repository))) return error(_("no cherry-pick or revert in progress")); return run_command_v_opt(argv, RUN_GIT_CMD); } @@@ -3617,7 -3507,7 +3619,7 @@@ static int commit_staged_changes(struc } if (is_clean) { - const char *cherry_pick_head = git_path_cherry_pick_head(); + const char *cherry_pick_head = git_path_cherry_pick_head(the_repository); if (file_exists(cherry_pick_head) && unlink(cherry_pick_head)) return error(_("could not remove CHERRY_PICK_HEAD")); @@@ -3667,8 -3557,8 +3669,8 @@@ int sequencer_continue(struct replay_op if (!is_rebase_i(opts)) { /* Verify that the conflict has been resolved */ - if (file_exists(git_path_cherry_pick_head()) || - file_exists(git_path_revert_head())) { + if (file_exists(git_path_cherry_pick_head(the_repository)) || + file_exists(git_path_revert_head(the_repository))) { res = continue_single_pick(); if (res) goto release_todo_list; @@@ -3720,7 -3610,7 +3722,7 @@@ int sequencer_pick_revisions(struct rep continue; if (!get_oid(name, &oid)) { - if (!lookup_commit_reference_gently(&oid, 1)) { + if (!lookup_commit_reference_gently(the_repository, &oid, 1)) { enum object_type type = oid_object_info(the_repository, &oid, NULL); @@@ -3746,10 -3636,8 +3748,10 @@@ if (prepare_revision_walk(opts->revs)) return error(_("revision walk setup failed")); cmit = get_revision(opts->revs); - if (!cmit || get_revision(opts->revs)) - return error("BUG: expected exactly one commit from walk"); + if (!cmit) + return error(_("empty commit set passed")); + if (get_revision(opts->revs)) + BUG("unexpected extra commit from walk"); return single_pick(cmit, opts); } @@@ -3991,6 -3879,7 +3993,6 @@@ static int make_script_with_merges(stru */ while ((commit = get_revision(revs))) { struct commit_list *to_merge; - int is_octopus; const char *p1, *p2; struct object_id *oid; int is_empty; @@@ -4022,6 -3911,11 +4024,6 @@@ continue; } - is_octopus = to_merge && to_merge->next; - - if (is_octopus) - BUG("Octopus merges not yet supported"); - /* Create a label */ strbuf_reset(&label); if (skip_prefix(oneline.buf, "Merge ", &p1) && @@@ -4043,17 -3937,13 +4045,17 @@@ strbuf_addf(&buf, "%s -C %s", cmd_merge, oid_to_hex(&commit->object.oid)); - /* label the tip of merged branch */ - oid = &to_merge->item->object.oid; - strbuf_addch(&buf, ' '); + /* label the tips of merged branches */ + for (; to_merge; to_merge = to_merge->next) { + oid = &to_merge->item->object.oid; + strbuf_addch(&buf, ' '); + + if (!oidset_contains(&interesting, oid)) { + strbuf_addstr(&buf, label_oid(oid, NULL, + &state)); + continue; + } - if (!oidset_contains(&interesting, oid)) - strbuf_addstr(&buf, label_oid(oid, NULL, &state)); - else { tips_tail = &commit_list_insert(to_merge->item, tips_tail)->next; @@@ -4106,7 -3996,7 +4108,7 @@@ entry = oidmap_get(&state.commit2label, &commit->object.oid); if (entry) - fprintf(out, "\n# Branch %s\n", entry->string); + fprintf(out, "\n%c Branch %s\n", comment_line_char, entry->string); else fprintf(out, "\n"); diff --combined sha1-file.c index dfa8a35d68,92c27583db..c6ca960eb2 --- a/sha1-file.c +++ b/sha1-file.c @@@ -71,17 -71,17 +71,17 @@@ static void git_hash_sha1_final(unsigne static void git_hash_unknown_init(git_hash_ctx *ctx) { - die("trying to init unknown hash"); + BUG("trying to init unknown hash"); } static void git_hash_unknown_update(git_hash_ctx *ctx, const void *data, size_t len) { - die("trying to update unknown hash"); + BUG("trying to update unknown hash"); } static void git_hash_unknown_final(unsigned char *hash, git_hash_ctx *ctx) { - die("trying to finalize unknown hash"); + BUG("trying to finalize unknown hash"); } const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { @@@ -336,7 -336,7 +336,7 @@@ out static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1) { int i; - for (i = 0; i < 20; i++) { + for (i = 0; i < the_hash_algo->rawsz; i++) { static char hex[] = "0123456789abcdef"; unsigned int val = sha1[i]; strbuf_addch(buf, hex[val >> 4]); @@@ -378,8 -378,8 +378,8 @@@ static int alt_odb_usable(struct raw_ob /* Detect cases where alternate disappeared */ if (!is_directory(path->buf)) { - error("object directory %s does not exist; " - "check .git/objects/info/alternates.", + error(_("object directory %s does not exist; " + "check .git/objects/info/alternates"), path->buf); return 0; } @@@ -429,7 -429,7 +429,7 @@@ static int link_alt_odb_entry(struct re strbuf_addstr(&pathbuf, entry); if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) { - error("unable to normalize alternate object path: %s", + error(_("unable to normalize alternate object path: %s"), pathbuf.buf); strbuf_release(&pathbuf); return -1; @@@ -500,14 -500,14 +500,14 @@@ static void link_alt_odb_entries(struc return; if (depth > 5) { - error("%s: ignoring alternate object stores, nesting too deep.", + error(_("%s: ignoring alternate object stores, nesting too deep"), relative_base); return; } strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir); if (strbuf_normalize_path(&objdirbuf) < 0) - die("unable to normalize object directory: %s", + die(_("unable to normalize object directory: %s"), objdirbuf.buf); while (*alt) { @@@ -562,7 -562,7 +562,7 @@@ void add_to_alternates_file(const char hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); out = fdopen_lock_file(&lock, "w"); if (!out) - die_errno("unable to fdopen alternates lockfile"); + die_errno(_("unable to fdopen alternates lockfile")); in = fopen(alts, "r"); if (in) { @@@ -580,14 -580,14 +580,14 @@@ fclose(in); } else if (errno != ENOENT) - die_errno("unable to read alternates file"); + die_errno(_("unable to read alternates file")); if (found) { rollback_lock_file(&lock); } else { fprintf_or_die(out, "%s\n", reference); if (commit_lock_file(&lock)) - die_errno("unable to move new alternates file into place"); + die_errno(_("unable to move new alternates file into place")); if (the_repository->objects->alt_odb_tail) link_alt_odb_entries(the_repository, reference, '\n', NULL, 0); @@@ -778,7 -778,7 +778,7 @@@ static void mmap_limit_check(size_t len limit = SIZE_MAX; } if (length > limit) - die("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX, + die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX), (uintmax_t)length, (uintmax_t)limit); } @@@ -803,7 -803,7 +803,7 @@@ void *xmmap(void *start, size_t length { void *ret = xmmap_gently(start, length, prot, flags, fd, offset); if (ret == MAP_FAILED) - die_errno("mmap failed"); + die_errno(_("mmap failed")); return ret; } @@@ -970,7 -970,7 +970,7 @@@ static void *map_sha1_file_1(struct rep *size = xsize_t(st.st_size); if (!*size) { /* mmap() is forbidden on empty files */ - error("object file %s is empty", path); + error(_("object file %s is empty"), path); return NULL; } map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); @@@ -1090,9 -1090,9 +1090,9 @@@ static void *unpack_sha1_rest(git_zstre } if (status < 0) - error("corrupt loose object '%s'", sha1_to_hex(sha1)); + error(_("corrupt loose object '%s'"), sha1_to_hex(sha1)); else if (stream->avail_in) - error("garbage at end of loose object '%s'", + error(_("garbage at end of loose object '%s'"), sha1_to_hex(sha1)); free(buf); return NULL; @@@ -1134,7 -1134,7 +1134,7 @@@ static int parse_sha1_header_extended(c if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE) && (type < 0)) type = 0; else if (type < 0) - die("invalid object type"); + die(_("invalid object type")); if (oi->typep) *oi->typep = type; @@@ -1216,19 -1216,19 +1216,19 @@@ static int sha1_loose_object_info(struc *oi->disk_sizep = mapsize; if ((flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE)) { if (unpack_sha1_header_to_strbuf(&stream, map, mapsize, hdr, sizeof(hdr), &hdrbuf) < 0) - status = error("unable to unpack %s header with --allow-unknown-type", + status = error(_("unable to unpack %s header with --allow-unknown-type"), sha1_to_hex(sha1)); } else if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) - status = error("unable to unpack %s header", + status = error(_("unable to unpack %s header"), sha1_to_hex(sha1)); if (status < 0) ; /* Do nothing */ else if (hdrbuf.len) { if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0) - status = error("unable to parse %s header with --allow-unknown-type", + status = error(_("unable to parse %s header with --allow-unknown-type"), sha1_to_hex(sha1)); } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0) - status = error("unable to parse %s header", sha1_to_hex(sha1)); + status = error(_("unable to parse %s header"), sha1_to_hex(sha1)); if (status >= 0 && oi->contentp) { *oi->contentp = unpack_sha1_rest(&stream, hdr, @@@ -1419,19 -1419,19 +1419,19 @@@ void *read_object_file_extended(const s return data; if (errno && errno != ENOENT) - die_errno("failed to read object %s", oid_to_hex(oid)); + die_errno(_("failed to read object %s"), oid_to_hex(oid)); /* die if we replaced an object with one that does not exist */ if (repl != oid) - die("replacement %s not found for %s", + die(_("replacement %s not found for %s"), oid_to_hex(repl), oid_to_hex(oid)); if (!stat_sha1_file(the_repository, repl->hash, &st, &path)) - die("loose object %s (stored in %s) is corrupt", + die(_("loose object %s (stored in %s) is corrupt"), oid_to_hex(repl), path); if ((p = has_packed_and_bad(repl->hash)) != NULL) - die("packed object %s (stored in %s) is corrupt", + die(_("packed object %s (stored in %s) is corrupt"), oid_to_hex(repl), p->pack_name); return NULL; @@@ -1473,7 -1473,7 +1473,7 @@@ void *read_object_with_reference(const } ref_length = strlen(ref_type); - if (ref_length + GIT_SHA1_HEXSZ > isize || + if (ref_length + the_hash_algo->hexsz > isize || memcmp(buffer, ref_type, ref_length) || get_oid_hex((char *) buffer + ref_length, &actual_oid)) { free(buffer); @@@ -1533,21 -1533,21 +1533,21 @@@ int finalize_object_file(const char *tm unlink_or_warn(tmpfile); if (ret) { if (ret != EEXIST) { - return error_errno("unable to write sha1 filename %s", filename); + return error_errno(_("unable to write sha1 filename %s"), filename); } /* FIXME!!! Collision check here ? */ } out: if (adjust_shared_perm(filename)) - return error("unable to set permission to '%s'", filename); + return error(_("unable to set permission to '%s'"), filename); return 0; } static int write_buffer(int fd, const void *buf, size_t len) { if (write_in_full(fd, buf, len) < 0) - return error_errno("file write error"); + return error_errno(_("file write error")); return 0; } @@@ -1566,7 -1566,7 +1566,7 @@@ static void close_sha1_file(int fd if (fsync_object_files) fsync_or_die(fd, "sha1 file"); if (close(fd) != 0) - die_errno("error when closing sha1 file"); + die_errno(_("error when closing sha1 file")); } /* Size of directory component, including the ending '/' */ @@@ -1632,9 -1632,9 +1632,9 @@@ static int write_loose_object(const str fd = create_tmpfile(&tmp_file, filename.buf); if (fd < 0) { if (errno == EACCES) - return error("insufficient permission for adding an object to repository database %s", get_object_directory()); + return error(_("insufficient permission for adding an object to repository database %s"), get_object_directory()); else - return error_errno("unable to create temporary file"); + return error_errno(_("unable to create temporary file")); } /* Set it up */ @@@ -1658,21 -1658,21 +1658,21 @@@ ret = git_deflate(&stream, Z_FINISH); the_hash_algo->update_fn(&c, in0, stream.next_in - in0); if (write_buffer(fd, compressed, stream.next_out - compressed) < 0) - die("unable to write sha1 file"); + die(_("unable to write sha1 file")); stream.next_out = compressed; stream.avail_out = sizeof(compressed); } while (ret == Z_OK); if (ret != Z_STREAM_END) - die("unable to deflate new object %s (%d)", oid_to_hex(oid), + die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid), ret); ret = git_deflate_end_gently(&stream); if (ret != Z_OK) - die("deflateEnd on object %s failed (%d)", oid_to_hex(oid), + die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid), ret); the_hash_algo->final_fn(parano_oid.hash, &c); if (oidcmp(oid, ¶no_oid) != 0) - die("confused by unstable object source data for %s", + die(_("confused by unstable object source data for %s"), oid_to_hex(oid)); close_sha1_file(fd); @@@ -1682,7 -1682,7 +1682,7 @@@ utb.actime = mtime; utb.modtime = mtime; if (utime(tmp_file.buf, &utb) < 0) - warning_errno("failed utime() on %s", tmp_file.buf); + warning_errno(_("failed utime() on %s"), tmp_file.buf); } return finalize_object_file(tmp_file.buf, filename.buf); @@@ -1757,7 -1757,7 +1757,7 @@@ int force_object_loose(const struct obj return 0; buf = read_object(oid->hash, &type, &len); if (!buf) - return error("cannot read sha1_file for %s", oid_to_hex(oid)); + return error(_("cannot read sha1_file for %s"), oid_to_hex(oid)); hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1; ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime); free(buf); @@@ -1801,16 -1801,16 +1801,16 @@@ static void check_commit(const void *bu { struct commit c; memset(&c, 0, sizeof(c)); - if (parse_commit_buffer(&c, buf, size, 0)) + if (parse_commit_buffer(the_repository, &c, buf, size, 0)) - die("corrupt commit"); + die(_("corrupt commit")); } static void check_tag(const void *buf, size_t size) { struct tag t; memset(&t, 0, sizeof(t)); - if (parse_tag_buffer(&t, buf, size)) + if (parse_tag_buffer(the_repository, &t, buf, size)) - die("corrupt tag"); + die(_("corrupt tag")); } static int index_mem(struct object_id *oid, void *buf, size_t size, @@@ -1903,10 -1903,10 +1903,10 @@@ static int index_core(struct object_id char *buf = xmalloc(size); ssize_t read_result = read_in_full(fd, buf, size); if (read_result < 0) - ret = error_errno("read error while indexing %s", + ret = error_errno(_("read error while indexing %s"), path ? path : ""); else if (read_result != size) - ret = error("short read while indexing %s", + ret = error(_("short read while indexing %s"), path ? path : ""); else ret = index_mem(oid, buf, size, type, path, flags); @@@ -1977,7 -1977,7 +1977,7 @@@ int index_path(struct object_id *oid, c if (fd < 0) return error_errno("open(\"%s\")", path); if (index_fd(oid, fd, st, OBJ_BLOB, path, flags) < 0) - return error("%s: failed to insert into database", + return error(_("%s: failed to insert into database"), path); break; case S_IFLNK: @@@ -1986,13 -1986,13 +1986,13 @@@ if (!(flags & HASH_WRITE_OBJECT)) hash_object_file(sb.buf, sb.len, blob_type, oid); else if (write_object_file(sb.buf, sb.len, blob_type, oid)) - rc = error("%s: failed to insert into database", path); + rc = error(_("%s: failed to insert into database"), path); strbuf_release(&sb); break; case S_IFDIR: return resolve_gitlink_ref(path, "HEAD", oid); default: - return error("%s: unsupported file type", path); + return error(_("%s: unsupported file type"), path); } return rc; } @@@ -2016,9 -2016,9 +2016,9 @@@ void assert_oid_type(const struct objec { enum object_type type = oid_object_info(the_repository, oid, NULL); if (type < 0) - die("%s is not a valid object", oid_to_hex(oid)); + die(_("%s is not a valid object"), oid_to_hex(oid)); if (type != expect) - die("%s is not a valid '%s' object", oid_to_hex(oid), + die(_("%s is not a valid '%s' object"), oid_to_hex(oid), type_name(expect)); } @@@ -2045,7 -2045,7 +2045,7 @@@ int for_each_file_in_obj_subdir(unsigne dir = opendir(path->buf); if (!dir) { if (errno != ENOENT) - r = error_errno("unable to open %s", path->buf); + r = error_errno(_("unable to open %s"), path->buf); strbuf_setlen(path, origlen); return r; } @@@ -2062,9 -2062,9 +2062,9 @@@ namelen = strlen(de->d_name); strbuf_setlen(path, baselen); strbuf_add(path, de->d_name, namelen); - if (namelen == GIT_SHA1_HEXSZ - 2 && + if (namelen == the_hash_algo->hexsz - 2 && !hex_to_bytes(oid.hash + 1, de->d_name, - GIT_SHA1_RAWSZ - 1)) { + the_hash_algo->rawsz - 1)) { if (obj_cb) { r = obj_cb(&oid, path->buf, data); if (r) @@@ -2202,18 -2202,18 +2202,18 @@@ static int check_stream_sha1(git_zstrea git_inflate_end(stream); if (status != Z_STREAM_END) { - error("corrupt loose object '%s'", sha1_to_hex(expected_sha1)); + error(_("corrupt loose object '%s'"), sha1_to_hex(expected_sha1)); return -1; } if (stream->avail_in) { - error("garbage at end of loose object '%s'", + error(_("garbage at end of loose object '%s'"), sha1_to_hex(expected_sha1)); return -1; } the_hash_algo->final_fn(real_sha1, &c); if (hashcmp(expected_sha1, real_sha1)) { - error("sha1 mismatch for %s (expected %s)", path, + error(_("sha1 mismatch for %s (expected %s)"), path, sha1_to_hex(expected_sha1)); return -1; } @@@ -2237,18 -2237,18 +2237,18 @@@ int read_loose_object(const char *path map = map_sha1_file_1(the_repository, path, NULL, &mapsize); if (!map) { - error_errno("unable to mmap %s", path); + error_errno(_("unable to mmap %s"), path); goto out; } if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0) { - error("unable to unpack header of %s", path); + error(_("unable to unpack header of %s"), path); goto out; } *type = parse_sha1_header(hdr, size); if (*type < 0) { - error("unable to parse header of %s", path); + error(_("unable to parse header of %s"), path); git_inflate_end(&stream); goto out; } @@@ -2259,13 -2259,13 +2259,13 @@@ } else { *contents = unpack_sha1_rest(&stream, hdr, *size, expected_oid->hash); if (!*contents) { - error("unable to unpack contents of %s", path); + error(_("unable to unpack contents of %s"), path); git_inflate_end(&stream); goto out; } if (check_object_signature(expected_oid, *contents, *size, type_name(*type))) { - error("sha1 mismatch for %s (expected %s)", path, + error(_("sha1 mismatch for %s (expected %s)"), path, oid_to_hex(expected_oid)); free(*contents); goto out; diff --combined t/t0021-conversion.sh index 6a213608cc,306b862d7f..308cd28f3b --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@@ -583,7 -583,7 +583,7 @@@ test_expect_success PERL 'process filte git checkout --quiet --no-progress . 2>git-stderr.log && grep "smudge write error at" git-stderr.log && - grep "error: external filter" git-stderr.log && + test_i18ngrep "error: external filter" git-stderr.log && cat >expected.log <<-EOF && START @@@ -785,7 -785,7 +785,7 @@@ test_expect_success PERL 'missing file cd repo && git init && echo "*.a filter=bug" >.gitattributes && - cp "$TEST_ROOT/test.o" missing-delay.a + cp "$TEST_ROOT/test.o" missing-delay.a && git add . && git commit -m "test commit" ) && @@@ -807,7 -807,7 +807,7 @@@ test_expect_success PERL 'invalid file git init && echo "*.a filter=bug" >.gitattributes && cp "$TEST_ROOT/test.o" invalid-delay.a && - cp "$TEST_ROOT/test.o" unfiltered + cp "$TEST_ROOT/test.o" unfiltered && git add . && git commit -m "test commit" ) && diff --combined t/t3210-pack-refs.sh index 724b4b9bc0,7e95713f9e..7333d7d545 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@@ -186,7 -186,7 +186,7 @@@ test_expect_success 'notice d/f conflic test_expect_success 'existing directory reports concrete ref' ' test_must_fail git branch foo 2>stderr && - grep refs/heads/foo/bar/baz stderr + test_i18ngrep refs/heads/foo/bar/baz stderr ' test_expect_success 'notice d/f conflict with existing ref' ' @@@ -231,9 -231,9 +231,9 @@@ test_expect_success 'timeout if packed- test_expect_success 'retry acquiring packed-refs.lock' ' LOCK=.git/packed-refs.lock && >"$LOCK" && - test_when_finished "wait; rm -f $LOCK" && + test_when_finished "wait && rm -f $LOCK" && { - ( sleep 1 ; rm -f $LOCK ) & + ( sleep 1 && rm -f $LOCK ) & } && git -c core.packedrefstimeout=3000 pack-refs --all --prune ' diff --combined t/t5500-fetch-pack.sh index fa03f56a20,d2d27f9b54..8f945235e3 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@@ -259,7 -259,7 +259,7 @@@ test_expect_success 'clone shallow obje test_expect_success 'pull in shallow repo with missing merge base' ' ( cd shallow && - git fetch --depth 4 .. A + git fetch --depth 4 .. A && test_must_fail git merge --allow-unrelated-histories FETCH_HEAD ) ' @@@ -403,7 -403,7 +403,7 @@@ test_expect_success 'fetch creating ne git fetch --depth=1 --progress 2>actual && # This should fetch only the empty commit, no tree or # blob objects - grep "remote: Total 1" actual + test_i18ngrep "remote: Total 1" actual ) ' @@@ -533,26 -533,19 +533,26 @@@ test_expect_success 'test --all wrt ta # are reachable only via created tag references. blob=$(echo "hello blob" | git hash-object -t blob -w --stdin) && git tag -a -m "tag -> blob" tag-to-blob $blob && - \ + tree=$(printf "100644 blob $blob\tfile" | git mktree) && git tag -a -m "tag -> tree" tag-to-tree $tree && - \ + tree2=$(printf "100644 blob $blob\tfile2" | git mktree) && commit=$(git commit-tree -m "hello commit" $tree) && git tag -a -m "tag -> commit" tag-to-commit $commit && - \ + blob2=$(echo "hello blob2" | git hash-object -t blob -w --stdin) && - tag=$(printf "object $blob2\ntype blob\ntag tag-to-blob2\n\ -tagger author A U Thor 0 +0000\n\nhello tag" | git mktag) && + tag=$(git mktag <<-EOF + object $blob2 + type blob + tag tag-to-blob2 + tagger author A U Thor 0 +0000 + + hello tag + EOF + ) && git tag -a -m "tag -> tag" tag-to-tag $tag && - \ + # `fetch-pack --all` should succeed fetching all those objects. mkdir fetchall && ( @@@ -814,39 -807,6 +814,39 @@@ test_expect_success 'fetching deepen' ) ' +test_expect_success 'use ref advertisement to prune "have" lines sent' ' + rm -rf server client && + git init server && + test_commit -C server both_have_1 && + git -C server tag -d both_have_1 && + test_commit -C server both_have_2 && + + git clone server client && + test_commit -C server server_has && + test_commit -C client client_has && + + # In both protocol v0 and v2, ensure that the parent of both_have_2 is + # not sent as a "have" line. The client should know that the server has + # both_have_2, so it only needs to inform the server that it has + # both_have_2, and the server can infer the rest. + + rm -f trace && + cp -r client clientv0 && + GIT_TRACE_PACKET="$(pwd)/trace" git -C clientv0 \ + fetch origin server_has both_have_2 && + grep "have $(git -C client rev-parse client_has)" trace && + grep "have $(git -C client rev-parse both_have_2)" trace && + ! grep "have $(git -C client rev-parse both_have_2^)" trace && + + rm -f trace && + cp -r client clientv2 && + GIT_TRACE_PACKET="$(pwd)/trace" git -C clientv2 -c protocol.version=2 \ + fetch origin server_has both_have_2 && + grep "have $(git -C client rev-parse client_has)" trace && + grep "have $(git -C client rev-parse both_have_2)" trace && + ! grep "have $(git -C client rev-parse both_have_2^)" trace +' + test_expect_success 'filtering by size' ' rm -rf server client && test_create_repo server && diff --combined t/t5505-remote.sh index 11e14a1e0f,ca4c222743..a6856e052b --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@@ -348,13 -348,17 +348,13 @@@ URL: $(pwd)/on EOF test_expect_success 'prune --dry-run' ' - ( - cd one && - git branch -m side2 side) && + git -C one branch -m side2 side && + test_when_finished "git -C one branch -m side side2" && ( cd test && git remote prune --dry-run origin >output && git rev-parse refs/remotes/origin/side2 && test_must_fail git rev-parse refs/remotes/origin/side && - ( - cd ../one && - git branch -m side side2) && test_i18ncmp expect output ) ' @@@ -844,7 -848,7 +844,7 @@@ test_expect_success 'migrate a remote f git remote rename origin origin && test_path_is_missing .git/branches/origin && test "$(git config remote.origin.url)" = "quux" && - test "$(git config remote.origin.fetch)" = "refs/heads/foom:refs/heads/origin" + test "$(git config remote.origin.fetch)" = "refs/heads/foom:refs/heads/origin" && test "$(git config remote.origin.push)" = "HEAD:refs/heads/foom" ) ' @@@ -872,7 -876,7 +872,7 @@@ test_expect_success 'remote prune to ca cd eight && test_must_fail git branch nomore origin ) 2>err && - grep "dangling symref" err + test_i18ngrep "dangling symref" err ' test_expect_success 'show empty remote' ' diff --combined t/t5801-remote-helpers.sh index ee5757966f,e3bc53b0c7..aaaa722cca --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@@ -96,7 -96,7 +96,7 @@@ test_expect_success 'push new branch wi test_expect_success 'push new branch with HEAD:new refspec' ' (cd local && - git checkout new-name + git checkout new-name && git push origin HEAD:new-refspec-2 ) && compare_refs local HEAD server refs/heads/new-refspec-2 @@@ -126,7 -126,7 +126,7 @@@ test_expect_success 'forced push' test_expect_success 'cloning without refspec' ' GIT_REMOTE_TESTGIT_REFSPEC="" \ git clone "testgit::${PWD}/server" local2 2>error && - grep "This remote helper should implement refspec capability" error && + test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@@ -134,7 -134,7 +134,7 @@@ test_expect_success 'pulling without re (cd local2 && git reset --hard && GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) && - grep "This remote helper should implement refspec capability" error && + test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@@ -146,7 -146,7 +146,7 @@@ test_expect_success 'pushing without re GIT_REMOTE_TESTGIT_REFSPEC="" && export GIT_REMOTE_TESTGIT_REFSPEC && test_must_fail git push 2>../error) && - grep "remote-helper doesn.t support push; refspec needed" error + test_i18ngrep "remote-helper doesn.t support push; refspec needed" error ' test_expect_success 'pulling without marks' ' @@@ -246,7 -246,7 +246,7 @@@ test_expect_success 'proper failure che (cd local && test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error && cat error && - grep -q "Error while running fast-import" error + test_i18ngrep -q "error while running fast-import" error ) ' diff --combined t/t7400-submodule-basic.sh index 2c2c97e144,d6853e94be..2b71e62ec2 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@@ -171,13 -171,12 +171,13 @@@ test_expect_success 'submodule add to . test_expect_success 'submodule add to reconfigure existing submodule with --force' ' ( cd addtest-ignore && - git submodule add --force bogus-url submod && - git submodule add -b initial "$submodurl" submod-branch && - test "bogus-url" = "$(git config -f .gitmodules submodule.submod.url)" && - test "bogus-url" = "$(git config submodule.submod.url)" && + bogus_url="$(pwd)/bogus-url" && + git submodule add --force "$bogus_url" submod && + git submodule add --force -b initial "$submodurl" submod-branch && + test "$bogus_url" = "$(git config -f .gitmodules submodule.submod.url)" && + test "$bogus_url" = "$(git config submodule.submod.url)" && # Restore the url - git submodule add --force "$submodurl" submod + git submodule add --force "$submodurl" submod && test "$submodurl" = "$(git config -f .gitmodules submodule.submod.url)" && test "$submodurl" = "$(git config submodule.submod.url)" ) @@@ -378,7 -377,7 +378,7 @@@ test_expect_success 'init should regist test_failure_with_unknown_submodule () { test_must_fail git submodule $1 no-such-submodule 2>output.err && - grep "^error: .*no-such-submodule" output.err + test_i18ngrep "^error: .*no-such-submodule" output.err } test_expect_success 'init should fail with unknown submodule' ' @@@ -819,7 -818,7 +819,7 @@@ test_expect_success '../bar/a/b/c work cp pristine-.git-config .git/config && cp pristine-.gitmodules .gitmodules && mkdir -p a/b/c && - (cd a/b/c; git init) && + (cd a/b/c && git init) && git config remote.origin.url ../foo/bar.git && git submodule add ../bar/a/b/c ./a/b/c && git submodule init && @@@ -994,11 -993,6 +994,11 @@@ test_expect_success 'submodule deinit s rmdir init ' +test_expect_success 'submodule deinit should unset core.worktree' ' + test_path_is_file .git/modules/example/config && + test_must_fail git config -f .git/modules/example/config core.worktree +' + test_expect_success 'submodule deinit from subdirectory' ' git submodule update --init && git config submodule.example.foo bar && diff --combined transport-helper.c index eab7f47565,84a10661cc..0a71929105 --- a/transport-helper.c +++ b/transport-helper.c @@@ -48,7 -48,7 +48,7 @@@ static void sendline(struct helper_dat if (debug) fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf); if (write_in_full(helper->helper->in, buffer->buf, buffer->len) < 0) - die_errno("Full write to remote helper failed"); + die_errno(_("full write to remote helper failed")); } static int recvline_fh(FILE *helper, struct strbuf *buffer) @@@ -77,7 -77,7 +77,7 @@@ static void write_constant(int fd, cons if (debug) fprintf(stderr, "Debug: Remote helper: -> %s", str); if (write_in_full(fd, str, strlen(str)) < 0) - die_errno("Full write to remote helper failed"); + die_errno(_("full write to remote helper failed")); } static const char *remove_ext_force(const char *url) @@@ -129,7 -129,7 +129,7 @@@ static struct child_process *get_helper code = start_command(helper); if (code < 0 && errno == ENOENT) - die("Unable to find remote helper for '%s'", data->name); + die(_("unable to find remote helper for '%s'"), data->name); else if (code != 0) exit(code); @@@ -145,7 -145,7 +145,7 @@@ */ duped = dup(helper->out); if (duped < 0) - die_errno("Can't dup helper output fd"); + die_errno(_("can't dup helper output fd")); data->out = xfdopen(duped, "r"); write_constant(helper->in, "capabilities\n"); @@@ -196,13 -196,13 +196,13 @@@ } else if (starts_with(capname, "no-private-update")) { data->no_private_update = 1; } else if (mandatory) { - die("Unknown mandatory capability %s. This remote " - "helper probably needs newer version of Git.", + die(_("unknown mandatory capability %s; this remote " + "helper probably needs newer version of Git"), capname); } } if (!data->rs.nr && (data->import || data->bidi_import || data->export)) { - warning("This remote helper should implement refspec capability."); + warning(_("this remote helper should implement refspec capability")); } strbuf_release(&buf); if (debug) @@@ -269,7 -269,7 +269,7 @@@ static int strbuf_set_helper_option(str else if (!strcmp(buf->buf, "unsupported")) ret = 1; else { - warning("%s unexpectedly said: '%s'", data->name, buf->buf); + warning(_("%s unexpectedly said: '%s'"), data->name, buf->buf); ret = 1; } return ret; @@@ -398,7 -398,7 +398,7 @@@ static int fetch_with_fetch(struct tran if (starts_with(buf.buf, "lock ")) { const char *name = buf.buf + 5; if (transport->pack_lockfile) - warning("%s also locked %s", data->name, name); + warning(_("%s also locked %s"), data->name, name); else transport->pack_lockfile = xstrdup(name); } @@@ -409,7 -409,7 +409,7 @@@ else if (!buf.len) break; else - warning("%s unexpectedly said: '%s'", data->name, buf.buf); + warning(_("%s unexpectedly said: '%s'"), data->name, buf.buf); } strbuf_release(&buf); return 0; @@@ -476,7 -476,7 +476,7 @@@ static int fetch_with_import(struct tra get_helper(transport); if (get_importer(transport, &fastimport)) - die("Couldn't run fast-import"); + die(_("couldn't run fast-import")); for (i = 0; i < nr_heads; i++) { posn = to_fetch[i]; @@@ -499,7 -499,7 +499,7 @@@ */ if (finish_command(&fastimport)) - die("Error while running fast-import"); + die(_("error while running fast-import")); /* * The fast-import stream of a remote helper that advertises @@@ -528,7 -528,7 +528,7 @@@ private = xstrdup(name); if (private) { if (read_ref(private, &posn->old_oid) < 0) - die("Could not read ref %s", private); + die(_("could not read ref %s"), private); free(private); } } @@@ -554,7 -554,7 +554,7 @@@ static int run_connect(struct transpor */ duped = dup(helper->out); if (duped < 0) - die_errno("Can't dup helper output fd"); + die_errno(_("can't dup helper output fd")); input = xfdopen(duped, "r"); setvbuf(input, NULL, _IONBF, 0); @@@ -573,8 -573,8 +573,8 @@@ fprintf(stderr, "Debug: Falling back to dumb " "transport.\n"); } else { - die("Unknown response to connect: %s", - cmdbuf->buf); + die(_(_("unknown response to connect: %s")), + cmdbuf->buf); } fclose(input); @@@ -595,9 -595,9 +595,9 @@@ static int process_connect_service(stru if (strcmp(name, exec)) { int r = set_helper_option(transport, "servpath", exec); if (r > 0) - warning("Setting remote service path not supported by protocol."); + warning(_("setting remote service path not supported by protocol")); else if (r < 0) - warning("Invalid remote service path."); + warning(_("invalid remote service path")); } if (data->connect) { @@@ -640,10 -640,10 +640,10 @@@ static int connect_helper(struct transp /* Get_helper so connect is inited. */ get_helper(transport); if (!data->connect) - die("Operation not supported by protocol."); + die(_("operation not supported by protocol")); if (!process_connect_service(transport, name, exec)) - die("Can't connect to subservice %s.", name); + die(_("can't connect to subservice %s"), name); fd[0] = data->helper->out; fd[1] = data->helper->in; @@@ -651,16 -651,14 +651,16 @@@ } static int fetch(struct transport *transport, - int nr_heads, struct ref **to_fetch) + int nr_heads, struct ref **to_fetch, + struct ref **fetched_refs) { struct helper_data *data = transport->data; int i, count; if (process_connect(transport, 0)) { do_take_over(transport); - return transport->vtable->fetch(transport, nr_heads, to_fetch); + return transport->vtable->fetch(transport, nr_heads, to_fetch, + fetched_refs); } count = 0; @@@ -686,9 -684,6 +686,9 @@@ transport, "filter", data->transport_options.filter_options.filter_spec); + if (data->transport_options.negotiation_tips) + warning("Ignoring --negotiation-tip because the protocol does not support it."); + if (data->fetch) return fetch_with_fetch(transport, nr_heads, to_fetch); @@@ -712,7 -707,7 +712,7 @@@ static int push_update_ref_status(struc status = REF_STATUS_REMOTE_REJECT; refname = buf->buf + 6; } else - die("expected ok/error, helper said '%s'", buf->buf); + die(_("expected ok/error, helper said '%s'"), buf->buf); msg = strchr(refname, ' '); if (msg) { @@@ -765,7 -760,7 +765,7 @@@ if (!*ref) *ref = find_ref_by_name(remote_refs, refname); if (!*ref) { - warning("helper reported unexpected status of %s", refname); + warning(_("helper reported unexpected status of %s"), refname); return 1; } @@@ -826,20 -821,20 +826,20 @@@ static void set_common_push_options(str { if (flags & TRANSPORT_PUSH_DRY_RUN) { if (set_helper_option(transport, "dry-run", "true") != 0) - die("helper %s does not support dry-run", name); + die(_("helper %s does not support dry-run"), name); } else if (flags & TRANSPORT_PUSH_CERT_ALWAYS) { if (set_helper_option(transport, TRANS_OPT_PUSH_CERT, "true") != 0) - die("helper %s does not support --signed", name); + die(_("helper %s does not support --signed"), name); } else if (flags & TRANSPORT_PUSH_CERT_IF_ASKED) { if (set_helper_option(transport, TRANS_OPT_PUSH_CERT, "if-asked") != 0) - die("helper %s does not support --signed=if-asked", name); + die(_("helper %s does not support --signed=if-asked"), name); } if (flags & TRANSPORT_PUSH_OPTIONS) { struct string_list_item *item; for_each_string_list_item(item, transport->push_options) if (set_helper_option(transport, "push-option", item->string) != 0) - die("helper %s does not support 'push-option'", name); + die(_("helper %s does not support 'push-option'"), name); } } @@@ -931,12 -926,12 +931,12 @@@ static int push_refs_with_export(struc struct strbuf buf = STRBUF_INIT; if (!data->rs.nr) - die("remote-helper doesn't support push; refspec needed"); + die(_("remote-helper doesn't support push; refspec needed")); set_common_push_options(transport, data->name, flags); if (flags & TRANSPORT_PUSH_FORCE) { if (set_helper_option(transport, "force", "true") != 0) - warning("helper %s does not support 'force'", data->name); + warning(_("helper %s does not support 'force'"), data->name); } helper = get_helper(transport); @@@ -983,12 -978,12 +983,12 @@@ } if (get_exporter(transport, &exporter, &revlist_args)) - die("Couldn't run fast-export"); + die(_("couldn't run fast-export")); string_list_clear(&revlist_args, 1); if (finish_command(&exporter)) - die("Error while running fast-export"); + die(_("error while running fast-export")); if (push_update_refs_status(data, remote_refs, flags)) return 1; @@@ -1012,8 -1007,9 +1012,9 @@@ static int push_refs(struct transport * } if (!remote_refs) { - fprintf(stderr, "No refs in common and none specified; doing nothing.\n" - "Perhaps you should specify a branch such as 'master'.\n"); + fprintf(stderr, + _("No refs in common and none specified; doing nothing.\n" + "Perhaps you should specify a branch such as 'master'.\n")); return 0; } @@@ -1075,7 -1071,7 +1076,7 @@@ static struct ref *get_refs_list(struc eov = strchr(buf.buf, ' '); if (!eov) - die("Malformed response in ref list: %s", buf.buf); + die(_("malformed response in ref list: %s"), buf.buf); eon = strchr(eov + 1, ' '); *eov = '\0'; if (eon) @@@ -1089,7 -1085,7 +1090,7 @@@ if (has_attribute(eon + 1, "unchanged")) { (*tail)->status |= REF_STATUS_UPTODATE; if (read_ref((*tail)->name, &(*tail)->old_oid) < 0) - die(_("Could not read ref %s"), + die(_("could not read ref %s"), (*tail)->name); } } @@@ -1228,7 -1224,7 +1229,7 @@@ static int udt_do_read(struct unidirect bytes = read(t->src, t->buf + t->bufuse, BUFFERSIZE - t->bufuse); if (bytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) { - error_errno("read(%s) failed", t->src_name); + error_errno(_("read(%s) failed"), t->src_name); return -1; } else if (bytes == 0) { transfer_debug("%s EOF (with %i bytes in buffer)", @@@ -1255,7 -1251,7 +1256,7 @@@ static int udt_do_write(struct unidirec transfer_debug("%s is writable", t->dest_name); bytes = xwrite(t->dest, t->buf, t->bufuse); if (bytes < 0 && errno != EWOULDBLOCK) { - error_errno("write(%s) failed", t->dest_name); + error_errno(_("write(%s) failed"), t->dest_name); return -1; } else if (bytes > 0) { t->bufuse -= bytes; @@@ -1304,11 -1300,11 +1305,11 @@@ static int tloop_join(pthread_t thread void *tret; err = pthread_join(thread, &tret); if (!tret) { - error("%s thread failed", name); + error(_("%s thread failed"), name); return 1; } if (err) { - error("%s thread failed to join: %s", name, strerror(err)); + error(_("%s thread failed to join: %s"), name, strerror(err)); return 1; } return 0; @@@ -1327,11 -1323,11 +1328,11 @@@ static int tloop_spawnwait_tasks(struc err = pthread_create(>p_thread, NULL, udt_copy_task_routine, &s->gtp); if (err) - die("Can't start thread for copying data: %s", strerror(err)); + die(_("can't start thread for copying data: %s"), strerror(err)); err = pthread_create(&ptg_thread, NULL, udt_copy_task_routine, &s->ptg); if (err) - die("Can't start thread for copying data: %s", strerror(err)); + die(_("can't start thread for copying data: %s"), strerror(err)); ret |= tloop_join(gtp_thread, "Git to program copy"); ret |= tloop_join(ptg_thread, "Program to git copy"); @@@ -1368,11 -1364,11 +1369,11 @@@ static int tloop_join(pid_t pid, const { int tret; if (waitpid(pid, &tret, 0) < 0) { - error_errno("%s process failed to wait", name); + error_errno(_("%s process failed to wait"), name); return 1; } if (!WIFEXITED(tret) || WEXITSTATUS(tret)) { - error("%s process failed", name); + error(_("%s process failed"), name); return 1; } return 0; @@@ -1390,7 -1386,7 +1391,7 @@@ static int tloop_spawnwait_tasks(struc /* Fork thread #1: git to program. */ pid1 = fork(); if (pid1 < 0) - die_errno("Can't start thread for copying data"); + die_errno(_("can't start thread for copying data")); else if (pid1 == 0) { udt_kill_transfer(&s->ptg); exit(udt_copy_task_routine(&s->gtp) ? 0 : 1); @@@ -1399,7 -1395,7 +1400,7 @@@ /* Fork thread #2: program to git. */ pid2 = fork(); if (pid2 < 0) - die_errno("Can't start thread for copying data"); + die_errno(_("can't start thread for copying data")); else if (pid2 == 0) { udt_kill_transfer(&s->gtp); exit(udt_copy_task_routine(&s->ptg) ? 0 : 1); diff --combined transport.c index b64b7bcb86,516a83b7f6..64c38bdeed --- a/transport.c +++ b/transport.c @@@ -139,7 -139,7 +139,7 @@@ static struct ref *get_refs_from_bundle close(data->fd); data->fd = read_bundle_header(transport->url, &data->header); if (data->fd < 0) - die ("Could not read bundle '%s'.", transport->url); + die(_("could not read bundle '%s'"), transport->url); for (i = 0; i < data->header.references.nr; i++) { struct ref_list_entry *e = data->header.references.list + i; struct ref *ref = alloc_ref(e->name); @@@ -151,8 -151,7 +151,8 @@@ } static int fetch_refs_from_bundle(struct transport *transport, - int nr_heads, struct ref **to_fetch) + int nr_heads, struct ref **to_fetch, + struct ref **fetched_refs) { struct bundle_transport_data *data = transport->data; return unbundle(&data->header, data->fd, @@@ -288,8 -287,7 +288,8 @@@ static struct ref *get_refs_via_connect } static int fetch_refs_via_pack(struct transport *transport, - int nr_heads, struct ref **to_fetch) + int nr_heads, struct ref **to_fetch, + struct ref **fetched_refs) { int ret = 0; struct git_transport_data *data = transport->data; @@@ -320,7 -318,6 +320,7 @@@ args.filter_options = data->options.filter_options; args.stateless_rpc = transport->stateless_rpc; args.server_options = transport->server_options; + args.negotiation_tips = data->options.negotiation_tips; if (!data->got_remote_heads) refs_tmp = get_refs_via_connect(transport, 0, NULL); @@@ -351,19 -348,14 +351,19 @@@ data->got_remote_heads = 0; data->options.self_contained_and_connected = args.self_contained_and_connected; + data->options.connectivity_checked = args.connectivity_checked; if (refs == NULL) ret = -1; if (report_unmatched_refs(to_fetch, nr_heads)) ret = -1; + if (fetched_refs) + *fetched_refs = refs; + else + free_refs(refs); + free_refs(refs_tmp); - free_refs(refs); free(dest); return ret; } @@@ -662,7 -654,7 +662,7 @@@ static int git_transport_push(struct tr switch (data->version) { case protocol_v2: - die("support for protocol v2 not implemented yet"); + die(_("support for protocol v2 not implemented yet")); break; case protocol_v1: case protocol_v0: @@@ -788,7 -780,7 +788,7 @@@ static enum protocol_allow_config parse else if (!strcasecmp(value, "user")) return PROTOCOL_ALLOW_USER_ONLY; - die("unknown value for config '%s': %s", key, value); + die(_("unknown value for config '%s': %s"), key, value); } static enum protocol_allow_config get_protocol_config(const char *type) @@@ -854,7 -846,7 +854,7 @@@ int is_transport_allowed(const char *ty void transport_check_allowed(const char *type) { if (!is_transport_allowed(type, -1)) - die("transport '%s' not allowed", type); + die(_("transport '%s' not allowed"), type); } static struct transport_vtable bundle_vtable = { @@@ -883,7 -875,7 +883,7 @@@ struct transport *transport_get(struct ret->progress = isatty(2); if (!remote) - die("No remote provided to transport_get()"); + BUG("No remote provided to transport_get()"); ret->got_remote_refs = 0; ret->remote = remote; @@@ -906,7 -898,7 +906,7 @@@ if (helper) { transport_helper_init(ret, helper); } else if (starts_with(url, "rsync:")) { - die("git-over-rsync is no longer supported"); + die(_("git-over-rsync is no longer supported")); } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); transport_check_allowed("file"); @@@ -1151,7 -1143,7 +1151,7 @@@ int transport_push(struct transport *tr transport->push_options, pretend)) { oid_array_clear(&commits); - die("Failed to push all needed submodules!"); + die(_("failed to push all needed submodules")); } oid_array_clear(&commits); } @@@ -1223,31 -1215,19 +1223,31 @@@ const struct ref *transport_get_remote_ return transport->remote_refs; } -int transport_fetch_refs(struct transport *transport, struct ref *refs) +int transport_fetch_refs(struct transport *transport, struct ref *refs, + struct ref **fetched_refs) { int rc; int nr_heads = 0, nr_alloc = 0, nr_refs = 0; struct ref **heads = NULL; + struct ref *nop_head = NULL, **nop_tail = &nop_head; struct ref *rm; for (rm = refs; rm; rm = rm->next) { nr_refs++; if (rm->peer_ref && !is_null_oid(&rm->old_oid) && - !oidcmp(&rm->peer_ref->old_oid, &rm->old_oid)) + !oidcmp(&rm->peer_ref->old_oid, &rm->old_oid)) { + /* + * These need to be reported as fetched, but we don't + * actually need to fetch them. + */ + if (fetched_refs) { + struct ref *nop_ref = copy_ref(rm); + *nop_tail = nop_ref; + nop_tail = &nop_ref->next; + } continue; + } ALLOC_GROW(heads, nr_heads + 1, nr_alloc); heads[nr_heads++] = rm; } @@@ -1265,11 -1245,7 +1265,11 @@@ heads[nr_heads++] = rm; } - rc = transport->vtable->fetch(transport, nr_heads, heads); + rc = transport->vtable->fetch(transport, nr_heads, heads, fetched_refs); + if (fetched_refs && nop_head) { + *nop_tail = *fetched_refs; + *fetched_refs = nop_head; + } free(heads); return rc; @@@ -1289,7 -1265,7 +1289,7 @@@ int transport_connect(struct transport if (transport->vtable->connect) return transport->vtable->connect(transport, name, exec, fd); else - die("Operation not supported by protocol"); + die(_("operation not supported by protocol")); } int transport_disconnect(struct transport *transport) @@@ -1371,7 -1347,7 +1371,7 @@@ static void read_alternate_refs(const c if (get_oid_hex(line.buf, &oid) || line.buf[GIT_SHA1_HEXSZ] != ' ') { - warning("invalid line while parsing alternate refs: %s", + warning(_("invalid line while parsing alternate refs: %s"), line.buf); break; }