From: Junio C Hamano Date: Sat, 2 Apr 2011 00:55:55 +0000 (-0700) Subject: Merge branch 'ab/i18n-st' X-Git-Tag: v1.7.5-rc1~19 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=6c80cd298a9f2f36ae4e741cf65d94b7c184fb82;p=git.git Merge branch 'ab/i18n-st' * ab/i18n-st: (69 commits) i18n: git-shortlog basic messages i18n: git-revert split up "could not revert/apply" message i18n: git-revert literal "me" messages i18n: git-revert "Your local changes" message i18n: git-revert basic messages i18n: git-notes GIT_NOTES_REWRITE_MODE error message i18n: git-notes basic commands i18n: git-gc "Auto packing the repository" message i18n: git-gc basic messages i18n: git-describe basic messages i18n: git-clean clean.requireForce messages i18n: git-clean basic messages i18n: git-bundle basic messages i18n: git-archive basic messages i18n: git-status "renamed: " message i18n: git-status "Initial commit" message i18n: git-status "Changes to be committed" message i18n: git-status shortstatus messages i18n: git-status "nothing to commit" messages i18n: git-status basic messages ... Conflicts: builtin/branch.c builtin/checkout.c builtin/clone.c builtin/commit.c builtin/grep.c builtin/merge.c builtin/push.c builtin/revert.c t/t3507-cherry-pick-conflict.sh t/t7607-merge-overwrite.sh --- 6c80cd298a9f2f36ae4e741cf65d94b7c184fb82 diff --cc builtin/branch.c index b9ba011f7,244589e73..9cca1b9af --- a/builtin/branch.c +++ b/builtin/branch.c @@@ -133,12 -133,12 +133,12 @@@ static int branch_merged(int kind, cons if ((head_rev != reference_rev) && in_merge_bases(rev, &head_rev, 1) != merged) { if (merged) - warning("deleting branch '%s' that has been merged to\n" - " '%s', but not yet been merged to HEAD.", + warning(_("deleting branch '%s' that has been merged to\n" - " '%s', but it is not yet merged to HEAD."), ++ " '%s', but not yet merged to HEAD."), name, reference_name); else - warning("not deleting branch '%s' that is not yet merged to\n" - " '%s', even though it is merged to HEAD.", + warning(_("not deleting branch '%s' that is not yet merged to\n" + " '%s', even though it is merged to HEAD."), name, reference_name); } return merged; diff --cc builtin/checkout.c index 686d0ffd3,9f8e41e37..eece5d6ac --- a/builtin/checkout.c +++ b/builtin/checkout.c @@@ -542,29 -543,21 +544,31 @@@ static void update_refs_for_switch(stru strbuf_addf(&msg, "checkout: moving from %s to %s", old_desc ? old_desc : "(invalid)", new->name); - if (new->path) { + if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) { + /* Nothing to do. */ + } else if (opts->force_detach || !new->path) { /* No longer on any branch. */ + update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL, + REF_NODEREF, DIE_ON_ERR); + if (!opts->quiet) { + if (old->path && advice_detached_head) + detach_advice(old->path, new->name); - describe_detached_head("HEAD is now at", new->commit); ++ describe_detached_head(_("HEAD is now at"), new->commit); + } + } else if (new->path) { /* Switch branches. */ create_symref("HEAD", new->path, msg.buf); if (!opts->quiet) { - if (old->path && !strcmp(new->path, old->path)) - fprintf(stderr, "Already on '%s'\n", - new->name); - else if (opts->new_branch) - fprintf(stderr, "Switched to%s branch '%s'\n", - opts->branch_exists ? " and reset" : " a new", + if (old->path && !strcmp(new->path, old->path)) { + fprintf(stderr, _("Already on '%s'\n"), new->name); - else - fprintf(stderr, "Switched to branch '%s'\n", + } else if (opts->new_branch) { + if (opts->branch_exists) + fprintf(stderr, _("Switched to and reset branch '%s'\n"), new->name); + else + fprintf(stderr, _("Switched to a new branch '%s'\n"), new->name); + } else { + fprintf(stderr, _("Switched to branch '%s'\n"), new->name); + } } if (old->path && old->name) { char log_file[PATH_MAX], ref_file[PATH_MAX]; @@@ -582,116 -582,6 +586,116 @@@ report_tracking(new); } +struct rev_list_args { + int argc; + int alloc; + const char **argv; +}; + +static void add_one_rev_list_arg(struct rev_list_args *args, const char *s) +{ + ALLOC_GROW(args->argv, args->argc + 1, args->alloc); + args->argv[args->argc++] = s; +} + +static int add_one_ref_to_rev_list_arg(const char *refname, + const unsigned char *sha1, + int flags, + void *cb_data) +{ + add_one_rev_list_arg(cb_data, refname); + return 0; +} + +static int clear_commit_marks_from_one_ref(const char *refname, + const unsigned char *sha1, + int flags, + void *cb_data) +{ + struct commit *commit = lookup_commit_reference_gently(sha1, 1); + if (commit) + clear_commit_marks(commit, -1); + return 0; +} + +static void describe_one_orphan(struct strbuf *sb, struct commit *commit) +{ + struct pretty_print_context ctx = { 0 }; + + parse_commit(commit); + strbuf_addstr(sb, " "); + strbuf_addstr(sb, + find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); + strbuf_addch(sb, ' '); + pretty_print_commit(CMIT_FMT_ONELINE, commit, sb, &ctx); + strbuf_addch(sb, '\n'); +} + +#define ORPHAN_CUTOFF 4 +static void suggest_reattach(struct commit *commit, struct rev_info *revs) +{ + struct commit *c, *last = NULL; + struct strbuf sb = STRBUF_INIT; + int lost = 0; + while ((c = get_revision(revs)) != NULL) { + if (lost < ORPHAN_CUTOFF) + describe_one_orphan(&sb, c); + last = c; + lost++; + } + if (ORPHAN_CUTOFF < lost) { + int more = lost - ORPHAN_CUTOFF; + if (more == 1) + describe_one_orphan(&sb, last); + else + strbuf_addf(&sb, " ... and %d more.\n", more); + } + + fprintf(stderr, + "Warning: you are leaving %d commit%s behind, " + "not connected to\n" + "any of your branches:\n\n" + "%s\n" + "If you want to keep them by creating a new branch, " + "this may be a good time\nto do so with:\n\n" + " git branch new_branch_name %s\n\n", + lost, ((1 < lost) ? "s" : ""), + sb.buf, + sha1_to_hex(commit->object.sha1)); + strbuf_release(&sb); +} + +/* + * We are about to leave commit that was at the tip of a detached + * HEAD. If it is not reachable from any ref, this is the last chance + * for the user to do so without resorting to reflog. + */ +static void orphaned_commit_warning(struct commit *commit) +{ + struct rev_list_args args = { 0, 0, NULL }; + struct rev_info revs; + + add_one_rev_list_arg(&args, "(internal)"); + add_one_rev_list_arg(&args, sha1_to_hex(commit->object.sha1)); + add_one_rev_list_arg(&args, "--not"); + for_each_ref(add_one_ref_to_rev_list_arg, &args); + add_one_rev_list_arg(&args, "--"); + add_one_rev_list_arg(&args, NULL); + + init_revisions(&revs, NULL); + if (setup_revisions(args.argc - 1, args.argv, &revs, NULL) != 1) - die("internal error: only -- alone should have been left"); ++ die(_("internal error: only -- alone should have been left")); + if (prepare_revision_walk(&revs)) - die("internal error in revision walk"); ++ die(_("internal error in revision walk")); + if (!(commit->object.flags & UNINTERESTING)) + suggest_reattach(commit, &revs); + else - describe_detached_head("Previous HEAD position was", commit); ++ describe_detached_head(_("Previous HEAD position was"), commit); + + clear_commit_marks(commit, -1); + for_each_ref(clear_commit_marks_from_one_ref, NULL); +} + static int switch_branches(struct checkout_opts *opts, struct branch_info *new) { int ret = 0; @@@ -784,119 -679,6 +788,119 @@@ static const char *unique_tracking_name return NULL; } +static int parse_branchname_arg(int argc, const char **argv, + int dwim_new_local_branch_ok, + struct branch_info *new, + struct tree **source_tree, + unsigned char rev[20], + const char **new_branch) +{ + int argcount = 0; + unsigned char branch_rev[20]; + const char *arg; + int has_dash_dash; + + /* + * case 1: git checkout -- [] + * + * must be a valid tree, everything after the '--' must be + * a path. + * + * case 2: git checkout -- [] + * + * everything after the '--' must be paths. + * + * case 3: git checkout [] + * + * With no paths, if is a commit, that is to + * switch to the branch or detach HEAD at it. As a special case, + * if is A...B (missing A or B means HEAD but you can + * omit at most one side), and if there is a unique merge base + * between A and B, A...B names that merge base. + * + * With no paths, if is _not_ a commit, no -t nor -b + * was given, 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. + * + * Otherwise shall not be ambiguous. + * - If it's *only* a reference, treat it like case (1). + * - If it's only a path, treat it like case (2). + * - else: fail. + * + */ + if (!argc) + return 0; + + if (!strcmp(argv[0], "--")) /* case (2) */ + return 1; + + arg = argv[0]; + has_dash_dash = (argc > 1) && !strcmp(argv[1], "--"); + + if (!strcmp(arg, "-")) + arg = "@{-1}"; + + if (get_sha1_mb(arg, rev)) { + if (has_dash_dash) /* case (1) */ - die("invalid reference: %s", arg); ++ die(_("invalid reference: %s"), arg); + if (dwim_new_local_branch_ok && + !check_filename(NULL, arg) && + argc == 1) { + const char *remote = unique_tracking_name(arg); + if (!remote || get_sha1(remote, rev)) + return argcount; + *new_branch = arg; + arg = remote; + /* DWIMmed to create local branch */ + } else { + return argcount; + } + } + + /* we can't end up being in (2) anymore, eat the argument */ + argcount++; + argv++; + argc--; + + new->name = arg; + setup_branch_path(new); + + if (check_ref_format(new->path) == CHECK_REF_FORMAT_OK && + resolve_ref(new->path, branch_rev, 1, NULL)) + hashcpy(rev, branch_rev); + else + new->path = NULL; /* not an existing branch */ + + new->commit = lookup_commit_reference_gently(rev, 1); + if (!new->commit) { + /* not a commit */ + *source_tree = parse_tree_indirect(rev); + } else { + parse_commit(new->commit); + *source_tree = new->commit->tree; + } + + if (!*source_tree) /* case (1): want a tree */ - die("reference is not a tree: %s", arg); ++ die(_("reference is not a tree: %s"), arg); + if (!has_dash_dash) {/* case (3 -> 1) */ + /* + * Do not complain the most common case + * git checkout branch + * even if there happen to be a file called 'branch'; + * it would be extremely annoying. + */ + if (argc) + verify_non_filename(NULL, arg); + } else { + argcount++; + argv++; + argc--; + } + + return argcount; +} + int cmd_checkout(int argc, const char **argv, const char *prefix) { struct checkout_opts opts; @@@ -952,15 -735,9 +956,15 @@@ opts.new_branch = opts.new_branch_force; if (patch_mode && (opts.track > 0 || opts.new_branch - || opts.new_branch_log || opts.merge || opts.force)) + || opts.new_branch_log || opts.merge || opts.force + || opts.force_detach)) - die ("--patch is incompatible with all other options"); + die (_("--patch is incompatible with all other options")); + if (opts.force_detach && (opts.new_branch || opts.new_orphan_branch)) + die("--detach cannot be used with -b/-B/--orphan"); + if (opts.force_detach && 0 < opts.track) + die("--detach cannot be used with -t"); + /* --track without -b should DWIM */ if (0 < opts.track && !opts.new_branch) { const char *argv0 = argv[0]; @@@ -990,33 -767,108 +994,33 @@@ } if (opts.force && opts.merge) - die("git checkout: -f and -m are incompatible"); + die(_("git checkout: -f and -m are incompatible")); /* - * case 1: git checkout -- [] + * Extract branch name from command line arguments, so + * all that is left is pathspecs. * - * must be a valid tree, everything after the '--' must be - * a path. - * - * case 2: git checkout -- [] - * - * everything after the '--' must be paths. - * - * case 3: git checkout [] - * - * With no paths, if is a commit, that is to - * switch to the branch or detach HEAD at it. As a special case, - * if is A...B (missing A or B means HEAD but you can - * omit at most one side), and if there is a unique merge base - * between A and B, A...B names that merge base. - * - * With no paths, if is _not_ a commit, no -t nor -b - * was given, and there is a remote-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. + * Handle * - * Otherwise shall not be ambiguous. - * - If it's *only* a reference, treat it like case (1). - * - If it's only a path, treat it like case (2). - * - else: fail. + * 1) git checkout -- [] + * 2) git checkout -- [] + * 3) git checkout [] * + * including "last branch" syntax and DWIM-ery for names of + * remote branches, erroring out for invalid or ambiguous cases. */ if (argc) { - if (!strcmp(argv[0], "--")) { /* case (2) */ - argv++; - argc--; - goto no_reference; - } - - arg = argv[0]; - has_dash_dash = (argc > 1) && !strcmp(argv[1], "--"); - - if (!strcmp(arg, "-")) - arg = "@{-1}"; - - if (get_sha1_mb(arg, rev)) { - if (has_dash_dash) /* case (1) */ - die(_("invalid reference: %s"), arg); - if (!patch_mode && - dwim_new_local_branch && - opts.track == BRANCH_TRACK_UNSPECIFIED && - !opts.new_branch && - !check_filename(NULL, arg) && - argc == 1) { - const char *remote = unique_tracking_name(arg); - if (!remote || get_sha1(remote, rev)) - goto no_reference; - opts.new_branch = arg; - arg = remote; - /* DWIMmed to create local branch */ - } - else - goto no_reference; - } - - /* we can't end up being in (2) anymore, eat the argument */ - argv++; - argc--; - - new.name = arg; - if ((new.commit = lookup_commit_reference_gently(rev, 1))) { - setup_branch_path(&new); - - if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) && - resolve_ref(new.path, rev, 1, NULL)) - ; - else - new.path = NULL; - parse_commit(new.commit); - source_tree = new.commit->tree; - } else - source_tree = parse_tree_indirect(rev); - - if (!source_tree) /* case (1): want a tree */ - die(_("reference is not a tree: %s"), arg); - if (!has_dash_dash) {/* case (3 -> 1) */ - /* - * Do not complain the most common case - * git checkout branch - * even if there happen to be a file called 'branch'; - * it would be extremely annoying. - */ - if (argc) - verify_non_filename(NULL, arg); - } - else { - argv++; - argc--; - } + int dwim_ok = + !patch_mode && + dwim_new_local_branch && + opts.track == BRANCH_TRACK_UNSPECIFIED && + !opts.new_branch; + int n = parse_branchname_arg(argc, argv, dwim_ok, + &new, &source_tree, rev, &opts.new_branch); + argv += n; + argc -= n; } -no_reference: - if (opts.track == BRANCH_TRACK_UNSPECIFIED) opts.track = git_branch_track; @@@ -1038,11 -890,8 +1042,11 @@@ } } + if (opts.force_detach) + die("git checkout: --detach does not take a path argument"); + if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge) - die("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index."); + die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index.")); return checkout_paths(source_tree, pathspec, &opts); } diff --cc builtin/clone.c index c6e10bb9e,b9394c415..0b5601a9b --- a/builtin/clone.c +++ b/builtin/clone.c @@@ -466,12 -465,15 +466,15 @@@ int cmd_clone(int argc, const char **ar setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1); if (safe_create_leading_directories_const(git_dir) < 0) - die("could not create leading directories of '%s'", git_dir); + die(_("could not create leading directories of '%s'"), git_dir); - set_git_dir(make_absolute_path(git_dir)); + set_git_dir(real_path(git_dir)); - if (0 <= option_verbosity) - printf("Cloning into %s%s...\n", - option_bare ? "bare repository " : "", dir); + if (0 <= option_verbosity) { + if (option_bare) + printf(_("Cloning into bare repository %s...\n"), dir); + else + printf(_("Cloning into %s...\n"), dir); + } init_db(option_template, INIT_DB_QUIET); /* diff --cc builtin/commit.c index 54b20497b,271f31127..67757e999 --- a/builtin/commit.c +++ b/builtin/commit.c @@@ -47,24 -47,16 +47,24 @@@ N_("Your name and email address were co "\n" "After doing this, you may fix the identity used for this commit with:\n" "\n" - " git commit --amend --reset-author\n"; + " git commit --amend --reset-author\n"); static const char empty_amend_advice[] = - "You asked to amend the most recent commit, but doing so would make\n" + N_("You asked to amend the most recent commit, but doing so would make\n" "it empty. You can repeat your command with --allow-empty, or you can\n" - "remove the commit entirely with \"git reset HEAD^\".\n"; + "remove the commit entirely with \"git reset HEAD^\".\n"); +static const char empty_cherry_pick_advice[] = - "The previous cherry-pick is now empty, possibly due to conflict resolution.\n" ++N_("The previous cherry-pick is now empty, possibly due to conflict resolution.\n" +"If you wish to commit it anyway, use:\n" +"\n" +" git commit --allow-empty\n" +"\n" - "Otherwise, please use 'git reset'\n"; ++"Otherwise, please use 'git reset'\n"); + static unsigned char head_sha1[20]; -static char *use_message_buffer; +static const char *use_message_buffer; static const char commit_editmsg[] = "COMMIT_EDITMSG"; static struct lock_file index_lock; /* real index */ static struct lock_file false_lock; /* used only for partial commits */ @@@ -422,8 -378,8 +422,8 @@@ static char *prepare_index(int argc, co */ commit_style = COMMIT_PARTIAL; - if (in_merge) - die(_("cannot do a partial commit during a merge.")); + if (whence != FROM_COMMIT) - die("cannot do a partial commit during a %s.", whence_s()); ++ die(_("cannot do a partial commit during a %s."), whence_s()); memset(&partial, 0, sizeof(partial)); partial.strdup_strings = 1; @@@ -513,18 -469,18 +513,18 @@@ static void determine_author_info(struc email = getenv("GIT_AUTHOR_EMAIL"); date = getenv("GIT_AUTHOR_DATE"); - if (use_message && !renew_authorship) { + if (author_message) { const char *a, *lb, *rb, *eol; - a = strstr(use_message_buffer, "\nauthor "); + a = strstr(author_message_buffer, "\nauthor "); if (!a) - die("invalid commit: %s", author_message); - die(_("invalid commit: %s"), use_message); ++ die(_("invalid commit: %s"), author_message); lb = strchrnul(a + strlen("\nauthor "), '<'); rb = strchrnul(lb, '>'); eol = strchrnul(rb, '\n'); if (!*lb || !*rb || !*eol) - die("invalid commit: %s", author_message); - die(_("invalid commit: %s"), use_message); ++ die(_("invalid commit: %s"), author_message); if (lb == a + strlen("\nauthor ")) /* \nauthor */ @@@ -675,11 -631,11 +675,11 @@@ static int prepare_to_commit(const cha hook_arg1 = "merge"; } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) { if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0) - die_errno("could not read SQUASH_MSG"); + die_errno(_("could not read SQUASH_MSG")); hook_arg1 = "squash"; - } else if (template_file && !stat(template_file, &statbuf)) { + } else if (template_file) { if (strbuf_read_file(&sb, template_file, 0) < 0) - die_errno("could not read '%s'", template_file); + die_errno(_("could not read '%s'"), template_file); hook_arg1 = "template"; } @@@ -741,18 -693,15 +741,18 @@@ strbuf_addstr(&committer_ident, git_committer_info(0)); if (use_editor && include_status) { char *ai_tmp, *ci_tmp; - if (in_merge) + if (whence != FROM_COMMIT) status_printf_ln(s, GIT_COLOR_NORMAL, - "\n" + _("\n" - "It looks like you may be committing a MERGE.\n" + "It looks like you may be committing a %s.\n" "If this is not correct, please remove the file\n" " %s\n" "and try again.\n" - "", + ""), - git_path("MERGE_HEAD")); + whence_s(), + git_path(whence == FROM_MERGE + ? "MERGE_HEAD" + : "CHERRY_PICK_HEAD")); fprintf(s->fp, "\n"); status_printf(s, GIT_COLOR_NORMAL, @@@ -826,9 -770,7 +826,9 @@@ !(amend && is_a_merge(head_sha1))) { run_status(stdout, index_file, prefix, 0, s); if (amend) - fputs(empty_amend_advice, stderr); + fputs(_(empty_amend_advice), stderr); + else if (whence == FROM_CHERRY_PICK) - fputs(empty_cherry_pick_advice, stderr); ++ fputs(_(empty_cherry_pick_advice), stderr); return 0; } @@@ -953,31 -895,9 +953,31 @@@ static void handle_untracked_files_arg( else if (!strcmp(untracked_files_arg, "all")) s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; else - die("Invalid untracked files mode '%s'", untracked_files_arg); + die(_("Invalid untracked files mode '%s'"), untracked_files_arg); } +static const char *read_commit_message(const char *name) +{ + const char *out_enc, *out; + struct commit *commit; + + commit = lookup_commit_reference_by_name(name); + if (!commit) - die("could not lookup commit %s", name); ++ die(_("could not lookup commit %s"), name); + out_enc = get_commit_output_encoding(); + out = logmsg_reencode(commit, out_enc); + + /* + * If we failed to reencode the buffer, just copy it + * byte for byte so the user can try to fix it up. + * This also handles the case where input and output + * encodings are identical. + */ + if (out == NULL) + out = xstrdup(commit->buffer); + return out; +} + static int parse_and_validate_options(int argc, const char *argv[], const char * const usage[], const char *prefix, @@@ -1006,11 -926,11 +1006,11 @@@ /* Sanity check options */ if (amend && initial_commit) - die("You have nothing to amend."); + die(_("You have nothing to amend.")); - if (amend && in_merge) - die(_("You are in the middle of a merge -- cannot amend.")); + if (amend && whence != FROM_COMMIT) - die("You are in the middle of a %s -- cannot amend.", whence_s()); ++ die(_("You are in the middle of a %s -- cannot amend."), whence_s()); if (fixup_message && squash_message) - die("Options --squash and --fixup cannot be used together"); + die(_("Options --squash and --fixup cannot be used together")); if (use_message) f++; if (edit_message) @@@ -1027,18 -947,26 +1027,18 @@@ use_message = edit_message; if (amend && !use_message && !fixup_message) use_message = "HEAD"; - if (!use_message && renew_authorship) + if (!use_message && whence != FROM_CHERRY_PICK && renew_authorship) - die("--reset-author can be used only with -C, -c or --amend."); + die(_("--reset-author can be used only with -C, -c or --amend.")); if (use_message) { - const char *out_enc; - struct commit *commit; - - commit = lookup_commit_reference_by_name(use_message); - if (!commit) - die(_("could not lookup commit %s"), use_message); - out_enc = get_commit_output_encoding(); - use_message_buffer = logmsg_reencode(commit, out_enc); - - /* - * If we failed to reencode the buffer, just copy it - * byte for byte so the user can try to fix it up. - * This also handles the case where input and output - * encodings are identical. - */ - if (use_message_buffer == NULL) - use_message_buffer = xstrdup(commit->buffer); + use_message_buffer = read_commit_message(use_message); + if (!renew_authorship) { + author_message = use_message; + author_message_buffer = use_message_buffer; + } + } + if (whence == FROM_CHERRY_PICK && !renew_authorship) { + author_message = "CHERRY_PICK_HEAD"; + author_message_buffer = read_commit_message(author_message); } if (!!also + !!only + !!all + !!interactive > 1) @@@ -1487,10 -1421,9 +1487,10 @@@ int cmd_commit(int argc, const char **a } if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) { rollback_index_files(); - die("cannot update HEAD ref"); + die(_("cannot update HEAD ref")); } + unlink(git_path("CHERRY_PICK_HEAD")); unlink(git_path("MERGE_HEAD")); unlink(git_path("MERGE_MSG")); unlink(git_path("MERGE_MODE")); diff --cc builtin/describe.c index 4afd1504a,037691e3d..66fc291c8 --- a/builtin/describe.c +++ b/builtin/describe.c @@@ -284,12 -284,12 +284,12 @@@ static void describe(const char *arg, i } if (!max_candidates) - die("no tag exactly matches '%s'", sha1_to_hex(cmit->object.sha1)); + die(_("no tag exactly matches '%s'"), sha1_to_hex(cmit->object.sha1)); if (debug) - fprintf(stderr, "searching to describe %s\n", arg); + fprintf(stderr, _("searching to describe %s\n"), arg); if (!have_util) { - for_each_hash(&names, set_util); + for_each_hash(&names, set_util, NULL); have_util = 1; } diff --cc builtin/diff.c index 655a013ed,00342730b..717fa1a34 --- a/builtin/diff.c +++ b/builtin/diff.c @@@ -367,12 -372,16 +367,12 @@@ int cmd_diff(int argc, const char **arg continue; } - die("unhandled object '%s' given.", name); + die(_("unhandled object '%s' given."), name); } - if (rev.prune_data) { - const char **pathspec = rev.prune_data; - while (*pathspec) { - if (!path) - path = *pathspec; - paths++; - pathspec++; - } + if (rev.prune_data.nr) { + if (!path) + path = rev.prune_data.items[0].match; + paths += rev.prune_data.nr; } /* diff --cc builtin/grep.c index 85e9583a1,dfc32fbe6..5b8f30d3e --- a/builtin/grep.c +++ b/builtin/grep.c @@@ -548,16 -664,12 +548,16 @@@ static int grep_tree(struct grep_opt *o data = lock_and_read_sha1_file(entry.sha1, &type, &size); if (!data) - die("unable to read tree (%s)", + die(_("unable to read tree (%s)"), sha1_to_hex(entry.sha1)); + + strbuf_addch(base, '/'); init_tree_desc(&sub, data, size); - hit |= grep_tree(opt, paths, &sub, tree_name, down); + hit |= grep_tree(opt, pathspec, &sub, base, tn_len); free(data); } + strbuf_setlen(base, old_baselen); + if (hit && opt->status_only) break; } @@@ -579,24 -690,16 +579,24 @@@ static int grep_object(struct grep_opt data = read_object_with_reference(obj->sha1, tree_type, &size, NULL); if (!data) - die("unable to read tree (%s)", sha1_to_hex(obj->sha1)); + die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1)); + + len = name ? strlen(name) : 0; + strbuf_init(&base, PATH_MAX + len + 1); + if (len) { + strbuf_add(&base, name, len); + strbuf_addch(&base, ':'); + } init_tree_desc(&tree, data, size); - hit = grep_tree(opt, paths, &tree, name, ""); + hit = grep_tree(opt, pathspec, &tree, &base, base.len); + strbuf_release(&base); free(data); return hit; } - die("unable to grep from object of type %s", typename(obj->type)); + die(_("unable to grep from object of type %s"), typename(obj->type)); } -static int grep_objects(struct grep_opt *opt, const char **paths, +static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, const struct object_array *list) { unsigned int i; @@@ -664,9 -762,9 +664,9 @@@ static int file_callback(const struct o int lno = 0; struct strbuf sb = STRBUF_INIT; - patterns = fopen(arg, "r"); + patterns = from_stdin ? stdin : fopen(arg, "r"); if (!patterns) - die_errno("cannot open '%s'", arg); + die_errno(_("cannot open '%s'"), arg); while (strbuf_getline(&sb, patterns, '\n') == 0) { char *s; size_t len; @@@ -963,12 -1059,9 +963,12 @@@ int cmd_grep(int argc, const char **arg paths[0] = prefix; paths[1] = NULL; } + init_pathspec(&pathspec, paths); + pathspec.max_depth = opt.max_depth; + pathspec.recursive = 1; if (show_in_pager && (cached || list.nr)) - die("--open-files-in-pager only works on the worktree"); + die(_("--open-files-in-pager only works on the worktree")); if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) { const char *pager = path_list.items[0].string; @@@ -993,19 -1086,19 +993,19 @@@ if (!use_index) { if (cached) - die("--cached cannot be used with --no-index."); + die(_("--cached cannot be used with --no-index.")); if (list.nr) - die("--no-index cannot be used with revs."); + die(_("--no-index cannot be used with revs.")); - hit = grep_directory(&opt, paths); + hit = grep_directory(&opt, &pathspec); } else if (!list.nr) { if (!cached) setup_work_tree(); - hit = grep_cache(&opt, paths, cached); + hit = grep_cache(&opt, &pathspec, cached); } else { if (cached) - die("both --cached and trees are given."); + die(_("both --cached and trees are given.")); - hit = grep_objects(&opt, paths, &list); + hit = grep_objects(&opt, &pathspec, &list); } if (use_threads) diff --cc builtin/init-db.c index 8f5cfd712,e0e5ce3b1..6621e5671 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@@ -507,10 -515,10 +513,10 @@@ int cmd_init_db(int argc, const char ** if (!git_work_tree_cfg) { git_work_tree_cfg = xcalloc(PATH_MAX, 1); if (!getcwd(git_work_tree_cfg, PATH_MAX)) - die_errno ("Cannot access current working directory"); + die_errno (_("Cannot access current working directory")); } if (work_tree) - set_git_work_tree(make_absolute_path(work_tree)); + set_git_work_tree(real_path(work_tree)); else set_git_work_tree(git_work_tree_cfg); if (access(get_git_work_tree(), X_OK)) diff --cc builtin/merge.c index c8d028cbc,f99820661..1e0bcfd79 --- a/builtin/merge.c +++ b/builtin/merge.c @@@ -801,32 -797,6 +801,32 @@@ static void add_strategies(const char * } +static void write_merge_msg(void) +{ + int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); + if (fd < 0) - die_errno("Could not open '%s' for writing", ++ die_errno(_("Could not open '%s' for writing"), + git_path("MERGE_MSG")); + if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len) - die_errno("Could not write to '%s'", git_path("MERGE_MSG")); ++ die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG")); + close(fd); +} + +static void read_merge_msg(void) +{ + strbuf_reset(&merge_msg); + if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0) + die_errno("Could not read from '%s'", git_path("MERGE_MSG")); +} + +static void run_prepare_commit_msg(void) +{ + write_merge_msg(); + run_hook(get_index_file(), "prepare-commit-msg", + git_path("MERGE_MSG"), "merge", NULL, NULL); + read_merge_msg(); +} + static int merge_trivial(void) { unsigned char result_tree[20], result_commit[20]; @@@ -1001,18 -966,11 +1001,18 @@@ int cmd_merge(int argc, const char **ar * add/rm ', just 'git commit'. */ if (advice_resolve_conflict) - die("You have not concluded your merge (MERGE_HEAD exists).\n" - "Please, commit your changes before you can merge."); + die(_("You have not concluded your merge (MERGE_HEAD exists).\n" + "Please, commit your changes before you can merge.")); else - die("You have not concluded your merge (MERGE_HEAD exists)."); + die(_("You have not concluded your merge (MERGE_HEAD exists).")); } + if (file_exists(git_path("CHERRY_PICK_HEAD"))) { + if (advice_resolve_conflict) + die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" + "Please, commit your changes before you can merge."); + else + die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."); + } resolve_undo_clear(); if (verbosity < 0) @@@ -1053,19 -1011,19 +1053,19 @@@ * We do the same for "git pull". */ if (argc != 1) - die("Can merge only exactly one commit into " - "empty head"); + die(_("Can merge only exactly one commit into " + "empty head")); if (squash) - die("Squash commit into empty head not supported yet"); + die(_("Squash commit into empty head not supported yet")); if (!allow_fast_forward) - die("Non-fast-forward commit does not make sense into " - "an empty head"); + die(_("Non-fast-forward commit does not make sense into " + "an empty head")); remote_head = peel_to_type(argv[0], 0, NULL, OBJ_COMMIT); if (!remote_head) - die("%s - not something we can merge", argv[0]); + die(_("%s - not something we can merge"), argv[0]); + read_empty(remote_head->sha1, 0); update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, DIE_ON_ERR); - read_empty(remote_head->sha1, 0); return 0; } else { struct strbuf merge_names = STRBUF_INIT; @@@ -1354,16 -1312,23 +1354,16 @@@ sha1_to_hex(j->item->object.sha1)); fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die_errno("Could not open '%s' for writing", + die_errno(_("Could not open '%s' for writing"), git_path("MERGE_HEAD")); if (write_in_full(fd, buf.buf, buf.len) != buf.len) - die_errno("Could not write to '%s'", git_path("MERGE_HEAD")); + die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD")); close(fd); strbuf_addch(&merge_msg, '\n'); - fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); - if (fd < 0) - die_errno(_("Could not open '%s' for writing"), - git_path("MERGE_MSG")); - if (write_in_full(fd, merge_msg.buf, merge_msg.len) != - merge_msg.len) - die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG")); - close(fd); + write_merge_msg(); fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) - die_errno("Could not open '%s' for writing", + die_errno(_("Could not open '%s' for writing"), git_path("MERGE_MODE")); strbuf_reset(&buf); if (!allow_fast_forward) diff --cc builtin/push.c index 6f6a66f98,8c8d8c717..9cebf9ea2 --- a/builtin/push.c +++ b/builtin/push.c @@@ -69,23 -69,13 +69,23 @@@ static void setup_push_upstream(struct struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); if (!branch) - die("You are not currently on a branch.\n" - die(_("You are not currently on a branch.")); ++ die(_("You are not currently on a branch.\n" + "To push the history leading to the current (detached HEAD)\n" + "state now, use\n" + "\n" - " git push %s HEAD:\n", ++ " git push %s HEAD:\n"), + remote->name); if (!branch->merge_nr || !branch->merge) - die("The current branch %s has no upstream branch.\n" - die(_("The current branch %s is not tracking anything."), ++ die(_("The current branch %s has no upstream branch.\n" + "To push the current branch and set the remote as upstream, use\n" + "\n" - " git push --set-upstream %s %s\n", ++ " git push --set-upstream %s %s\n"), + branch->name, + remote->name, branch->name); if (branch->merge_nr != 1) - die("The current branch %s has multiple upstream branches, " - "refusing to push.", branch->name); - die(_("The current branch %s is tracking multiple branches, " ++ die(_("The current branch %s has multiple upstream branches, " + "refusing to push."), branch->name); strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src); add_refspec(refspec.buf); } @@@ -156,15 -146,8 +156,15 @@@ static int do_push(const char *repo, in if (!remote) { if (repo) - die("bad repository '%s'", repo); - die("No configured push destination.\n" + die(_("bad repository '%s'"), repo); - die(_("No destination configured to push to.")); ++ die(_("No configured push destination.\n" + "Either specify the URL from the command-line or configure a remote repository using\n" + "\n" + " git remote add \n" + "\n" + "and then push using the remote name\n" + "\n" - " git push \n"); ++ " git push \n")); } if (remote->mirror) diff --cc builtin/revert.c index c57b872fe,98dfd4d13..2bb13ebb1 --- a/builtin/revert.c +++ b/builtin/revert.c @@@ -197,20 -198,54 +197,20 @@@ static void add_message_to_msg(struct s strbuf_addstr(msgbuf, p); } -static void set_author_ident_env(const char *message) +static void write_cherry_pick_head(void) { - const char *p = message; - if (!p) - die (_("Could not read commit message of %s"), - sha1_to_hex(commit->object.sha1)); - while (*p && *p != '\n') { - const char *eol; - - for (eol = p; *eol && *eol != '\n'; eol++) - ; /* do nothing */ - if (!prefixcmp(p, "author ")) { - char *line, *pend, *email, *timestamp; - - p += 7; - line = xmemdupz(p, eol - p); - email = strchr(line, '<'); - if (!email) - die (_("Could not extract author email from %s"), - sha1_to_hex(commit->object.sha1)); - if (email == line) - pend = line; - else - for (pend = email; pend != line + 1 && - isspace(pend[-1]); pend--); - ; /* do nothing */ - *pend = '\0'; - email++; - timestamp = strchr(email, '>'); - if (!timestamp) - die (_("Could not extract author time from %s"), - sha1_to_hex(commit->object.sha1)); - *timestamp = '\0'; - for (timestamp++; *timestamp && isspace(*timestamp); - timestamp++) - ; /* do nothing */ - setenv("GIT_AUTHOR_NAME", line, 1); - setenv("GIT_AUTHOR_EMAIL", email, 1); - setenv("GIT_AUTHOR_DATE", timestamp, 1); - free(line); - return; - } - p = eol; - if (*p == '\n') - p++; - } - die (_("No author information found in %s"), - sha1_to_hex(commit->object.sha1)); + int fd; + struct strbuf buf = STRBUF_INIT; + + strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1)); + + fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666); + if (fd < 0) - die_errno("Could not open '%s' for writing", ++ die_errno(_("Could not open '%s' for writing"), + git_path("CHERRY_PICK_HEAD")); + if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd)) - die_errno("Could not write to '%s'", git_path("CHERRY_PICK_HEAD")); ++ die_errno(_("Could not write to '%s'"), git_path("CHERRY_PICK_HEAD")); + strbuf_release(&buf); } static void advise(const char *advice, ...) diff --cc t/t3507-cherry-pick-conflict.sh index 95741801b,f7e407231..c0c8330c2 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@@ -44,8 -38,13 +44,8 @@@ test_expect_success 'failed cherry-pic test "$head" = "$newhead" ' - test_expect_success 'advice from failed cherry-pick' " + test_expect_success C_LOCALE_OUTPUT 'advice from failed cherry-pick' " - git checkout -f initial^0 && - git read-tree -u --reset HEAD && - git clean -d -f -f -q -x && - - git update-index --refresh && - git diff-index --exit-code HEAD && + pristine_detach initial && picked=\$(git rev-parse --short picked) && cat <<-EOF >expected && diff --cc t/t7607-merge-overwrite.sh index b54e840ee,0a9b90b33..ef84f0410 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@@ -150,9 -150,14 +150,15 @@@ test_expect_success 'will not overwrit git rm -fr . && git checkout --orphan new && cp important c0.c && + test_must_fail git merge c0 2>out + ' + + test_expect_success C_LOCALE_OUTPUT 'will not overwrite untracked file on unborn branch: output' ' + test_cmp out expect + ' + + test_expect_success 'will not overwrite untracked file on unborn branch .git/MERGE_HEAD sanity etc.' ' + test_when_finished "rm c0.c" && - test_must_fail git merge c0 2>out && - test_cmp out expect && test_path_is_missing .git/MERGE_HEAD && test_cmp important c0.c ' diff --cc wt-status.c index 53558d7e5,9ff059012..9f4e0ba9c --- a/wt-status.c +++ b/wt-status.c @@@ -131,16 -131,16 +131,16 @@@ static void wt_status_print_unmerged_he { const char *c = color(WT_STATUS_HEADER, s); - status_printf_ln(s, c, "Unmerged paths:"); + status_printf_ln(s, c, _("Unmerged paths:")); if (!advice_status_hints) return; - if (s->in_merge) + if (s->whence != FROM_COMMIT) ; else if (!s->is_initial) - status_printf_ln(s, c, " (use \"git reset %s ...\" to unstage)", s->reference); + status_printf_ln(s, c, _(" (use \"git reset %s ...\" to unstage)"), s->reference); else - status_printf_ln(s, c, " (use \"git rm --cached ...\" to unstage)"); - status_printf_ln(s, c, " (use \"git add/rm ...\" as appropriate to mark resolution)"); + status_printf_ln(s, c, _(" (use \"git rm --cached ...\" to unstage)")); + status_printf_ln(s, c, _(" (use \"git add/rm ...\" as appropriate to mark resolution)")); status_printf_ln(s, c, ""); } @@@ -148,15 -148,15 +148,15 @@@ static void wt_status_print_cached_head { const char *c = color(WT_STATUS_HEADER, s); - status_printf_ln(s, c, "Changes to be committed:"); + status_printf_ln(s, c, _("Changes to be committed:")); if (!advice_status_hints) return; - if (s->in_merge) + if (s->whence != FROM_COMMIT) ; /* NEEDSWORK: use "git reset --unresolve"??? */ else if (!s->is_initial) - status_printf_ln(s, c, " (use \"git reset %s ...\" to unstage)", s->reference); + status_printf_ln(s, c, _(" (use \"git reset %s ...\" to unstage)"), s->reference); else - status_printf_ln(s, c, " (use \"git rm --cached ...\" to unstage)"); + status_printf_ln(s, c, _(" (use \"git rm --cached ...\" to unstage)")); status_printf_ln(s, c, ""); }