summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig4
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md5
-rw-r--r--azure-pipelines.yml8
-rw-r--r--azure-pipelines/docker.yml6
-rw-r--r--azure-pipelines/docker/bionic14
-rw-r--r--azure-pipelines/docker/entrypoint.sh4
-rw-r--r--azure-pipelines/docker/xenial10
-rwxr-xr-xazure-pipelines/setup-linux.sh27
-rw-r--r--cmake/Modules/PkgBuildConfig.cmake39
-rw-r--r--deps/ntlmclient/compat.h22
-rw-r--r--docs/changelog.md360
-rw-r--r--docs/fuzzing.md13
-rw-r--r--include/git2/version.h6
-rwxr-xr-xscript/release.py171
-rw-r--r--src/CMakeLists.txt11
-rw-r--r--src/cache.c12
-rw-r--r--src/indexer.c6
-rw-r--r--src/notes.c9
-rw-r--r--src/odb_pack.c1
-rw-r--r--src/pack-objects.c4
-rw-r--r--src/pack.c22
-rw-r--r--src/push.c5
-rw-r--r--src/repository.c113
-rw-r--r--src/revwalk.c2
-rw-r--r--src/sha1_lookup.c35
-rw-r--r--src/sha1_lookup.h19
-rw-r--r--src/streams/openssl.c76
-rw-r--r--src/transports/auth_ntlm.c4
-rw-r--r--src/transports/httpclient.c13
-rw-r--r--src/unix/posix.h2
-rw-r--r--src/worktree.c72
-rw-r--r--tests/blame/blame_helpers.c4
-rw-r--r--tests/blame/blame_helpers.h2
-rw-r--r--tests/config/global.c2
-rw-r--r--tests/config/new.c2
-rw-r--r--tests/diff/tree.c49
-rw-r--r--tests/diff/workdir.c43
-rw-r--r--tests/ignore/path.c5
-rw-r--r--tests/index/nsec.c2
-rw-r--r--tests/index/tests.c3
-rw-r--r--tests/network/refspecs.c2
-rw-r--r--tests/notes/notes.c12
-rw-r--r--tests/object/cache.c8
44 files changed, 919 insertions, 315 deletions
diff --git a/.editorconfig b/.editorconfig
index 34c5e9234..2230fd860 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -15,3 +15,7 @@ indent_size = 2
indent_style = space
indent_size = 4
trim_trailing_whitespace = false
+
+[*.py]
+indent_style = space
+indent_size = 4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8765a97b5..113e554d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,7 +58,6 @@ OPTION(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS/Gene
OPTION(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
OPTION(USE_STANDALONE_FUZZERS "Enable standalone fuzzers (compatible with gcc)" OFF)
OPTION(USE_LEAK_CHECKER "Run tests with leak checker" OFF)
-OPTION(VALGRIND "Configure build for valgrind" OFF)
OPTION(DEBUG_POOL "Enable debug pool allocator" OFF)
OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF)
OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
@@ -111,8 +110,8 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_V
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
-FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$")
-STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
+FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION \"([0-9.]+)\"$")
+STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION \"([0-9.]+)\"$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
IF (DEPRECATE_HARD)
ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD)
diff --git a/README.md b/README.md
index 9dafffec0..ef85fd9f6 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,8 @@ libgit2 - the Git linkable library
| Build Status | |
| ------------ | - |
| **master** branch CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=master)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=master) |
+| **v0.99 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.99)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.99) |
| **v0.28 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.28)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.28) |
-| **v0.27 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.27)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.27) |
-| **v0.26 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.26)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.26) |
| **Nightly** builds | [![Azure Pipelines Build Status](https://libgit2.visualstudio.com/libgit2/_apis/build/status/nightly?branchName=master&label=Full+Build)](https://libgit2.visualstudio.com/libgit2/_build/latest?definitionId=9&branchName=master) [![Coverity Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/coverity?branchName=master&label=Coverity+Build)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=21?branchName=master) [![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) |
`libgit2` is a portable, pure C implementation of the Git core methods
@@ -330,6 +329,8 @@ Here are the bindings to libgit2 that are currently available:
* hgit2 <https://github.com/jwiegley/gitlib>
* Java
* Jagged <https://github.com/ethomson/jagged>
+* Javascript / WebAssembly ( browser and nodejs )
+ * WASM-git <https://github.com/petersalomonsen/wasm-git>
* Julia
* LibGit2.jl <https://github.com/JuliaLang/julia/tree/master/stdlib/LibGit2>
* Lua
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2b593dd2c..2575f475f 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -19,7 +19,7 @@ jobs:
environmentVariables: |
CC=gcc
CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DVALGRIND=on -DUSE_GSSAPI=ON
+ CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
- job: linux_amd64_xenial_gcc_mbedtls
@@ -35,7 +35,7 @@ jobs:
environmentVariables: |
CC=gcc
CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DVALGRIND=on -DUSE_GSSAPI=ON
+ CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
- job: linux_amd64_xenial_clang_openssl
@@ -51,7 +51,7 @@ jobs:
environmentVariables: |
CC=clang
CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DVALGRIND=on -DUSE_GSSAPI=ON
+ CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
- job: linux_amd64_xenial_clang_mbedtls
@@ -67,7 +67,7 @@ jobs:
environmentVariables: |
CC=clang
CMAKE_GENERATOR=Ninja
- CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DVALGRIND=on -DUSE_GSSAPI=ON
+ CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }}
- job: macos
diff --git a/azure-pipelines/docker.yml b/azure-pipelines/docker.yml
index 0e1988c8a..0f0885770 100644
--- a/azure-pipelines/docker.yml
+++ b/azure-pipelines/docker.yml
@@ -13,9 +13,9 @@ steps:
if [ -f /tmp/dockercache/${{parameters.docker.image}}.tar ]; then docker load < /tmp/dockercache/${{parameters.docker.image}}.tar; fi
displayName: 'Load Docker cache'
- script: |
- cd $(Build.SourcesDirectory)/azure-pipelines/docker
- docker build -t libgit2/${{parameters.docker.image}} --build-arg BASE=${{parameters.docker.base}} -f ${{parameters.docker.image}} .
- if [ ! -d /tmp/dockercache ]; then mkdir /tmp/dockercache; fi
+ cd $(Build.SourcesDirectory)/azure-pipelines/docker &&
+ docker build -t libgit2/${{parameters.docker.image}} --build-arg BASE=${{parameters.docker.base}} -f ${{parameters.docker.image}} . &&
+ if [ ! -d /tmp/dockercache ]; then mkdir /tmp/dockercache; fi &&
docker save libgit2/${{parameters.docker.image}} $(docker history -q libgit2/${{parameters.docker.image}} | grep -v '<missing>') > /tmp/dockercache/${{parameters.docker.image}}.tar
displayName: 'Build Docker image'
- task: docker@0
diff --git a/azure-pipelines/docker/bionic b/azure-pipelines/docker/bionic
index 648bda704..33175a0b7 100644
--- a/azure-pipelines/docker/bionic
+++ b/azure-pipelines/docker/bionic
@@ -1,13 +1,12 @@
ARG BASE
-FROM $BASE
+FROM $BASE AS apt
RUN apt-get update && \
- apt-get install -y --no-install-recommends \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
clang \
cmake \
curl \
gcc \
git \
- gosu \
libcurl4-openssl-dev \
libpcre3-dev \
libssh2-1-dev \
@@ -19,13 +18,16 @@ RUN apt-get update && \
openssl \
pkgconf \
python \
+ sudo \
valgrind \
&& \
rm -rf /var/lib/apt/lists/*
-RUN mkdir /var/run/sshd
+FROM apt AS mbedtls
RUN cd /tmp && \
- curl --location --silent https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
+ curl --location http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt | openssl x509 -inform der -out /tmp/cacert.pem && \
+ curl --location https://curl.haxx.se/ca/cacert.pem >> /tmp/cacert.pem && \
+ curl --location --silent https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz --cacert /tmp/cacert.pem | \
tar -xz && \
cd mbedtls-2.16.2 && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
@@ -34,7 +36,9 @@ RUN cd /tmp && \
cd .. && \
rm -rf mbedtls-2.16.2
+FROM mbedtls AS configure
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod a+x /usr/local/bin/entrypoint.sh
+RUN mkdir /var/run/sshd
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
diff --git a/azure-pipelines/docker/entrypoint.sh b/azure-pipelines/docker/entrypoint.sh
index 38eedf02b..8d96e3acd 100644
--- a/azure-pipelines/docker/entrypoint.sh
+++ b/azure-pipelines/docker/entrypoint.sh
@@ -1,4 +1,4 @@
#!/bin/bash -e
useradd --shell /bin/bash libgit2
-chown -R $(id -u libgit2) /home/libgit2
-exec gosu libgit2 "$@"
+chown --recursive libgit2:libgit2 /home/libgit2
+exec sudo --preserve-env --set-home --user=libgit2 "$@"
diff --git a/azure-pipelines/docker/xenial b/azure-pipelines/docker/xenial
index cb5d4919a..475956f3d 100644
--- a/azure-pipelines/docker/xenial
+++ b/azure-pipelines/docker/xenial
@@ -8,7 +8,6 @@ RUN apt-get update && \
curl \
gcc \
git \
- gosu \
krb5-user \
libcurl4-gnutls-dev \
libgcrypt20-dev \
@@ -23,11 +22,16 @@ RUN apt-get update && \
openssl \
pkgconf \
python \
- valgrind
+ sudo \
+ valgrind \
+ && \
+ rm -rf /var/lib/apt/lists/*
FROM apt AS mbedtls
RUN cd /tmp && \
- curl --location --silent https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
+ curl --location http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt | openssl x509 -inform der -out /tmp/cacert.pem && \
+ curl --location https://curl.haxx.se/ca/cacert.pem >> /tmp/cacert.pem && \
+ curl --location --silent https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz --cacert /tmp/cacert.pem | \
tar -xz && \
cd mbedtls-2.16.2 && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
diff --git a/azure-pipelines/setup-linux.sh b/azure-pipelines/setup-linux.sh
deleted file mode 100755
index c5ecb550b..000000000
--- a/azure-pipelines/setup-linux.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-set -e
-set -x
-
-TMPDIR=${TMPDIR:-/tmp}
-
-if [ -z "$SKIP_APT" ]; then
- apt-get update
- apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server
-fi
-
-mkdir -p /var/run/sshd
-
-if [ "$MBEDTLS" ]; then
- MBEDTLS_DIR=${MBEDTLS_DIR:-$(mktemp -d ${TMPDIR}/mbedtls.XXXXXXXX)}
-
- git clone --depth 10 --single-branch --branch mbedtls-2.6.1 https://github.com/ARMmbed/mbedtls.git ${MBEDTLS_DIR}
- cd ${MBEDTLS_DIR}
-
- CFLAGS=-fPIC cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON .
- cmake --build .
-
- if [ -z "$SKIP_MBEDTLS_INSTALL" ]; then
- make install
- fi
-fi
diff --git a/cmake/Modules/PkgBuildConfig.cmake b/cmake/Modules/PkgBuildConfig.cmake
index 1c0079eb0..e4c574431 100644
--- a/cmake/Modules/PkgBuildConfig.cmake
+++ b/cmake/Modules/PkgBuildConfig.cmake
@@ -1,10 +1,5 @@
# pkg-config file generation
#
-# Uses the following globals:
-# - PKG_BUILD_PREFIX: the build location (aka prefix). Defaults to CMAKE_INSTALL_PREFIX
-# - PKG_BUILD_LIBDIR: the libdir location. Defaults to ${prefix}/lib.
-# - PKG_BUILD_INCLUDEDIR: the includedir location. Defaults to ${prefix}/include.
-#
function(pkg_build_config)
set(options)
@@ -29,37 +24,11 @@ function(pkg_build_config)
message(FATAL_ERROR "Missing VERSION argument")
endif()
- if (DEFINED PKG_BUILD_PREFIX)
- set(PKGCONFIG_PREFIX "${PKG_BUILD_PREFIX}")
- else()
- set(PKGCONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}")
- endif()
-
- if(DEFINED PKG_BUILD_LIBDIR)
- if (IS_ABSOLUTE ${PKG_BUILD_LIBDIR})
- set(PKGCONFIG_LIBDIR ${PKG_BUILD_LIBDIR})
- else()
- set(PKGCONFIG_LIBDIR "\${prefix}/${PKG_BUILD_LIBDIR}")
- endif()
- else()
- set(PKGCONFIG_LIBDIR "\${prefix}/lib")
- endif()
-
- if(DEFINED PKG_BUILD_INCLUDEDIR)
- if (IS_ABSOLUTE ${PKG_BUILD_INCLUDEDIR})
- set(PKGCONFIG_INCLUDEDIR ${PKG_BUILD_INCLUDEDIR})
- else()
- set(PKGCONFIG_INCLUDEDIR "\${prefix}/${PKG_BUILD_INCLUDEDIR}")
- endif()
- else()
- set(PKGCONFIG_INCLUDEDIR "\${prefix}/include")
- endif()
-
# Write .pc "header"
file(WRITE "${PKGCONFIG_FILE}"
- "prefix=\"${PKGCONFIG_PREFIX}\"\n"
- "libdir=\"${PKGCONFIG_LIBDIR}\"\n"
- "includedir=\"${PKGCONFIG_INCLUDEDIR}\"\n"
+ "prefix=\"${CMAKE_INSTALL_PREFIX}\"\n"
+ "libdir=\"${LIB_INSTALL_DIR}\"\n"
+ "includedir=\"${INCLUDE_INSTALL_DIR}\"\n"
"\n"
"Name: ${PKGCONFIG_NAME}\n"
"Description: ${PKGCONFIG_DESCRIPTION}\n"
@@ -105,6 +74,6 @@ function(pkg_build_config)
# Install .pc file
install(FILES "${PKGCONFIG_FILE}"
- DESTINATION "${PKGCONFIG_PREFIX}/${PKGCONFIG_LIBDIR}/pkgconfig"
+ DESTINATION "${LIB_INSTALL_DIR}/pkgconfig"
)
endfunction()
diff --git a/deps/ntlmclient/compat.h b/deps/ntlmclient/compat.h
index efdf34514..555fa3fe4 100644
--- a/deps/ntlmclient/compat.h
+++ b/deps/ntlmclient/compat.h
@@ -22,8 +22,30 @@
#endif
#ifdef __linux__
+/* See man page endian(3) */
# include <endian.h>
# define htonll htobe64
+#elif defined(__OpenBSD__)
+/* See man page htobe64(3) */
+# include <endian.h>
+# define htonll htobe64
+#elif defined(__FreeBSD__)
+/* See man page bwaps64(9) */
+# include <sys/endian.h>
+# define htonll htobe64
+#elif defined(sun) || defined(__sun)
+/* See man page byteorder(3SOCKET) */
+# include <sys/types.h>
+# include <netinet/in.h>
+# include <inttypes.h>
+
+# if !defined(htonll)
+# if defined(_BIG_ENDIAN)
+# define htonll(x) (x)
+# else
+# define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl((uint64_t)(x) >> 32))
+# endif
+# endif
#endif
#ifndef MIN
diff --git a/docs/changelog.md b/docs/changelog.md
index c75164901..2c50a6611 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,289 @@
-v0.28 + 1
----------
+v0.99
+-----
+
+This is v0.99 "Torschlusspanik". This will be the last minor release
+before libgit2 v1.0. We expect to only respond to bugs in this release,
+to stabilize it for next major release.
+
+It contains significant refactorings, but is expected to be API-compatible
+with v0.28.0.
+
+### Changes or improvements
+
+* When fetching from an anonymous remote using a URL with authentication
+ information provided in the URL (eg `https://foo:bar@example.com/repo`),
+ we would erroneously include the literal URL in the FETCH_HEAD file.
+ We now remove that to match git's behavior.
+
+* Some credential structures, enums and values have been renamed:
+ `git_cred` is now `git_credential`. `git_credtype_t` is now
+ `git_credential_t`. Functions and types beginning with
+ `git_cred_` now begin with `git_credential`, and constants beginning
+ with `GIT_CREDTYPE` now begin with `GIT_CREDENTIAL`. The former names
+ are deprecated.
+
+* Several function signatures have been changed to return an `int` to
+ indicate error conditions. We encourage you to check them for errors
+ in the standard way.
+
+ * `git_attr_cache_flush`
+ * `git_error_set_str`
+ * `git_index_name_clear`
+ * `git_index_reuc_clear`
+ * `git_libgit2_version`
+ * `git_mempack_reset`
+ * `git_oid_cpy`
+ * `git_oid_fmt`
+ * `git_oid_fromraw`
+ * `git_oid_nfmt`
+ * `git_oid_pathfmt`
+ * `git_remote_stop`
+ * `git_remote_disconnect`
+ * `git_repository__cleanup`
+ * `git_repository_set_config`
+ * `git_repository_set_index`
+ * `git_repository_set_odb`
+ * `git_repository_set_refdb`
+ * `git_revwalk_reset`
+ * `git_revwalk_simplify_first_parent`
+ * `git_revwalk_sorting`
+ * `git_treebuilder_clear`
+ * `git_treebuilder_filter`
+
+* The NTLM and Negotiate authentication mechanisms are now supported when
+ talking to git implementations hosted on Apache or nginx servers.
+
+* The `HEAD` symbolic reference can no longer be deleted.
+
+* `git_merge_driver_source_repo` no longer returns a `const git_repository *`,
+ it now returns a non-`const` `git_repository *`.
+
+* Relative symbolic links are now supported on Windows when `core.symlinks`
+ is enabled.
+
+* Servers that provide query parameters with a redirect are now supported.
+
+* `git_submodule_sync` will now resolve relative URLs.
+
+* When creating git endpoint URLs, double-slashes are no longer used when
+ the given git URL has a trailing slash.
+
+* On Windows, a `DllMain` function is no longer included and thread-local
+ storage has moved to fiber-local storage in order to prevent race
+ conditions during shutdown.
+
+* The tracing mechanism (`GIT_TRACE`) is now enabled by default and does
+ not need to be explicitly enabled in CMake.
+
+* The size of Git objects is now represented by `git_object_size_t`
+ instead of `off_t`.
+
+* Binary patches without data can now be parsed.
+
+* A configuration snapshot can now be created from another configuration
+ snapshot, not just a "true" configuration object.
+
+* The `git_commit_with_signature` API will now ensure that referenced
+ objects exist in the object database.
+
+* Stash messages containing newlines will now be replaced with spaces;
+ they will no longer be (erroneously) written to the repository.
+
+* `git_commit_create_with_signature` now verifies the commit information
+ to ensure that it points to a valid tree and valid parents.
+
+* `git_apply` has an option `GIT_APPLY_CHECK` that will only do a dry-run.
+ The index and working directory will remain unmodified, and application
+ will report if it would have worked.
+
+* Patches produced by Mercurial (those that lack some git extended headers)
+ can now be parsed and applied.
+
+* Reference locks are obeyed correctly on POSIX platforms, instead of
+ being removed.
+
+* Patches with empty new files can now be read and applied.
+
+* `git_apply_to_tree` can now correctly apply patches that add new files.
+
+* The program data configuration on Windows (`C:\ProgramData\Git\config`)
+ must be owned by an administrator, a system account or the current user
+ to be read.
+
+* `git_blob_filtered_content` is now deprecated in favor of `git_blob_filter`.
+
+* Configuration files can now be included conditionally using the
+ `onbranch` conditional.
+
+* Checkout can now properly create and remove symbolic links to directories
+ on Windows.
+
+* Stash no longer recomputes trees when committing a worktree, for
+ improved performance.
+
+* Repository templates can now include a `HEAD` file to default the
+ initial default branch.
+
+* Some configuration structures, enums and values have been renamed:
+ `git_cvar_map` is now `git_configmap`, `git_cvar_t` is now
+ `git_configmap_t`, `GIT_CVAR_FALSE` is now `GIT_CONFIGMAP_FALSE`,
+ `GIT_CVAR_TRUE` is now `GIT_CONFIGMAP_TRUE`, `GIT_CVAR_INT32` is now
+ `GIT_CONFIGMAP_INT32`, and `GIT_CVAR_STRING` is now `GIT_CONFIGMAP_STRING`.
+ The former names are deprecated.
+
+* Repositories can now be created at the root of a Windows drive.
+
+* Configuration lookups are now more efficiently cached.
+
+* `git_commit_create_with_signature` now supports a `NULL` signature,
+ which will create a commit without adding a signature.
+
+* When a repository lacks an `info` "common directory", we will no
+ longer erroneously return `GIT_ENOTFOUND` for all attribute lookups.
+
+* Several attribute macros have been renamed: `GIT_ATTR_TRUE` is now
+ `GIT_ATTR_IS_TRUE`, `GIT_ATTR_FALSE` is now `GIT_ATTR_IS_FALSE`,
+ `GIT_ATTR_UNSPECIFIED` is now `GIT_ATTR_IS_UNSPECIFIED`. The
+ attribute enum `git_attr_t` is now `git_attr_value_t` and its
+ values have been renamed: `GIT_ATTR_UNSPECIFIED_T` is now
+ `GIT_ATTR_VALUE_UNSPECIFIED`, `GIT_ATTR_TRUE_T` is now
+ `GIT_ATTR_VALUE_TRUE`, `GIT_ATTR_FALSE_T` is now `GIT_ATTR_VALUE_FALSE`,
+ and `GIT_ATTR_VALUE_T` is now `GIT_ATTR_VALUE_STRING`. The
+ former names are deprecated.
+
+* `git_object__size` is now `git_object_size`. The former name is
+ deprecated.
+
+* `git_tag_create_frombuffer` is now `git_tag_create_from_buffer`. The
+ former name is deprecated.
+
+* Several blob creation functions have been renamed:
+ `git_blob_create_frombuffer` is now named `git_blob_create_from_buffer`,
+ `git_blob_create_fromdisk` is now named `git_blob_create_from_disk`,
+ `git_blob_create_fromworkdir` is now named `git_blob_create_from_workdir`,
+ `git_blob_create_fromstream` is now named `git_blob_create_from_stream`,
+ and `git_blob_create_fromstream_commit` is now named
+ `git_blob_create_from_stream_commit`. The former names are deprecated.
+
+* The function `git_oid_iszero` is now named `git_oid_is_zero`. The
+ former name is deprecated.
+
+* Pattern matching is now done using `wildmatch` instead of `fnmatch`
+ for compatibility with git.
+
+* The option initialization functions suffixed by `init_options` are now
+ suffixed with `options_init`. (For example, `git_checkout_init_options`
+ is now `git_checkout_options_init`.) The former names are deprecated.
+
+* NTLM2 authentication is now supported on non-Windows platforms.
+
+* The `git_cred_sign_callback` callback is now named `git_cred_sign_cb`.
+ The `git_cred_ssh_interactive_callback` callback is now named
+ `git_cred_ssh_interactive_cb`.
+
+* Ignore files now:
+
+ * honor escaped trailing whitespace.
+ * do not incorrectly negate sibling paths of a negated pattern.
+ * honor rules that stop ignoring files after a wildcard
+
+* Attribute files now:
+
+ * honor leading and trailing whitespace.
+ * treat paths beginning with `\` as absolute only on Windows.
+ * properly handle escaped characters.
+ * stop reading macros defined in subdirectories
+
+* The C locale is now correctly used when parsing regular expressions.
+
+* The system PCRE2 or PCRE regular expression libraries are now used
+ when `regcomp_l` is not available on the system. If none of these
+ are available on the system, an included version of PCRE is used.
+
+* Wildcards in reference specifications are now supported beyond simply
+ a bare wildcard (`*`) for compatibility with git.
+
+* When `git_ignore_path_is_ignored` is provided a path with a trailing
+ slash (eg, `dir/`), it will now treat it as a directory for the
+ purposes of ignore matching.
+
+* Patches that add or remove a file with a space in the path can now
+ be correctly parsed.
+
+* The `git_remote_completion_type` type is now `git_remote_completion_t`.
+ The former name is deprecated.
+
+* The `git_odb_backend_malloc` is now `git_odb_backend_data_alloc`. The
+ former name is deprecated.
+
+* The `git_transfer_progress_cb` callback is now `git_indexer_progress_cb`
+ and the `git_transfer_progress` structure is now `git_indexer_progress`.
+ The former names are deprecated.
+
+* The example projects are now contained in a single `lg2` executable
+ for ease of use.
+
+* libgit2 now correctly handles more URLs, such as
+ `http://example.com:/repo.git` (colon but no port),
+ `http://example.com` (no path),
+ and `http://example.com:8080/` (path is /, nonstandard port).
+
+* A carefully constructed commit object with a very large number
+ of parents may lead to potential out-of-bounds writes or
+ potential denial of service.
+
+* The ProgramData configuration file is always read for compatibility
+ with Git for Windows and Portable Git installations. The ProgramData
+ location is not necessarily writable only by administrators, so we
+ now ensure that the configuration file is owned by the administrator
+ or the current user.
+
+### API additions
+
+* The SSH host key now supports SHA-256 when `GIT_CERT_SSH_SHA256` is set.
+
+* The diff format option `GIT_DIFF_FORMAT_PATCH_ID` can now be used to
+ emit an output like `git patch-id`.
+
+* The `git_apply_options_init` function will initialize a
+ `git_apply_options` structure.
+
+* The remote callbacks structure adds a `git_url_resolve_cb` callback
+ that is invoked when connecting to a server, so that applications
+ may edit or replace the URL before connection.
+
+* The information about the original `HEAD` in a rebase operation is
+ available with `git_rebase_orig_head_name`. Its ID is available with
+ `git_rebase_orig_head_id`. The `onto` reference name is available with
+ `git_rebase_onto_name` and its ID is available with `git_rebase_onto_id`.
+
+* ODB backends can now free backend data when an error occurs during its
+ backend data creation using `git_odb_backend_data_free`.
+
+* Options may be specified to `git_repository_foreach_head` to control
+ its behavior: `GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO` will not skip
+ the main repository's HEAD reference, while
+ `GIT_REPOSITORY_FOREACH_HEAD_SKIP_WORKTREES` will now skip the
+ worktree HEAD references.
+
+* The `GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS` option can be specified to
+ `git_libgit2_opts()` to avoid looking for `.keep` files that correspond
+ to packfiles. This setting can improve performance when packfiles are
+ stored on high-latency filesystems like network filesystems.
+
+* Blobs can now be filtered with `git_blob_filter`, which allows for
+ options to be set with `git_blob_filter_options`, including
+ `GIT_FILTER_NO_SYSTEM_ATTRIBUTES` to disable filtering with system-level
+ attributes in `/etc/gitattributes` and `GIT_ATTR_CHECK_INCLUDE_HEAD` to
+ enable filtering with `.gitattributes` files in the HEAD revision.
+
+### API removals
+
+* The unused `git_headlist_cb` function declaration was removed.
+
+* The unused `git_time_monotonic` API is removed.
+
+* The erroneously exported `inttypes.h` header was removed.
# Security Fixes
@@ -82,22 +366,62 @@ v0.28 + 1
"CollisionDetection". If you were using `SHA1_BACKEND` previously, you'll
need to check the value you've used, or switch to the autodetection.
-### Changes or improvements
-
-* libgit2 now correctly handles more URLs, such as
- `http://example.com:/repo.git` (colon but no port),
- `http://example.com` (no path),
- and `http://example.com:8080/` (path is /, nonstandard port).
-
-* A carefully constructed commit object with a very large number
- of parents may lead to potential out-of-bounds writes or
- potential denial of service.
-
-* The ProgramData configuration file is always read for compatibility
- with Git for Windows and Portable Git installations. The ProgramData
- location is not necessarily writable only by administrators, so we
- now ensure that the configuration file is owned by the administrator
- or the current user.
+### Authors
+
+The following individuals provided changes that were included in this
+release:
+
+* Aaron Patterson
+* Alberto Fanjul
+* Anders Borum
+* Augie Fackler
+* Augustin Fabre
+* Ayush Shridhar
+* brian m. carlson
+* buddyspike
+* Carlos Martín Nieto
+* cheese1
+* Dan Skorupski
+* Daniel Cohen Gindi
+* Dave Lee
+* David Brooks
+* David Turner
+* Denis Laxalde
+* Dhruva Krishnamurthy
+* Dominik Ritter
+* Drew DeVault
+* Edward Thomson
+* Eric Huss
+* Erik Aigner
+* Etienne Samson
+* Gregory Herrero
+* Heiko Voigt
+* Ian Hattendorf
+* Jacques Germishuys
+* Janardhan Pulivarthi
+* Jason Haslam
+* Johannes Schindelin
+* Jordan Wallet
+* Josh Bleecher Snyder
+* kas
+* kdj0c
+* Laurence McGlashan
+* lhchavez
+* Lukas Berk
+* Max Kostyukevich
+* Patrick Steinhardt
+* pcpthm
+* Remy Suen
+* Robert Coup
+* romkatv
+* Scott Furry
+* Sebastian Henke
+* Stefan Widgren
+* Steve King Jr
+* Sven Strickroth
+* Tobias Nießen
+* Tyler Ang-Wanek
+* Tyler Wanek
v0.28
-----
diff --git a/docs/fuzzing.md b/docs/fuzzing.md
index cd825766b..25b32cb04 100644
--- a/docs/fuzzing.md
+++ b/docs/fuzzing.md
@@ -3,7 +3,7 @@
libgit2 is currently using [libFuzzer](https://libfuzzer.info) to perform
automated fuzz testing. libFuzzer only works with clang.
-## Prerequisites** for building fuzz targets:
+## Prerequisites for building fuzz targets:
1. All the prerequisites for [building libgit2](https://github.com/libgit2/libgit2).
2. A recent version of clang. 6.0 is preferred. [pre-build Debian/Ubuntu
@@ -27,14 +27,15 @@ automated fuzz testing. libFuzzer only works with clang.
## Run the fuzz targets
-1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize-6.0
+1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize
LSAN_OPTIONS=allocator_may_return_null=1
- ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzz/fuzz_packfile_raw
- fuzz/corpora/fuzz_packfile_raw/`
+ ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzzers/packfile_fuzzer
+ fuzzers/corpora/packfile/`
The `LSAN_OPTIONS` and `ASAN_OPTIONS` are there to allow `malloc(3)` to return
-`NULL`. The `LLVM_PROFILE_FILE` is there to override the path where libFuzzer
-will write the coverage report.
+`NULL`, which is expected if a huge chunk of memory is allocated. The
+`LLVM_PROFILE_FILE` environment string can also be added to override the path
+where libFuzzer will write the coverage report.
## Get coverage
diff --git a/include/git2/version.h b/include/git2/version.h
index 148808ca0..4a824ffea 100644
--- a/include/git2/version.h
+++ b/include/git2/version.h
@@ -7,12 +7,12 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
-#define LIBGIT2_VERSION "0.28.0"
+#define LIBGIT2_VERSION "0.99.0"
#define LIBGIT2_VER_MAJOR 0
-#define LIBGIT2_VER_MINOR 28
+#define LIBGIT2_VER_MINOR 99
#define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_PATCH 0
-#define LIBGIT2_SOVERSION 28
+#define LIBGIT2_SOVERSION "0.99"
#endif
diff --git a/script/release.py b/script/release.py
new file mode 100755
index 000000000..e0f29538e
--- /dev/null
+++ b/script/release.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+from collections import namedtuple
+
+import argparse
+import base64
+import copy
+import json
+import subprocess
+import sys
+import urllib.parse
+import urllib.request
+import urllib.error
+
+class Error(Exception):
+ pass
+
+class Version(object):
+ def __init__(self, version):
+ versions = version.split(sep='.')
+ if len(versions) < 2 or len(versions) > 3:
+ raise Error("Invalid version string '{}'".format(version))
+ self.major = int(versions[0])
+ self.minor = int(versions[1])
+ self.revision = int(versions[2]) if len(versions) == 3 else 0
+
+ def __str__(self):
+ return '{}.{}.{}'.format(self.major, self.minor, self.revision)
+
+ def __eq__(self, other):
+ return self.major == other.major and self.minor == other.minor and self.revision == other.revision
+
+def verify_version(version):
+ expected = {
+ 'VERSION': [ '"{}"'.format(version), None ],
+ 'VER_MAJOR': [ str(version.major), None ],
+ 'VER_MINOR': [ str(version.minor), None ],
+ 'VER_REVISION': [ str(version.revision), None ],
+ 'VER_PATCH': [ '0', None ],
+ 'SOVERSION': [ '"{}.{}"'.format(version.major, version.minor), None ],
+ }
+
+ with open('include/git2/version.h') as f:
+ lines = f.readlines()
+
+ for key in expected.keys():
+ define = '#define LIBGIT2_{} '.format(key)
+ for line in lines:
+ if line.startswith(define):
+ expected[key][1] = line[len(define):].strip()
+ break
+ else:
+ raise Error("version.h: missing define for '{}'".format(key))
+
+ for k, v in expected.items():
+ if v[0] != v[1]:
+ raise Error("version.h: define '{}' does not match (got '{}', expected '{}')".format(k, v[0], v[1]))
+
+def generate_relnotes(tree, version):
+ with open('docs/changelog.md') as f:
+ lines = f.readlines()
+
+ if not lines[0].startswith('v'):
+ raise Error("changelog.md: missing section for v{}".format(version))
+ try:
+ v = Version(lines[0][1:].strip())
+ except:
+ raise Error("changelog.md: invalid version string {}".format(lines[0].strip()))
+ if v != version:
+ raise Error("changelog.md: changelog version doesn't match (got {}, expected {})".format(v, version))
+ if not lines[1].startswith('----'):
+ raise Error("changelog.md: missing version header")
+ if lines[2] != '\n':
+ raise Error("changelog.md: missing newline after version header")
+
+ for i, line in enumerate(lines[3:]):
+ if not line.startswith('v'):
+ continue
+ try:
+ Version(line[1:].strip())
+ break
+ except:
+ continue
+ else:
+ raise Error("changelog.md: cannot find section header of preceding release")
+
+ return ''.join(lines[3:i + 3]).strip()
+
+def git(*args):
+ process = subprocess.run([ 'git', *args ], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if process.returncode != 0:
+ raise Error('Failed executing git {}: {}'.format(' '.join(args), process.stderr.decode()))
+ return process.stdout
+
+def post(url, data, contenttype, user, password):
+ request = urllib.request.Request(url, data=data)
+ request.add_header('Accept', 'application/json')
+ request.add_header('Content-Type', contenttype)
+ request.add_header('Content-Length', len(data))
+ request.add_header('Authorization', 'Basic ' + base64.b64encode('{}:{}'.format(user, password).encode()).decode())
+
+ try:
+ response = urllib.request.urlopen(request)
+ if response.getcode() != 201:
+ raise Error("POST to '{}' failed: {}".format(url, response.reason))
+ except urllib.error.URLError as e:
+ raise Error("POST to '{}' failed: {}".format(url, e))
+ data = json.load(response)
+
+ return data
+
+def generate_asset(version, tree, archive_format):
+ Asset = namedtuple('Asset', ['name', 'label', 'mimetype', 'data'])
+ mimetype = 'application/{}'.format('gzip' if archive_format == 'tar.gz' else 'zip')
+ return Asset(
+ "libgit2-{}.{}".format(version, archive_format), "Release sources: libgit2-{}.{}".format(version, archive_format), mimetype,
+ git('archive', '--format', archive_format, '--prefix', 'libgit2-{}/'.format(version), tree)
+ )
+
+def release(args):
+ params = {
+ "tag_name": 'v' + str(args.version),
+ "name": 'libgit2 v' + str(args.version),
+ "target_commitish": git('rev-parse', args.tree).decode().strip(),
+ "body": generate_relnotes(args.tree, args.version),
+ }
+ assets = [
+ generate_asset(args.version, args.tree, 'tar.gz'),
+ generate_asset(args.version, args.tree, 'zip'),
+ ]
+
+ if args.dryrun:
+ for k, v in params.items():
+ print('{}: {}'.format(k, v))
+ for asset in assets:
+ print('asset: name={}, label={}, mimetype={}, bytes={}'.format(asset.name, asset.label, asset.mimetype, len(asset.data)))
+ return
+
+ try:
+ url = 'https://api.github.com/repos/{}/releases'.format(args.repository)
+ response = post(url, json.dumps(params).encode(), 'application/json', args.user, args.password)
+ except Error as e:
+ raise Error('Could not create release: ' + str(e))
+
+ for asset in assets:
+ try:
+ url = list(urllib.parse.urlparse(response['upload_url'].split('{?')[0]))
+ url[4] = urllib.parse.urlencode({ 'name': asset.name, 'label': asset.label })
+ post(urllib.parse.urlunparse(url), asset.data, asset.mimetype, args.user, args.password)
+ except Error as e:
+ raise Error('Could not upload asset: ' + str(e))
+
+def main():
+ parser = argparse.ArgumentParser(description='Create a libgit2 release')
+ parser.add_argument('--tree', default='HEAD', help='tree to create release for (default: HEAD)')
+ parser.add_argument('--dryrun', action='store_true', help='generate release, but do not post it')
+ parser.add_argument('--repository', default='libgit2/libgit2', help='GitHub repository to create repository in')
+ parser.add_argument('--user', help='user to authenitcate as')
+ parser.add_argument('--password', help='password to authenticate with')
+ parser.add_argument('version', type=Version, help='version of the new release')
+ args = parser.parse_args()
+
+ verify_version(args.version)
+ release(args)
+
+if __name__ == '__main__':
+ try:
+ main()
+ except Error as e:
+ print(e)
+ sys.exit(1)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de24b975a..1915e8a9a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -140,7 +140,7 @@ ELSEIF(REGEX_BACKEND STREQUAL "pcre2")
LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE2_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBS ${PCRE2_LIBRARIES})
- LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre2")
+ LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre2-8")
ELSEIF(REGEX_BACKEND STREQUAL "pcre")
ADD_FEATURE_INFO(regex ON "using system PCRE")
SET(GIT_REGEX_PCRE 1)
@@ -288,14 +288,13 @@ IF (WIN32 AND NOT CYGWIN)
ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
ELSE()
- ADD_FEATURE_INFO(valgrind VALGRIND "valgrind hints")
- IF (VALGRIND)
- ADD_DEFINITIONS(-DVALGRIND)
- ENDIF()
-
FILE(GLOB SRC_OS unix/*.c unix/*.h)
ENDIF()
+IF (USE_LEAK_CHECKER STREQUAL "valgrind")
+ ADD_DEFINITIONS(-DVALGRIND)
+ENDIF()
+
FILE(GLOB SRC_GIT2 *.c *.h
allocators/*.c allocators/*.h
streams/*.c streams/*.h
diff --git a/src/cache.c b/src/cache.c
index 32ba993b0..af42b3959 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -208,10 +208,14 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
entry = stored_entry;
} else if (stored_entry->flags == GIT_CACHE_STORE_RAW &&
entry->flags == GIT_CACHE_STORE_PARSED) {
- git_cached_obj_decref(stored_entry);
- git_cached_obj_incref(entry);
-
- git_oidmap_set(cache->map, &entry->oid, entry);
+ if (git_oidmap_set(cache->map, &entry->oid, entry) == 0) {
+ git_cached_obj_decref(stored_entry);
+ git_cached_obj_incref(entry);
+ } else {
+ git_cached_obj_decref(entry);
+ git_cached_obj_incref(stored_entry);
+ entry = stored_entry;
+ }
} else {
/* NO OP */
}
diff --git a/src/indexer.c b/src/indexer.c
index 717549fa2..68fdd85c5 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -150,11 +150,11 @@ int git_indexer_new(
idx->progress_cb = opts.progress_cb;
idx->progress_payload = opts.progress_cb_payload;
idx->mode = mode ? mode : GIT_PACK_FILE_MODE;
- git_hash_ctx_init(&idx->hash_ctx);
- git_hash_ctx_init(&idx->trailer);
git_buf_init(&idx->entry_data, 0);
- if ((error = git_oidmap_new(&idx->expected_oids)) < 0)
+ if ((error = git_hash_ctx_init(&idx->hash_ctx)) < 0 ||
+ (error = git_hash_ctx_init(&idx->trailer)) < 0 ||
+ (error = git_oidmap_new(&idx->expected_oids)) < 0)
goto cleanup;
idx->do_verify = opts.verify;
diff --git a/src/notes.c b/src/notes.c
index 4633a16ea..68d2ae9ec 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -808,8 +808,11 @@ int git_note_next(
git_oid_cpy(note_id, &item->id);
- if (!(error = process_entry_path(item->path, annotated_id)))
- git_iterator_advance(NULL, it);
+ if ((error = process_entry_path(item->path, annotated_id)) < 0)
+ return error;
- return error;
+ if ((error = git_iterator_advance(NULL, it)) < 0 && error != GIT_ITEROVER)
+ return error;
+
+ return 0;
}
diff --git a/src/odb_pack.c b/src/odb_pack.c
index c93d07c46..86c858df1 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -15,7 +15,6 @@
#include "hash.h"
#include "odb.h"
#include "delta.h"
-#include "sha1_lookup.h"
#include "mwindow.h"
#include "pack.h"
diff --git a/src/pack-objects.c b/src/pack-objects.c
index bdd5171a8..49b4e4772 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -374,7 +374,9 @@ static int write_object(
GIT_ERROR_CHECK_ALLOC(zbuf);
git_zstream_reset(&pb->zstream);
- git_zstream_set_input(&pb->zstream, data, data_len);
+
+ if ((error = git_zstream_set_input(&pb->zstream, data, data_len)) < 0)
+ goto done;
while (!git_zstream_done(&pb->zstream)) {
if ((error = git_zstream_get_output(zbuf, &zbuf_len, &pb->zstream)) < 0 ||
diff --git a/src/pack.c b/src/pack.c
index 7c6fc2cdb..fcf64f57d 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -12,7 +12,6 @@
#include "mwindow.h"
#include "odb.h"
#include "oid.h"
-#include "sha1_lookup.h"
/* Option to bypass checking existence of '.keep' files */
bool git_disable_pack_keep_file_checks = false;
@@ -1239,6 +1238,27 @@ int git_pack_foreach_entry(
return error;
}
+static int sha1_position(const void *table, size_t stride, unsigned lo,
+ unsigned hi, const unsigned char *key)
+{
+ const unsigned char *base = table;
+
+ while (lo < hi) {
+ unsigned mi = (lo + hi) / 2;
+ int cmp = git_oid__hashcmp(base + mi * stride, key);
+
+ if (!cmp)
+ return mi;
+
+ if (cmp > 0)
+ hi = mi;
+ else
+ lo = mi+1;
+ }
+
+ return -((int)lo)-1;
+}
+
static int pack_entry_find_offset(
off64_t *offset_out,
git_oid *found_oid,
diff --git a/src/push.c b/src/push.c
index 67ebcfb3e..34867c2e4 100644
--- a/src/push.c
+++ b/src/push.c
@@ -349,8 +349,9 @@ static int queue_objects(git_push *push)
if (git_oid_is_zero(&head->oid))
continue;
- /* TODO */
- git_revwalk_hide(rw, &head->oid);
+ if ((error = git_revwalk_hide(rw, &head->oid)) < 0 &&
+ error != GIT_ENOTFOUND && error != GIT_EINVALIDSPEC && error != GIT_EPEEL)
+ goto on_error;
}
error = git_packbuilder_insert_walk(push->pb, rw);
diff --git a/src/repository.c b/src/repository.c
index 2469e13e6..fe0d696c6 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -189,19 +189,25 @@ void git_repository_free(git_repository *repo)
*
* Open a repository object from its path
*/
-static bool valid_repository_path(git_buf *repository_path, git_buf *common_path)
+static int is_valid_repository_path(bool *out, git_buf *repository_path, git_buf *common_path)
{
+ int error;
+
+ *out = false;
+
/* Check if we have a separate commondir (e.g. we have a
* worktree) */
if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
git_buf common_link = GIT_BUF_INIT;
- git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE);
- git_futils_readbuffer(&common_link, common_link.ptr);
- git_buf_rtrim(&common_link);
+ if ((error = git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 ||
+ (error = git_futils_readbuffer(&common_link, common_link.ptr)) < 0)
+ return error;
+ git_buf_rtrim(&common_link);
if (git_path_is_relative(common_link.ptr)) {
- git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr);
+ if ((error = git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr)) < 0)
+ return error;
} else {
git_buf_swap(common_path, &common_link);
}
@@ -209,24 +215,26 @@ static bool valid_repository_path(git_buf *repository_path, git_buf *common_path
git_buf_dispose(&common_link);
}
else {
- git_buf_set(common_path, repository_path->ptr, repository_path->size);
+ if ((error = git_buf_set(common_path, repository_path->ptr, repository_path->size)) < 0)
+ return error;
}
/* Make sure the commondir path always has a trailing * slash */
if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1)
- git_buf_putc(common_path, '/');
+ if ((error = git_buf_putc(common_path, '/')) < 0)
+ return error;
/* Ensure HEAD file exists */
if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
- return false;
-
+ return 0;
/* Check files in common dir */
if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
- return false;
+ return 0;
if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false)
- return false;
+ return 0;
- return true;
+ *out = true;
+ return 0;
}
static git_repository *repository_alloc(void)
@@ -441,15 +449,15 @@ static int find_repo(
uint32_t flags,
const char *ceiling_dirs)
{
- int error;
git_buf path = GIT_BUF_INIT;
git_buf repo_link = GIT_BUF_INIT;
git_buf common_link = GIT_BUF_INIT;
struct stat st;
dev_t initial_device = 0;
int min_iterations;
- bool in_dot_git;
+ bool in_dot_git, is_valid;
size_t ceiling_offset = 0;
+ int error;
git_buf_clear(gitdir_path);
@@ -475,9 +483,8 @@ static int find_repo(
for (;;) {
if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
if (!in_dot_git) {
- error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
- if (error < 0)
- break;
+ if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
+ goto out;
}
in_dot_git = !in_dot_git;
}
@@ -491,28 +498,33 @@ static int find_repo(
break;
if (S_ISDIR(st.st_mode)) {
- if (valid_repository_path(&path, &common_link)) {
- git_path_to_dir(&path);
- git_buf_set(gitdir_path, path.ptr, path.size);
+ if ((error = is_valid_repository_path(&is_valid, &path, &common_link)) < 0)
+ goto out;
+
+ if (is_valid) {
+ if ((error = git_path_to_dir(&path)) < 0 ||
+ (error = git_buf_set(gitdir_path, path.ptr, path.size)) < 0)
+ goto out;
if (gitlink_path)
- git_buf_attach(gitlink_path,
- git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0);
+ if ((error = git_buf_attach(gitlink_path, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0)
+ goto out;
if (commondir_path)
git_buf_swap(&common_link, commondir_path);
break;
}
- }
- else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
- error = read_gitfile(&repo_link, path.ptr);
- if (error < 0)
- break;
- if (valid_repository_path(&repo_link, &common_link)) {
+ } else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
+ if ((error = read_gitfile(&repo_link, path.ptr)) < 0 ||
+ (error = is_valid_repository_path(&is_valid, &repo_link, &common_link)) < 0)
+ goto out;
+
+ if (is_valid) {
git_buf_swap(gitdir_path, &repo_link);
if (gitlink_path)
- error = git_buf_put(gitlink_path, path.ptr, path.size);
+ if ((error = git_buf_put(gitlink_path, path.ptr, path.size)) < 0)
+ goto out;
if (commondir_path)
git_buf_swap(&common_link, commondir_path);
}
@@ -523,10 +535,8 @@ static int find_repo(
/* Move up one directory. If we're in_dot_git, we'll search the
* parent itself next. If we're !in_dot_git, we'll search .git
* in the parent directory next (added at the top of the loop). */
- if (git_path_dirname_r(&path, path.ptr) < 0) {
- error = -1;
- break;
- }
+ if ((error = git_path_dirname_r(&path, path.ptr)) < 0)
+ goto out;
/* Once we've checked the directory (and .git if applicable),
* find the ceiling for a search. */
@@ -534,31 +544,28 @@ static int find_repo(
ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
/* Check if we should stop searching here. */
- if (min_iterations == 0
- && (path.ptr[ceiling_offset] == 0
- || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
+ if (min_iterations == 0 &&
+ (path.ptr[ceiling_offset] == 0 || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
break;
}
- if (!error && workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
+ if (workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
if (!git_buf_len(gitdir_path))
git_buf_clear(workdir_path);
- else {
- git_path_dirname_r(workdir_path, path.ptr);
- git_path_to_dir(workdir_path);
- }
- if (git_buf_oom(workdir_path))
- return -1;
+ else if ((error = git_path_dirname_r(workdir_path, path.ptr)) < 0 ||
+ (error = git_path_to_dir(workdir_path)) < 0)
+ goto out;
}
/* If we didn't find the repository, and we don't have any other error
* to report, report that. */
- if (!git_buf_len(gitdir_path) && !error) {
- git_error_set(GIT_ERROR_REPOSITORY,
- "could not find repository from '%s'", start_path);
+ if (!git_buf_len(gitdir_path)) {
+ git_error_set(GIT_ERROR_REPOSITORY, "could not find repository from '%s'", start_path);
error = GIT_ENOTFOUND;
+ goto out;
}
+out:
git_buf_dispose(&path);
git_buf_dispose(&repo_link);
git_buf_dispose(&common_link);
@@ -569,14 +576,16 @@ int git_repository_open_bare(
git_repository **repo_ptr,
const char *bare_path)
{
- int error;
git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT;
git_repository *repo = NULL;
+ bool is_valid;
+ int error;
- if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0)
+ if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0 ||
+ (error = is_valid_repository_path(&is_valid, &path, &common_path)) < 0)
return error;
- if (!valid_repository_path(&path, &common_path)) {
+ if (!is_valid) {
git_buf_dispose(&path);
git_buf_dispose(&common_path);
git_error_set(GIT_ERROR_REPOSITORY, "path is not a repository: %s", bare_path);
@@ -2055,6 +2064,7 @@ int git_repository_init_ext(
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
common_path = GIT_BUF_INIT, head_path = GIT_BUF_INIT;
const char *wd;
+ bool is_valid;
int error;
assert(out && given_repo && opts);
@@ -2066,7 +2076,10 @@ int git_repository_init_ext(
wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
- if (valid_repository_path(&repo_path, &common_path)) {
+ if ((error = is_valid_repository_path(&is_valid, &repo_path, &common_path)) < 0)
+ goto out;
+
+ if (is_valid) {
if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
git_error_set(GIT_ERROR_REPOSITORY,
"attempt to reinitialize '%s'", given_repo);
diff --git a/src/revwalk.c b/src/revwalk.c
index 4587b5acc..abbd65ac2 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -58,7 +58,7 @@ int git_revwalk__push_commit(git_revwalk *walk, const git_oid *oid, const git_re
return 0;
git_error_set(GIT_ERROR_INVALID, "object is not a committish");
- return -1;
+ return error;
}
if (error < 0)
return error;
diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c
deleted file mode 100644
index 14fcb40e5..000000000
--- a/src/sha1_lookup.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "sha1_lookup.h"
-
-#include <stdio.h>
-
-#include "oid.h"
-
-int sha1_position(const void *table,
- size_t stride,
- unsigned lo, unsigned hi,
- const unsigned char *key)
-{
- const unsigned char *base = table;
-
- while (lo < hi) {
- unsigned mi = (lo + hi) / 2;
- int cmp = git_oid__hashcmp(base + mi * stride, key);
-
- if (!cmp)
- return mi;
-
- if (cmp > 0)
- hi = mi;
- else
- lo = mi+1;
- }
-
- return -((int)lo)-1;
-}
diff --git a/src/sha1_lookup.h b/src/sha1_lookup.h
deleted file mode 100644
index 841ea5b22..000000000
--- a/src/sha1_lookup.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef INCLUDE_sha1_lookup_h__
-#define INCLUDE_sha1_lookup_h__
-
-#include "common.h"
-
-#include <stdlib.h>
-
-int sha1_position(const void *table,
- size_t stride,
- unsigned lo, unsigned hi,
- const unsigned char *key);
-
-#endif
diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 98a3635af..5b66352ca 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -30,10 +30,6 @@
#include <openssl/x509v3.h>
#include <openssl/bio.h>
-#ifdef VALGRIND
-# include <valgrind/memcheck.h>
-#endif
-
SSL_CTX *git__ssl_ctx;
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
@@ -160,7 +156,7 @@ static void openssl_locking_function(
lock = mode & CRYPTO_LOCK;
if (lock) {
- git_mutex_lock(&openssl_locks[n]);
+ (void)git_mutex_lock(&openssl_locks[n]);
} else {
git_mutex_unlock(&openssl_locks[n]);
}
@@ -200,16 +196,69 @@ static void shutdown_ssl(void)
}
}
+#ifdef VALGRIND
+#ifdef OPENSSL_LEGACY_API
+static void *git_openssl_malloc(size_t bytes)
+{
+ return git__calloc(1, bytes);
+}
+
+static void *git_openssl_realloc(void *mem, size_t size)
+{
+ return git__realloc(mem, size);
+}
+
+static void git_openssl_free(void *mem)
+{
+ return git__free(mem);
+}
+#else
+static void *git_openssl_malloc(size_t bytes, const char *file, int line)
+{
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+ return git__calloc(1, bytes);
+}
+
+static void *git_openssl_realloc(void *mem, size_t size, const char *file, int line)
+{
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+ return git__realloc(mem, size);
+}
+
+static void git_openssl_free(void *mem, const char *file, int line)
+{
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+ return git__free(mem);
+}
+#endif
+#endif
+
int git_openssl_stream_global_init(void)
{
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
const char *ciphers = git_libgit2__ssl_ciphers();
+#ifdef VALGRIND
+ static bool allocators_initialized = false;
+#endif
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
+#ifdef VALGRIND
+ /* Swap in our own allocator functions that initialize allocated memory */
+ if (!allocators_initialized &&
+ CRYPTO_set_mem_functions(git_openssl_malloc,
+ git_openssl_realloc,
+ git_openssl_free) != 1)
+ goto error;
+ allocators_initialized = true;
+#endif
+
OPENSSL_init_ssl(0, NULL);
/*
@@ -314,11 +363,6 @@ static int bio_read(BIO *b, char *buf, int len)
static int bio_write(BIO *b, const char *buf, int len)
{
git_stream *io = (git_stream *) BIO_get_data(b);
-
-#ifdef VALGRIND
- VALGRIND_MAKE_MEM_DEFINED(buf, len);
-#endif
-
return (int) git_stream_write(io, buf, len, 0);
}
@@ -595,10 +639,6 @@ static int openssl_connect(git_stream *stream)
BIO_set_data(bio, st->io);
SSL_set_bio(st->ssl, bio, bio);
-#ifdef VALGRIND
- VALGRIND_MAKE_MEM_DEFINED(st->ssl, sizeof(SSL));
-#endif
-
/* specify the host in case SNI is needed */
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_set_tlsext_host_name(st->ssl, st->host);
@@ -609,10 +649,6 @@ static int openssl_connect(git_stream *stream)
st->connected = true;
-#ifdef VALGRIND
- VALGRIND_MAKE_MEM_DEFINED(st->ssl, sizeof(SSL));
-#endif
-
return verify_server_cert(st->ssl, st->host);
}
@@ -679,10 +715,6 @@ static ssize_t openssl_read(git_stream *stream, void *data, size_t len)
if ((ret = SSL_read(st->ssl, data, len)) <= 0)
return ssl_set_error(st->ssl, ret);
-#ifdef VALGRIND
- VALGRIND_MAKE_MEM_DEFINED(data, ret);
-#endif
-
return ret;
}
diff --git a/src/transports/auth_ntlm.c b/src/transports/auth_ntlm.c
index 02a861f07..d134a3db6 100644
--- a/src/transports/auth_ntlm.c
+++ b/src/transports/auth_ntlm.c
@@ -50,10 +50,10 @@ static int ntlm_set_credentials(http_auth_ntlm_context *ctx, git_credential *_cr
cred = (git_credential_userpass_plaintext *)_cred;
if ((sep = strchr(cred->username, '\\')) != NULL) {
- domain = strndup(cred->username, (sep - cred->username));
+ domain = git__strndup(cred->username, (sep - cred->username));
GIT_ERROR_CHECK_ALLOC(domain);
- domainuser = strdup(sep + 1);
+ domainuser = git__strdup(sep + 1);
GIT_ERROR_CHECK_ALLOC(domainuser);
username = domainuser;
diff --git a/src/transports/httpclient.c b/src/transports/httpclient.c
index f5c2ce58d..3008aaaad 100644
--- a/src/transports/httpclient.c
+++ b/src/transports/httpclient.c
@@ -29,7 +29,18 @@ static git_http_auth_scheme auth_schemes[] = {
{ GIT_HTTP_AUTH_BASIC, "Basic", GIT_CREDENTIAL_USERPASS_PLAINTEXT, git_http_auth_basic },
};
-#define GIT_READ_BUFFER_SIZE 8192
+/*
+ * Use a 16kb read buffer to match the maximum size of a TLS packet. This
+ * is critical for compatibility with SecureTransport, which will always do
+ * a network read on every call, even if it has data buffered to return to
+ * you. That buffered data may be the _end_ of a keep-alive response, so
+ * if SecureTransport performs another network read, it will wait until the
+ * server ultimately times out before it returns that buffered data to you.
+ * Since SecureTransport only reads a single TLS packet at a time, by
+ * calling it with a read buffer that is the maximum size of a TLS packet,
+ * we ensure that it will never buffer.
+ */
+#define GIT_READ_BUFFER_SIZE (16 * 1024)
typedef struct {
git_net_url url;
diff --git a/src/unix/posix.h b/src/unix/posix.h
index d1f902489..4fa725013 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -33,7 +33,7 @@ typedef int GIT_SOCKET;
# define st_atime_nsec st_atim.tv_nsec
# define st_mtime_nsec st_mtim.tv_nsec
# define st_ctime_nsec st_ctim.tv_nsec
-#elif !defined(GIT_USE_STAT_MTIME_NSEC) && defined(GIT_USE_NEC)
+#elif !defined(GIT_USE_STAT_MTIME_NSEC) && defined(GIT_USE_NSEC)
# error GIT_USE_NSEC defined but unknown struct stat nanosecond type
#endif
diff --git a/src/worktree.c b/src/worktree.c
index ef4ebfda8..e171afbb2 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -136,11 +136,11 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
goto out;
}
- if ((wt->name = git__strdup(name)) == NULL
- || (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL
- || (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL
- || (parent && (wt->parent_path = git__strdup(parent)) == NULL)
- || (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) {
+ if ((wt->name = git__strdup(name)) == NULL ||
+ (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL ||
+ (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL ||
+ (parent && (wt->parent_path = git__strdup(parent)) == NULL) ||
+ (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) {
error = -1;
goto out;
}
@@ -149,7 +149,10 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
goto out;
wt->gitdir_path = git_buf_detach(&gitdir);
- wt->locked = !!git_worktree_is_locked(NULL, wt);
+ if ((error = git_worktree_is_locked(NULL, wt)) < 0)
+ goto out;
+ wt->locked = !!error;
+ error = 0;
*out = wt;
@@ -403,20 +406,24 @@ out:
int git_worktree_lock(git_worktree *wt, const char *reason)
{
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
- int err;
+ int error;
assert(wt);
- if ((err = git_worktree_is_locked(NULL, wt)) < 0)
+ if ((error = git_worktree_is_locked(NULL, wt)) < 0)
+ goto out;
+ if (error) {
+ error = GIT_ELOCKED;
goto out;
+ }
- if ((err = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+ if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
goto out;
if (reason)
git_buf_attach_notowned(&buf, reason, strlen(reason));
- if ((err = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
+ if ((error = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
goto out;
wt->locked = 1;
@@ -424,16 +431,19 @@ int git_worktree_lock(git_worktree *wt, const char *reason)
out:
git_buf_dispose(&path);
- return err;
+ return error;
}
int git_worktree_unlock(git_worktree *wt)
{
git_buf path = GIT_BUF_INIT;
+ int error;
assert(wt);
- if (!git_worktree_is_locked(NULL, wt))
+ if ((error = git_worktree_is_locked(NULL, wt)) < 0)
+ return error;
+ if (!error)
return 1;
if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
@@ -454,22 +464,25 @@ int git_worktree_unlock(git_worktree *wt)
int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
{
git_buf path = GIT_BUF_INIT;
- int ret;
+ int error, locked;
assert(wt);
if (reason)
git_buf_clear(reason);
- if ((ret = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+ if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+ goto out;
+ locked = git_path_exists(path.ptr);
+ if (locked && reason &&
+ (error = git_futils_readbuffer(reason, path.ptr)) < 0)
goto out;
- if ((ret = git_path_exists(path.ptr)) && reason)
- git_futils_readbuffer(reason, path.ptr);
+ error = locked;
out:
git_buf_dispose(&path);
- return ret;
+ return error;
}
const char *git_worktree_name(const git_worktree *wt)
@@ -502,7 +515,6 @@ int git_worktree_pruneinit_options(git_worktree_prune_options *opts,
int git_worktree_is_prunable(git_worktree *wt,
git_worktree_prune_options *opts)
{
- git_buf reason = GIT_BUF_INIT;
git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
GIT_ERROR_CHECK_VERSION(
@@ -512,20 +524,24 @@ int git_worktree_is_prunable(git_worktree *wt,
if (opts)
memcpy(&popts, opts, sizeof(popts));
- if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
- git_worktree_is_locked(&reason, wt))
- {
- if (!reason.size)
- git_buf_attach_notowned(&reason, "no reason given", 15);
- git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr);
- git_buf_dispose(&reason);
+ if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0) {
+ git_buf reason = GIT_BUF_INIT;
+ int error;
- return 0;
+ if ((error = git_worktree_is_locked(&reason, wt)) < 0)
+ return error;
+
+ if (error) {
+ if (!reason.size)
+ git_buf_attach_notowned(&reason, "no reason given", 15);
+ git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr);
+ git_buf_dispose(&reason);
+ return 0;
+ }
}
if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
- git_worktree_validate(wt) == 0)
- {
+ git_worktree_validate(wt) == 0) {
git_error_set(GIT_ERROR_WORKTREE, "not pruning valid working tree");
return 0;
}
diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c
index 61e87350c..6b3ce677d 100644
--- a/tests/blame/blame_helpers.c
+++ b/tests/blame/blame_helpers.c
@@ -31,13 +31,13 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx,
}
if (hunk->final_start_line_number != start_line) {
- hunk_message(idx, hunk, "mismatched start line number: expected %d, got %d",
+ hunk_message(idx, hunk, "mismatched start line number: expected %"PRIuZ", got %"PRIuZ,
start_line, hunk->final_start_line_number);
}
cl_assert_equal_i(hunk->final_start_line_number, start_line);
if (hunk->lines_in_hunk != len) {
- hunk_message(idx, hunk, "mismatched line count: expected %d, got %d",
+ hunk_message(idx, hunk, "mismatched line count: expected %"PRIuZ", got %"PRIuZ,
len, hunk->lines_in_hunk);
}
cl_assert_equal_i(hunk->lines_in_hunk, len);
diff --git a/tests/blame/blame_helpers.h b/tests/blame/blame_helpers.h
index fd5a35d2c..5b34b4aef 100644
--- a/tests/blame/blame_helpers.h
+++ b/tests/blame/blame_helpers.h
@@ -1,7 +1,7 @@
#include "clar_libgit2.h"
#include "blame.h"
-void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...);
+void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) GIT_FORMAT_PRINTF(3, 4);
void check_blame_hunk_index(
git_repository *repo,
diff --git a/tests/config/global.c b/tests/config/global.c
index b64b71677..ed47d0251 100644
--- a/tests/config/global.c
+++ b/tests/config/global.c
@@ -81,7 +81,7 @@ void test_config_global__lock_missing_global_config(void)
git_config_entry *entry;
git_transaction *transaction;
- p_unlink("home/.gitconfig"); /* No global config */
+ (void)p_unlink("home/.gitconfig"); /* No global config */
cl_git_pass(git_config_open_default(&cfg));
cl_git_pass(git_config_lock(&transaction, cfg));
diff --git a/tests/config/new.c b/tests/config/new.c
index 2f5d83d52..22c330f6f 100644
--- a/tests/config/new.c
+++ b/tests/config/new.c
@@ -30,5 +30,5 @@ void test_config_new__write_new_config(void)
git_buf_dispose(&buf);
git_config_free(config);
- p_unlink(TEST_CONFIG);
+ cl_must_pass(p_unlink(TEST_CONFIG));
}
diff --git a/tests/diff/tree.c b/tests/diff/tree.c
index 2359a834b..dfe4d254c 100644
--- a/tests/diff/tree.c
+++ b/tests/diff/tree.c
@@ -524,3 +524,52 @@ void test_diff_tree__diff_configs(void)
cl_assert_equal_i(7, expect.line_adds);
cl_assert_equal_i(15, expect.line_dels);
}
+
+void test_diff_tree__diff_tree_with_empty_dir_entry_succeeds(void)
+{
+ const char *content = "This is a blob\n";
+ const git_diff_delta *delta;
+ git_oid empty_tree, invalid_tree, blob;
+ git_buf patch = GIT_BUF_INIT;
+ git_treebuilder *builder;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ cl_git_pass(git_blob_create_from_buffer(&blob, g_repo, content, strlen(content)));
+ cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
+ cl_git_pass(git_treebuilder_write(&empty_tree, builder));
+ cl_git_pass(git_treebuilder_insert(NULL, builder, "empty_tree", &empty_tree, GIT_FILEMODE_TREE));
+ cl_git_pass(git_treebuilder_insert(NULL, builder, "blob", &blob, GIT_FILEMODE_BLOB));
+ cl_git_pass(git_treebuilder_write(&invalid_tree, builder));
+
+ cl_git_pass(git_tree_lookup(&a, g_repo, &empty_tree));
+ cl_git_pass(git_tree_lookup(&b, g_repo, &invalid_tree));
+ cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL));
+
+ cl_git_pass(git_diff_foreach(diff,
+ diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
+ cl_assert_equal_i(1, expect.files);
+ cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(1, expect.hunks);
+ cl_assert_equal_i(1, expect.lines);
+ cl_assert_equal_i(0, expect.line_ctxt);
+ cl_assert_equal_i(1, expect.line_adds);
+ cl_assert_equal_i(0, expect.line_dels);
+
+ cl_git_pass(git_diff_to_buf(&patch, diff, GIT_DIFF_FORMAT_PATCH));
+ cl_assert_equal_s(patch.ptr,
+ "diff --git a/blob b/blob\n"
+ "new file mode 100644\n"
+ "index 0000000..bbf2e80\n"
+ "--- /dev/null\n"
+ "+++ b/blob\n"
+ "@@ -0,0 +1 @@\n"
+ "+This is a blob\n");
+
+ cl_assert_equal_i(git_diff_num_deltas(diff), 1);
+ delta = git_diff_get_delta(diff, 0);
+ cl_assert_equal_s(delta->new_file.path, "blob");
+
+ git_treebuilder_free(builder);
+ git_buf_dispose(&patch);
+}
diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c
index 8b0445214..71b2e91a7 100644
--- a/tests/diff/workdir.c
+++ b/tests/diff/workdir.c
@@ -2160,3 +2160,46 @@ void test_diff_workdir__symlink_changed_on_non_symlink_platform(void)
git_tree_free(tree);
git_vector_free(&pathlist);
}
+
+void test_diff_workdir__order(void)
+{
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_buf patch = GIT_BUF_INIT;
+ git_oid tree_oid, blob_oid;
+ git_treebuilder *builder;
+ git_tree *tree;
+ git_diff *diff;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ /* Build tree with a single file "abc.txt" */
+ cl_git_pass(git_blob_create_from_buffer(&blob_oid, g_repo, "foo\n", 4));
+ cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
+ cl_git_pass(git_treebuilder_insert(NULL, builder, "abc.txt", &blob_oid, GIT_FILEMODE_BLOB));
+ cl_git_pass(git_treebuilder_write(&tree_oid, builder));
+ cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid));
+
+ /* Create a directory that sorts before and one that sorts after "abc.txt" */
+ cl_git_mkfile("empty_standard_repo/abc.txt", "bar\n");
+ cl_must_pass(p_mkdir("empty_standard_repo/abb", 0777));
+ cl_must_pass(p_mkdir("empty_standard_repo/abd", 0777));
+
+ opts.flags = GIT_DIFF_INCLUDE_UNTRACKED;
+ cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
+
+ cl_assert_equal_i(1, git_diff_num_deltas(diff));
+ cl_git_pass(git_diff_to_buf(&patch, diff, GIT_DIFF_FORMAT_PATCH));
+ cl_assert_equal_s(patch.ptr,
+ "diff --git a/abc.txt b/abc.txt\n"
+ "index 257cc56..5716ca5 100644\n"
+ "--- a/abc.txt\n"
+ "+++ b/abc.txt\n"
+ "@@ -1 +1 @@\n"
+ "-foo\n"
+ "+bar\n");
+
+ git_treebuilder_free(builder);
+ git_buf_dispose(&patch);
+ git_diff_free(diff);
+ git_tree_free(tree);
+}
diff --git a/tests/ignore/path.c b/tests/ignore/path.c
index 864fba41b..e23ac7712 100644
--- a/tests/ignore/path.c
+++ b/tests/ignore/path.c
@@ -255,7 +255,7 @@ void test_ignore_path__globs_without_star(void)
void test_ignore_path__skip_gitignore_directory(void)
{
cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder");
- p_unlink("attr/.gitignore");
+ cl_must_pass(p_unlink("attr/.gitignore"));
cl_assert(!git_path_exists("attr/.gitignore"));
p_mkdir("attr/.gitignore", 0777);
cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n");
@@ -268,12 +268,11 @@ void test_ignore_path__skip_gitignore_directory(void)
void test_ignore_path__subdirectory_gitignore(void)
{
- p_unlink("attr/.gitignore");
+ cl_must_pass(p_unlink("attr/.gitignore"));
cl_assert(!git_path_exists("attr/.gitignore"));
cl_git_mkfile(
"attr/.gitignore",
"file1\n");
- p_mkdir("attr/dir", 0777);
cl_git_mkfile(
"attr/dir/.gitignore",
"file2/\n");
diff --git a/tests/index/nsec.c b/tests/index/nsec.c
index dee1509e1..6edcf030a 100644
--- a/tests/index/nsec.c
+++ b/tests/index/nsec.c
@@ -54,7 +54,7 @@ static bool should_expect_nsecs(void)
expect = try_create_file_with_nsec_timestamp(nsec_path.ptr);
- p_unlink(nsec_path.ptr);
+ cl_must_pass(p_unlink(nsec_path.ptr));
git_buf_dispose(&nsec_path);
diff --git a/tests/index/tests.c b/tests/index/tests.c
index 4c9deaaba..d9d8371dd 100644
--- a/tests/index/tests.c
+++ b/tests/index/tests.c
@@ -566,8 +566,7 @@ void test_index_tests__cannot_add_invalid_filename(void)
{
git_repository *repo;
- p_mkdir("invalid", 0700);
-
+ cl_must_pass(p_mkdir("invalid", 0700));
cl_git_pass(git_repository_init(&repo, "./invalid", 0));
cl_must_pass(p_mkdir("./invalid/subdir", 0777));
diff --git a/tests/network/refspecs.c b/tests/network/refspecs.c
index 734759060..5c8eb1502 100644
--- a/tests/network/refspecs.c
+++ b/tests/network/refspecs.c
@@ -153,7 +153,7 @@ static void assert_invalid_rtransform(const char *refspec, const char *name)
git_refspec spec;
git_buf buf = GIT_BUF_INIT;
- git_refspec__parse(&spec, refspec, true);
+ cl_git_pass(git_refspec__parse(&spec, refspec, true));
cl_git_fail(git_refspec_rtransform(&buf, &spec, name));
git_buf_dispose(&buf);
diff --git a/tests/notes/notes.c b/tests/notes/notes.c
index f2457665c..af9686790 100644
--- a/tests/notes/notes.c
+++ b/tests/notes/notes.c
@@ -400,15 +400,11 @@ void test_notes_notes__can_read_a_note_from_a_commit(void)
git_note *note;
cl_git_pass(git_oid_fromstr(&oid, "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"));
-
cl_git_pass(git_note_commit_create(&notes_commit_oid, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 1));
-
- git_commit_lookup(&notes_commit, _repo, &notes_commit_oid);
-
+ cl_git_pass(git_commit_lookup(&notes_commit, _repo, &notes_commit_oid));
cl_assert(notes_commit);
cl_git_pass(git_note_commit_read(&note, _repo, notes_commit, &oid));
-
cl_assert_equal_s(git_note_message(note), "I decorate 4a20\n");
git_commit_free(notes_commit);
@@ -457,7 +453,7 @@ void test_notes_notes__can_insert_a_note_in_an_existing_fanout(void)
git_note *_note;
cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125"));
-
+
for (i = 0; i < MESSAGES_COUNT; i++) {
cl_git_pass(git_note_create(&note_oid, _repo, "refs/notes/fanout", _sig, _sig, &target_oid, messages[i], 0));
cl_git_pass(git_note_read(&_note, _repo, "refs/notes/fanout", &target_oid));
@@ -511,7 +507,7 @@ void test_notes_notes__can_remove_a_note_from_commit(void)
cl_git_pass(git_note_commit_create(&notes_commit_oid, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 0));
- git_commit_lookup(&existing_notes_commit, _repo, &notes_commit_oid);
+ cl_git_pass(git_commit_lookup(&existing_notes_commit, _repo, &notes_commit_oid));
cl_assert(existing_notes_commit);
@@ -547,7 +543,7 @@ void test_notes_notes__removing_a_note_which_doesnt_exists_returns_ENOTFOUND(voi
cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479"));
cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid));
-
+
error = git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid);
cl_git_fail(error);
cl_assert_equal_i(GIT_ENOTFOUND, error);
diff --git a/tests/object/cache.c b/tests/object/cache.c
index 3ccc325e4..08bf03648 100644
--- a/tests/object/cache.c
+++ b/tests/object/cache.c
@@ -244,15 +244,15 @@ static void *cache_quick(void *arg)
void test_object_cache__fast_thread_rush(void)
{
- int try, th, data[THREADCOUNT*2];
+ int try, th, data[THREADCOUNT];
#ifdef GIT_THREADS
- git_thread t[THREADCOUNT*2];
+ git_thread t[THREADCOUNT];
#endif
for (try = 0; try < REPEAT; ++try) {
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
- for (th = 0; th < THREADCOUNT*2; ++th) {
+ for (th = 0; th < THREADCOUNT; ++th) {
data[th] = th;
#ifdef GIT_THREADS
cl_git_pass(
@@ -263,7 +263,7 @@ void test_object_cache__fast_thread_rush(void)
}
#ifdef GIT_THREADS
- for (th = 0; th < THREADCOUNT*2; ++th) {
+ for (th = 0; th < THREADCOUNT; ++th) {
void *rval;
cl_git_pass(git_thread_join(&t[th], &rval));
cl_assert_equal_i(th, *((int *)rval));