diff options
-rw-r--r-- | Documentation/RelNotes/1.7.11.6.txt | 30 | ||||
-rw-r--r-- | builtin.h | 2 | ||||
-rw-r--r-- | builtin/blame.c | 9 | ||||
-rw-r--r-- | builtin/cat-file.c | 2 | ||||
-rw-r--r-- | builtin/diff.c | 8 | ||||
-rw-r--r-- | builtin/receive-pack.c | 3 | ||||
-rw-r--r-- | combine-diff.c | 4 | ||||
-rw-r--r-- | diff-lib.c | 20 | ||||
-rw-r--r-- | diff-no-index.c | 2 | ||||
-rw-r--r-- | diff.c | 16 | ||||
-rw-r--r-- | diff.h | 5 | ||||
-rw-r--r-- | diffcore-rename.c | 2 | ||||
-rw-r--r-- | diffcore.h | 2 | ||||
-rw-r--r-- | fsck.c | 8 | ||||
-rw-r--r-- | git-rebase--interactive.sh | 3 | ||||
-rwxr-xr-x | git-send-email.perl | 10 | ||||
-rw-r--r-- | git-sh-setup.sh | 4 | ||||
-rwxr-xr-x | gitweb/gitweb.perl | 5 | ||||
-rw-r--r-- | read-cache.c | 2 | ||||
-rw-r--r-- | revision.c | 2 | ||||
-rw-r--r-- | setup.c | 8 | ||||
-rwxr-xr-x | t/t1450-fsck.sh | 26 | ||||
-rwxr-xr-x | t/t2107-update-index-basic.sh | 19 | ||||
-rwxr-xr-x | t/t4054-diff-bogus-tree.sh | 83 | ||||
-rwxr-xr-x | t/t5400-send-pack.sh | 35 | ||||
-rwxr-xr-x | t/t9001-send-email.sh | 13 | ||||
-rw-r--r-- | tree-diff.c | 8 |
27 files changed, 288 insertions, 43 deletions
diff --git a/Documentation/RelNotes/1.7.11.6.txt b/Documentation/RelNotes/1.7.11.6.txt index e548a59824..84ba827b1b 100644 --- a/Documentation/RelNotes/1.7.11.6.txt +++ b/Documentation/RelNotes/1.7.11.6.txt @@ -4,7 +4,8 @@ Git v1.7.11.6 Release Notes Fixes since v1.7.11.5 --------------------- -This is primarily documentation and low-impact code clarification. +This consists primarily of documentation updates and low-impact code +clarification and bugfixes. - "ciabot" script (in contrib/) has been updated with extensive documentation. @@ -32,3 +33,30 @@ This is primarily documentation and low-impact code clarification. - "git commit --amend" let the user edit the log message and then died when the human-readable committer name was given insufficiently by getpwent(3). + + - The reflog entries left by "git rebase" and "git rebase -i" were + inconsistent (the interactive one gave an abbreviated object name). + + - When the user exports a non-default IFS without HT, scripts that + rely on being able to parse "ls-files -s | while read a b c..." + started to fail. Protect them from such a misconfiguration. + + - When "git push" triggered the automatic gc on the receiving end, a + message from "git prune" that said it was removing cruft leaked to + the standard output, breaking the communication protocol. + + - "git diff" had a confusion between taking data from a path in the + working tree and taking data from an object that happens to have + name 0{40} recorded in a tree. + + - "git send-email" did not unquote encoded words that appear on the + header correctly, and lost "_" from strings. + + - When the user gives an argument that can be taken as both a + revision name and a pathname without disambiguating with "--", we + used to give a help message "Use '--' to separate". The message + has been clarified to show where that '--' goes on the command + line. + + - "gitweb" when used with PATH_INFO failed to notice directories with + SP (and other characters that need URL-style quoting) in them. @@ -43,7 +43,7 @@ extern int check_pager_config(const char *cmd); struct diff_options; extern void setup_diff_pager(struct diff_options *); -extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, char **buf, unsigned long *buf_size); +extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size); extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_annotate(int argc, const char **argv, const char *prefix); diff --git a/builtin/blame.c b/builtin/blame.c index 0d50273ce9..f2c48ef5af 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -110,6 +110,7 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen, int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, + int sha1_valid, char **buf, unsigned long *buf_size) { @@ -117,7 +118,7 @@ int textconv_object(const char *path, struct userdiff_driver *textconv; df = alloc_filespec(path); - fill_filespec(df, sha1, mode); + fill_filespec(df, sha1, sha1_valid, mode); textconv = get_textconv(df); if (!textconv) { free_filespec(df); @@ -142,7 +143,7 @@ static void fill_origin_blob(struct diff_options *opt, num_read_blob++; if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size)) + textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size)) ; else file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size); @@ -2123,7 +2124,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, switch (st.st_mode & S_IFMT) { case S_IFREG: if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) && - textconv_object(read_from, mode, null_sha1, &buf_ptr, &buf_len)) + textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len)) strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1); else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) die_errno("cannot open or read '%s'", read_from); @@ -2516,7 +2517,7 @@ parse_done: die("no such path %s in %s", path, final_commit_name); if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) && - textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf, + textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf, &sb.final_buf_size)) ; else diff --git a/builtin/cat-file.c b/builtin/cat-file.c index af74e775a1..0eca2d7bd0 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -146,7 +146,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) die("git cat-file --textconv %s: <object> must be <sha1:path>", obj_name); - if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size)) + if (!textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size)) die("git cat-file --textconv: unable to run textconv on %s", obj_name); break; diff --git a/builtin/diff.c b/builtin/diff.c index da8f6aac2b..bf72298752 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -29,6 +29,8 @@ static void stuff_change(struct diff_options *opt, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, + int new_sha1_valid, const char *old_name, const char *new_name) { @@ -54,8 +56,8 @@ static void stuff_change(struct diff_options *opt, one = alloc_filespec(old_name); two = alloc_filespec(new_name); - fill_filespec(one, old_sha1, old_mode); - fill_filespec(two, new_sha1, new_mode); + fill_filespec(one, old_sha1, old_sha1_valid, old_mode); + fill_filespec(two, new_sha1, new_sha1_valid, new_mode); diff_queue(&diff_queued_diff, one, two); } @@ -84,6 +86,7 @@ static int builtin_diff_b_f(struct rev_info *revs, stuff_change(&revs->diffopt, blob[0].mode, canon_mode(st.st_mode), blob[0].sha1, null_sha1, + 1, 0, path, path); diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); @@ -108,6 +111,7 @@ static int builtin_diff_blobs(struct rev_info *revs, stuff_change(&revs->diffopt, blob[0].mode, blob[1].mode, blob[0].sha1, blob[1].sha1, + 1, 1, blob[0].name, blob[1].name); diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 0afb8b2896..3f05d971ec 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -977,7 +977,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) const char *argv_gc_auto[] = { "gc", "--auto", "--quiet", NULL, }; - run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); + int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) update_server_info(0); diff --git a/combine-diff.c b/combine-diff.c index 9786680368..bb1cc96c4e 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -111,7 +111,7 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, return xcalloc(1, 1); } else if (textconv) { struct diff_filespec *df = alloc_filespec(path); - fill_filespec(df, sha1, mode); + fill_filespec(df, sha1, 1, mode); *size = fill_textconv(textconv, df, &blob); free_filespec(df); } else { @@ -823,7 +823,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, &result_size, NULL, NULL); } else if (textconv) { struct diff_filespec *df = alloc_filespec(elem->path); - fill_filespec(df, null_sha1, st.st_mode); + fill_filespec(df, null_sha1, 0, st.st_mode); result_size = fill_textconv(textconv, df, &result); free_filespec(df); } else if (0 <= (fd = open(elem->path, O_RDONLY))) { diff --git a/diff-lib.c b/diff-lib.c index fc0dff31b5..f35de0ffa0 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -206,7 +206,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (silent_on_removed) continue; diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->sha1, ce->name, 0); + ce->sha1, !is_null_sha1(ce->sha1), + ce->name, 0); continue; } changed = match_stat_with_submodule(&revs->diffopt, ce, &st, @@ -220,6 +221,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) newmode = ce_mode_from_stat(ce, st.st_mode); diff_change(&revs->diffopt, oldmode, newmode, ce->sha1, (changed ? null_sha1 : ce->sha1), + !is_null_sha1(ce->sha1), (changed ? 0 : !is_null_sha1(ce->sha1)), ce->name, 0, dirty_submodule); } @@ -236,11 +238,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option) static void diff_index_show_file(struct rev_info *revs, const char *prefix, struct cache_entry *ce, - const unsigned char *sha1, unsigned int mode, + const unsigned char *sha1, int sha1_valid, + unsigned int mode, unsigned dirty_submodule) { diff_addremove(&revs->diffopt, prefix[0], mode, - sha1, ce->name, dirty_submodule); + sha1, sha1_valid, ce->name, dirty_submodule); } static int get_stat_data(struct cache_entry *ce, @@ -295,7 +298,7 @@ static void show_new_file(struct rev_info *revs, &dirty_submodule, &revs->diffopt) < 0) return; - diff_index_show_file(revs, "+", new, sha1, mode, dirty_submodule); + diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule); } static int show_modified(struct rev_info *revs, @@ -312,7 +315,7 @@ static int show_modified(struct rev_info *revs, &dirty_submodule, &revs->diffopt) < 0) { if (report_missing) diff_index_show_file(revs, "-", old, - old->sha1, old->ce_mode, 0); + old->sha1, 1, old->ce_mode, 0); return -1; } @@ -347,7 +350,8 @@ static int show_modified(struct rev_info *revs, return 0; diff_change(&revs->diffopt, oldmode, mode, - old->sha1, sha1, old->name, 0, dirty_submodule); + old->sha1, sha1, 1, !is_null_sha1(sha1), + old->name, 0, dirty_submodule); return 0; } @@ -380,7 +384,7 @@ static void do_oneway_diff(struct unpack_trees_options *o, struct diff_filepair *pair; pair = diff_unmerge(&revs->diffopt, idx->name); if (tree) - fill_filespec(pair->one, tree->sha1, tree->ce_mode); + fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode); return; } @@ -396,7 +400,7 @@ static void do_oneway_diff(struct unpack_trees_options *o, * Something removed from the tree? */ if (!idx) { - diff_index_show_file(revs, "-", tree, tree->sha1, tree->ce_mode, 0); + diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0); return; } diff --git a/diff-no-index.c b/diff-no-index.c index 7d805a06af..0b46a0f79f 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -82,7 +82,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode) if (!name) name = "/dev/null"; s = alloc_filespec(name); - fill_filespec(s, null_sha1, mode); + fill_filespec(s, null_sha1, 0, mode); if (name == file_from_standard_input) populate_from_stdin(s); return s; @@ -2541,12 +2541,12 @@ void free_filespec(struct diff_filespec *spec) } void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, - unsigned short mode) + int sha1_valid, unsigned short mode) { if (mode) { spec->mode = canon_mode(mode); hashcpy(spec->sha1, sha1); - spec->sha1_valid = !is_null_sha1(sha1); + spec->sha1_valid = sha1_valid; } } @@ -4693,6 +4693,7 @@ static int is_submodule_ignored(const char *path, struct diff_options *options) void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *concatpath, unsigned dirty_submodule) { struct diff_filespec *one, *two; @@ -4724,9 +4725,9 @@ void diff_addremove(struct diff_options *options, two = alloc_filespec(concatpath); if (addremove != '+') - fill_filespec(one, sha1, mode); + fill_filespec(one, sha1, sha1_valid, mode); if (addremove != '-') { - fill_filespec(two, sha1, mode); + fill_filespec(two, sha1, sha1_valid, mode); two->dirty_submodule = dirty_submodule; } @@ -4739,6 +4740,7 @@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, int new_sha1_valid, const char *concatpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule) { @@ -4753,6 +4755,8 @@ void diff_change(struct diff_options *options, const unsigned char *tmp_c; tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; + tmp = old_sha1_valid; old_sha1_valid = new_sha1_valid; + new_sha1_valid = tmp; tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule; new_dirty_submodule = tmp; } @@ -4763,8 +4767,8 @@ void diff_change(struct diff_options *options, one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); - fill_filespec(one, old_sha1, old_mode); - fill_filespec(two, new_sha1, new_mode); + fill_filespec(one, old_sha1, old_sha1_valid, old_mode); + fill_filespec(two, new_sha1, new_sha1_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; @@ -19,12 +19,14 @@ typedef void (*change_fn_t)(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, int new_sha1_valid, const char *fullpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule); typedef void (*add_remove_fn_t)(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *fullpath, unsigned dirty_submodule); typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, @@ -214,12 +216,15 @@ extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *fullpath, unsigned dirty_submodule); extern void diff_change(struct diff_options *, unsigned mode1, unsigned mode2, const unsigned char *sha1, const unsigned char *sha2, + int sha1_valid, + int sha2_valid, const char *fullpath, unsigned dirty_submodule1, unsigned dirty_submodule2); diff --git a/diffcore-rename.c b/diffcore-rename.c index 216a7a4bbc..512d0ac5fd 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -48,7 +48,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two, memmove(rename_dst + first + 1, rename_dst + first, (rename_dst_nr - first - 1) * sizeof(*rename_dst)); rename_dst[first].two = alloc_filespec(two->path); - fill_filespec(rename_dst[first].two, two->sha1, two->mode); + fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode); rename_dst[first].pair = NULL; return &(rename_dst[first]); } diff --git a/diffcore.h b/diffcore.h index be0739c5c4..1c16c8595b 100644 --- a/diffcore.h +++ b/diffcore.h @@ -55,7 +55,7 @@ struct diff_filespec { extern struct diff_filespec *alloc_filespec(const char *); extern void free_filespec(struct diff_filespec *); extern void fill_filespec(struct diff_filespec *, const unsigned char *, - unsigned short); + int, unsigned short); extern int diff_populate_filespec(struct diff_filespec *, int); extern void diff_free_filespec_data(struct diff_filespec *); @@ -139,6 +139,7 @@ static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, con static int fsck_tree(struct tree *item, int strict, fsck_error error_func) { int retval; + int has_null_sha1 = 0; int has_full_path = 0; int has_empty_name = 0; int has_zero_pad = 0; @@ -157,9 +158,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) while (desc.size) { unsigned mode; const char *name; + const unsigned char *sha1; - tree_entry_extract(&desc, &name, &mode); + sha1 = tree_entry_extract(&desc, &name, &mode); + if (is_null_sha1(sha1)) + has_null_sha1 = 1; if (strchr(name, '/')) has_full_path = 1; if (!*name) @@ -207,6 +211,8 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) } retval = 0; + if (has_null_sha1) + retval += error_func(&item->object, FSCK_WARN, "contains entries pointing to null sha1"); if (has_full_path) retval += error_func(&item->object, FSCK_WARN, "contains full pathnames"); if (has_empty_name) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 0d2056f027..a09e8423dd 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -569,11 +569,10 @@ do_next () { test -s "$todo" && return comment_for_reflog finish && - shortonto=$(git rev-parse --short $onto) && newhead=$(git rev-parse HEAD) && case $head_name in refs/*) - message="$GIT_REFLOG_ACTION: $head_name onto $shortonto" && + message="$GIT_REFLOG_ACTION: $head_name onto $onto" && git update-ref -m "$message" $head_name $newhead $orig_head && git symbolic-ref \ -m "$GIT_REFLOG_ACTION: returning to $head_name" \ diff --git a/git-send-email.perl b/git-send-email.perl index ef30c557c7..664713709c 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -862,11 +862,13 @@ $time = time - scalar $#files; sub unquote_rfc2047 { local ($_) = @_; my $encoding; - if (s/=\?([^?]+)\?q\?(.*)\?=/$2/g) { + s{=\?([^?]+)\?q\?(.*?)\?=}{ $encoding = $1; - s/_/ /g; - s/=([0-9A-F]{2})/chr(hex($1))/eg; - } + my $e = $2; + $e =~ s/_/ /g; + $e =~ s/=([0-9A-F]{2})/chr(hex($1))/eg; + $e; + }eg; return wantarray ? ($_, $encoding) : $_; } diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 770a86e2b7..ee0e0bc045 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -9,8 +9,12 @@ # you would cause "cd" to be taken to unexpected places. If you # like CDPATH, define it for your interactive shell sessions without # exporting it. +# But we protect ourselves from such a user mistake nevertheless. unset CDPATH +# Similarly for IFS +unset IFS + git_broken_path_fix () { case ":$PATH:" in *:$1:*) : ok ;; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3d6a705388..7f8c1878d4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -54,6 +54,11 @@ sub evaluate_uri { # to build the base URL ourselves: our $path_info = decode_utf8($ENV{"PATH_INFO"}); if ($path_info) { + # $path_info has already been URL-decoded by the web server, but + # $my_url and $my_uri have not. URL-decode them so we can properly + # strip $path_info. + $my_url = unescape($my_url); + $my_uri = unescape($my_uri); if ($my_url =~ s,\Q$path_info\E$,, && $my_uri =~ s,\Q$path_info\E$,, && defined $ENV{'SCRIPT_NAME'}) { diff --git a/read-cache.c b/read-cache.c index 2f8159fb16..d2be78ea95 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1800,6 +1800,8 @@ int write_index(struct index_state *istate, int newfd) continue; if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce)) ce_smudge_racily_clean_entry(ce); + if (is_null_sha1(ce->sha1)) + return error("cache entry has null sha1: %s", ce->name); if (ce_write_entry(&c, newfd, ce, previous_name) < 0) return -1; } diff --git a/revision.c b/revision.c index 9e8f47a25d..04c7de87d0 100644 --- a/revision.c +++ b/revision.c @@ -345,6 +345,7 @@ static int tree_difference = REV_TREE_SAME; static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, + int sha1_valid, const char *fullpath, unsigned dirty_submodule) { int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD; @@ -358,6 +359,7 @@ static void file_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, + int old_sha1_valid, int new_sha1_valid, const char *fullpath, unsigned old_dirty_submodule, unsigned new_dirty_submodule) { @@ -79,7 +79,7 @@ static void NORETURN die_verify_filename(const char *prefix, { if (!diagnose_misspelt_rev) die("%s: no such path in the working tree.\n" - "Use '-- <path>...' to specify paths that do not exist locally.", + "Use 'git <command> -- <path>...' to specify paths that do not exist locally.", arg); /* * Saying "'(icase)foo' does not exist in the index" when the @@ -92,7 +92,8 @@ static void NORETURN die_verify_filename(const char *prefix, /* ... or fall back the most general message. */ die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" - "Use '--' to separate paths from revisions", arg); + "Use '--' to separate paths from revisions, like this:\n" + "'git <command> [<revision>...] -- [<file>...]'", arg); } @@ -141,7 +142,8 @@ void verify_non_filename(const char *prefix, const char *arg) if (!check_filename(prefix, arg)) return; die("ambiguous argument '%s': both revision and filename\n" - "Use '--' to separate filenames from revisions", arg); + "Use '--' to separate paths from revisions, like this:\n" + "'git <command> [<revision>...] -- [<file>...]'", arg); } /* diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 5b79c51b8c..bf7a2cd6fb 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -213,4 +213,30 @@ test_expect_success 'rev-list --verify-objects with bad sha1' ' grep -q "error: sha1 mismatch 63ffffffffffffffffffffffffffffffffffffff" out ' +_bz='\0' +_bz5="$_bz$_bz$_bz$_bz$_bz" +_bz20="$_bz5$_bz5$_bz5$_bz5" + +test_expect_success 'fsck notices blob entry pointing to null sha1' ' + (git init null-blob && + cd null-blob && + sha=$(printf "100644 file$_bz$_bz20" | + git hash-object -w --stdin -t tree) && + git fsck 2>out && + cat out && + grep "warning.*null sha1" out + ) +' + +test_expect_success 'fsck notices submodule entry pointing to null sha1' ' + (git init null-commit && + cd null-commit && + sha=$(printf "160000 submodule$_bz$_bz20" | + git hash-object -w --stdin -t tree) && + git fsck 2>out && + cat out && + grep "warning.*null sha1" out + ) +' + test_done diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh index 809fafe208..0dbbb00d74 100755 --- a/t/t2107-update-index-basic.sh +++ b/t/t2107-update-index-basic.sh @@ -29,4 +29,23 @@ test_expect_success 'update-index -h with corrupt index' ' grep "[Uu]sage: git update-index" broken/usage ' +test_expect_success '--cacheinfo does not accept blob null sha1' ' + echo content >file && + git add file && + git rev-parse :file >expect && + test_must_fail git update-index --cacheinfo 100644 $_z40 file && + git rev-parse :file >actual && + test_cmp expect actual +' + +test_expect_success '--cacheinfo does not accept gitlink null sha1' ' + git init submodule && + (cd submodule && test_commit foo) && + git add submodule && + git rev-parse :submodule >expect && + test_must_fail git update-index --cacheinfo 160000 $_z40 submodule && + git rev-parse :submodule >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh new file mode 100755 index 0000000000..0843c87890 --- /dev/null +++ b/t/t4054-diff-bogus-tree.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +test_description='test diff with a bogus tree containing the null sha1' +. ./test-lib.sh + +empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + +test_expect_success 'create bogus tree' ' + bogus_tree=$( + printf "100644 fooQQQQQQQQQQQQQQQQQQQQQ" | + q_to_nul | + git hash-object -w --stdin -t tree + ) +' + +test_expect_success 'create tree with matching file' ' + echo bar >foo && + git add foo && + good_tree=$(git write-tree) + blob=$(git rev-parse :foo) +' + +test_expect_success 'raw diff shows null sha1 (addition)' ' + echo ":000000 100644 $_z40 $_z40 A foo" >expect && + git diff-tree $empty_tree $bogus_tree >actual && + test_cmp expect actual +' + +test_expect_success 'raw diff shows null sha1 (removal)' ' + echo ":100644 000000 $_z40 $_z40 D foo" >expect && + git diff-tree $bogus_tree $empty_tree >actual && + test_cmp expect actual +' + +test_expect_success 'raw diff shows null sha1 (modification)' ' + echo ":100644 100644 $blob $_z40 M foo" >expect && + git diff-tree $good_tree $bogus_tree >actual && + test_cmp expect actual +' + +test_expect_success 'raw diff shows null sha1 (other direction)' ' + echo ":100644 100644 $_z40 $blob M foo" >expect && + git diff-tree $bogus_tree $good_tree >actual && + test_cmp expect actual +' + +test_expect_success 'raw diff shows null sha1 (reverse)' ' + echo ":100644 100644 $_z40 $blob M foo" >expect && + git diff-tree -R $good_tree $bogus_tree >actual && + test_cmp expect actual +' + +test_expect_success 'raw diff shows null sha1 (index)' ' + echo ":100644 100644 $_z40 $blob M foo" >expect && + git diff-index $bogus_tree >actual && + test_cmp expect actual +' + +test_expect_success 'patch fails due to bogus sha1 (addition)' ' + test_must_fail git diff-tree -p $empty_tree $bogus_tree +' + +test_expect_success 'patch fails due to bogus sha1 (removal)' ' + test_must_fail git diff-tree -p $bogus_tree $empty_tree +' + +test_expect_success 'patch fails due to bogus sha1 (modification)' ' + test_must_fail git diff-tree -p $good_tree $bogus_tree +' + +test_expect_success 'patch fails due to bogus sha1 (other direction)' ' + test_must_fail git diff-tree -p $bogus_tree $good_tree +' + +test_expect_success 'patch fails due to bogus sha1 (reverse)' ' + test_must_fail git diff-tree -R -p $good_tree $bogus_tree +' + +test_expect_success 'patch fails due to bogus sha1 (index)' ' + test_must_fail git diff-index -p $bogus_tree +' + +test_done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 0eace37a03..250c720c14 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -145,6 +145,41 @@ test_expect_success 'push --all excludes remote-tracking hierarchy' ' ) ' +test_expect_success 'receive-pack runs auto-gc in remote repo' ' + rm -rf parent child && + git init parent && + ( + # Setup a repo with 2 packs + cd parent && + echo "Some text" >file.txt && + git add . && + git commit -m "Initial commit" && + git repack -adl && + echo "Some more text" >>file.txt && + git commit -a -m "Second commit" && + git repack + ) && + cp -a parent child && + ( + # Set the child to auto-pack if more than one pack exists + cd child && + git config gc.autopacklimit 1 && + git branch test_auto_gc && + # And create a file that follows the temporary object naming + # convention for the auto-gc to remove + : >.git/objects/tmp_test_object && + test-chmtime =-1209601 .git/objects/tmp_test_object + ) && + ( + cd parent && + echo "Even more text" >>file.txt && + git commit -a -m "Third commit" && + git send-pack ../child HEAD:refs/heads/test_auto_gc >output 2>&1 && + grep "Auto packing the repository for optimum performance." output + ) && + test ! -e child/.git/objects/tmp_test_object +' + rewound_push_setup() { rm -rf parent child && mkdir parent && diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 8c12c65c72..035122808b 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -841,6 +841,19 @@ test_expect_success $PREREQ '--compose adds MIME for utf8 subject' ' grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 ' +test_expect_success $PREREQ 'utf8 author is correctly passed on' ' + clean_fake_sendmail && + test_commit weird_author && + test_when_finished "git reset --hard HEAD^" && + git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" && + git format-patch --stdout -1 >funny_name.patch && + git send-email --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + funny_name.patch && + grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1 +' + test_expect_success $PREREQ 'detects ambiguous reference/file conflict' ' echo master > master && git add master && diff --git a/tree-diff.c b/tree-diff.c index 28ad6db9ff..7e5483366e 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -49,12 +49,12 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { opt->change(opt, mode1, mode2, - sha1, sha2, base->buf, 0, 0); + sha1, sha2, 1, 1, base->buf, 0, 0); } strbuf_addch(base, '/'); diff_tree_sha1(sha1, sha2, base->buf, opt); } else { - opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0); + opt->change(opt, mode1, mode2, sha1, sha2, 1, 1, base->buf, 0, 0); } strbuf_setlen(base, old_baselen); return 0; @@ -100,7 +100,7 @@ static void show_entry(struct diff_options *opt, const char *prefix, die("corrupt tree sha %s", sha1_to_hex(sha1)); if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) - opt->add_remove(opt, *prefix, mode, sha1, base->buf, 0); + opt->add_remove(opt, *prefix, mode, sha1, 1, base->buf, 0); strbuf_addch(base, '/'); @@ -108,7 +108,7 @@ static void show_entry(struct diff_options *opt, const char *prefix, show_tree(opt, prefix, &inner, base); free(tree); } else - opt->add_remove(opt, prefix[0], mode, sha1, base->buf, 0); + opt->add_remove(opt, prefix[0], mode, sha1, 1, base->buf, 0); strbuf_setlen(base, old_baselen); } |