diff options
-rw-r--r-- | Documentation/git-check-attr.txt | 5 | ||||
-rw-r--r-- | Documentation/git-commit.txt | 12 | ||||
-rw-r--r-- | Documentation/git-log.txt | 8 | ||||
-rw-r--r-- | Documentation/git-merge.txt | 3 | ||||
-rw-r--r-- | Documentation/git-rev-list.txt | 10 | ||||
-rw-r--r-- | Documentation/git-shortlog.txt | 19 | ||||
-rw-r--r-- | Documentation/gitattributes.txt | 37 | ||||
-rw-r--r-- | builtin-commit.c | 62 | ||||
-rw-r--r-- | combine-diff.c | 32 | ||||
-rw-r--r-- | config.c | 31 | ||||
-rwxr-xr-x | contrib/examples/git-revert.sh | 197 | ||||
-rw-r--r-- | diff.c | 12 | ||||
-rwxr-xr-x | git-cvsimport.perl | 1 | ||||
-rw-r--r-- | quote.c | 16 | ||||
-rw-r--r-- | quote.h | 1 | ||||
-rw-r--r-- | revision.c | 6 | ||||
-rwxr-xr-x | t/t1300-repo-config.sh | 17 | ||||
-rwxr-xr-x | t/t4202-log.sh | 74 | ||||
-rwxr-xr-x | t/t7005-editor.sh | 2 | ||||
-rwxr-xr-x | t/t7502-commit.sh | 65 |
20 files changed, 554 insertions, 56 deletions
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt index 856d2af2ed..47cb1bdfa3 100644 --- a/Documentation/git-check-attr.txt +++ b/Documentation/git-check-attr.txt @@ -23,6 +23,11 @@ OPTIONS be treated as an attribute. +SEE ALSO +-------- +gitlink:gitattributes[5]. + + Author ------ Written by Junio C Hamano <junkio@cox.net> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 4261384158..96383b6543 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -11,7 +11,7 @@ SYNOPSIS 'git-commit' [-a | --interactive] [-s] [-v] [-u] [(-c | -C) <commit> | -F <file> | -m <msg> | --amend] [--allow-empty] [--no-verify] [-e] [--author <author>] - [--] [[-i | -o ]<file>...] + [--cleanup=<mode>] [--] [[-i | -o ]<file>...] DESCRIPTION ----------- @@ -95,6 +95,16 @@ OPTIONS from making such a commit. This option bypasses the safety, and is primarily for use by foreign scm interface scripts. +--cleanup=<mode>:: + This option sets how the commit message is cleaned up. + The '<mode>' can be one of 'verbatim', 'whitespace', 'strip', + and 'default'. The 'default' mode will strip leading and + trailing empty lines and #commentary from the commit message + only if the message is to be edited. Otherwise only whitespace + removed. The 'verbatim' mode does not change message at all, + 'whitespace' removes just leading/trailing whitespace lines + and 'strip' removes both whitespace and commentary. + -e|--edit:: The message taken from file with `-F`, command line with `-m`, and from file with `-C` are usually used as the diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 5920d1799a..d71e51ad46 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -43,8 +43,12 @@ include::diff-options.txt[] --first-parent:: Follow only the first parent commit upon seeing a merge - commit. This option gives a better overview of the - evolution of a particular branch. + commit. This option can give a better overview when + viewing the evolution of a particular topic branch, + because merges into a topic branch tend to be only about + adjusting to updated upstream from time to time, and + this option allows you to ignore the individual commits + brought in to your history by such a merge. -g, \--walk-reflogs:: Show commits as they were recorded in the reflog. The log contains diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index eabd7ef33f..1521a9ee0f 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -163,7 +163,8 @@ After seeing a conflict, you can do two things: SEE ALSO -------- -gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1] +gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1], +gitlink:gitattributes[5] Author diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index a03f9fe5fa..438dae02e2 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -15,6 +15,7 @@ SYNOPSIS [ \--min-age=timestamp ] [ \--sparse ] [ \--no-merges ] + [ \--first-parent ] [ \--remove-empty ] [ \--full-history ] [ \--not ] @@ -256,6 +257,15 @@ limiting may be applied. Do not print commits with more than one parent. +--first-parent:: + Follow only the first parent commit upon seeing a merge + commit. This option can give a better overview when + viewing the evolution of a particular topic branch, + because merges into a topic branch tend to be only about + adjusting to updated upstream from time to time, and + this option allows you to ignore the individual commits + brought in to your history by such a merge. + --not:: Reverses the meaning of the '{caret}' prefix (or lack thereof) diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index e14720b73f..36510a8451 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -38,15 +38,16 @@ OPTIONS FILES ----- -.mailmap:: - If this file exists, it will be used for mapping author email - addresses to a real author name. One mapping per line, first - the author name followed by the email address enclosed by - '<' and '>'. Use hash '#' for comments. Example: - - # Keep alphabetized - Adam Morrow <adam@localhost.localdomain> - Eve Jones <eve@laptop.(none)> +If the file `.mailmap` exists, it will be used for mapping author +email addresses to a real author name. One mapping per line, first +the author name followed by the email address enclosed by +'<' and '>'. Use hash '#' for comments. Example: + +------------ +# Keep alphabetized +Adam Morrow <adam@localhost.localdomain> +Eve Jones <eve@laptop.(none)> +------------ Author ------ diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 71c7ad76d5..cc9c7c52c0 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -322,12 +322,43 @@ String:: requested with "binary". +Built-in merge drivers +^^^^^^^^^^^^^^^^^^^^^^ + +There are a few built-in low-level merge drivers defined that +can be asked for via the `merge` attribute. + +text:: + + Usual 3-way file level merge for text files. Conflicted + regions are marked with conflict markers `<<<<<<<`, + `=======` and `>>>>>>>`. The version from your branch + appears before the `=======` marker, and the version + from the merged branch appears after the `=======` + marker. + +binary:: + + Keep the version from your branch in the work tree, but + leave the path in the conflicted state for the user to + sort out. + +union:: + + Run 3-way file level merge for text files, but take + lines from both versions, instead of leaving conflict + markers. This tends to leave the added lines in the + resulting file in random order and the user should + verify the result. Do not use this if you do not + understand the implications. + + Defining a custom merge driver ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The definition of a merge driver is done in `gitconfig` not -`gitattributes` file, so strictly speaking this manual page is a -wrong place to talk about it. However... +The definition of a merge driver is done in the `.git/config` +file, not in the `gitattributes` file, so strictly speaking this +manual page is a wrong place to talk about it. However... To define a custom merge driver `filfre`, add a section to your `$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this: diff --git a/builtin-commit.c b/builtin-commit.c index 96410de55d..73f1e3576a 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -47,8 +47,21 @@ static char *logfile, *force_author, *template_file; static char *edit_message, *use_message; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, untracked_files, no_verify, allow_empty; +/* + * The default commit message cleanup mode will remove the lines + * beginning with # (shell comments) and leading and trailing + * whitespaces (empty lines or containing only whitespaces) + * if editor is used, and only the whitespaces if the message + * is specified explicitly. + */ +static enum { + CLEANUP_SPACE, + CLEANUP_NONE, + CLEANUP_ALL, +} cleanup_mode; +static char *cleanup_arg; -static int no_edit, initial_commit, in_merge; +static int use_editor = 1, initial_commit, in_merge; const char *only_include_assumed; struct strbuf message; @@ -88,6 +101,7 @@ static struct option builtin_commit_options[] = { OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), OPT_BOOLEAN(0, "untracked-files", &untracked_files, "show all untracked files"), OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"), + OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"), OPT_END() }; @@ -346,7 +360,8 @@ static int prepare_log_message(const char *index_file, const char *prefix) if (fp == NULL) die("could not open %s", git_path(commit_editmsg)); - stripspace(&sb, 0); + if (cleanup_mode != CLEANUP_NONE) + stripspace(&sb, 0); if (signoff) { struct strbuf sob; @@ -372,9 +387,9 @@ static int prepare_log_message(const char *index_file, const char *prefix) strbuf_release(&sb); - if (no_edit) { + if (!use_editor) { struct rev_info rev; - unsigned char sha1[40]; + unsigned char sha1[20]; const char *parent = "HEAD"; fclose(fp); @@ -382,12 +397,12 @@ static int prepare_log_message(const char *index_file, const char *prefix) if (!active_nr && read_cache() < 0) die("Cannot read index"); - if (get_sha1("HEAD", sha1) != 0) - return !!active_nr; - if (amend) parent = "HEAD^1"; + if (get_sha1(parent, sha1)) + return !!active_nr; + init_revisions(&rev, ""); rev.abbrev = 0; setup_revisions(0, NULL, &rev, parent); @@ -398,7 +413,7 @@ static int prepare_log_message(const char *index_file, const char *prefix) return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES); } - if (in_merge && !no_edit) + if (in_merge) fprintf(fp, "#\n" "# It looks like you may be committing a MERGE.\n" @@ -411,7 +426,12 @@ static int prepare_log_message(const char *index_file, const char *prefix) fprintf(fp, "\n" "# Please enter the commit message for your changes.\n" - "# (Comment lines starting with '#' will not be included)\n"); + "# (Comment lines starting with '#' will "); + if (cleanup_mode == CLEANUP_ALL) + fprintf(fp, "not be included)\n"); + else /* CLEANUP_SPACE, that is. */ + fprintf(fp, "be kept.\n" + "# You can remove them yourself if you want to)\n"); if (only_include_assumed) fprintf(fp, "# %s\n", only_include_assumed); @@ -435,10 +455,13 @@ static int message_is_empty(struct strbuf *sb, int start) const char *nl; int eol, i; + if (cleanup_mode == CLEANUP_NONE && sb->len) + return 0; + /* See if the template is just a prefix of the message. */ strbuf_init(&tmpl, 0); if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) { - stripspace(&tmpl, 1); + stripspace(&tmpl, cleanup_mode == CLEANUP_ALL); if (start + tmpl.len <= sb->len && memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0) start += tmpl.len; @@ -513,9 +536,9 @@ static int parse_and_validate_options(int argc, const char *argv[], argc = parse_options(argc, argv, builtin_commit_options, usage, 0); if (logfile || message.len || use_message) - no_edit = 1; + use_editor = 0; if (edit_flag) - no_edit = 0; + use_editor = 1; if (get_sha1("HEAD", head_sha1)) initial_commit = 1; @@ -591,6 +614,16 @@ static int parse_and_validate_options(int argc, const char *argv[], only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths..."; also = 0; } + if (!cleanup_arg || !strcmp(cleanup_arg, "default")) + cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE; + else if (!strcmp(cleanup_arg, "verbatim")) + cleanup_mode = CLEANUP_NONE; + else if (!strcmp(cleanup_arg, "whitespace")) + cleanup_mode = CLEANUP_SPACE; + else if (!strcmp(cleanup_arg, "strip")) + cleanup_mode = CLEANUP_ALL; + else + die("Invalid cleanup mode %s", cleanup_arg); if (all && argc > 0) die("Paths with -a does not make sense."); @@ -796,7 +829,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) /* Get the commit message and validate it */ header_len = sb.len; - if (!no_edit) { + if (use_editor) { char index[PATH_MAX]; const char *env[2] = { index, NULL }; snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file); @@ -817,7 +850,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (p != NULL) strbuf_setlen(&sb, p - sb.buf + 1); - stripspace(&sb, 1); + if (cleanup_mode != CLEANUP_NONE) + stripspace(&sb, cleanup_mode == CLEANUP_ALL); if (sb.len < header_len || message_is_empty(&sb, header_len)) { rollback_index_files(); die("no commit message? aborting commit."); diff --git a/combine-diff.c b/combine-diff.c index e22db89932..0e19cbaacc 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -646,12 +646,19 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt, sline->p_lno[i] = sline->p_lno[j]; } -static void dump_quoted_path(const char *prefix, const char *path, +static void dump_quoted_path(const char *head, + const char *prefix, + const char *path, const char *c_meta, const char *c_reset) { - printf("%s%s", c_meta, prefix); - quote_c_style(path, NULL, stdout, 0); - printf("%s\n", c_reset); + static struct strbuf buf = STRBUF_INIT; + + strbuf_reset(&buf); + strbuf_addstr(&buf, c_meta); + strbuf_addstr(&buf, head); + quote_two_c_style(&buf, prefix, path, 0); + strbuf_addstr(&buf, c_reset); + puts(buf.buf); } static void show_patch_diff(struct combine_diff_path *elem, int num_parent, @@ -793,7 +800,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, if (rev->loginfo && !rev->no_commit_id) show_log(rev, opt->msg_sep); dump_quoted_path(dense ? "diff --cc " : "diff --combined ", - elem->path, c_meta, c_reset); + "", elem->path, c_meta, c_reset); printf("%sindex ", c_meta); for (i = 0; i < num_parent; i++) { abb = find_unique_abbrev(elem->parent[i].sha1, @@ -829,14 +836,19 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, printf("%s\n", c_reset); } if (added) - dump_quoted_path("--- /dev/", "null", c_meta, c_reset); + dump_quoted_path("--- ", "", "/dev/null", + c_meta, c_reset); else - dump_quoted_path("--- a/", elem->path, c_meta, c_reset); + dump_quoted_path("--- ", opt->a_prefix, elem->path, + c_meta, c_reset); if (deleted) - dump_quoted_path("+++ /dev/", "null", c_meta, c_reset); + dump_quoted_path("+++ ", "", "/dev/null", + c_meta, c_reset); else - dump_quoted_path("+++ b/", elem->path, c_meta, c_reset); - dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF)); + dump_quoted_path("+++ ", opt->b_prefix, elem->path, + c_meta, c_reset); + dump_sline(sline, cnt, num_parent, + DIFF_OPT_TST(opt, COLOR_DIFF)); } free(result); @@ -234,17 +234,23 @@ static int git_parse_file(config_fn_t fn) die("bad config file line %d in %s", config_linenr, config_file_name); } -static unsigned long get_unit_factor(const char *end) +static int parse_unit_factor(const char *end, unsigned long *val) { if (!*end) return 1; - else if (!strcasecmp(end, "k")) - return 1024; - else if (!strcasecmp(end, "m")) - return 1024 * 1024; - else if (!strcasecmp(end, "g")) - return 1024 * 1024 * 1024; - die("unknown unit: '%s'", end); + else if (!strcasecmp(end, "k")) { + *val *= 1024; + return 1; + } + else if (!strcasecmp(end, "m")) { + *val *= 1024 * 1024; + return 1; + } + else if (!strcasecmp(end, "g")) { + *val *= 1024 * 1024 * 1024; + return 1; + } + return 0; } int git_parse_long(const char *value, long *ret) @@ -252,7 +258,10 @@ int git_parse_long(const char *value, long *ret) if (value && *value) { char *end; long val = strtol(value, &end, 0); - *ret = val * get_unit_factor(end); + unsigned long factor = 1; + if (!parse_unit_factor(end, &factor)) + return 0; + *ret = val * factor; return 1; } return 0; @@ -263,7 +272,9 @@ int git_parse_ulong(const char *value, unsigned long *ret) if (value && *value) { char *end; unsigned long val = strtoul(value, &end, 0); - *ret = val * get_unit_factor(end); + if (!parse_unit_factor(end, &val)) + return 0; + *ret = val; return 1; } return 0; diff --git a/contrib/examples/git-revert.sh b/contrib/examples/git-revert.sh new file mode 100755 index 0000000000..49f00321b2 --- /dev/null +++ b/contrib/examples/git-revert.sh @@ -0,0 +1,197 @@ +#!/bin/sh +# +# Copyright (c) 2005 Linus Torvalds +# Copyright (c) 2005 Junio C Hamano +# + +case "$0" in +*-revert* ) + test -t 0 && edit=-e + replay= + me=revert + USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;; +*-cherry-pick* ) + replay=t + edit= + me=cherry-pick + USAGE='[--edit] [-n] [-r] [-x] <commit-ish>' ;; +* ) + echo >&2 "What are you talking about?" + exit 1 ;; +esac + +SUBDIRECTORY_OK=Yes ;# we will cd up +. git-sh-setup +require_work_tree +cd_to_toplevel + +no_commit= +while case "$#" in 0) break ;; esac +do + case "$1" in + -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\ + --no-commi|--no-commit) + no_commit=t + ;; + -e|--e|--ed|--edi|--edit) + edit=-e + ;; + --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit) + edit= + ;; + -r) + : no-op ;; + -x|--i-really-want-to-expose-my-private-commit-object-name) + replay= + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift +done + +set_reflog_action "$me" + +test "$me,$replay" = "revert,t" && usage + +case "$no_commit" in +t) + # We do not intend to commit immediately. We just want to + # merge the differences in. + head=$(git-write-tree) || + die "Your index file is unmerged." + ;; +*) + head=$(git-rev-parse --verify HEAD) || + die "You do not have a valid HEAD" + files=$(git-diff-index --cached --name-only $head) || exit + if [ "$files" ]; then + die "Dirty index: cannot $me (dirty: $files)" + fi + ;; +esac + +rev=$(git-rev-parse --verify "$@") && +commit=$(git-rev-parse --verify "$rev^0") || + die "Not a single commit $@" +prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) || + die "Cannot run $me a root commit" +git-rev-parse --verify "$commit^2" >/dev/null 2>&1 && + die "Cannot run $me a multi-parent commit." + +encoding=$(git config i18n.commitencoding || echo UTF-8) + +# "commit" is an existing commit. We would want to apply +# the difference it introduces since its first parent "prev" +# on top of the current HEAD if we are cherry-pick. Or the +# reverse of it if we are revert. + +case "$me" in +revert) + git show -s --pretty=oneline --encoding="$encoding" $commit | + sed -e ' + s/^[^ ]* /Revert "/ + s/$/"/ + ' + echo + echo "This reverts commit $commit." + test "$rev" = "$commit" || + echo "(original 'git revert' arguments: $@)" + base=$commit next=$prev + ;; + +cherry-pick) + pick_author_script=' + /^author /{ + s/'\''/'\''\\'\'\''/g + h + s/^author \([^<]*\) <[^>]*> .*$/\1/ + s/'\''/'\''\'\'\''/g + s/.*/GIT_AUTHOR_NAME='\''&'\''/p + + g + s/^author [^<]* <\([^>]*\)> .*$/\1/ + s/'\''/'\''\'\'\''/g + s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p + + g + s/^author [^<]* <[^>]*> \(.*\)$/\1/ + s/'\''/'\''\'\'\''/g + s/.*/GIT_AUTHOR_DATE='\''&'\''/p + + q + }' + + logmsg=`git show -s --pretty=raw --encoding="$encoding" "$commit"` + set_author_env=`echo "$logmsg" | + LANG=C LC_ALL=C sed -ne "$pick_author_script"` + eval "$set_author_env" + export GIT_AUTHOR_NAME + export GIT_AUTHOR_EMAIL + export GIT_AUTHOR_DATE + + echo "$logmsg" | + sed -e '1,/^$/d' -e 's/^ //' + case "$replay" in + '') + echo "(cherry picked from commit $commit)" + test "$rev" = "$commit" || + echo "(original 'git cherry-pick' arguments: $@)" + ;; + esac + base=$prev next=$commit + ;; + +esac >.msg + +eval GITHEAD_$head=HEAD +eval GITHEAD_$next='`git show -s \ + --pretty=oneline --encoding="$encoding" "$commit" | + sed -e "s/^[^ ]* //"`' +export GITHEAD_$head GITHEAD_$next + +# This three way merge is an interesting one. We are at +# $head, and would want to apply the change between $commit +# and $prev on top of us (when reverting), or the change between +# $prev and $commit on top of us (when cherry-picking or replaying). + +git-merge-recursive $base -- $head $next && +result=$(git-write-tree 2>/dev/null) || { + mv -f .msg "$GIT_DIR/MERGE_MSG" + { + echo ' +Conflicts: +' + git ls-files --unmerged | + sed -e 's/^[^ ]* / /' | + uniq + } >>"$GIT_DIR/MERGE_MSG" + echo >&2 "Automatic $me failed. After resolving the conflicts," + echo >&2 "mark the corrected paths with 'git-add <paths>'" + echo >&2 "and commit the result." + case "$me" in + cherry-pick) + echo >&2 "You may choose to use the following when making" + echo >&2 "the commit:" + echo >&2 "$set_author_env" + esac + exit 1 +} +echo >&2 "Finished one $me." + +# If we are cherry-pick, and if the merge did not result in +# hand-editing, we will hit this commit and inherit the original +# author date and name. +# If we are revert, or if our cherry-pick results in a hand merge, +# we had better say that the current user is responsible for that. + +case "$no_commit" in +'') + git-commit -n -F .msg $edit + rm -f .msg + ;; +esac @@ -300,19 +300,25 @@ static void emit_rewrite_diff(const char *name_a, const char *old = diff_get_color(color_diff, DIFF_FILE_OLD); const char *new = diff_get_color(color_diff, DIFF_FILE_NEW); const char *reset = diff_get_color(color_diff, DIFF_RESET); + static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT; name_a += (*name_a == '/'); name_b += (*name_b == '/'); name_a_tab = strchr(name_a, ' ') ? "\t" : ""; name_b_tab = strchr(name_b, ' ') ? "\t" : ""; + strbuf_reset(&a_name); + strbuf_reset(&b_name); + quote_two_c_style(&a_name, o->a_prefix, name_a, 0); + quote_two_c_style(&b_name, o->b_prefix, name_b, 0); + diff_populate_filespec(one, 0); diff_populate_filespec(two, 0); lc_a = count_lines(one->data, one->size); lc_b = count_lines(two->data, two->size); - printf("%s--- %s%s%s%s\n%s+++ %s%s%s%s\n%s@@ -", - metainfo, o->a_prefix, name_a, name_a_tab, reset, - metainfo, o->b_prefix, name_b, name_b_tab, reset, fraginfo); + printf("%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -", + metainfo, a_name.buf, name_a_tab, reset, + metainfo, b_name.buf, name_b_tab, reset, fraginfo); print_line_count(lc_a); printf(" +"); print_line_count(lc_b); diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 1fa9a22376..6d8ff93f5f 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -632,6 +632,7 @@ unless ($opt_P) { print $cvspsfh $_; } close CVSPS; + $? == 0 or die "git-cvsimport: fatal: cvsps reported error\n"; close $cvspsfh; } else { $cvspsfile = $opt_P; @@ -213,6 +213,22 @@ size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) return quote_c_style_counted(name, -1, sb, fp, nodq); } +void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq) +{ + if (quote_c_style(prefix, NULL, NULL, 0) || + quote_c_style(path, NULL, NULL, 0)) { + if (!nodq) + strbuf_addch(sb, '"'); + quote_c_style(prefix, sb, NULL, 1); + quote_c_style(path, sb, NULL, 1); + if (!nodq) + strbuf_addch(sb, '"'); + } else { + strbuf_addstr(sb, prefix); + strbuf_addstr(sb, path); + } +} + void write_name_quoted(const char *name, FILE *fp, int terminator) { if (terminator) { @@ -41,6 +41,7 @@ extern char *sq_dequote(char *); extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq); +extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); extern void write_name_quoted(const char *name, FILE *, int terminator); extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, diff --git a/revision.c b/revision.c index 7e2f4f1eb5..6e85aaa3fb 100644 --- a/revision.c +++ b/revision.c @@ -1290,8 +1290,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) revs->diff = 1; - /* Pickaxe and rename following needs diffs */ - if (revs->diffopt.pickaxe || DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES)) + /* Pickaxe, diff-filter and rename following need diffs */ + if (revs->diffopt.pickaxe || + revs->diffopt.filter || + DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES)) revs->diff = 1; if (revs->topo_order) diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index e894629e7e..42eac2a7cb 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -448,6 +448,23 @@ test_expect_success numbers ' test z1048576 = "z$m" ' +cat > expect <<EOF +fatal: bad config value for 'aninvalid.unit' in .git/config +EOF + +test_expect_success 'invalid unit' ' + + git config aninvalid.unit "1auto" && + s=$(git config aninvalid.unit) && + test "z1auto" = "z$s" && + if git config --int --get aninvalid.unit 2>actual + then + echo config should have failed + false + fi && + cmp actual expect +' + cat > expect << EOF true false diff --git a/t/t4202-log.sh b/t/t4202-log.sh new file mode 100755 index 0000000000..b53645417b --- /dev/null +++ b/t/t4202-log.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +test_description='git log' + +. ./test-lib.sh + +test_expect_success setup ' + + echo one >one && + git add one && + test_tick && + git commit -m initial && + + echo ichi >one && + git add one && + test_tick && + git commit -m second && + + mkdir a && + echo ni >a/two && + git add a/two && + test_tick && + git commit -m third && + + echo san >a/three && + git add a/three && + test_tick && + git commit -m fourth && + + git rm a/three && + test_tick && + git commit -m fifth + +' + +test_expect_success 'diff-filter=A' ' + + actual=$(git log --pretty="format:%s" --diff-filter=A HEAD) && + expect=$(echo fourth ; echo third ; echo initial) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'diff-filter=M' ' + + actual=$(git log --pretty="format:%s" --diff-filter=M HEAD) && + expect=$(echo second) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + +test_expect_success 'diff-filter=D' ' + + actual=$(git log --pretty="format:%s" --diff-filter=D HEAD) && + expect=$(echo fifth) && + test "$actual" = "$expect" || { + echo Oops + echo "Actual: $actual" + false + } + +' + + + +test_done
\ No newline at end of file diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 44228b5ac1..c1cec55306 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -37,7 +37,7 @@ test_expect_success 'dumb should error out when falling back on vi' ' if git commit --amend then echo "Oops?" - exit 1 + false else : happy fi diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 21ac785e3d..aaf497e6a5 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -89,4 +89,69 @@ test_expect_success 'verbose' ' ' +test_expect_success 'cleanup commit messages (verbatim,-t)' ' + + echo >>negative && + { echo;echo "# text";echo; } >expect && + git commit --cleanup=verbatim -t expect -a && + git cat-file -p HEAD |sed -e "1,/^\$/d" |head -n 3 >actual && + diff -u expect actual + +' + +test_expect_success 'cleanup commit messages (verbatim,-F)' ' + + echo >>negative && + git commit --cleanup=verbatim -F expect -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + diff -u expect actual + +' + +test_expect_success 'cleanup commit messages (verbatim,-m)' ' + + echo >>negative && + git commit --cleanup=verbatim -m "$(cat expect)" -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + diff -u expect actual + +' + +test_expect_success 'cleanup commit messages (whitespace,-F)' ' + + echo >>negative && + { echo;echo "# text";echo; } >text && + echo "# text" >expect && + git commit --cleanup=whitespace -F text -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + diff -u expect actual + +' + +test_expect_success 'cleanup commit messages (strip,-F)' ' + + echo >>negative && + { echo;echo "# text";echo sample;echo; } >text && + echo sample >expect && + git commit --cleanup=strip -F text -a && + git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + diff -u expect actual + +' + +echo "sample + +# Please enter the commit message for your changes. +# (Comment lines starting with '#' will not be included)" >expect + +test_expect_success 'cleanup commit messages (strip,-F,-e)' ' + + echo >>negative && + { echo;echo sample;echo; } >text && + git commit -e -F text -a && + head -n 4 .git/COMMIT_EDITMSG >actual && + diff -u expect actual + +' + test_done |