From 25a48f056427c4c15790cf1bc98b1226f29ce179 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Wed, 3 Mar 2021 15:15:08 +0900 Subject: [PATCH] Imported Upstream version 2.4.2 --- Documentation/RelNotes/2.4.2.txt | 45 ++++++++++++++++++++++++++++++++++ Documentation/git-hash-object.txt | 10 ++++++-- Documentation/git.txt | 3 ++- GIT-VERSION-GEN | 2 +- RelNotes | 2 +- builtin/hash-object.c | 4 +-- cache.h | 1 + contrib/completion/git-completion.bash | 2 +- daemon.c | 2 +- exec_cmd.c | 1 - git-filter-branch.sh | 10 +++++++- git-rebase.sh | 2 +- git-stash.sh | 2 ++ revision.c | 23 ++++++++++++++--- sha1_file.c | 26 +++++++++++++++++--- t/t1007-hash-object.sh | 11 +++++++++ t/t3903-stash.sh | 21 ++++++++++------ t/t7003-filter-branch.sh | 10 ++++++++ 18 files changed, 149 insertions(+), 28 deletions(-) create mode 100644 Documentation/RelNotes/2.4.2.txt diff --git a/Documentation/RelNotes/2.4.2.txt b/Documentation/RelNotes/2.4.2.txt new file mode 100644 index 0000000..250cdc4 --- /dev/null +++ b/Documentation/RelNotes/2.4.2.txt @@ -0,0 +1,45 @@ +Git v2.4.2 Release Notes +======================== + +Fixes since v2.4.1 +------------------ + + * "git rev-list --objects $old --not --all" to see if everything that + is reachable from $old is already connected to the existing refs + was very inefficient. + + * "hash-object --literally" introduced in v2.2 was not prepared to + take a really long object type name. + + * "git rebase --quiet" was not quite quiet when there is nothing to + do. + + * The completion for "log --decorate=" parameter value was incorrect. + + * "filter-branch" corrupted commit log message that ends with an + incomplete line on platforms with some "sed" implementations that + munge such a line. Work it around by avoiding to use "sed". + + * "git daemon" fails to build from the source under NO_IPV6 + configuration (regression in 2.4). + + * "git stash pop/apply" forgot to make sure that not just the working + tree is clean but also the index is clean. The latter is important + as a stash application can conflict and the index will be used for + conflict resolution. + + * We have prepended $GIT_EXEC_PATH and the path "git" is installed in + (typically "/usr/bin") to $PATH when invoking subprograms and hooks + for almost eternity, but the original use case the latter tried to + support was semi-bogus (i.e. install git to /opt/foo/git and run it + without having /opt/foo on $PATH), and more importantly it has + become less and less relevant as Git grew more mainstream (i.e. the + users would _want_ to have it on their $PATH). Stop prepending the + path in which "git" is installed to users' $PATH, as that would + interfere the command search order people depend on (e.g. they may + not like versions of programs that are unrelated to Git in /usr/bin + and want to override them by having different ones in /usr/local/bin + and have the latter directory earlier in their $PATH). + +Also contains typofixes, documentation updates and trivial code +clean-ups. diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index 02c1f12..0c75f3b 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -9,7 +9,7 @@ git-hash-object - Compute object ID and optionally creates a blob from a file SYNOPSIS -------- [verse] -'git hash-object' [-t ] [-w] [--path=|--no-filters] [--stdin] [--] ... +'git hash-object' [-t ] [-w] [--path=|--no-filters] [--stdin [--literally]] [--] ... 'git hash-object' [-t ] [-w] --stdin-paths [--no-filters] < DESCRIPTION @@ -51,7 +51,13 @@ OPTIONS Hash the contents as is, ignoring any input filter that would have been chosen by the attributes mechanism, including the end-of-line conversion. If the file is read from standard input then this - is always implied, unless the --path option is given. + is always implied, unless the `--path` option is given. + +--literally:: + Allow `--stdin` to hash any garbage into a loose object which might not + otherwise pass standard object parsing or git-fsck checks. Useful for + stress-testing Git itself or reproducing characteristics of corrupt or + bogus objects encountered in the wild. GIT --- diff --git a/Documentation/git.txt b/Documentation/git.txt index 5808df6..f582742 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.4.1/git.html[documentation for release 2.4.1] +* link:v2.4.2/git.html[documentation for release 2.4.2] * release notes for + link:RelNotes/2.4.2.txt[2.4.2], link:RelNotes/2.4.1.txt[2.4.1], link:RelNotes/2.4.0.txt[2.4]. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 6dd8e04..c4a6631 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.4.1 +DEF_VER=v2.4.2 LF=' ' diff --git a/RelNotes b/RelNotes index 17b2de7..f43dfd9 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.4.1.txt \ No newline at end of file +Documentation/RelNotes/2.4.2.txt \ No newline at end of file diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 207b90c..07fef3c 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -22,10 +22,8 @@ static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigne if (strbuf_read(&buf, fd, 4096) < 0) ret = -1; - else if (flags & HASH_WRITE_OBJECT) - ret = write_sha1_file(buf.buf, buf.len, type, sha1); else - ret = hash_sha1_file(buf.buf, buf.len, type, sha1); + ret = hash_sha1_file_literally(buf.buf, buf.len, type, sha1, flags); strbuf_release(&buf); return ret; } diff --git a/cache.h b/cache.h index eabde38..e42be4b 100644 --- a/cache.h +++ b/cache.h @@ -874,6 +874,7 @@ static inline const unsigned char *lookup_replace_object_extended(const unsigned extern int sha1_object_info(const unsigned char *, unsigned long *); extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1); +extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); extern int git_open_noatime(const char *name); diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 5944c82..eae9dce 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1448,7 +1448,7 @@ _git_log () return ;; --decorate=*) - __gitcomp "long short" "" "${cur##--decorate=}" + __gitcomp "full short no" "" "${cur##--decorate=}" return ;; --*) diff --git a/daemon.c b/daemon.c index 9ee2187..4be1091 100644 --- a/daemon.c +++ b/daemon.c @@ -633,7 +633,7 @@ static void lookup_hostname(struct hostinfo *hi) char **ap; static char addrbuf[HOST_NAME_MAX + 1]; - hent = gethostbyname(hostname.buf); + hent = gethostbyname(hi->hostname.buf); if (hent) { ap = hent->h_addr_list; memset(&sa, 0, sizeof sa); diff --git a/exec_cmd.c b/exec_cmd.c index 8ab37b5..e85f0fd 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -96,7 +96,6 @@ void setup_path(void) struct strbuf new_path = STRBUF_INIT; add_path(&new_path, git_exec_path()); - add_path(&new_path, argv0_path); if (old_path) strbuf_addstr(&new_path, old_path); diff --git a/git-filter-branch.sh b/git-filter-branch.sh index e6e99f5..5b3f63d 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -346,7 +346,15 @@ while read commit parents; do die "parent filter failed: $filter_parent" fi - sed -e '1,/^$/d' <../commit | \ + { + while read -r header_line && test -n "$header_line" + do + # skip header lines... + :; + done + # and output the actual commit message + cat + } <../commit | eval "$filter_msg" > ../message || die "msg filter failed: $filter_msg" workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \ diff --git a/git-rebase.sh b/git-rebase.sh index 55da9db..90854e3 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -582,7 +582,7 @@ then # Lazily switch to the target branch if needed... test -z "$switch_to" || GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \ - git checkout "$switch_to" -- + git checkout -q "$switch_to" -- say "$(eval_gettext "Current branch \$branch_name is up to date.")" finish_rebase exit 0 diff --git a/git-stash.sh b/git-stash.sh index d4cf818..cc28368 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -442,6 +442,8 @@ apply_stash () { assert_stash_like "$@" git update-index -q --refresh || die "$(gettext "unable to refresh index")" + git diff-index --cached --quiet --ignore-submodules HEAD -- || + die "$(gettext "Cannot apply stash: Your index contains uncommitted changes.")" # current index state c_tree=$(git write-tree) || diff --git a/revision.c b/revision.c index 6399a04..7ddbaa0 100644 --- a/revision.c +++ b/revision.c @@ -345,14 +345,24 @@ static struct commit *handle_commit(struct rev_info *revs, die("%s is unknown object", name); } -static int everybody_uninteresting(struct commit_list *orig) +static int everybody_uninteresting(struct commit_list *orig, + struct commit **interesting_cache) { struct commit_list *list = orig; + + if (*interesting_cache) { + struct commit *commit = *interesting_cache; + if (!(commit->object.flags & UNINTERESTING)) + return 0; + } + while (list) { struct commit *commit = list->item; list = list->next; if (commit->object.flags & UNINTERESTING) continue; + if (interesting_cache) + *interesting_cache = commit; return 0; } return 1; @@ -940,7 +950,8 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs) /* How many extra uninteresting commits we want to see.. */ #define SLOP 5 -static int still_interesting(struct commit_list *src, unsigned long date, int slop) +static int still_interesting(struct commit_list *src, unsigned long date, int slop, + struct commit **interesting_cache) { /* * No source list at all? We're definitely done.. @@ -959,7 +970,7 @@ static int still_interesting(struct commit_list *src, unsigned long date, int sl * Does the source list still have interesting commits in * it? Definitely not done.. */ - if (!everybody_uninteresting(src)) + if (!everybody_uninteresting(src, interesting_cache)) return SLOP; /* Ok, we're closing in.. */ @@ -1078,6 +1089,7 @@ static int limit_list(struct rev_info *revs) struct commit_list *newlist = NULL; struct commit_list **p = &newlist; struct commit_list *bottom = NULL; + struct commit *interesting_cache = NULL; if (revs->ancestry_path) { bottom = collect_bottom_commits(list); @@ -1094,6 +1106,9 @@ static int limit_list(struct rev_info *revs) list = list->next; free(entry); + if (commit == interesting_cache) + interesting_cache = NULL; + if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; if (add_parents_to_list(revs, commit, &list, NULL) < 0) @@ -1102,7 +1117,7 @@ static int limit_list(struct rev_info *revs) mark_parents_uninteresting(commit); if (revs->show_all) p = &commit_list_insert(commit, p)->next; - slop = still_interesting(list, date, slop); + slop = still_interesting(list, date, slop, &interesting_cache); if (slop) continue; /* If showing all, add the whole pending list to the end */ diff --git a/sha1_file.c b/sha1_file.c index f860d67..47f56f2 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -3009,9 +3009,8 @@ static int freshen_packed_object(const unsigned char *sha1) return 1; } -int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *returnsha1) +int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1) { - unsigned char sha1[20]; char hdr[32]; int hdrlen; @@ -3019,13 +3018,32 @@ int write_sha1_file(const void *buf, unsigned long len, const char *type, unsign * it out into .git/objects/??/?{38} file. */ write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen); - if (returnsha1) - hashcpy(returnsha1, sha1); if (freshen_packed_object(sha1) || freshen_loose_object(sha1)) return 0; return write_loose_object(sha1, hdr, hdrlen, buf, len, 0); } +int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, + unsigned char *sha1, unsigned flags) +{ + char *header; + int hdrlen, status = 0; + + /* type string, SP, %lu of the length plus NUL must fit this */ + header = xmalloc(strlen(type) + 32); + write_sha1_file_prepare(buf, len, type, sha1, header, &hdrlen); + + if (!(flags & HASH_WRITE_OBJECT)) + goto cleanup; + if (freshen_packed_object(sha1) || freshen_loose_object(sha1)) + goto cleanup; + status = write_loose_object(sha1, header, hdrlen, buf, len, 0); + +cleanup: + free(header); + return status; +} + int force_object_loose(const unsigned char *sha1, time_t mtime) { void *buf; diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index ebb3a69..7d2baa1 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -209,4 +209,15 @@ test_expect_success 'hash-object complains about truncated type name' ' test_must_fail git hash-object -t bl --stdin file && git add file && + echo unrelated >other-file && + git add other-file && test_tick && git commit -m initial && echo 2 > file && @@ -43,10 +45,15 @@ test_expect_success 'applying bogus stash does nothing' ' test_cmp expect file ' +test_expect_success 'apply requires a clean index' ' + test_when_finished "git reset --hard" && + echo changed >other-file && + git add other-file && + test_must_fail git stash apply +' + test_expect_success 'apply does not need clean working directory' ' echo 4 >other-file && - git add other-file && - echo 5 >other-file && git stash apply && echo 3 >expect && test_cmp expect file @@ -695,8 +702,8 @@ test_expect_success 'setup stash with index and worktree changes' ' ' test_expect_success 'stash list implies --first-parent -m' ' - cat >expect <<-\EOF && - stash@{0}: WIP on master: b27a2bc subdir + cat >expect <<-EOF && + stash@{0} diff --git a/file b/file index 257cc56..d26b33d 100644 @@ -706,13 +713,13 @@ test_expect_success 'stash list implies --first-parent -m' ' -foo +working EOF - git stash list -p >actual && + git stash list --format=%gd -p >actual && test_cmp expect actual ' test_expect_success 'stash list --cc shows combined diff' ' cat >expect <<-\EOF && - stash@{0}: WIP on master: b27a2bc subdir + stash@{0} diff --cc file index 257cc56,9015a7a..d26b33d @@ -723,7 +730,7 @@ test_expect_success 'stash list --cc shows combined diff' ' -index ++working EOF - git stash list -p --cc >actual && + git stash list --format=%gd -p --cc >actual && test_cmp expect actual ' diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 66643e4..855afda 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -394,4 +394,14 @@ test_expect_success 'replace submodule revision' ' test $orig_head != `git show-ref --hash --head HEAD` ' +test_expect_success 'filter commit message without trailing newline' ' + git reset --hard original && + commit=$(printf "no newline" | git commit-tree HEAD^{tree}) && + git update-ref refs/heads/no-newline $commit && + git filter-branch -f refs/heads/no-newline && + echo $commit >expect && + git rev-parse refs/heads/no-newline >actual && + test_cmp expect actual +' + test_done -- 2.7.4