diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Documentation/RelNotes/2.42.0.txt | 20 | ||||
-rw-r--r-- | Documentation/git-bisect.txt | 11 | ||||
-rwxr-xr-x | GIT-VERSION-GEN | 2 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | advice.c | 5 | ||||
-rw-r--r-- | compat/mingw.c | 5 | ||||
-rw-r--r-- | compat/mingw.h | 3 | ||||
-rw-r--r-- | hash-ll.h | 18 | ||||
-rw-r--r-- | ident.c | 1 | ||||
-rw-r--r-- | parse-options.c | 3 | ||||
-rw-r--r-- | run-command.c | 2 | ||||
-rw-r--r-- | sequencer.c | 26 | ||||
-rw-r--r-- | sha1/openssl.h | 49 | ||||
-rw-r--r-- | sha256/openssl.h | 49 | ||||
-rwxr-xr-x | t/t3418-rebase-continue.sh | 58 | ||||
-rwxr-xr-x | t/t3437-rebase-fixup-options.sh | 15 | ||||
-rwxr-xr-x | t/t4203-mailmap.sh | 4 | ||||
-rwxr-xr-x | t/t7518-ident-corner-cases.sh | 11 | ||||
-rw-r--r-- | t/test-lib-functions.sh | 33 |
20 files changed, 271 insertions, 51 deletions
diff --git a/.gitignore b/.gitignore index e875c59054..5e56e471b3 100644 --- a/.gitignore +++ b/.gitignore @@ -222,6 +222,7 @@ /TAGS /cscope* /compile_commands.json +/.cache/ *.hcc *.obj *.lib diff --git a/Documentation/RelNotes/2.42.0.txt b/Documentation/RelNotes/2.42.0.txt index f2262f84bf..62665697ff 100644 --- a/Documentation/RelNotes/2.42.0.txt +++ b/Documentation/RelNotes/2.42.0.txt @@ -258,6 +258,25 @@ Fixes since v2.41 submodule.<name>.update configuration variable. (merge 7cebc5bd78 pv/doc-submodule-update-settings later to maint). + * Adjust to OpenSSL 3+, which deprecates its SHA-1 functions based on + its traditional API, by using its EVP API instead. + (merge bda9c12073 ew/hash-with-openssl-evp later to maint). + + * Exclude "." from the set of characters to be removed from the + beginning and the end of the human-readable name. + (merge 1c04cb0744 bc/ident-dot-is-no-longer-crud-letter later to maint). + + * "git bisect visualize" stopped running "gitk" on Git for Windows + when the command was reimplemented in C around Git 2.34 timeframe. + This has been corrected. + (merge fff1594fa7 ma/locate-in-path-for-windows later to maint). + + * "git rebase -i" with a series of squash/fixup, when one of the + steps stopped in conflicts and ended up getting skipped, did not + handle the accumulated commit log messages, which has been + corrected. + (merge 6ce7afe163 pw/rebase-skip-commit-message-fix later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 51f9d2e563 sa/doc-ls-remote later to maint). (merge c6d26a9dda jk/format-patch-message-id-unleak later to maint). @@ -294,3 +313,4 @@ Fixes since v2.41 (merge 30c8c55cbf jc/tree-walk-drop-base-offset later to maint). (merge d089a06421 rs/bundle-parseopt-cleanup later to maint). (merge 823839bda1 ew/sha256-gcrypt-leak-fixes later to maint). + (merge a5c01603b3 bc/ignore-clangd-cache later to maint). diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index fbb39fbdf5..7872dba3ae 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -204,9 +204,14 @@ as an alternative to `visualize`): $ git bisect visualize ------------ -If the `DISPLAY` environment variable is not set, 'git log' is used -instead. You can also give command-line options such as `-p` and -`--stat`. +Git detects a graphical environment through various environment variables: +`DISPLAY`, which is set in X Window System environments on Unix systems. +`SESSIONNAME`, which is set under Cygwin in interactive desktop sessions. +`MSYSTEM`, which is set under Msys2 and Git for Windows. +`SECURITYSESSIONID`, which may be set on macOS in interactive desktop sessions. + +If none of these environment variables is set, 'git log' is used instead. +You can also give command-line options such as `-p` and `--stat`. ------------ $ git bisect visualize --stat diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 7313f8aa3e..a1afa6a2bd 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.42.0-rc0 +DEF_VER=v2.42.0-rc1 LF=' ' @@ -3216,6 +3216,12 @@ $(SP_OBJ): %.sp: %.c %.o sparse: $(SP_OBJ) EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% +ifndef OPENSSL_SHA1 + EXCEPT_HDRS += sha1/openssl.h +endif +ifndef OPENSSL_SHA256 + EXCEPT_HDRS += sha256/openssl.h +endif ifndef NETTLE_SHA256 EXCEPT_HDRS += sha256/nettle.h endif @@ -191,9 +191,10 @@ int error_resolve_conflict(const char *me) error(_("Pulling is not possible because you have unmerged files.")); else if (!strcmp(me, "revert")) error(_("Reverting is not possible because you have unmerged files.")); + else if (!strcmp(me, "rebase")) + error(_("Rebasing is not possible because you have unmerged files.")); else - error(_("It is not possible to %s because you have unmerged files."), - me); + BUG("Unhandled conflict reason '%s'", me); if (advice_enabled(ADVICE_RESOLVE_CONFLICT)) /* diff --git a/compat/mingw.c b/compat/mingw.c index f7f5d0ce0c..ec5280da16 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1347,6 +1347,11 @@ static char *path_lookup(const char *cmd, int exe_only) return prog; } +char *mingw_locate_in_PATH(const char *cmd) +{ + return path_lookup(cmd, 0); +} + static const wchar_t *wcschrnul(const wchar_t *s, wchar_t c) { while (*s && *s != c) diff --git a/compat/mingw.h b/compat/mingw.h index 5e34c87347..6aec50e412 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -177,6 +177,9 @@ pid_t waitpid(pid_t pid, int *status, int options); #define kill mingw_kill int mingw_kill(pid_t pid, int sig); +#define locate_in_PATH mingw_locate_in_PATH +char *mingw_locate_in_PATH(const char *cmd); + #ifndef NO_OPENSSL #include <openssl/ssl.h> static inline int mingw_SSL_set_fd(SSL *ssl, int fd) @@ -4,7 +4,11 @@ #if defined(SHA1_APPLE) #include <CommonCrypto/CommonDigest.h> #elif defined(SHA1_OPENSSL) -#include <openssl/sha.h> +# include <openssl/sha.h> +# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 +# define SHA1_NEEDS_CLONE_HELPER +# include "sha1/openssl.h" +# endif #elif defined(SHA1_DC) #include "sha1dc_git.h" #else /* SHA1_BLK */ @@ -17,7 +21,11 @@ #define SHA256_NEEDS_CLONE_HELPER #include "sha256/gcrypt.h" #elif defined(SHA256_OPENSSL) -#include <openssl/sha.h> +# include <openssl/sha.h> +# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 +# define SHA256_NEEDS_CLONE_HELPER +# include "sha256/openssl.h" +# endif #else #include "sha256/block/sha256.h" #endif @@ -41,6 +49,10 @@ #define git_SHA1_Update platform_SHA1_Update #define git_SHA1_Final platform_SHA1_Final +#ifdef platform_SHA1_Clone +#define git_SHA1_Clone platform_SHA1_Clone +#endif + #ifndef platform_SHA256_CTX #define platform_SHA256_CTX SHA256_CTX #define platform_SHA256_Init SHA256_Init @@ -63,10 +75,12 @@ #define git_SHA1_Update git_SHA1_Update_Chunked #endif +#ifndef SHA1_NEEDS_CLONE_HELPER static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src) { memcpy(dst, src, sizeof(*dst)); } +#endif #ifndef SHA256_NEEDS_CLONE_HELPER static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src) @@ -203,7 +203,6 @@ void reset_ident_date(void) static int crud(unsigned char c) { return c <= 32 || - c == '.' || c == ',' || c == ':' || c == ';' || diff --git a/parse-options.c b/parse-options.c index 87c9fae634..60224cf8d0 100644 --- a/parse-options.c +++ b/parse-options.c @@ -480,6 +480,9 @@ static void parse_options_check(const struct option *opts) opts->long_name)) optbug(opts, "uses feature " "not supported for dashless options"); + if (opts->type == OPTION_SET_INT && !opts->defval && + opts->long_name && !(opts->flags & PARSE_OPT_NONEG)) + optbug(opts, "OPTION_SET_INT 0 should not be negatable"); switch (opts->type) { case OPTION_COUNTUP: case OPTION_BIT: diff --git a/run-command.c b/run-command.c index b22ee36073..a558042c87 100644 --- a/run-command.c +++ b/run-command.c @@ -170,6 +170,7 @@ int is_executable(const char *name) return st.st_mode & S_IXUSR; } +#ifndef locate_in_PATH /* * Search $PATH for a command. This emulates the path search that * execvp would perform, without actually executing the command so it @@ -218,6 +219,7 @@ static char *locate_in_PATH(const char *file) strbuf_release(&buf); return NULL; } +#endif int exists_in_PATH(const char *command) { diff --git a/sequencer.c b/sequencer.c index adc9cfb4df..5e0c15a16b 100644 --- a/sequencer.c +++ b/sequencer.c @@ -5048,19 +5048,31 @@ static int commit_staged_changes(struct repository *r, * We need to update the squash message to skip * the latest commit message. */ + int res = 0; struct commit *commit; + const char *msg; const char *path = rebase_path_squash_msg(); const char *encoding = get_commit_output_encoding(); - if (parse_head(r, &commit) || - !(p = repo_logmsg_reencode(r, commit, NULL, encoding)) || - write_message(p, strlen(p), path, 0)) { - repo_unuse_commit_buffer(r, commit, p); - return error(_("could not write file: " + if (parse_head(r, &commit)) + return error(_("could not parse HEAD")); + + p = repo_logmsg_reencode(r, commit, NULL, encoding); + if (!p) { + res = error(_("could not parse commit %s"), + oid_to_hex(&commit->object.oid)); + goto unuse_commit_buffer; + } + find_commit_subject(p, &msg); + if (write_message(msg, strlen(msg), path, 0)) { + res = error(_("could not write file: " "'%s'"), path); + goto unuse_commit_buffer; } - repo_unuse_commit_buffer(r, - commit, p); + unuse_commit_buffer: + repo_unuse_commit_buffer(r, commit, p); + if (res) + return res; } } diff --git a/sha1/openssl.h b/sha1/openssl.h new file mode 100644 index 0000000000..006c1f4ba5 --- /dev/null +++ b/sha1/openssl.h @@ -0,0 +1,49 @@ +/* wrappers for the EVP API of OpenSSL 3+ */ +#ifndef SHA1_OPENSSL_H +#define SHA1_OPENSSL_H +#include <openssl/evp.h> + +struct openssl_SHA1_CTX { + EVP_MD_CTX *ectx; +}; + +typedef struct openssl_SHA1_CTX openssl_SHA1_CTX; + +static inline void openssl_SHA1_Init(struct openssl_SHA1_CTX *ctx) +{ + const EVP_MD *type = EVP_sha1(); + + ctx->ectx = EVP_MD_CTX_new(); + if (!ctx->ectx) + die("EVP_MD_CTX_new: out of memory"); + + EVP_DigestInit_ex(ctx->ectx, type, NULL); +} + +static inline void openssl_SHA1_Update(struct openssl_SHA1_CTX *ctx, + const void *data, + size_t len) +{ + EVP_DigestUpdate(ctx->ectx, data, len); +} + +static inline void openssl_SHA1_Final(unsigned char *digest, + struct openssl_SHA1_CTX *ctx) +{ + EVP_DigestFinal_ex(ctx->ectx, digest, NULL); + EVP_MD_CTX_free(ctx->ectx); +} + +static inline void openssl_SHA1_Clone(struct openssl_SHA1_CTX *dst, + const struct openssl_SHA1_CTX *src) +{ + EVP_MD_CTX_copy_ex(dst->ectx, src->ectx); +} + +#define platform_SHA_CTX openssl_SHA1_CTX +#define platform_SHA1_Init openssl_SHA1_Init +#define platform_SHA1_Clone openssl_SHA1_Clone +#define platform_SHA1_Update openssl_SHA1_Update +#define platform_SHA1_Final openssl_SHA1_Final + +#endif /* SHA1_OPENSSL_H */ diff --git a/sha256/openssl.h b/sha256/openssl.h new file mode 100644 index 0000000000..c1083d9491 --- /dev/null +++ b/sha256/openssl.h @@ -0,0 +1,49 @@ +/* wrappers for the EVP API of OpenSSL 3+ */ +#ifndef SHA256_OPENSSL_H +#define SHA256_OPENSSL_H +#include <openssl/evp.h> + +struct openssl_SHA256_CTX { + EVP_MD_CTX *ectx; +}; + +typedef struct openssl_SHA256_CTX openssl_SHA256_CTX; + +static inline void openssl_SHA256_Init(struct openssl_SHA256_CTX *ctx) +{ + const EVP_MD *type = EVP_sha256(); + + ctx->ectx = EVP_MD_CTX_new(); + if (!ctx->ectx) + die("EVP_MD_CTX_new: out of memory"); + + EVP_DigestInit_ex(ctx->ectx, type, NULL); +} + +static inline void openssl_SHA256_Update(struct openssl_SHA256_CTX *ctx, + const void *data, + size_t len) +{ + EVP_DigestUpdate(ctx->ectx, data, len); +} + +static inline void openssl_SHA256_Final(unsigned char *digest, + struct openssl_SHA256_CTX *ctx) +{ + EVP_DigestFinal_ex(ctx->ectx, digest, NULL); + EVP_MD_CTX_free(ctx->ectx); +} + +static inline void openssl_SHA256_Clone(struct openssl_SHA256_CTX *dst, + const struct openssl_SHA256_CTX *src) +{ + EVP_MD_CTX_copy_ex(dst->ectx, src->ectx); +} + +#define platform_SHA256_CTX openssl_SHA256_CTX +#define platform_SHA256_Init openssl_SHA256_Init +#define platform_SHA256_Clone openssl_SHA256_Clone +#define platform_SHA256_Update openssl_SHA256_Update +#define platform_SHA256_Final openssl_SHA256_Final + +#endif /* SHA256_OPENSSL_H */ diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 2d0789e554..fb7b68990c 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -115,15 +115,23 @@ test_expect_success '--skip after failed fixup cleans commit message' ' test_when_finished "test_might_fail git rebase --abort" && git checkout -b with-conflicting-fixup && test_commit wants-fixup && - test_commit "fixup! wants-fixup" wants-fixup.t 1 wants-fixup-1 && - test_commit "fixup! wants-fixup" wants-fixup.t 2 wants-fixup-2 && - test_commit "fixup! wants-fixup" wants-fixup.t 3 wants-fixup-3 && + test_commit "fixup 1" wants-fixup.t 1 wants-fixup-1 && + test_commit "fixup 2" wants-fixup.t 2 wants-fixup-2 && + test_commit "fixup 3" wants-fixup.t 3 wants-fixup-3 && test_must_fail env FAKE_LINES="1 fixup 2 squash 4" \ git rebase -i HEAD~4 && : now there is a conflict, and comments in the commit message && - git show HEAD >out && - grep "fixup! wants-fixup" out && + test_commit_message HEAD <<-\EOF && + # This is a combination of 2 commits. + # This is the 1st commit message: + + wants-fixup + + # The commit message #2 will be skipped: + + # fixup 1 + EOF : skip and continue && echo "cp \"\$1\" .git/copy.txt" | write_script copy-editor.sh && @@ -133,33 +141,49 @@ test_expect_success '--skip after failed fixup cleans commit message' ' test_path_is_missing .git/copy.txt && : now the comments in the commit message should have been cleaned up && - git show HEAD >out && - ! grep "fixup! wants-fixup" out && + test_commit_message HEAD -m wants-fixup && : now, let us ensure that "squash" is handled correctly && git reset --hard wants-fixup-3 && - test_must_fail env FAKE_LINES="1 squash 4 squash 2 squash 4" \ + test_must_fail env FAKE_LINES="1 squash 2 squash 1 squash 3 squash 1" \ git rebase -i HEAD~4 && - : the first squash failed, but there are two more in the chain && + : the second squash failed, but there are two more in the chain && (test_set_editor "$PWD/copy-editor.sh" && test_must_fail git rebase --skip) && : not the final squash, no need to edit the commit message && test_path_is_missing .git/copy.txt && - : The first squash was skipped, therefore: && - git show HEAD >out && - test_i18ngrep "# This is a combination of 2 commits" out && - test_i18ngrep "# This is the commit message #2:" out && + : The first and third squashes succeeded, therefore: && + test_commit_message HEAD <<-\EOF && + # This is a combination of 3 commits. + # This is the 1st commit message: + + wants-fixup + + # This is the commit message #2: + + fixup 1 + + # This is the commit message #3: + + fixup 2 + EOF (test_set_editor "$PWD/copy-editor.sh" && git rebase --skip) && - git show HEAD >out && - test_i18ngrep ! "# This is a combination" out && + test_commit_message HEAD <<-\EOF && + wants-fixup + + fixup 1 + + fixup 2 + EOF : Final squash failed, but there was still a squash && - test_i18ngrep "# This is a combination of 2 commits" .git/copy.txt && - test_i18ngrep "# This is the commit message #2:" .git/copy.txt + head -n1 .git/copy.txt >first-line && + test_i18ngrep "# This is a combination of 3 commits" first-line && + test_i18ngrep "# This is the commit message #3:" .git/copy.txt ' test_expect_success 'setup rerere database' ' diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh index dd3b301fa7..7929e2e2e3 100755 --- a/t/t3437-rebase-fixup-options.sh +++ b/t/t3437-rebase-fixup-options.sh @@ -21,21 +21,6 @@ TEST_PASSES_SANITIZE_LEAK=true EMPTY="" -# test_commit_message <rev> -m <msg> -# test_commit_message <rev> <path> -# Verify that the commit message of <rev> matches -# <msg> or the content of <path>. -test_commit_message () { - git show --no-patch --pretty=format:%B "$1" >actual && - case "$2" in - -m) - echo "$3" >expect && - test_cmp expect actual ;; - *) - test_cmp "$2" actual ;; - esac -} - get_author () { rev="$1" && git log -1 --pretty=format:"%an %ae %at" "$rev" diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index fa7f987284..2016132f51 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -466,7 +466,7 @@ test_expect_success 'gitmailmap(5) example output: example #1' ' Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@laptop.(none)> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> - Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)> + Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> EOF git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && @@ -494,7 +494,7 @@ test_expect_success 'gitmailmap(5) example output: example #2' ' Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@example.com> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> - Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@example.com> + Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@example.com> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> EOF git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh index fffdb6ff2e..9ab2ae2f3b 100755 --- a/t/t7518-ident-corner-cases.sh +++ b/t/t7518-ident-corner-cases.sh @@ -20,10 +20,19 @@ test_expect_success 'empty name and missing email' ' ' test_expect_success 'commit rejects all-crud name' ' - test_must_fail env GIT_AUTHOR_NAME=" .;<>" \ + test_must_fail env GIT_AUTHOR_NAME=" ,;<>" \ git commit --allow-empty -m foo ' +test_expect_success 'commit does not strip trailing dot' ' + author_name="Pat Doe Jr." && + env GIT_AUTHOR_NAME="$author_name" \ + git commit --allow-empty -m foo && + git log -1 --format=%an >actual && + echo "$author_name" >expected && + test_cmp actual expected +' + # We must test the actual error message here, as an unwanted # auto-detection could fail for other reasons. test_expect_success 'empty configured name does not auto-detect' ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 2fa716c567..2f8868caa1 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -1291,6 +1291,39 @@ test_cmp_rev () { fi } +# Tests that a commit message matches the expected text +# +# Usage: test_commit_message <rev> [-m <msg> | <file>] +# +# When using "-m" <msg> will have a line feed appended. If the second +# argument is omitted then the expected message is read from stdin. + +test_commit_message () { + local msg_file=expect.msg + + case $# in + 3) + if test "$2" = "-m" + then + printf "%s\n" "$3" >"$msg_file" + else + BUG "Usage: test_commit_message <rev> [-m <message> | <file>]" + fi + ;; + 2) + msg_file="$2" + ;; + 1) + cat >"$msg_file" + ;; + *) + BUG "Usage: test_commit_message <rev> [-m <message> | <file>]" + ;; + esac + git show --no-patch --pretty=format:%B "$1" -- >actual.msg && + test_cmp "$msg_file" actual.msg +} + # Compare paths respecting core.ignoreCase test_cmp_fspath () { if test "x$1" = "x$2" |