From a6fa59924d154f2dcfc331357bf553e043aa0242 Mon Sep 17 00:00:00 2001 From: Pat Notz Date: Tue, 2 Nov 2010 13:59:07 -0600 Subject: commit: helper methods to reduce redundant blocks of code * builtin/commit.c: Replace block of code with a one-liner call to logmsg_reencode(). * commit.c: new function for looking up a comit by name * pretty.c: helper methods for getting output encodings Add helpers get_log_output_encoding() and get_commit_output_encoding() that eliminate some messy and duplicate if-blocks. Signed-off-by: Pat Notz Signed-off-by: Junio C Hamano --- builtin/commit.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'builtin/commit.c') diff --git a/builtin/commit.c b/builtin/commit.c index 66fdd22024..54fcc6d142 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -896,30 +896,14 @@ static int parse_and_validate_options(int argc, const char *argv[], if (!use_message && renew_authorship) die("--reset-author can be used only with -C, -c or --amend."); if (use_message) { - unsigned char sha1[20]; - static char utf8[] = "UTF-8"; const char *out_enc; - char *enc, *end; struct commit *commit; - if (get_sha1(use_message, sha1)) + commit = lookup_commit_reference_by_name(use_message); + if (!commit) die("could not lookup commit %s", use_message); - commit = lookup_commit_reference(sha1); - if (!commit || parse_commit(commit)) - die("could not parse commit %s", use_message); - - enc = strstr(commit->buffer, "\nencoding"); - if (enc) { - end = strchr(enc + 10, '\n'); - enc = xstrndup(enc + 10, end - (enc + 10)); - } else { - enc = utf8; - } - out_enc = git_commit_encoding ? git_commit_encoding : utf8; - - if (strcmp(out_enc, enc)) - use_message_buffer = - reencode_string(commit->buffer, out_enc, enc); + out_enc = get_commit_output_encoding(); + use_message_buffer = logmsg_reencode(commit, out_enc); /* * If we failed to reencode the buffer, just copy it @@ -929,8 +913,6 @@ static int parse_and_validate_options(int argc, const char *argv[], */ if (use_message_buffer == NULL) use_message_buffer = xstrdup(commit->buffer); - if (enc != utf8) - free(enc); } if (!!also + !!only + !!all + !!interactive > 1) -- cgit v1.2.3 From d71b8ba7c959e414d36974af890e3e2cbd2acbb9 Mon Sep 17 00:00:00 2001 From: Pat Notz Date: Tue, 2 Nov 2010 13:59:09 -0600 Subject: commit: --fixup option for use with rebase --autosquash This option makes it convenient to construct commit messages for use with 'rebase --autosquash'. The resulting commit message will be "fixup! ..." where "..." is the subject line of the specified commit message. Example usage: $ git commit --fixup HEAD~2 Signed-off-by: Pat Notz Signed-off-by: Junio C Hamano --- Documentation/git-commit.txt | 14 ++++++++++---- builtin/commit.c | 22 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'builtin/commit.c') diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 42fb1f57b2..f4a2b8c897 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -9,10 +9,10 @@ SYNOPSIS -------- [verse] 'git commit' [-a | --interactive] [-s] [-v] [-u] [--amend] [--dry-run] - [(-c | -C) ] [-F | -m ] [--reset-author] - [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=] - [--date=] [--cleanup=] [--status | --no-status] [--] - [[-i | -o ]...] + [(-c | -C | --fixup) ] [-F | -m ] + [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify] + [-e] [--author=] [--date=] [--cleanup=] + [--status | --no-status] [--] [[-i | -o ]...] DESCRIPTION ----------- @@ -70,6 +70,12 @@ OPTIONS Like '-C', but with '-c' the editor is invoked, so that the user can further edit the commit message. +--fixup=:: + Construct a commit message for use with `rebase --autosquash`. + The commit message will be the subject line from the specified + commit with a prefix of "fixup! ". See linkgit:git-rebase[1] + for details. + --reset-author:: When used with -C/-c/--amend options, declare that the authorship of the resulting commit now belongs of the committer. diff --git a/builtin/commit.c b/builtin/commit.c index 54fcc6d142..22498c6811 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -69,6 +69,7 @@ static enum { static const char *logfile, *force_author; static const char *template_file; static char *edit_message, *use_message; +static char *fixup_message; static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; @@ -124,6 +125,7 @@ static struct option builtin_commit_options[] = { OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m), OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"), OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"), + OPT_STRING(0, "fixup", &fixup_message, "COMMIT", "use autosquash formatted message to fixup specified commit"), OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"), OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"), OPT_FILENAME('t', "template", &template_file, "use specified template file"), @@ -586,6 +588,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix, strbuf_add(&sb, buffer + 2, strlen(buffer + 2)); hook_arg1 = "commit"; hook_arg2 = use_message; + } else if (fixup_message) { + struct pretty_print_context ctx = {0}; + struct commit *commit; + commit = lookup_commit_reference_by_name(fixup_message); + if (!commit) + die("could not lookup commit %s", fixup_message); + ctx.output_encoding = get_commit_output_encoding(); + format_commit_message(commit, "fixup! %s\n\n", + &sb, &ctx); + hook_arg1 = "message"; } else if (!stat(git_path("MERGE_MSG"), &statbuf)) { if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0) die_errno("could not read MERGE_MSG"); @@ -863,7 +875,7 @@ static int parse_and_validate_options(int argc, const char *argv[], if (force_author && renew_authorship) die("Using both --reset-author and --author does not make sense"); - if (logfile || message.len || use_message) + if (logfile || message.len || use_message || fixup_message) use_editor = 0; if (edit_flag) use_editor = 1; @@ -883,15 +895,17 @@ static int parse_and_validate_options(int argc, const char *argv[], f++; if (edit_message) f++; + if (fixup_message) + f++; if (logfile) f++; if (f > 1) - die("Only one of -c/-C/-F can be used."); + die("Only one of -c/-C/-F/--fixup can be used."); if (message.len && f > 0) - die("Option -m cannot be combined with -c/-C/-F."); + die("Option -m cannot be combined with -c/-C/-F/--fixup."); if (edit_message) use_message = edit_message; - if (amend && !use_message) + if (amend && !use_message && !fixup_message) use_message = "HEAD"; if (!use_message && renew_authorship) die("--reset-author can be used only with -C, -c or --amend."); -- cgit v1.2.3 From 89ac1223c08a19a83f6efb32234ed8665d5ad1ee Mon Sep 17 00:00:00 2001 From: Pat Notz Date: Tue, 2 Nov 2010 13:59:11 -0600 Subject: commit: --squash option for use with rebase --autosquash This option makes it convenient to construct commit messages for use with 'rebase --autosquash'. The resulting commit message will be "squash! ..." where "..." is the subject line of the specified commit message. This option can be used with other commit message options such as -m, -c, -C and -F. If an editor is invoked (as with -c or -eF or no message options) the commit message is seeded with the correctly formatted subject line. Example usage: $ git commit --squash HEAD~2 $ git commit --squash HEAD~2 -m "clever comment" $ git commit --squash HEAD~2 -F msgfile $ git commit --squash HEAD~2 -C deadbeef Signed-off-by: Pat Notz Signed-off-by: Junio C Hamano --- Documentation/git-commit.txt | 9 ++++++++- builtin/commit.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'builtin/commit.c') diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index f4a2b8c897..6e4c220f20 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git commit' [-a | --interactive] [-s] [-v] [-u] [--amend] [--dry-run] - [(-c | -C | --fixup) ] [-F | -m ] + [(-c | -C | --fixup | --squash) ] [-F | -m ] [--reset-author] [--allow-empty] [--allow-empty-message] [--no-verify] [-e] [--author=] [--date=] [--cleanup=] [--status | --no-status] [--] [[-i | -o ]...] @@ -76,6 +76,13 @@ OPTIONS commit with a prefix of "fixup! ". See linkgit:git-rebase[1] for details. +--squash=:: + Construct a commit message for use with `rebase --autosquash`. + The commit message subject line is taken from the specified + commit with a prefix of "squash! ". Can be used with additional + commit message options (`-m`/`-c`/`-C`/`-F`). See + linkgit:git-rebase[1] for details. + --reset-author:: When used with -C/-c/--amend options, declare that the authorship of the resulting commit now belongs of the committer. diff --git a/builtin/commit.c b/builtin/commit.c index 22498c6811..05c2c8129e 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -69,7 +69,7 @@ static enum { static const char *logfile, *force_author; static const char *template_file; static char *edit_message, *use_message; -static char *fixup_message; +static char *fixup_message, *squash_message; static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; @@ -126,6 +126,7 @@ static struct option builtin_commit_options[] = { OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"), OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"), OPT_STRING(0, "fixup", &fixup_message, "COMMIT", "use autosquash formatted message to fixup specified commit"), + OPT_STRING(0, "squash", &squash_message, "COMMIT", "use autosquash formatted message to squash specified commit"), OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"), OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"), OPT_FILENAME('t', "template", &template_file, "use specified template file"), @@ -567,6 +568,25 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (!no_verify && run_hook(index_file, "pre-commit", NULL)) return 0; + if (squash_message) { + /* + * Insert the proper subject line before other commit + * message options add their content. + */ + if (use_message && !strcmp(use_message, squash_message)) + strbuf_addstr(&sb, "squash! "); + else { + struct pretty_print_context ctx = {0}; + struct commit *c; + c = lookup_commit_reference_by_name(squash_message); + if (!c) + die("could not lookup commit %s", squash_message); + ctx.output_encoding = get_commit_output_encoding(); + format_commit_message(c, "squash! %s\n\n", &sb, + &ctx); + } + } + if (message.len) { strbuf_addbuf(&sb, &message); hook_arg1 = "message"; @@ -619,6 +639,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix, else if (in_merge) hook_arg1 = "merge"; + if (squash_message) { + /* + * If squash_commit was used for the commit subject, + * then we're possibly hijacking other commit log options. + * Reset the hook args to tell the real story. + */ + hook_arg1 = "message"; + hook_arg2 = ""; + } + fp = fopen(git_path(commit_editmsg), "w"); if (fp == NULL) die_errno("could not open '%s'", git_path(commit_editmsg)); @@ -890,7 +920,8 @@ static int parse_and_validate_options(int argc, const char *argv[], die("You have nothing to amend."); if (amend && in_merge) die("You are in the middle of a merge -- cannot amend."); - + if (fixup_message && squash_message) + die("Options --squash and --fixup cannot be used together"); if (use_message) f++; if (edit_message) -- cgit v1.2.3