diff options
-rw-r--r-- | Documentation/RelNotes/1.7.3.txt | 12 | ||||
-rw-r--r-- | Documentation/config.txt | 14 | ||||
-rw-r--r-- | Documentation/git.txt | 7 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | builtin.h | 2 | ||||
-rw-r--r-- | builtin/fast-export.c | 10 | ||||
-rw-r--r-- | builtin/fetch.c | 7 | ||||
-rw-r--r-- | builtin/notes.c | 14 | ||||
-rw-r--r-- | cache.h | 6 | ||||
-rw-r--r-- | config.c | 60 | ||||
-rw-r--r-- | connect.c | 7 | ||||
-rw-r--r-- | diff.c | 5 | ||||
-rw-r--r-- | environment.c | 2 | ||||
-rw-r--r-- | git.c | 8 | ||||
-rw-r--r-- | help.h | 19 | ||||
-rw-r--r-- | notes.c | 14 | ||||
-rw-r--r-- | notes.h | 4 | ||||
-rwxr-xr-x | t/t3301-notes.sh | 7 | ||||
-rwxr-xr-x | t/t4018-diff-funcname.sh | 9 | ||||
-rwxr-xr-x | t/t5400-send-pack.sh | 23 | ||||
-rwxr-xr-x | t/t5510-fetch.sh | 32 | ||||
-rwxr-xr-x | t/t7008-grep-binary.sh | 14 | ||||
-rw-r--r-- | t/test-lib.sh | 23 | ||||
-rw-r--r-- | xdiff-interface.c | 5 |
24 files changed, 255 insertions, 51 deletions
diff --git a/Documentation/RelNotes/1.7.3.txt b/Documentation/RelNotes/1.7.3.txt index 3512bbb238..f1243ff112 100644 --- a/Documentation/RelNotes/1.7.3.txt +++ b/Documentation/RelNotes/1.7.3.txt @@ -60,11 +60,19 @@ release, unless otherwise noted. * "git fetch" and friends were accidentally broken for url with "+" in its path, e.g. "git://git.gnome.org/gtk+". + * "git fetch $url" (i.e. without refspecs) was broken for quite some + time, if the current branch happen to be tracking some remote. + + * "git note remove" created unnecessary extra commit when named object + did not have any note to begin with. + + * "git -c foo=bar subcmd" did not work well for subcmd that is not + implemented as a built-in command. + --- exec >/var/tmp/1 echo O=$(git describe master) -O=v1.7.2.2-268-g7e42332 -O=v1.7.2 +O=v1.7.3-rc0 git shortlog --no-merges $O..master ^maint exit 0 diff --git a/Documentation/config.txt b/Documentation/config.txt index cda6721013..d82c0da2cf 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -450,6 +450,15 @@ core.excludesfile:: to the value of `$HOME` and "{tilde}user/" to the specified user's home directory. See linkgit:gitignore[5]. +core.askpass:: + Some commands (e.g. svn and http interfaces) that interactively + ask for a password can be told to use an external program given + via the value of this variable. Can be overridden by the 'GIT_ASKPASS' + environment variable. If not set, fall back to the value of the + 'SSH_ASKPASS' environment variable or, failing that, a simple password + prompt. The external program shall be given a suitable prompt as + command line argument and write the password on its STDOUT. + core.editor:: Commands such as `commit` and `tag` that lets you edit messages by launching an editor uses the value of this @@ -804,8 +813,6 @@ diff.mnemonicprefix:: standard "a/" and "b/" depending on what is being compared. When this configuration is in effect, reverse diff output also swaps the order of the prefixes: -diff.noprefix:: - If set, 'git diff' does not show any source or destination prefix. `git diff`;; compares the (i)ndex and the (w)ork tree; `git diff HEAD`;; @@ -817,6 +824,9 @@ diff.noprefix:: `git diff --no-index a b`;; compares two non-git things (1) and (2). +diff.noprefix:: + If set, 'git diff' does not show any source or destination prefix. + diff.renameLimit:: The number of files to consider when performing the copy/rename detection; equivalent to the 'git diff' option '-l'. diff --git a/Documentation/git.txt b/Documentation/git.txt index d9988f167c..69ef12e272 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -639,6 +639,13 @@ Usually it is easier to configure any desired options through your personal `.ssh/config` file. Please consult your ssh documentation for further details. +'GIT_ASKPASS':: + If this environment variable is set, then git commands which need to + acquire passwords or passphrases (e.g. for HTTP or IMAP authentication) + will call this program with a suitable prompt as command line argument + and read the password from its STDOUT. See also the 'core.askpass' + option in linkgit:git-config[1]. + 'GIT_FLUSH':: If this environment variable is set to "1", then commands such as 'git blame' (in incremental mode), 'git rev-list', 'git log', @@ -982,6 +982,7 @@ ifeq ($(uname_S),IRIX) # NO_MMAP. If you suspect that your compiler is not affected by this # issue, comment out the NO_MMAP statement. NO_MMAP = YesPlease + NO_REGEX = YesPlease SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH = /usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease @@ -1000,6 +1001,7 @@ ifeq ($(uname_S),IRIX64) # NO_MMAP. If you suspect that your compiler is not affected by this # issue, comment out the NO_MMAP statement. NO_MMAP = YesPlease + NO_REGEX = YesPlease SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH=/usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease @@ -11,8 +11,6 @@ extern const char git_version_string[]; extern const char git_usage_string[]; extern const char git_more_info_string[]; -extern void list_common_cmds_help(void); -extern const char *help_unknown_cmd(const char *cmd); extern void prune_packed_objects(int); extern int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out); diff --git a/builtin/fast-export.c b/builtin/fast-export.c index a9bbf8653d..c8fd46b872 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -167,7 +167,15 @@ static int depth_first(const void *a_, const void *b_) cmp = memcmp(name_a, name_b, len); if (cmp) return cmp; - return (len_b - len_a); + cmp = len_b - len_a; + if (cmp) + return cmp; + /* + * Move 'R'ename entries last so that all references of the file + * appear in the output before it is renamed (e.g., when a file + * was copied and renamed in the same commit). + */ + return (a->status == 'R') - (b->status == 'R'); } static void show_filemodify(struct diff_queue_struct *q, diff --git a/builtin/fetch.c b/builtin/fetch.c index fab3fce512..6fc5047703 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -146,7 +146,10 @@ static struct ref *get_ref_map(struct transport *transport, struct remote *remote = transport->remote; struct branch *branch = branch_get(NULL); int has_merge = branch_has_merge_config(branch); - if (remote && (remote->fetch_refspec_nr || has_merge)) { + if (remote && + (remote->fetch_refspec_nr || + /* Note: has_merge implies non-NULL branch->remote_name */ + (has_merge && !strcmp(branch->remote_name, remote->name)))) { for (i = 0; i < remote->fetch_refspec_nr; i++) { get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0); if (remote->fetch[i].dst && @@ -160,6 +163,8 @@ static struct ref *get_ref_map(struct transport *transport, * if the remote we're fetching from is the same * as given in branch.<name>.remote, we add the * ref given in branch.<name>.merge, too. + * + * Note: has_merge implies non-NULL branch->remote_name */ if (has_merge && !strcmp(branch->remote_name, remote->name)) diff --git a/builtin/notes.c b/builtin/notes.c index fbc347c9f0..6d07aac80c 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -769,6 +769,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) const char *object_ref; struct notes_tree *t; unsigned char object[20]; + int retval; argc = parse_options(argc, argv, prefix, options, git_notes_remove_usage, 0); @@ -785,12 +786,17 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) t = init_notes_check("remove"); - fprintf(stderr, "Removing note for object %s\n", sha1_to_hex(object)); - remove_note(t, object); + retval = remove_note(t, object); + if (retval) + fprintf(stderr, "Object %s has no note\n", sha1_to_hex(object)); + else { + fprintf(stderr, "Removing note for object %s\n", + sha1_to_hex(object)); - commit_notes(t, "Notes removed by 'git notes remove'"); + commit_notes(t, "Notes removed by 'git notes remove'"); + } free_notes(t); - return 0; + return retval; } static int prune(int argc, const char **argv, const char *prefix) @@ -378,6 +378,7 @@ static inline enum object_type object_type(unsigned int mode) #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE" #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR" #define CONFIG_ENVIRONMENT "GIT_CONFIG" +#define CONFIG_DATA_ENVIRONMENT "GIT_CONFIG_PARAMETERS" #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" @@ -396,7 +397,7 @@ static inline enum object_type object_type(unsigned int mode) * environment creation or simple walk of the list. * The number of non-NULL entries is available as a macro. */ -#define LOCAL_REPO_ENV_SIZE 8 +#define LOCAL_REPO_ENV_SIZE 9 extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1]; extern int is_bare_repository_cfg; @@ -973,7 +974,9 @@ extern int update_server_info(int); typedef int (*config_fn_t)(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); +extern void git_config_push_parameter(const char *text); extern int git_config_parse_parameter(const char *text); +extern int git_config_parse_environment(void); extern int git_config_from_parameters(config_fn_t fn, void *data); extern int git_config(config_fn_t fn, void *); extern int git_parse_ulong(const char *, unsigned long *); @@ -1032,6 +1035,7 @@ extern int pager_in_use(void); extern int pager_use_color; extern const char *editor_program; +extern const char *askpass_program; extern const char *excludes_file; /* base85 */ @@ -8,6 +8,7 @@ #include "cache.h" #include "exec_cmd.h" #include "strbuf.h" +#include "quote.h" #define MAXNAME (256) @@ -34,6 +35,19 @@ static void lowercase(char *p) *p = tolower(*p); } +void git_config_push_parameter(const char *text) +{ + struct strbuf env = STRBUF_INIT; + const char *old = getenv(CONFIG_DATA_ENVIRONMENT); + if (old) { + strbuf_addstr(&env, old); + strbuf_addch(&env, ' '); + } + sq_quote_buf(&env, text); + setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1); + strbuf_release(&env); +} + int git_config_parse_parameter(const char *text) { struct config_item *ct; @@ -61,6 +75,37 @@ int git_config_parse_parameter(const char *text) return 0; } +int git_config_parse_environment(void) { + const char *env = getenv(CONFIG_DATA_ENVIRONMENT); + char *envw; + const char **argv = NULL; + int nr = 0, alloc = 0; + int i; + + if (!env) + return 0; + /* sq_dequote will write over it */ + envw = xstrdup(env); + + if (sq_dequote_to_argv(envw, &argv, &nr, &alloc) < 0) { + free(envw); + return error("bogus format in " CONFIG_DATA_ENVIRONMENT); + } + + for (i = 0; i < nr; i++) { + if (git_config_parse_parameter(argv[i]) < 0) { + error("bogus config parameter: %s", argv[i]); + free(argv); + free(envw); + return -1; + } + } + + free(argv); + free(envw); + return 0; +} + static int get_next_char(void) { int c; @@ -560,6 +605,9 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.editor")) return git_config_string(&editor_program, var, value); + if (!strcmp(var, "core.askpass")) + return git_config_string(&askpass_program, var, value); + if (!strcmp(var, "core.excludesfile")) return git_config_pathname(&excludes_file, var, value); @@ -773,7 +821,14 @@ int git_config_global(void) int git_config_from_parameters(config_fn_t fn, void *data) { + static int loaded_environment; const struct config_item *ct; + + if (!loaded_environment) { + if (git_config_parse_environment() < 0) + return -1; + loaded_environment = 1; + } for (ct = config_parameters; ct; ct = ct->next) if (fn(ct->name, ct->value, data) < 0) return -1; @@ -812,10 +867,9 @@ int git_config(config_fn_t fn, void *data) } free(repo_config); - if (config_parameters) { - ret += git_config_from_parameters(fn, data); + ret += git_config_from_parameters(fn, data); + if (config_parameters) found += 1; - } if (found == 0) return -1; @@ -621,13 +621,16 @@ int finish_connect(struct child_process *conn) char *git_getpass(const char *prompt) { - char *askpass; + const char *askpass; struct child_process pass; const char *args[3]; static struct strbuf buffer = STRBUF_INIT; askpass = getenv("GIT_ASKPASS"); - + if (!askpass) + askpass = askpass_program; + if (!askpass) + askpass = getenv("SSH_ASKPASS"); if (!askpass || !(*askpass)) return getpass(prompt); @@ -919,7 +919,10 @@ static void free_diff_words_data(struct emit_callback *ecbdata) free (ecbdata->diff_words->minus.orig); free (ecbdata->diff_words->plus.text.ptr); free (ecbdata->diff_words->plus.orig); - free(ecbdata->diff_words->word_regex); + if (ecbdata->diff_words->word_regex) { + regfree(ecbdata->diff_words->word_regex); + free(ecbdata->diff_words->word_regex); + } free(ecbdata->diff_words); ecbdata->diff_words = NULL; } diff --git a/environment.c b/environment.c index eeb26876a1..2d0c315379 100644 --- a/environment.c +++ b/environment.c @@ -37,6 +37,7 @@ size_t delta_base_cache_limit = 16 * 1024 * 1024; const char *pager_program; int pager_use_color = 1; const char *editor_program; +const char *askpass_program; const char *excludes_file; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; int read_replace_refs = 1; @@ -73,6 +74,7 @@ static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file; const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = { ALTERNATE_DB_ENVIRONMENT, CONFIG_ENVIRONMENT, + CONFIG_DATA_ENVIRONMENT, DB_ENVIRONMENT, GIT_DIR_ENVIRONMENT, GIT_WORK_TREE_ENVIRONMENT, @@ -1,6 +1,7 @@ #include "builtin.h" -#include "exec_cmd.h" #include "cache.h" +#include "exec_cmd.h" +#include "help.h" #include "quote.h" #include "run-command.h" @@ -56,9 +57,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) { int handled = 0; - if (!getenv("GIT_ASKPASS") && getenv("SSH_ASKPASS")) - setenv("GIT_ASKPASS", getenv("SSH_ASKPASS"), 1); - while (*argc > 0) { const char *cmd = (*argv)[0]; if (cmd[0] != '-') @@ -137,7 +135,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) fprintf(stderr, "-c expects a configuration string\n" ); usage(git_usage_string); } - git_config_parse_parameter((*argv)[1]); + git_config_push_parameter((*argv)[1]); (*argv)++; (*argc)--; } else { @@ -16,14 +16,17 @@ static inline void mput_char(char c, unsigned int num) putchar(c); } -void load_command_list(const char *prefix, - struct cmdnames *main_cmds, - struct cmdnames *other_cmds); -void add_cmdname(struct cmdnames *cmds, const char *name, int len); +extern void list_common_cmds_help(void); +extern const char *help_unknown_cmd(const char *cmd); +extern void load_command_list(const char *prefix, + struct cmdnames *main_cmds, + struct cmdnames *other_cmds); +extern void add_cmdname(struct cmdnames *cmds, const char *name, int len); /* Here we require that excludes is a sorted list. */ -void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); -int is_in_cmdlist(struct cmdnames *c, const char *s); -void list_commands(const char *title, struct cmdnames *main_cmds, - struct cmdnames *other_cmds); +extern void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); +extern int is_in_cmdlist(struct cmdnames *cmds, const char *name); +extern void list_commands(const char *title, + struct cmdnames *main_cmds, + struct cmdnames *other_cmds); #endif /* HELP_H */ @@ -263,11 +263,13 @@ static int note_tree_consolidate(struct int_node *tree, * To remove a leaf_node: * Search to the tree location appropriate for the given leaf_node's key: * - If location does not hold a matching entry, abort and do nothing. + * - Copy the matching entry's value into the given entry. * - Replace the matching leaf_node with a NULL entry (and free the leaf_node). * - Consolidate int_nodes repeatedly, while walking up the tree towards root. */ -static void note_tree_remove(struct notes_tree *t, struct int_node *tree, - unsigned char n, struct leaf_node *entry) +static void note_tree_remove(struct notes_tree *t, + struct int_node *tree, unsigned char n, + struct leaf_node *entry) { struct leaf_node *l; struct int_node *parent_stack[20]; @@ -282,6 +284,7 @@ static void note_tree_remove(struct notes_tree *t, struct int_node *tree, return; /* key mismatch, nothing to remove */ /* we have found a matching entry */ + hashcpy(entry->val_sha1, l->val_sha1); free(l); *p = SET_PTR_TYPE(NULL, PTR_TYPE_NULL); @@ -1003,17 +1006,20 @@ void add_note(struct notes_tree *t, const unsigned char *object_sha1, note_tree_insert(t, t->root, 0, l, PTR_TYPE_NOTE, combine_notes); } -void remove_note(struct notes_tree *t, const unsigned char *object_sha1) +int remove_note(struct notes_tree *t, const unsigned char *object_sha1) { struct leaf_node l; if (!t) t = &default_notes_tree; assert(t->initialized); - t->dirty = 1; hashcpy(l.key_sha1, object_sha1); hashclr(l.val_sha1); note_tree_remove(t, t->root, 0, &l); + if (is_null_sha1(l.val_sha1)) // no note was removed + return 1; + t->dirty = 1; + return 0; } const unsigned char *get_note(struct notes_tree *t, @@ -89,8 +89,10 @@ void add_note(struct notes_tree *t, const unsigned char *object_sha1, * IMPORTANT: The changes made by remove_note() to the given notes_tree * structure are not persistent until a subsequent call to write_notes_tree() * returns zero. + * + * Return 0 if a note was removed; 1 if there was no note to remove. */ -void remove_note(struct notes_tree *t, const unsigned char *object_sha1); +int remove_note(struct notes_tree *t, const unsigned char *object_sha1); /* * Get the note object SHA1 containing the note data for the given object diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 96b75813d7..a2b79a0430 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -365,6 +365,13 @@ c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd7 c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5 EOF +test_expect_success 'removing non-existing note should not create new commit' ' + git rev-parse --verify refs/notes/commits > before_commit && + test_must_fail git notes remove HEAD^ && + git rev-parse --verify refs/notes/commits > after_commit && + test_cmp before_commit after_commit +' + test_expect_success 'list notes with "git notes list"' ' git notes list > output && test_cmp expect output diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 61de8a2718..c8e19372b0 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -37,8 +37,13 @@ for p in $builtin_patterns do test_expect_success "builtin $p pattern compiles" ' echo "*.java diff=$p" > .gitattributes && - ! ( git diff --no-index Beer.java Beer-correct.java 2>&1 | - grep "fatal" > /dev/null ) + ! { git diff --no-index Beer.java Beer-correct.java 2>&1 | + grep "fatal" > /dev/null; } + ' + test_expect_success "builtin $p wordRegex pattern compiles" ' + ! { git diff --no-index --word-diff \ + Beer.java Beer-correct.java 2>&1 | + grep "fatal" > /dev/null; } ' done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index c718253673..5bcf0b867a 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -94,6 +94,29 @@ test_expect_success 'refuse deleting push with denyDeletes' ' test_must_fail git send-pack ./victim :extra master ' +test_expect_success 'cannot override denyDeletes with git -c send-pack' ' + ( + cd victim && + test_might_fail git branch -D extra && + git config receive.denyDeletes true && + git branch extra master + ) && + test_must_fail git -c receive.denyDeletes=false \ + send-pack ./victim :extra master +' + +test_expect_success 'override denyDeletes with git -c receive-pack' ' + ( + cd victim && + test_might_fail git branch -D extra && + git config receive.denyDeletes true && + git branch extra master + ) && + git send-pack \ + --receive-pack="git -c receive.denyDeletes=false receive-pack" \ + ./victim :extra master +' + test_expect_success 'denyNonFastforwards trumps --force' ' ( cd victim && diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 4eb10f602f..efb42d1540 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -240,6 +240,38 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' ' git fetch blub ' +# URL supplied to fetch does not match the url of the configured branch's remote +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' ' + one_head=$(cd one && git rev-parse HEAD) && + this_head=$(git rev-parse HEAD) && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + +# URL supplied to fetch matches the url of the configured branch's remote and +# the merge spec matches the branch the remote HEAD points to +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [2]' ' + one_ref=$(cd one && git symbolic-ref HEAD) && + git config branch.master.remote blub && + git config branch.master.merge "$one_ref" && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + +# URL supplied to fetch matches the url of the configured branch's remote, but +# the merge spec does not match the branch the remote HEAD points to +test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' ' + git config branch.master.merge "${one_ref}_not" && + git update-ref -d FETCH_HEAD && + git fetch one && + test $one_head = "$(git rev-parse --verify FETCH_HEAD)" && + test $this_head = "$(git rev-parse --verify HEAD)" +' + # the strange name is: a\!'b test_expect_success 'quoting of a strangely named repo' ' test_must_fail git fetch "a\\!'\''b" > result 2>&1 && diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh index c0f9f3f705..e058d184d1 100755 --- a/t/t7008-grep-binary.sh +++ b/t/t7008-grep-binary.sh @@ -5,7 +5,7 @@ test_description='git grep in binary files' . ./test-lib.sh test_expect_success 'setup' " - printf 'binary\000file\n' >a && + echo 'binaryQfile' | q_to_nul >a && git add a && git commit -m. " @@ -70,32 +70,32 @@ test_expect_failure 'git grep .fi a' ' ' test_expect_success 'git grep -F y<NUL>f a' " - printf 'y\000f' >f && + printf 'yQf' | q_to_nul >f && git grep -f f -F a " test_expect_success 'git grep -F y<NUL>x a' " - printf 'y\000x' >f && + printf 'yQx' | q_to_nul >f && test_must_fail git grep -f f -F a " test_expect_success 'git grep -Fi Y<NUL>f a' " - printf 'Y\000f' >f && + printf 'YQf' | q_to_nul >f && git grep -f f -Fi a " test_expect_failure 'git grep -Fi Y<NUL>x a' " - printf 'Y\000x' >f && + printf 'YQx' | q_to_nul >f && test_must_fail git grep -f f -Fi a " test_expect_success 'git grep y<NUL>f a' " - printf 'y\000f' >f && + printf 'yQf' | q_to_nul >f && git grep -f f a " test_expect_failure 'git grep y<NUL>x a' " - printf 'y\000x' >f && + printf 'yQx' | q_to_nul >f && test_must_fail git grep -f f a " diff --git a/t/test-lib.sh b/t/test-lib.sh index dff5e25ae6..830e5e7360 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -620,7 +620,18 @@ test_path_is_missing () { test_must_fail () { "$@" - test $? -gt 0 -a $? -le 129 -o $? -gt 192 + exit_code=$? + if test $exit_code = 0; then + echo >&2 "test_must_fail: command succeeded: $*" + return 1 + elif test $exit_code -gt 129 -a $exit_code -le 192; then + echo >&2 "test_must_fail: died by signal: $*" + return 1 + elif test $exit_code = 127; then + echo >&2 "test_must_fail: command not found: $*" + return 1 + fi + return 0 } # Similar to test_must_fail, but tolerates success, too. This is @@ -636,7 +647,15 @@ test_must_fail () { test_might_fail () { "$@" - test $? -ge 0 -a $? -le 129 -o $? -gt 192 + exit_code=$? + if test $exit_code -gt 129 -a $exit_code -le 192; then + echo >&2 "test_might_fail: died by signal: $*" + return 1 + elif test $exit_code = 127; then + echo >&2 "test_might_fail: command not found: $*" + return 1 + fi + return 0 } # test_cmp is a helper function to compare actual and expected output. diff --git a/xdiff-interface.c b/xdiff-interface.c index cd2285de1c..e1e054e4d9 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -286,9 +286,8 @@ static long ff_regexp(const char *line, long len, result = pmatch[i].rm_eo - pmatch[i].rm_so; if (result > buffer_size) result = buffer_size; - else - while (result > 0 && (isspace(line[result - 1]))) - result--; + while (result > 0 && (isspace(line[result - 1]))) + result--; memcpy(buffer, line, result); fail: free(line_buffer); |