From 5d38ed8a579f1092b6c13e61c3fe82a6273f0a50 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 8 Nov 2016 16:39:44 +0100 Subject: [PATCH 1/8] Really work around "uninitialized value" warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ever since 457f08a (git-rev-list: add --bisect-vars option., 2007-03-21), Git's source code uses the following trick to fool GCC into *not* warning about uninitialized values: int value = value; We use this trick to silence the "warning: ‘x’ is used uninitialized in this function [-Wuninitialized]" when the variables are not really used uninitialized (but it is hard for the compiler to determine that). This trick works well for GCC, and even Clang seems to appease that workaround. Not so Visual C. It does realize that this is just a trick to fool it, and it simply refuses to be fooled. The only way to silence the warning for Visual C would be to write something like this: #pragma warning(suppress: 4700) int value; Obviously this is not portable, and neither is that trick that fools GCC. So let's just introduce a new macro that continues to fool GCC, but simply initializes the values everywhere else. Signed-off-by: Johannes Schindelin --- builtin/rev-list.c | 3 ++- fast-import.c | 4 ++-- git-compat-util.h | 17 +++++++++++++++++ merge-recursive.c | 2 +- read-cache.c | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/builtin/rev-list.c b/builtin/rev-list.c index d95acaa40e..9d8dc34758 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -479,7 +479,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) mark_edges_uninteresting(&revs, show_edge); if (bisect_list) { - int reaches = reaches, all = all; + FAKE_INIT(int, reaches, 0); + FAKE_INIT(int, all, 0); find_bisection(&revs.commits, &reaches, &all, bisect_find_all); diff --git a/fast-import.c b/fast-import.c index b70ac025e0..04023e7c5f 100644 --- a/fast-import.c +++ b/fast-import.c @@ -3003,7 +3003,7 @@ static void cat_blob(struct object_entry *oe, struct object_id *oid) static void parse_get_mark(const char *p) { - struct object_entry *oe = oe; + FAKE_INIT(struct object_entry *, oe, NULL); char output[GIT_MAX_HEXSZ + 2]; /* get-mark SP LF */ @@ -3020,7 +3020,7 @@ static void parse_get_mark(const char *p) static void parse_cat_blob(const char *p) { - struct object_entry *oe = oe; + FAKE_INIT(struct object_entry *, oe, NULL); struct object_id oid; /* cat-blob SP LF */ diff --git a/git-compat-util.h b/git-compat-util.h index bbd92a8627..6069a4bffb 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -51,6 +51,23 @@ #endif #endif +/* + * Under certain circumstances Git's source code is cleverer than the C + * compiler when the latter warns about some "uninitialized value", e.g. when + * a value is both initialized and used under the same condition. + * + * GCC can be fooled to not spit out this warning by using the construct: + * "int value = value;". Other C compilers are not that easily fooled and would + * require a #pragma (which is not portable, and would litter the source code). + * + * To keep things simple, we only fool GCC, and initialize such values instead + * when compiling with other C compilers. + */ +#ifdef __GNUC__ +#define FAKE_INIT(a, b, c) a b = b +#else +#define FAKE_INIT(a, b, c) a b = c +#endif /* * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. diff --git a/merge-recursive.c b/merge-recursive.c index cc5fa0a949..12c968eeaa 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -2070,7 +2070,7 @@ int merge_recursive(struct merge_options *o, { struct commit_list *iter; struct commit *merged_common_ancestors; - struct tree *mrtree = mrtree; + FAKE_INIT(struct tree *, mrtree, NULL); int clean; if (show(o, 4)) { diff --git a/read-cache.c b/read-cache.c index 198e72b685..0e41ceac36 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2104,7 +2104,7 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce, struct strbuf *previous_name, struct ondisk_cache_entry *ondisk) { int size; - int saved_namelen = saved_namelen; /* compiler workaround */ + FAKE_INIT(int, saved_namelen, 0); int result; static unsigned char padding[8] = { 0x00 }; From 9d65f86b7a28c28bb460f3c49b6274a4b1324e5c Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Sun, 19 Jul 2015 15:59:04 +0100 Subject: [PATCH 2/8] perl/Makefile: treat a missing PM.stamp as if empty 'make clean', or a 'git clean -dfx' will delete the PM stamp file, so it cannot be a direct target in such clean conditions, resulting in an error. Normally the PM.stamp is recreated by the git/Makefile, except when a dry-run is requested, for example, as used in the msysgit msvc-build script which implements the compat/vcbuild/README using contrib/buildsystems. The script msvc-build is introduced later in this series. Protect the PM.stamp target when the PM.stamp file does not exist, allowing a Git 'Makefile -n' to succeed on a clean repo. Signed-off-by: Philip Oakley --- This is development of the original "[PATCH 4/17] Makefile: a dry-run can error out if no perl. Document the issue" 2015-06-25, (http://marc.info/?l=git&m=143519054716960&w=2), which simply documented the issue and then used NO_PERL to avoid the problem. See follow on email thread for some discussion. --- perl/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/perl/Makefile b/perl/Makefile index f657de20e3..cf2f699362 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -22,7 +22,9 @@ clean: $(RM) $(makfile).old $(RM) PM.stamp +ifneq (,$(wildcard PM.stamp)) $(makfile): PM.stamp +endif ifdef NO_PERL_MAKEMAKER instdir_SQ = $(subst ','\'',$(prefix)/lib) From 66b557ab5ddcc006c3d7c0633ebf749f87f2f5a5 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Fri, 6 May 2016 11:46:05 +0100 Subject: [PATCH 3/8] Avoid multiple PREFIX definitions The short and sweet PREFIX can be confused when used in many places. Rename both usages to better describe their purpose. EXEC_CMD_PREFIX is used in full to disambiguate it from the nearby GIT_EXEC_PATH. The PREFIX in sideband.c, while nominally independant of the exec_cmd PREFIX, does reside within libgit[1], so the definitions would clash when taken together with a PREFIX given on the command line for use by exec_cmd.c. Noticed when compiling Git for Windows using MSVC/Visual Studio [1] which reports the conflict beteeen the command line definition and the definition in sideband.c within the libgit project. [1] the libgit functions are brought into a single sub-project within the Visual Studio construction script provided in contrib, and hence uses a single command for both exec_cmd.c and sideband.c. Signed-off-by: Philip Oakley --- Makefile | 2 +- exec_cmd.c | 4 ++-- sideband.c | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 35897be59f..ee5b225546 100644 --- a/Makefile +++ b/Makefile @@ -2155,7 +2155,7 @@ exec_cmd.sp exec_cmd.s exec_cmd.o: GIT-PREFIX exec_cmd.sp exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \ '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \ '-DBINDIR="$(bindir_relative_SQ)"' \ - '-DPREFIX="$(prefix_SQ)"' + '-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"' builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX builtin/init-db.sp builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \ diff --git a/exec_cmd.c b/exec_cmd.c index ce192a2d64..978af936f7 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -20,7 +20,7 @@ static const char *system_prefix(void) !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) && !(prefix = strip_path_suffix(argv0_path, BINDIR)) && !(prefix = strip_path_suffix(argv0_path, "git"))) { - prefix = PREFIX; + prefix = FALLBACK_RUNTIME_PREFIX; trace_printf("RUNTIME_PREFIX requested, " "but prefix computation failed. " "Using static fallback '%s'.\n", prefix); @@ -45,7 +45,7 @@ void git_extract_argv0_path(const char *argv0) static const char *system_prefix(void) { - return PREFIX; + return FALLBACK_RUNTIME_PREFIX; } void git_extract_argv0_path(const char *argv0) diff --git a/sideband.c b/sideband.c index 6d7f943e43..325bf0e974 100644 --- a/sideband.c +++ b/sideband.c @@ -13,7 +13,7 @@ * the remote died unexpectedly. A flush() concludes the stream. */ -#define PREFIX "remote: " +#define DISPLAY_PREFIX "remote: " #define ANSI_SUFFIX "\033[K" #define DUMB_SUFFIX " " @@ -49,7 +49,7 @@ int recv_sideband(const char *me, int in_stream, int out) switch (band) { case 3: strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "", - PREFIX, buf + 1); + DISPLAY_PREFIX, buf + 1); retval = SIDEBAND_REMOTE_ERROR; break; case 2: @@ -67,7 +67,7 @@ int recv_sideband(const char *me, int in_stream, int out) int linelen = brk - b; if (!outbuf.len) - strbuf_addstr(&outbuf, PREFIX); + strbuf_addstr(&outbuf, DISPLAY_PREFIX); if (linelen > 0) { strbuf_addf(&outbuf, "%.*s%s%c", linelen, b, suffix, *brk); @@ -81,8 +81,8 @@ int recv_sideband(const char *me, int in_stream, int out) } if (*b) - strbuf_addf(&outbuf, "%s%s", - outbuf.len ? "" : PREFIX, b); + strbuf_addf(&outbuf, "%s%s", outbuf.len ? + "" : DISPLAY_PREFIX, b); break; case 1: write_or_die(out, buf + 1, len); From e140160eaac5544044fefa1584e0c93a32538af6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 27 Oct 2016 06:25:56 -0700 Subject: [PATCH 4/8] obstack: fix compiler warning MS Visual C suggests that the construct condition ? (int) i : (ptrdiff_t) d is incorrect. Let's fix this by casting to ptrdiff_t also for the positive arm of the conditional. Signed-off-by: Johannes Schindelin --- compat/obstack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/obstack.h b/compat/obstack.h index 6bc24b7644..f0807eaa3b 100644 --- a/compat/obstack.h +++ b/compat/obstack.h @@ -492,7 +492,7 @@ __extension__ \ ( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ ((((h)->temp.tempint > 0 \ && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ - ? (int) ((h)->next_free = (h)->object_base \ + ? (ptrdiff_t) ((h)->next_free = (h)->object_base \ = (h)->temp.tempint + (char *) (h)->chunk) \ : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) From 86dc23d5d620472b2c8a9cc1d2a8f66afb09f6a2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 27 Oct 2016 08:06:29 -0700 Subject: [PATCH 5/8] terminal.c: guard the inclusion of inttypes.h We do have a lovely Makefile option to state that that header file is not available. Let's use it everywhere... Signed-off-by: Johannes Schindelin --- compat/terminal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compat/terminal.c b/compat/terminal.c index 1d37f0aafb..d9d3945afa 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -1,4 +1,6 @@ +#ifndef NO_INTTYPES_H #include +#endif #include "git-compat-util.h" #include "run-command.h" #include "compat/terminal.h" From 810c221d73a61f1ca3f458b42440dc08b95218ed Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 25 Nov 2016 18:29:51 +0100 Subject: [PATCH 6/8] Ensure that bin-wrappers/* targets adds `.exe` if necessary When compiling with Visual Studio, the projects' names are identical to the executables modulo the extensions. Which means that the bin-wrappers *need* to target the .exe files lest they try to execute directories. Signed-off-by: Johannes Schindelin --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ee5b225546..0b1f8f5a34 100644 --- a/Makefile +++ b/Makefile @@ -2451,7 +2451,7 @@ bin-wrappers/%: wrap-for-bin.sh @mkdir -p bin-wrappers $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's|@@BUILD_DIR@@|$(shell pwd)|' \ - -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))|' < $< > $@ && \ + -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \ chmod +x $@ # GNU make supports exporting all variables by "export" without parameters. From 87ab963968f43243e49ea283e8b3f3f1ce6bebbd Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 29 Nov 2016 23:07:18 +0100 Subject: [PATCH 7/8] windows: clarify the need for invalidcontinue.obj Git's source code wants to be able to close() the same file descriptor multiple times, ignoring the error returned by the second call (and the ones after that), or to access the osfhandle of an already-closed stdout, among other things that the UCRT does not like. Simply linking invalidcontinue.obj allows such usage without resorting to Debug Assertions (or exiting with exit code 9 in Release Mode). Let's add a note so we don't forget, as suggested by Jeff Hostetler. See https://msdn.microsoft.com/en-us/library/ms235330.aspx for more details. Signed-off-by: Johannes Schindelin --- config.mak.uname | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.mak.uname b/config.mak.uname index 029e5cdaa0..1cd42fa3d2 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -387,6 +387,9 @@ ifeq ($(uname_S),Windows) compat/win32/dirent.o compat/win32/fscache.o COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\" BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE + # invalidcontinue.obj allows Git's source code to close the same file + # handle twice, or to access the osfhandle of an already-closed stdout + # See https://msdn.microsoft.com/en-us/library/ms235330.aspx EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib PTHREAD_LIBS = lib = From e50afdbfc49341c8a813f3708e4a210f9be5fd3b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Nov 2016 12:00:59 +0100 Subject: [PATCH 8/8] t5505,t5516: create .git/branches/ when needed It is a real old anachronism from the Cogito days to have a .git/branches/ directory. And to have tests that ensure that Cogito users can migrate away from using that directory. But so be it, let's continue testing it. Let's make sure, however, that git init does not need to create that directory. This bug was noticed when testing with templates that had been pre-committed, skipping the empty branches/ directory of course because Git does not track empty directories. Signed-off-by: Johannes Schindelin --- t/t5505-remote.sh | 2 ++ t/t5516-fetch-push.sh | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index a6c0178f3a..f14afab5dd 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -830,6 +830,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' ( cd six && git remote rm origin && + mkdir -p .git/branches && echo "$origin_url" >.git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && @@ -844,6 +845,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' ( cd seven && git remote rm origin && + mkdir -p .git/branches && echo "quux#foom" > .git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 177897ea0b..457f648ad9 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -866,6 +866,7 @@ test_expect_success 'fetch with branches' ' mk_empty testrepo && git branch second $the_first_commit && git checkout second && + mkdir -p testrepo/.git/branches && echo ".." > testrepo/.git/branches/branch1 && ( cd testrepo && @@ -879,6 +880,7 @@ test_expect_success 'fetch with branches' ' test_expect_success 'fetch with branches containing #' ' mk_empty testrepo && + mkdir -p testrepo/.git/branches && echo "..#second" > testrepo/.git/branches/branch2 && ( cd testrepo && @@ -893,6 +895,7 @@ test_expect_success 'fetch with branches containing #' ' test_expect_success 'push with branches' ' mk_empty testrepo && git checkout second && + mkdir -p .git/branches && echo "testrepo" > .git/branches/branch1 && git push branch1 && ( @@ -905,6 +908,7 @@ test_expect_success 'push with branches' ' test_expect_success 'push with branches containing #' ' mk_empty testrepo && + mkdir -p .git/branches && echo "testrepo#branch3" > .git/branches/branch2 && git push branch2 && (