aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-02-06 14:56:45 -0800
committerJunio C Hamano <gitster@pobox.com>2025-02-06 14:56:45 -0800
commit9d0e81e2ae3bd7f6d8a655be53c2396d7af3d2b0 (patch)
tree54481fadf7f95c85d003db2a4b591ce51cb266d5
parent9fad473faed7862855ced123de81a53fa27187d9 (diff)
parent78cdeed4c79d165c915e8de0355cc3fb7f5797c5 (diff)
downloadgit-9d0e81e2ae3bd7f6d8a655be53c2396d7af3d2b0.tar.gz
Merge branch 'ps/zlib-ng'
The code paths to interact with zlib has been cleaned up in preparation for building with zlib-ng. * ps/zlib-ng: ci: make "linux-musl" job use zlib-ng ci: switch linux-musl to use Meson compat/zlib: allow use of zlib-ng as backend git-zlib: cast away potential constness of `next_in` pointer compat/zlib: provide stubs for `deflateSetHeader()` compat/zlib: provide `deflateBound()` shim centrally git-compat-util: move include of "compat/zlib.h" into "git-zlib.h" compat: introduce new "zlib.h" header git-compat-util: drop `z_const` define compat: drop `uncompress2()` compatibility shim
-rw-r--r--.github/workflows/main.yml2
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--Makefile21
-rw-r--r--archive-tar.c4
-rw-r--r--archive.c1
-rwxr-xr-xci/install-dependencies.sh4
-rwxr-xr-xci/lib.sh5
-rwxr-xr-xci/run-build-and-tests.sh3
-rw-r--r--compat/zlib-compat.h53
-rw-r--r--compat/zlib-uncompress2.c96
-rw-r--r--config.c1
-rw-r--r--csum-file.c3
-rw-r--r--environment.c1
-rw-r--r--git-compat-util.h12
-rw-r--r--git-zlib.c7
-rw-r--r--git-zlib.h2
-rw-r--r--meson.build24
-rw-r--r--meson_options.txt4
-rw-r--r--reftable/block.c1
-rw-r--r--reftable/system.h1
20 files changed, 107 insertions, 140 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5d76999d09..5f756dfc2e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -390,7 +390,7 @@ jobs:
- jobname: linux-meson
image: ubuntu:rolling
cc: gcc
- - jobname: linux-musl
+ - jobname: linux-musl-meson
image: alpine:latest
# Supported until 2025-04-02.
- jobname: linux32
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index be00a1572c..629492694c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -60,7 +60,7 @@ test:linux:
CC: clang
- jobname: pedantic
image: fedora:latest
- - jobname: linux-musl
+ - jobname: linux-musl-meson
image: alpine:latest
- jobname: linux32
image: i386/ubuntu:20.04
diff --git a/Makefile b/Makefile
index 0739c5c1c0..40582cefdb 100644
--- a/Makefile
+++ b/Makefile
@@ -183,7 +183,8 @@ include shared.mak
# byte-order mark (BOM) when writing UTF-16 or UTF-32 and always writes in
# big-endian format.
#
-# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound.
+# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound. Define
+# ZLIB_NG if you want to use zlib-ng instead of zlib.
#
# Define NO_NORETURN if using buggy versions of gcc 4.6+ and profile feedback,
# as the compiler can crash (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299)
@@ -985,7 +986,6 @@ LIB_OBJS += commit.o
LIB_OBJS += compat/nonblock.o
LIB_OBJS += compat/obstack.o
LIB_OBJS += compat/terminal.o
-LIB_OBJS += compat/zlib-uncompress2.o
LIB_OBJS += config.o
LIB_OBJS += connect.o
LIB_OBJS += connected.o
@@ -1692,11 +1692,20 @@ else
endif
IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
-ifdef ZLIB_PATH
- BASIC_CFLAGS += -I$(ZLIB_PATH)/include
- EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib))
+ifdef ZLIB_NG
+ BASIC_CFLAGS += -DHAVE_ZLIB_NG
+ ifdef ZLIB_NG_PATH
+ BASIC_CFLAGS += -I$(ZLIB_NG_PATH)/include
+ EXTLIBS += $(call libpath_template,$(ZLIB_NG_PATH)/$(lib))
+ endif
+ EXTLIBS += -lz-ng
+else
+ ifdef ZLIB_PATH
+ BASIC_CFLAGS += -I$(ZLIB_PATH)/include
+ EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib))
+ endif
+ EXTLIBS += -lz
endif
-EXTLIBS += -lz
ifndef NO_OPENSSL
OPENSSL_LIBSSL = -lssl
diff --git a/archive-tar.c b/archive-tar.c
index e7b3489e1e..0edf13fba7 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -473,9 +473,7 @@ static const char internal_gzip_command[] = "git archive gzip";
static int write_tar_filter_archive(const struct archiver *ar,
struct archiver_args *args)
{
-#if ZLIB_VERNUM >= 0x1221
struct gz_header_s gzhead = { .os = 3 }; /* Unix, for reproducibility */
-#endif
struct strbuf cmd = STRBUF_INIT;
struct child_process filter = CHILD_PROCESS_INIT;
int r;
@@ -486,10 +484,8 @@ static int write_tar_filter_archive(const struct archiver *ar,
if (!strcmp(ar->filter_command, internal_gzip_command)) {
write_block = tgz_write_block;
git_deflate_init_gzip(&gzstream, args->compression_level);
-#if ZLIB_VERNUM >= 0x1221
if (deflateSetHeader(&gzstream.z, &gzhead) != Z_OK)
BUG("deflateSetHeader() called too late");
-#endif
gzstream.next_out = outbuf;
gzstream.avail_out = sizeof(outbuf);
diff --git a/archive.c b/archive.c
index b9c200cba6..8be4e7ac8d 100644
--- a/archive.c
+++ b/archive.c
@@ -7,6 +7,7 @@
#include "convert.h"
#include "environment.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "hex.h"
#include "object-name.h"
#include "path.h"
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index d5a959e25f..332ba96003 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -24,8 +24,8 @@ fi
case "$distro" in
alpine-*)
- apk add --update shadow sudo build-base curl-dev openssl-dev expat-dev gettext \
- pcre2-dev python3 musl-libintl perl-utils ncurses \
+ apk add --update shadow sudo meson ninja-build gcc libc-dev curl-dev openssl-dev expat-dev gettext \
+ zlib-ng-dev pcre2-dev python3 musl-libintl perl-utils ncurses \
apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \
bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null
;;
diff --git a/ci/lib.sh b/ci/lib.sh
index c2574edff2..028fea0e7b 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -349,10 +349,7 @@ linux32)
CC=gcc
;;
linux-musl)
- CC=gcc
- MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3 USE_LIBPCRE2=Yes"
- MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes"
- MAKEFLAGS="$MAKEFLAGS GIT_TEST_UTF8_LOCALE=C.UTF-8"
+ MESONFLAGS="$MESONFLAGS -DGIT_TEST_UTF8_LOCALE=C.UTF-8"
;;
linux-leaks|linux-reftable-leaks)
export SANITIZE=leak
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index 03d10c61d5..1c69846723 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -56,7 +56,8 @@ case "$jobname" in
--fatal-meson-warnings \
--warnlevel 2 --werror \
--wrap-mode nofallback \
- -Dfuzzers=true
+ -Dfuzzers=true \
+ $MESONFLAGS
group "Build" meson compile -C build --
if test -n "$run_tests"
then
diff --git a/compat/zlib-compat.h b/compat/zlib-compat.h
new file mode 100644
index 0000000000..0c60e3af33
--- /dev/null
+++ b/compat/zlib-compat.h
@@ -0,0 +1,53 @@
+#ifndef COMPAT_ZLIB_H
+#define COMPAT_ZLIB_H
+
+#ifdef HAVE_ZLIB_NG
+# include <zlib-ng.h>
+
+# define z_stream zng_stream
+#define gz_header_s zng_gz_header_s
+
+# define crc32(crc, buf, len) zng_crc32(crc, buf, len)
+
+# define inflate(strm, bits) zng_inflate(strm, bits)
+# define inflateEnd(strm) zng_inflateEnd(strm)
+# define inflateInit(strm) zng_inflateInit(strm)
+# define inflateInit2(strm, bits) zng_inflateInit2(strm, bits)
+# define inflateReset(strm) zng_inflateReset(strm)
+
+# define deflate(strm, flush) zng_deflate(strm, flush)
+# define deflateBound(strm, source_len) zng_deflateBound(strm, source_len)
+# define deflateEnd(strm) zng_deflateEnd(strm)
+# define deflateInit(strm, level) zng_deflateInit(strm, level)
+# define deflateInit2(stream, level, method, window_bits, mem_level, strategy) zng_deflateInit2(stream, level, method, window_bits, mem_level, strategy)
+# define deflateReset(strm) zng_deflateReset(strm)
+# define deflateSetHeader(strm, head) zng_deflateSetHeader(strm, head)
+
+#else
+# include <zlib.h>
+
+# if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
+# define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
+# endif
+
+/*
+ * zlib only gained support for setting up the gzip header in v1.2.2.1. In
+ * Git we only set the header to make archives reproducible across different
+ * operating systems, so it's fine to simply make this a no-op when using a
+ * zlib version that doesn't support this yet.
+ */
+# if ZLIB_VERNUM < 0x1221
+struct gz_header_s {
+ int os;
+};
+
+static int deflateSetHeader(z_streamp strm, struct gz_header_s *head)
+{
+ (void)(strm);
+ (void)(head);
+ return Z_OK;
+}
+# endif
+#endif /* HAVE_ZLIB_NG */
+
+#endif /* COMPAT_ZLIB_H */
diff --git a/compat/zlib-uncompress2.c b/compat/zlib-uncompress2.c
deleted file mode 100644
index 77a1b08048..0000000000
--- a/compat/zlib-uncompress2.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "git-compat-util.h"
-
-#if ZLIB_VERNUM < 0x1290
-/* taken from zlib's uncompr.c
-
- commit cacf7f1d4e3d44d871b605da3b647f07d718623f
- Author: Mark Adler <madler@alumni.caltech.edu>
- Date: Sun Jan 15 09:18:46 2017 -0800
-
- zlib 1.2.11
-
-*/
-
-/*
- * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* clang-format off */
-
-/* ===========================================================================
- Decompresses the source buffer into the destination buffer. *sourceLen is
- the byte length of the source buffer. Upon entry, *destLen is the total size
- of the destination buffer, which must be large enough to hold the entire
- uncompressed data. (The size of the uncompressed data must have been saved
- previously by the compressor and transmitted to the decompressor by some
- mechanism outside the scope of this compression library.) Upon exit,
- *destLen is the size of the decompressed data and *sourceLen is the number
- of source bytes consumed. Upon return, source + *sourceLen points to the
- first unused input byte.
-
- uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
- Z_DATA_ERROR if the input data was corrupted, including if the input data is
- an incomplete zlib stream.
-*/
-int ZEXPORT uncompress2 (
- Bytef *dest,
- uLongf *destLen,
- const Bytef *source,
- uLong *sourceLen) {
- z_stream stream;
- int err;
- const uInt max = (uInt)-1;
- uLong len, left;
- Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
-
- len = *sourceLen;
- if (*destLen) {
- left = *destLen;
- *destLen = 0;
- }
- else {
- left = 1;
- dest = buf;
- }
-
- stream.next_in = (z_const Bytef *)source;
- stream.avail_in = 0;
- stream.zalloc = (alloc_func)0;
- stream.zfree = (free_func)0;
- stream.opaque = (voidpf)0;
-
- err = inflateInit(&stream);
- if (err != Z_OK) return err;
-
- stream.next_out = dest;
- stream.avail_out = 0;
-
- do {
- if (stream.avail_out == 0) {
- stream.avail_out = left > (uLong)max ? max : (uInt)left;
- left -= stream.avail_out;
- }
- if (stream.avail_in == 0) {
- stream.avail_in = len > (uLong)max ? max : (uInt)len;
- len -= stream.avail_in;
- }
- err = inflate(&stream, Z_NO_FLUSH);
- } while (err == Z_OK);
-
- *sourceLen -= len + stream.avail_in;
- if (dest != buf)
- *destLen = stream.total_out;
- else if (stream.total_out && err == Z_BUF_ERROR)
- left = 1;
-
- inflateEnd(&stream);
- return err == Z_STREAM_END ? Z_OK :
- err == Z_NEED_DICT ? Z_DATA_ERROR :
- err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
- err;
-}
-#else
-static void *dummy_variable = &dummy_variable;
-#endif
diff --git a/config.c b/config.c
index 50f2d17b39..36f76fafe5 100644
--- a/config.c
+++ b/config.c
@@ -19,6 +19,7 @@
#include "convert.h"
#include "environment.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "ident.h"
#include "repository.h"
#include "lockfile.h"
diff --git a/csum-file.c b/csum-file.c
index 232121f415..c81645ba08 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -11,9 +11,10 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
-#include "progress.h"
#include "csum-file.h"
+#include "git-zlib.h"
#include "hash.h"
+#include "progress.h"
static void verify_buffer_or_die(struct hashfile *f,
const void *buf,
diff --git a/environment.c b/environment.c
index 8389a27270..e5b361bb5d 100644
--- a/environment.c
+++ b/environment.c
@@ -16,6 +16,7 @@
#include "convert.h"
#include "environment.h"
#include "gettext.h"
+#include "git-zlib.h"
#include "repository.h"
#include "config.h"
#include "refs.h"
diff --git a/git-compat-util.h b/git-compat-util.h
index d43dd248c4..e123288e8f 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1539,18 +1539,6 @@ int cmd_main(int, const char **);
int common_exit(const char *file, int line, int code);
#define exit(code) exit(common_exit(__FILE__, __LINE__, (code)))
-#define z_const
-#include <zlib.h>
-
-#if ZLIB_VERNUM < 0x1290
-/*
- * This is uncompress2, which is only available in zlib >= 1.2.9
- * (released as of early 2017). See compat/zlib-uncompress2.c.
- */
-int uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
- uLong *sourceLen);
-#endif
-
/*
* This include must come after system headers, since it introduces macros that
* replace system names.
diff --git a/git-zlib.c b/git-zlib.c
index d43bbeb6da..651dd9e07c 100644
--- a/git-zlib.c
+++ b/git-zlib.c
@@ -59,7 +59,8 @@ static void zlib_post_call(git_zstream *s)
s->total_out = s->z.total_out;
s->total_in = s->z.total_in;
- s->next_in = s->z.next_in;
+ /* zlib-ng marks `next_in` as `const`, so we have to cast it away. */
+ s->next_in = (unsigned char *) s->z.next_in;
s->next_out = s->z.next_out;
s->avail_in -= bytes_consumed;
s->avail_out -= bytes_produced;
@@ -147,10 +148,6 @@ int git_inflate(git_zstream *strm, int flush)
return status;
}
-#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
-#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
-#endif
-
unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
{
return deflateBound(&strm->z, size);
diff --git a/git-zlib.h b/git-zlib.h
index d8a670aff9..1e8d9aabcb 100644
--- a/git-zlib.h
+++ b/git-zlib.h
@@ -1,6 +1,8 @@
#ifndef GIT_ZLIB_H
#define GIT_ZLIB_H
+#include "compat/zlib-compat.h"
+
typedef struct git_zstream {
z_stream z;
unsigned long avail_in;
diff --git a/meson.build b/meson.build
index d54184befc..3d56d717c2 100644
--- a/meson.build
+++ b/meson.build
@@ -263,7 +263,6 @@ libgit_sources = [
'compat/nonblock.c',
'compat/obstack.c',
'compat/terminal.c',
- 'compat/zlib-uncompress2.c',
'config.c',
'connect.c',
'connected.c',
@@ -666,7 +665,7 @@ build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '')
build_options_config.set('GIT_TEST_INDEX_VERSION', '')
build_options_config.set('GIT_TEST_OPTS', '')
build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '')
-build_options_config.set('GIT_TEST_UTF8_LOCALE', '')
+build_options_config.set_quoted('GIT_TEST_UTF8_LOCALE', get_option('test_utf8_locale'))
build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir')))
build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb'))
@@ -799,11 +798,23 @@ else
build_options_config.set('NO_PERL_CPAN_FALLBACKS', '')
endif
-zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled'])
-if zlib.version().version_compare('<1.2.0')
- libgit_c_args += '-DNO_DEFLATE_BOUND'
+zlib_backend = get_option('zlib_backend')
+if zlib_backend in ['auto', 'zlib-ng']
+ zlib_ng = dependency('zlib-ng', required: zlib_backend == 'zlib-ng')
+ if zlib_ng.found()
+ zlib_backend = 'zlib-ng'
+ libgit_c_args += '-DHAVE_ZLIB_NG'
+ libgit_dependencies += zlib_ng
+ endif
+endif
+if zlib_backend in ['auto', 'zlib']
+ zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled'])
+ if zlib.version().version_compare('<1.2.0')
+ libgit_c_args += '-DNO_DEFLATE_BOUND'
+ endif
+ zlib_backend = 'zlib'
+ libgit_dependencies += zlib
endif
-libgit_dependencies += zlib
threads = dependency('threads', required: false)
if threads.found()
@@ -2012,4 +2023,5 @@ summary({
'sha1': sha1_backend,
'sha1_unsafe': sha1_unsafe_backend,
'sha256': sha256_backend,
+ 'zlib': zlib_backend,
}, section: 'Backends')
diff --git a/meson_options.txt b/meson_options.txt
index e62a433902..5c12e9055e 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -59,6 +59,8 @@ option('sha1_unsafe_backend', type: 'combo', choices: ['openssl', 'block', 'Comm
description: 'The backend used for hashing data with the SHA1 object format in case no cryptographic security is needed.')
option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', 'block'], value: 'block',
description: 'The backend used for hashing objects with the SHA256 object format.')
+option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], value: 'auto',
+ description: 'The backend used for compressing objects and other data.')
# Build tweaks.
option('breaking_changes', type: 'boolean', value: false,
@@ -101,5 +103,7 @@ option('tests', type: 'boolean', value: true,
description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.')
option('test_output_directory', type: 'string',
description: 'Path to the directory used to store test outputs')
+option('test_utf8_locale', type: 'string',
+ description: 'Name of a UTF-8 locale used for testing.')
option('fuzzers', type: 'boolean', value: false,
description: 'Enable building fuzzers.')
diff --git a/reftable/block.c b/reftable/block.c
index 8ac865ce78..b14a8f1259 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -13,7 +13,6 @@ https://developers.google.com/open-source/licenses/bsd
#include "record.h"
#include "reftable-error.h"
#include "system.h"
-#include <zlib.h>
size_t header_size(int version)
{
diff --git a/reftable/system.h b/reftable/system.h
index 7d5f803eeb..d02eacea8f 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -12,6 +12,7 @@ https://developers.google.com/open-source/licenses/bsd
/* This header glues the reftable library to the rest of Git */
#include "git-compat-util.h"
+#include "compat/zlib-compat.h"
/*
* An implementation-specific temporary file. By making this specific to the