diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000..d6e9cfceb
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,92 @@
+# This file is an example configuration for clang-format 5.0.
+#
+# Note that this style definition should only be understood as a hint
+# for writing new code. The rules are still work-in-progress and does
+# not yet exactly match the style we have in the existing code.
+
+# C Language specifics
+Language: Cpp
+
+# Use tabs whenever we need to fill whitespace that spans at least from one tab
+# stop to the next one.
+#
+# These settings are mirrored in .editorconfig. Keep them in sync.
+UseTab: ForIndentation
+TabWidth: 8
+IndentWidth: 8
+ContinuationIndentWidth: 8
+ColumnLimit: 80
+
+AlignAfterOpenBracket: AlwaysBreak
+AlignEscapedNewlines: Left
+AlignTrailingComments: false
+
+# Allow putting parameters onto the next line
+AllowAllArgumentsOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
+
+# Don't allow short braced statements to be on a single line
+# if (a) not if (a) return;
+# return;
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortLoopsOnASingleLine: false
+AllowShortLambdasOnASingleLine: None
+
+# Pack as many parameters or arguments onto the same line as possible
+# int myFunction(int aaaaaaaaaaaa, int bbbbbbbb,
+# int cccc);
+BinPackArguments: true
+BinPackParameters: false
+
+BreakBeforeBraces: Linux
+BreakBeforeBinaryOperators: None
+BreakBeforeTernaryOperators: false
+BreakStringLiterals: false
+
+# The number of spaces before trailing line comments (// - comments).
+# This does not affect trailing block comments (/* - comments).
+SpacesBeforeTrailingComments: 1
+
+# Don't insert spaces in casts
+# x = (int32) y; not x = ( int32 ) y;
+SpacesInCStyleCastParentheses: false
+
+# Don't insert spaces inside container literals
+# var arr = [1, 2, 3]; not var arr = [ 1, 2, 3 ];
+SpacesInContainerLiterals: false
+
+# Don't insert spaces after '(' or before ')'
+# f(arg); not f( arg );
+SpacesInParentheses: false
+
+# Don't insert spaces after '[' or before ']'
+# int a[5]; not int a[ 5 ];
+SpacesInSquareBrackets: false
+
+# Insert a space after '{' and before '}' in struct initializers
+Cpp11BracedListStyle: false
+
+# A list of macros that should be interpreted as foreach loops instead of as
+# function calls.
+ForEachMacros:
+ - 'git_array_foreach'
+ - 'git_vector_foreach'
+
+# The maximum number of consecutive empty lines to keep.
+MaxEmptyLinesToKeep: 1
+
+# No empty line at the start of a block.
+KeepEmptyLinesAtTheStartOfBlocks: false
+
+# Penalties
+# This decides what order things should be done if a line is too long
+PenaltyBreakAssignment: 10
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+SortIncludes: false
diff --git a/.github/release.yml b/.github/release.yml
index c3c8da290..79158f492 100644
--- a/.github/release.yml
+++ b/.github/release.yml
@@ -6,10 +6,13 @@ changelog:
- title: Bug fixes
labels:
- bug
+ - title: Security fixes
+ labels:
+ - security
- title: Code cleanups
labels:
- cleanup
- - title: CI improvements
+ - title: Build and CI improvements
labels:
- build
- title: Documentation improvements
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
new file mode 100644
index 000000000..285c273b1
--- /dev/null
+++ b/.github/workflows/benchmark.yml
@@ -0,0 +1,82 @@
+# Benchmark libgit2 against the git reference implementation.
+name: Benchmark
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '15 4 * * *'
+
+jobs:
+ # Run our nightly builds. We build a matrix with the various build
+ # targets and their details. Then we build either in a docker container
+ # (Linux) or on the actual hosts (macOS, Windows).
+ build:
+ # Only run scheduled workflows on the main repository; prevents people
+ # from using build minutes on their forks.
+ if: github.repository == 'libgit2/libgit2'
+
+ strategy:
+ matrix:
+ platform:
+ - name: "Linux (clang, OpenSSL)"
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DBUILD_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
+ CMAKE_BUILD_OPTIONS: --config Release
+ id: linux
+ os: ubuntu-latest
+ setup-script: ubuntu
+ - name: "macOS"
+ os: macos-10.15
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DBUILD_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
+ CMAKE_BUILD_OPTIONS: --config Release
+ PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
+ id: macos
+ setup-script: osx
+ - name: "Windows (amd64, Visual Studio)"
+ os: windows-2019
+ env:
+ ARCH: amd64
+ CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON -DBUILD_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
+ CMAKE_BUILD_OPTIONS: --config Release
+ id: windows
+ setup-script: win32
+ fail-fast: false
+ name: "Build ${{ matrix.platform.name }}"
+ env: ${{ matrix.platform.env }}
+ runs-on: ${{ matrix.platform.os }}
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v2
+ with:
+ path: source
+ fetch-depth: 0
+ - name: Set up benchmark environment
+ run: source/ci/setup-${{ matrix.platform.setup-script }}-benchmark.sh
+ shell: bash
+ if: matrix.platform.setup-script != ''
+ - name: Build
+ run: |
+ mkdir build && cd build
+ ../source/ci/build.sh
+ shell: bash
+ - name: Benchmark
+ run: |
+ if [[ "$(uname -s)" == MINGW* ]]; then
+ GIT2_CLI="$(cygpath -w $(pwd))\\build\\Release\\git2_cli"
+ else
+ GIT2_CLI="$(pwd)/build/git2_cli"
+ fi
+
+ mkdir benchmark && cd benchmark
+ ../source/tests/benchmarks/benchmark.sh --baseline-cli "git" --cli "${GIT2_CLI}" --json benchmarks.json --zip benchmarks.zip
+ shell: bash
+ - name: Upload results
+ uses: actions/upload-artifact@v2
+ with:
+ name: benchmark-${{ matrix.platform.id }}
+ path: benchmark
+ if: always()
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
deleted file mode 100644
index 38b4a044a..000000000
--- a/.github/workflows/codeql.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-name: "CodeQL"
-
-on:
- workflow_dispatch:
- schedule:
- - cron: '21 3 * * 1'
-
-env:
- docker-registry: docker.pkg.github.com
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out repository
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v1
- with:
- languages: 'cpp'
-
- - name: Build
- run: |
- mkdir build
- cd build
- cmake .. -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
- cmake --build .
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 74bab53f3..bcad84b8b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -10,7 +10,7 @@ on:
workflow_dispatch:
env:
- docker-registry: docker.pkg.github.com
+ docker-registry: ghcr.io
docker-config-path: source/ci/docker
jobs:
@@ -69,7 +69,7 @@ jobs:
if [ "${{ matrix.container.base }}" != "" ]; then
BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
fi
- docker build -t ${{ env.docker-registry-container-sha }} ${BASE_ARG} -f ${{ env.dockerfile }} .
+ docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
docker tag ${{ env.docker-registry-container-sha }} ${{ env.docker-registry-container-latest }}
docker push ${{ env.docker-registry-container-sha }}
docker push ${{ env.docker-registry-container-latest }}
@@ -85,6 +85,7 @@ jobs:
matrix:
platform:
- name: "Linux (Xenial, GCC, OpenSSL)"
+ id: xenial-gcc-openssl
container:
name: xenial
env:
@@ -93,6 +94,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DDEBUG_STRICT_ALLOC=ON -DDEBUG_STRICT_OPEN=ON
os: ubuntu-latest
- name: Linux (Xenial, GCC, mbedTLS)
+ id: xenial-gcc-mbedtls
container:
name: xenial
env:
@@ -101,6 +103,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
os: ubuntu-latest
- name: "Linux (Xenial, Clang, OpenSSL)"
+ id: xenial-clang-openssl
container:
name: xenial
env:
@@ -109,6 +112,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
os: ubuntu-latest
- name: "Linux (Xenial, Clang, mbedTLS)"
+ id: xenial-clang-mbedtls
container:
name: xenial
env:
@@ -117,6 +121,7 @@ jobs:
CMAKE_GENERATOR: Ninja
os: ubuntu-latest
- name: "Linux (MemorySanitizer)"
+ id: memorysanitizer
container:
name: focal
env:
@@ -130,6 +135,7 @@ jobs:
UBSAN_OPTIONS: print_stacktrace=1
os: ubuntu-latest
- name: "Linux (UndefinedBehaviorSanitizer)"
+ id: ubsanitizer
container:
name: focal
env:
@@ -143,6 +149,7 @@ jobs:
UBSAN_OPTIONS: print_stacktrace=1
os: ubuntu-latest
- name: "Linux (ThreadSanitizer)"
+ id: threadsanitizer
container:
name: focal
env:
@@ -157,6 +164,7 @@ jobs:
TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
os: ubuntu-latest
- name: "macOS"
+ id: macos
os: macos-10.15
env:
CC: clang
@@ -166,6 +174,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
setup-script: osx
- name: "Windows (amd64, Visual Studio)"
+ id: windows-amd64-vs
os: windows-2019
env:
ARCH: amd64
@@ -174,6 +183,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio)"
+ id: windows-x86-vs
os: windows-2019
env:
ARCH: x86
@@ -182,6 +192,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw)"
+ id: windows-amd64-mingw
os: windows-2019
setup-script: mingw
env:
@@ -193,6 +204,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw)"
+ id: windows-x86-mingw
os: windows-2019
setup-script: mingw
env:
@@ -214,7 +226,7 @@ jobs:
path: source
fetch-depth: 0
- name: Set up build environment
- run: source/ci/setup-${{ matrix.platform.setup-script }}.sh
+ run: source/ci/setup-${{ matrix.platform.setup-script }}-build.sh
shell: bash
if: matrix.platform.setup-script != ''
- name: Setup QEMU
@@ -229,7 +241,11 @@ jobs:
working-directory: ${{ env.docker-config-path }}
if: matrix.platform.container.name != ''
- name: Create container
- run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ env.dockerfile }} .
+ run: |
+ if [ "${{ matrix.container.base }}" != "" ]; then
+ BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
+ fi
+ docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
working-directory: ${{ env.docker-config-path }}
if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
- name: Build and test
@@ -237,10 +253,12 @@ jobs:
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
if [ -n "${{ matrix.platform.container.name }}" ]; then
+ mkdir build
docker run \
--rm \
- --user libgit2:libgit2 \
+ --user "$(id -u):$(id -g)" \
-v "$(pwd)/source:/home/libgit2/source" \
+ -v "$(pwd)/build:/home/libgit2/build" \
-w /home/libgit2 \
-e ASAN_SYMBOLIZER_PATH \
-e CC \
@@ -248,19 +266,40 @@ jobs:
-e CMAKE_GENERATOR \
-e CMAKE_OPTIONS \
-e GITTEST_NEGOTIATE_PASSWORD \
+ -e GITTEST_FLAKY_STAT \
-e PKG_CONFIG_PATH \
-e SKIP_NEGOTIATE_TESTS \
-e SKIP_SSH_TESTS \
-e TSAN_OPTIONS \
-e UBSAN_OPTIONS \
${{ env.docker-registry-container-sha }} \
- /bin/bash -c "mkdir build && cd build && ../source/ci/build.sh && ../source/ci/test.sh"
+ /bin/bash -c "cd build && ../source/ci/build.sh && ../source/ci/test.sh"
else
- mkdir build && cd build
+ mkdir build
+ cd build
../source/ci/build.sh
../source/ci/test.sh
fi
shell: bash
+ - name: Upload test results
+ uses: actions/upload-artifact@v3
+ if: success() || failure()
+ with:
+ name: test-results-${{ matrix.platform.id }}
+ path: build/results_*.xml
+
+ test_results:
+ name: Test results
+ needs: [ build ]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download test results
+ uses: actions/download-artifact@v3
+ - name: Generate test summary
+ uses: test-summary/action@v1
+ with:
+ paths: 'test-results-*/*.xml'
+
# Generate documentation using docurium. We'll upload the documentation
# as a build artifact so that it can be reviewed as part of a pull
@@ -270,6 +309,7 @@ jobs:
documentation:
name: Generate documentation
needs: [ containers ]
+ if: success() || failure()
runs-on: ubuntu-latest
steps:
- name: Check out repository
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 5513d5b43..856da28a3 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -7,7 +7,7 @@ on:
- cron: '15 1 * * *'
env:
- docker-registry: docker.pkg.github.com
+ docker-registry: ghcr.io
docker-config-path: source/ci/docker
jobs:
@@ -15,6 +15,10 @@ jobs:
# targets and their details. Then we build either in a docker container
# (Linux) or on the actual hosts (macOS, Windows).
build:
+ # Only run scheduled workflows on the main repository; prevents people
+ # from using build minutes on their forks.
+ if: github.repository == 'libgit2/libgit2'
+
strategy:
matrix:
platform:
@@ -247,6 +251,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DUSE_SSH=ON
RUN_INVASIVE_TESTS: true
SKIP_PROXY_TESTS: true
+ GITTEST_FLAKY_STAT: true
os: ubuntu-latest
- name: "Linux (arm64, Bionic, GCC, OpenSSL)"
container:
@@ -271,7 +276,7 @@ jobs:
path: source
fetch-depth: 0
- name: Set up build environment
- run: source/ci/setup-${{ matrix.platform.setup-script }}.sh
+ run: source/ci/setup-${{ matrix.platform.setup-script }}-build.sh
shell: bash
if: matrix.platform.setup-script != ''
- name: Setup QEMU
@@ -305,6 +310,7 @@ jobs:
-e CMAKE_GENERATOR \
-e CMAKE_OPTIONS \
-e GITTEST_NEGOTIATE_PASSWORD \
+ -e GITTEST_FLAKY_STAT \
-e PKG_CONFIG_PATH \
-e SKIP_NEGOTIATE_TESTS \
-e SKIP_SSH_TESTS \
@@ -319,6 +325,10 @@ jobs:
shell: bash
coverity:
+ # Only run scheduled workflows on the main repository; prevents people
+ # from using build minutes on their forks.
+ if: github.repository == 'libgit2/libgit2'
+
name: Coverity
runs-on: ubuntu-latest
steps:
@@ -338,3 +348,32 @@ jobs:
run: source/ci/coverity.sh
env:
COVERITY_TOKEN: ${{ secrets.coverity_token }}
+
+ codeql:
+ # Only run scheduled workflows on the main repository; prevents people
+ # from using build minutes on their forks.
+ if: github.repository == 'libgit2/libgit2'
+
+ name: CodeQL
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: 'cpp'
+
+ - name: Build
+ run: |
+ mkdir build
+ cd build
+ cmake .. -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ cmake --build .
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ff6748e0..2b5a2842c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,12 @@
-# CMake build script for the libgit2 project
+# libgit2: the cross-platform, linkable library implementation of git.
# See `README.md` for build instructions.
+#
+# This top-level CMakeLists.txt sets up configuration options and
+# determines which subprojects to build.
cmake_minimum_required(VERSION 3.5.1)
-project(libgit2 VERSION "1.4.3" LANGUAGES C)
+project(libgit2 VERSION "1.5.0" LANGUAGES C)
# Add find modules to the path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
@@ -15,6 +18,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
# Optional subsystems
option(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
option(BUILD_TESTS "Build Tests using the Clar suite" ON)
+option(BUILD_CLI "Build the command-line interface" ON)
option(BUILD_EXAMPLES "Build library usage example apps" OFF)
option(BUILD_FUZZERS "Build the fuzz targets" OFF)
@@ -25,7 +29,8 @@ option(USE_NSEC "Support nanosecond precision file mtimes and cti
# Backend selection
option(USE_SSH "Link with libssh2 to enable SSH support" OFF)
option(USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON)
-option(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS/Generic" ON)
+option(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS" ON)
+option(USE_SHA256 "Enable SHA256. Can be set to HTTPS/Builtin" ON)
option(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
set(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
set(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
@@ -127,6 +132,14 @@ if(BUILD_FUZZERS)
endif()
+# Export for people who use us as a dependency
+
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+ set(LIBGIT2_DEPENDENCY_OBJECTS ${LIBGIT2_DEPENDENCY_OBJECTS} PARENT_SCOPE)
+ set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE)
+endif()
+
+
# Summary
feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
diff --git a/COPYING b/COPYING
index ccfb7dbf8..28226696d 100644
--- a/COPYING
+++ b/COPYING
@@ -1144,3 +1144,43 @@ worldwide. This software is distributed without any warranty.
See .
+----------------------------------------------------------------------
+
+The built-in SHA256 support (src/hash/rfc6234) is taken from RFC 6234
+under the following license:
+
+Copyright (c) 2011 IETF Trust and the persons identified as
+authors of the code. All rights reserved.
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+- Redistributions of source code must retain the above
+ copyright notice, this list of conditions and
+ the following disclaimer.
+
+- Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+- Neither the name of Internet Society, IETF or IETF Trust, nor
+ the names of specific contributors, may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README.md b/README.md
index c73b50701..a9deaa01d 100644
--- a/README.md
+++ b/README.md
@@ -392,6 +392,8 @@ Here are the bindings to libgit2 that are currently available:
* parrot-libgit2
* Perl
* Git-Raw
+* Pharo Smalltalk
+ * libgit2-pharo-bindings
* PHP
* php-git
* Python
@@ -405,6 +407,8 @@ Here are the bindings to libgit2 that are currently available:
* git2-rs
* Swift
* SwiftGit2
+* Tcl
+ * lg2
* Vala
* libgit2.vapi
diff --git a/ci/build.sh b/ci/build.sh
index 5a51f925a..21a45af5f 100755
--- a/ci/build.sh
+++ b/ci/build.sh
@@ -59,7 +59,7 @@ echo "##########################################################################
echo "## Configuring build environment"
echo "##############################################################################"
-echo cmake -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G \"${CMAKE_GENERATOR}\" ${CMAKE_OPTIONS} -S \"${SOURCE_DIR}\"
+echo "${CMAKE}" -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G \"${CMAKE_GENERATOR}\" ${CMAKE_OPTIONS} -S \"${SOURCE_DIR}\"
env PATH="${BUILD_PATH}" "${CMAKE}" -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G "${CMAKE_GENERATOR}" ${CMAKE_OPTIONS} -S "${SOURCE_DIR}"
echo ""
@@ -69,10 +69,11 @@ echo "##########################################################################
# Determine parallelism; newer cmake supports `--build --parallel` but
# we cannot yet rely on that.
-if [ "${CMAKE_GENERATOR}" = "Unix Makefiles" -a "${CORES}" != "" ]; then
+if [ "${CMAKE_GENERATOR}" = "Unix Makefiles" -a "${CORES}" != "" -a "${CMAKE_BUILD_OPTIONS}" = "" ]; then
BUILDER=(make -j ${CORES})
else
- BUILDER=("${CMAKE}" --build .)
+ BUILDER=("${CMAKE}" --build . ${CMAKE_BUILD_OPTIONS})
fi
+echo "${BUILDER[@]}"
env PATH="${BUILD_PATH}" "${BUILDER[@]}"
diff --git a/ci/docker/bionic b/ci/docker/bionic
index 51af5c01c..f1b69edef 100644
--- a/ci/docker/bionic
+++ b/ci/docker/bionic
@@ -28,17 +28,22 @@ RUN apt-get update && \
FROM apt AS mbedtls
RUN cd /tmp && \
- curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
- tar -xz && \
- cd mbedtls-2.16.2 && \
+ curl --location --silent --show-error https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-2.16.2.tar.gz | \
+ tar -xz && \
+ cd mbedtls-mbedtls-2.16.2 && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
CFLAGS=-fPIC cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON . && \
ninja install && \
cd .. && \
- rm -rf mbedtls-2.16.2
+ rm -rf mbedtls-mbedtls-2.16.2
FROM mbedtls AS adduser
-RUN useradd --shell /bin/bash libgit2 --create-home
+ARG UID=""
+ARG GID=""
+RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
+ if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
+ groupadd ${GROUP_ARG} libgit2 && \
+ useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
RUN mkdir /var/run/sshd
diff --git a/ci/docker/centos7 b/ci/docker/centos7
index 8105f1442..28ed65081 100644
--- a/ci/docker/centos7
+++ b/ci/docker/centos7
@@ -48,7 +48,12 @@ RUN cd /tmp && \
rm -rf cmake-3.21.1
FROM cmake AS adduser
-RUN useradd --shell /bin/bash libgit2 --create-home
+ARG UID=""
+ARG GID=""
+RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
+ if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
+ groupadd ${GROUP_ARG} libgit2 && \
+ useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
diff --git a/ci/docker/centos8 b/ci/docker/centos8
index cca088103..81f0c3c76 100644
--- a/ci/docker/centos8
+++ b/ci/docker/centos8
@@ -1,6 +1,10 @@
ARG BASE=centos:8
-FROM ${BASE} AS yum
+FROM ${BASE} AS stream
+RUN dnf -y --disablerepo '*' --enablerepo=extras swap centos-linux-repos centos-stream-repos && \
+ dnf -y distro-sync
+
+FROM stream AS yum
RUN yum install -y \
which \
bzip2 \
@@ -40,7 +44,12 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
-RUN useradd --shell /bin/bash libgit2 --create-home
+ARG UID=""
+ARG GID=""
+RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
+ if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
+ groupadd ${GROUP_ARG} libgit2 && \
+ useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
diff --git a/ci/docker/focal b/ci/docker/focal
index 37d7d6356..b3a402cb0 100644
--- a/ci/docker/focal
+++ b/ci/docker/focal
@@ -32,9 +32,9 @@ RUN apt-get update && \
FROM apt AS mbedtls
RUN cd /tmp && \
- curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
+ curl --location --silent --show-error https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-2.16.2.tar.gz | \
tar -xz && \
- cd mbedtls-2.16.2 && \
+ cd mbedtls-mbedtls-2.16.2 && \
scripts/config.pl unset MBEDTLS_AESNI_C && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
mkdir build build-msan && \
@@ -45,7 +45,7 @@ RUN cd /tmp && \
CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=MemSanDbg -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \
ninja install && \
cd .. && \
- rm -rf mbedtls-2.16.2
+ rm -rf mbedtls-mbedtls-2.16.2
FROM mbedtls AS libssh2
RUN cd /tmp && \
@@ -73,7 +73,13 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
-RUN useradd --shell /bin/bash libgit2 --create-home
+ARG UID=""
+ARG GID=""
+RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
+ if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
+ groupadd ${GROUP_ARG} libgit2 && \
+ useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
+
FROM adduser AS configure
RUN mkdir /var/run/sshd
diff --git a/ci/docker/xenial b/ci/docker/xenial
index c19fe421d..f5fa5a315 100644
--- a/ci/docker/xenial
+++ b/ci/docker/xenial
@@ -30,14 +30,14 @@ RUN apt-get update && \
FROM apt AS mbedtls
RUN cd /tmp && \
- curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \
- tar -xz && \
- cd mbedtls-2.16.2 && \
+ curl --location --silent --show-error https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-2.16.2.tar.gz | \
+ tar -xz && \
+ cd mbedtls-mbedtls-2.16.2 && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
CFLAGS=-fPIC cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON . && \
ninja install && \
cd .. && \
- rm -rf mbedtls-2.16.2
+ rm -rf mbedtls-mbedtls-2.16.2
FROM mbedtls AS libssh2
RUN cd /tmp && \
@@ -60,7 +60,13 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
-RUN useradd --shell /bin/bash libgit2 --create-home
+ARG UID=""
+ARG GID=""
+RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
+ if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
+ groupadd ${GROUP_ARG} libgit2 && \
+ useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
+
FROM adduser AS configure
RUN mkdir /var/run/sshd
diff --git a/ci/getcontainer.sh b/ci/getcontainer.sh
index 07ef7b8ea..81d0c1d92 100755
--- a/ci/getcontainer.sh
+++ b/ci/getcontainer.sh
@@ -37,9 +37,13 @@ DOCKER_REGISTRY_CONTAINER_SHA="${DOCKER_REGISTRY_CONTAINER}:${DOCKER_SHA}"
echo "docker-registry-container-sha=${DOCKER_REGISTRY_CONTAINER_SHA}" >> $GITHUB_ENV
echo "docker-registry-container-latest=${DOCKER_REGISTRY_CONTAINER}:latest" >> $GITHUB_ENV
+echo "::: logging in to ${DOCKER_REGISTRY} as ${GITHUB_ACTOR}"
+
exists="true"
docker login https://${DOCKER_REGISTRY} -u ${GITHUB_ACTOR} -p ${GITHUB_TOKEN} || exists="false"
+echo "::: pulling ${DOCKER_REGISTRY_CONTAINER_SHA}"
+
if [ "${exists}" != "false" ]; then
docker pull ${DOCKER_REGISTRY_CONTAINER_SHA} || exists="false"
fi
diff --git a/ci/setup-mingw.sh b/ci/setup-mingw-build.sh
similarity index 97%
rename from ci/setup-mingw.sh
rename to ci/setup-mingw-build.sh
index f5a882d2b..3d72b24eb 100755
--- a/ci/setup-mingw.sh
+++ b/ci/setup-mingw-build.sh
@@ -1,4 +1,6 @@
-#!/bin/sh -e
+#!/bin/sh
+
+set -ex
echo "##############################################################################"
echo "## Downloading mingw"
diff --git a/ci/setup-osx-benchmark.sh b/ci/setup-osx-benchmark.sh
new file mode 100755
index 000000000..80d87682b
--- /dev/null
+++ b/ci/setup-osx-benchmark.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -ex
+
+brew update
+brew install hyperfine
diff --git a/ci/setup-osx.sh b/ci/setup-osx-build.sh
similarity index 95%
rename from ci/setup-osx.sh
rename to ci/setup-osx-build.sh
index 2e630eedb..0b95e7629 100755
--- a/ci/setup-osx.sh
+++ b/ci/setup-osx-build.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-set -x
+set -ex
brew update
brew install pkgconfig zlib curl openssl libssh2 ninja
diff --git a/ci/setup-ubuntu-benchmark.sh b/ci/setup-ubuntu-benchmark.sh
new file mode 100755
index 000000000..561a18fd9
--- /dev/null
+++ b/ci/setup-ubuntu-benchmark.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -ex
+
+sudo apt-get update
+sudo apt-get install -y --no-install-recommends \
+ cargo \
+ cmake \
+ gcc \
+ git \
+ krb5-user \
+ libkrb5-dev \
+ libssl-dev \
+ libz-dev \
+ make \
+ ninja-build \
+ pkgconf
+
+wget https://github.com/sharkdp/hyperfine/releases/download/v1.12.0/hyperfine_1.12.0_amd64.deb
+sudo dpkg -i hyperfine_1.12.0_amd64.deb
diff --git a/ci/setup-win32-benchmark.sh b/ci/setup-win32-benchmark.sh
new file mode 100755
index 000000000..0eac2f666
--- /dev/null
+++ b/ci/setup-win32-benchmark.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -ex
+
+choco install hyperfine zip
+
+CHOCO_PATH=$(mktemp -d)
+curl -L https://github.com/ethomson/PurgeStandbyList/releases/download/v1.0/purgestandbylist.1.0.0.nupkg -o "${CHOCO_PATH}/purgestandbylist.1.0.0.nupkg"
+choco install purgestandbylist -s $(cygpath -w "${CHOCO_PATH}")
diff --git a/ci/test.sh b/ci/test.sh
index a94839778..0815522a9 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -159,10 +159,18 @@ fi
if [ -z "$SKIP_OFFLINE_TESTS" ]; then
echo ""
echo "##############################################################################"
- echo "## Running (offline) tests"
+ echo "## Running core tests"
echo "##############################################################################"
+ echo ""
+ echo "Running libgit2 integration (offline) tests"
+ echo ""
run_test offline
+
+ echo ""
+ echo "Running utility tests"
+ echo ""
+ run_test util
fi
if [ -n "$RUN_INVASIVE_TESTS" ]; then
@@ -186,7 +194,7 @@ if [ -z "$SKIP_ONLINE_TESTS" ]; then
echo ""
echo "##############################################################################"
- echo "## Running (online) tests"
+ echo "## Running networking (online) tests"
echo "##############################################################################"
export GITTEST_REMOTE_REDIRECT_INITIAL="http://localhost:9000/initial-redirect/libgit2/TestGitRepository"
@@ -198,9 +206,9 @@ if [ -z "$SKIP_ONLINE_TESTS" ]; then
# Run the online tests that immutably change global state separately
# to avoid polluting the test environment.
echo ""
- echo "##############################################################################"
- echo "## Running (online_customcert) tests"
- echo "##############################################################################"
+ echo "Running custom certificate (online_customcert) tests"
+ echo ""
+
run_test online_customcert
fi
diff --git a/cmake/AddClarTest.cmake b/cmake/AddClarTest.cmake
new file mode 100644
index 000000000..743941638
--- /dev/null
+++ b/cmake/AddClarTest.cmake
@@ -0,0 +1,7 @@
+function(ADD_CLAR_TEST project name)
+ if(NOT USE_LEAK_CHECKER STREQUAL "OFF")
+ add_test(${name} "${PROJECT_SOURCE_DIR}/script/${USE_LEAK_CHECKER}.sh" "${PROJECT_BINARY_DIR}/${project}" ${ARGN})
+ else()
+ add_test(${name} "${PROJECT_BINARY_DIR}/${project}" ${ARGN})
+ endif()
+endfunction(ADD_CLAR_TEST)
diff --git a/cmake/FindPCRE.cmake b/cmake/FindPCRE.cmake
index 3a7cfad91..02e7edce1 100644
--- a/cmake/FindPCRE.cmake
+++ b/cmake/FindPCRE.cmake
@@ -16,19 +16,18 @@
# PCRE_FOUND - True if pcre found.
# Look for the header file.
-find_path(PCRE_INCLUDE_DIR NAMES pcreposix.h)
+find_path(PCRE_INCLUDE_DIR NAMES pcre.h)
# Look for the library.
find_library(PCRE_LIBRARY NAMES pcre)
-find_library(PCRE_POSIX_LIBRARY NAMES pcreposix)
# Handle the QUIETLY and REQUIRED arguments and set PCRE_FOUND to TRUE if all listed variables are TRUE.
include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_POSIX_LIBRARY PCRE_INCLUDE_DIR)
+find_package_handle_standard_args(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_INCLUDE_DIR)
# Copy the results to the output variables.
if(PCRE_FOUND)
- set(PCRE_LIBRARIES ${PCRE_LIBRARY} ${PCRE_POSIX_LIBRARY})
+ set(PCRE_LIBRARIES ${PCRE_LIBRARY})
set(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR})
else(PCRE_FOUND)
set(PCRE_LIBRARIES)
diff --git a/cmake/FindPCRE2.cmake b/cmake/FindPCRE2.cmake
index d4b8e6761..41c165b65 100644
--- a/cmake/FindPCRE2.cmake
+++ b/cmake/FindPCRE2.cmake
@@ -16,7 +16,7 @@
# PCRE2_FOUND - True if pcre found.
# Look for the header file.
-find_path(PCRE2_INCLUDE_DIR NAMES pcre2posix.h)
+find_path(PCRE2_INCLUDE_DIR NAMES pcre2.h)
# Look for the library.
find_library(PCRE2_LIBRARY NAMES pcre2-8)
diff --git a/cmake/SelectHTTPSBackend.cmake b/cmake/SelectHTTPSBackend.cmake
index 79319502e..20221bf9f 100644
--- a/cmake/SelectHTTPSBackend.cmake
+++ b/cmake/SelectHTTPSBackend.cmake
@@ -64,7 +64,7 @@ if(USE_HTTPS)
if(NOT CERT_LOCATION)
message(STATUS "Auto-detecting default certificates location")
- if(CMAKE_SYSTEM_NAME MATCHES Darwin)
+ if(EXISTS "/usr/local/opt/openssl/bin/openssl")
# Check for an Homebrew installation
set(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl")
else()
diff --git a/cmake/SelectHashes.cmake b/cmake/SelectHashes.cmake
index bedd8c4e3..faf9e2ea3 100644
--- a/cmake/SelectHashes.cmake
+++ b/cmake/SelectHashes.cmake
@@ -4,6 +4,9 @@ include(SanitizeBool)
# USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF
sanitizebool(USE_SHA1)
+sanitizebool(USE_SHA256)
+
+# sha1
if(USE_SHA1 STREQUAL ON)
SET(USE_SHA1 "CollisionDetection")
@@ -21,32 +24,77 @@ endif()
if(USE_SHA1 STREQUAL "CollisionDetection")
set(GIT_SHA1_COLLISIONDETECT 1)
- add_definitions(-DSHA1DC_NO_STANDARD_INCLUDES=1)
- add_definitions(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
- add_definitions(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
elseif(USE_SHA1 STREQUAL "OpenSSL")
- # OPENSSL_FOUND should already be set, we're checking USE_HTTPS
-
set(GIT_SHA1_OPENSSL 1)
+elseif(USE_SHA1 STREQUAL "OpenSSL-Dynamic")
+ set(GIT_SHA1_OPENSSL 1)
+ set(GIT_SHA1_OPENSSL_DYNAMIC 1)
+ list(APPEND LIBGIT2_SYSTEM_LIBS dl)
+elseif(USE_SHA1 STREQUAL "CommonCrypto")
+ set(GIT_SHA1_COMMON_CRYPTO 1)
+elseif(USE_SHA1 STREQUAL "mbedTLS")
+ set(GIT_SHA1_MBEDTLS 1)
+elseif(USE_SHA1 STREQUAL "Win32")
+ set(GIT_SHA1_WIN32 1)
+else()
+ message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
+endif()
+
+# sha256
+
+if(USE_SHA256 STREQUAL ON AND USE_HTTPS)
+ SET(USE_SHA256 "HTTPS")
+elseif(USE_SHA256 STREQUAL ON)
+ SET(USE_SHA256 "Builtin")
+endif()
+
+if(USE_SHA256 STREQUAL "HTTPS")
+ if(USE_HTTPS STREQUAL "SecureTransport")
+ set(USE_SHA256 "CommonCrypto")
+ elseif(USE_HTTPS STREQUAL "WinHTTP")
+ set(USE_SHA256 "Win32")
+ elseif(USE_HTTPS)
+ set(USE_SHA256 ${USE_HTTPS})
+ endif()
+endif()
+
+if(USE_SHA256 STREQUAL "Builtin")
+ set(GIT_SHA256_BUILTIN 1)
+elseif(USE_SHA256 STREQUAL "OpenSSL")
+ set(GIT_SHA256_OPENSSL 1)
+elseif(USE_SHA256 STREQUAL "OpenSSL-Dynamic")
+ set(GIT_SHA256_OPENSSL 1)
+ set(GIT_SHA256_OPENSSL_DYNAMIC 1)
+ list(APPEND LIBGIT2_SYSTEM_LIBS dl)
+elseif(USE_SHA256 STREQUAL "CommonCrypto")
+ set(GIT_SHA256_COMMON_CRYPTO 1)
+elseif(USE_SHA256 STREQUAL "mbedTLS")
+ set(GIT_SHA256_MBEDTLS 1)
+elseif(USE_SHA256 STREQUAL "Win32")
+ set(GIT_SHA256_WIN32 1)
+else()
+ message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
+endif()
+
+# add library requirements
+if(USE_SHA1 STREQUAL "OpenSSL" OR USE_SHA256 STREQUAL "OpenSSL")
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
list(APPEND LIBGIT2_PC_LIBS "-lssl")
else()
list(APPEND LIBGIT2_PC_REQUIRES "openssl")
endif()
-elseif(USE_SHA1 STREQUAL "CommonCrypto")
- set(GIT_SHA1_COMMON_CRYPTO 1)
-elseif(USE_SHA1 STREQUAL "mbedTLS")
- set(GIT_SHA1_MBEDTLS 1)
+endif()
+
+if(USE_SHA1 STREQUAL "mbedTLS" OR USE_SHA256 STREQUAL "mbedTLS")
list(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR})
list(APPEND LIBGIT2_SYSTEM_LIBS ${MBEDTLS_LIBRARIES})
# mbedTLS has no pkgconfig file, hence we can't require it
# https://github.com/ARMmbed/mbedtls/issues/228
# For now, pass its link flags as our own
list(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
-elseif(USE_SHA1 STREQUAL "Win32")
- set(GIT_SHA1_WIN32 1)
-elseif(NOT (USE_SHA1 STREQUAL "Generic"))
- message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
endif()
-add_feature_info(SHA ON "using ${USE_SHA1}")
+# notify feature enablement
+
+add_feature_info(SHA1 ON "using ${USE_SHA1}")
+add_feature_info(SHA256 ON "using ${USE_SHA256}")
diff --git a/debian/README.source b/debian/README.source
index 80dcb6da5..6e4f234ba 100644
--- a/debian/README.source
+++ b/debian/README.source
@@ -1,4 +1,9 @@
The DFSG version string is added because the /deps directory is removed from the
upstream tarball since it's not used in any part of the packaging.
- -- Russell Sim , Sat, 29 Jul 2017 18:32:25 +0200
+ -- Russell Sim Sat, 29 Jul 2017 18:32:25 +0200
+
+I replaced the DFSG suffix with DS, because the removal is merely reducing the
+source tarball in size, not fixing any DFSG violations.
+
+ -- Timo Röhling Sun, 28 Aug 2022 14:08:22 +0200
diff --git a/debian/changelog b/debian/changelog
index 3d214b6f4..d67e9153c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,52 @@
+libgit2 (1.5.0+ds-6) unstable; urgency=medium
+
+ * Team upload.
+ * Upload to unstable.
+
+ -- Timo Röhling Sun, 02 Oct 2022 16:07:23 +0200
+
+libgit2 (1.5.0+ds-5) experimental; urgency=medium
+
+ * Team upload.
+ * Fix libpcre2-dev dependency of libgit2-dev
+
+ -- Timo Röhling Thu, 08 Sep 2022 22:17:22 +0200
+
+libgit2 (1.5.0+ds-4) experimental; urgency=medium
+
+ * Team upload.
+ * Disable even more flaky lstat() tests
+
+ -- Timo Röhling Wed, 31 Aug 2022 15:54:12 +0200
+
+libgit2 (1.5.0+ds-3) experimental; urgency=medium
+
+ * Team upload.
+ * Guard more lstat() asserts with GITTEST_FLAKY_STAT
+
+ -- Timo Röhling Wed, 31 Aug 2022 13:36:51 +0200
+
+libgit2 (1.5.0+ds-2) experimental; urgency=medium
+
+ * Team upload.
+ * Enable GITTEST_FLAKY_STAT workaround for unit tests
+ * Apply M-A hint to libgit2-fixtures
+
+ -- Timo Röhling Mon, 29 Aug 2022 23:04:36 +0200
+
+libgit2 (1.5.0+ds-1) experimental; urgency=medium
+
+ * Team upload.
+ * Update d/watch
+ * Bump Standards-Version to 4.6.1
+ * New upstream version 1.5.0+ds (Closes: #1016800)
+ * Explicitly set USE_SSH=ON (Closes: #1015965)
+ * Bump SONAME to libgit2.so.1.5
+ * Add lintian overrides for fixture data
+ * Switch to PCRE2 (Closes: #1000045)
+
+ -- Timo Röhling Sun, 28 Aug 2022 19:56:46 +0200
+
libgit2 (1.4.3+dfsg.1-1~bpo11+pve1) proxmox-rust; urgency=medium
* Rebuild for Debian Bullseye / Proxmox
diff --git a/debian/clean b/debian/clean
index 1df35a1e6..c30105cba 100644
--- a/debian/clean
+++ b/debian/clean
@@ -1,2 +1,2 @@
-tests/.clarcache
-tests/clar.suite
+build-debian-devel/
+build-debian-release/
diff --git a/debian/control b/debian/control
index 0b28da913..9156c3be6 100644
--- a/debian/control
+++ b/debian/control
@@ -13,10 +13,10 @@ Build-Depends: debhelper-compat (= 13),
libmbedtls-dev,
libssh2-1-dev,
libhttp-parser-dev,
- libpcre3-dev,
+ libpcre2-dev,
libkrb5-dev,
ca-certificates
-Standards-Version: 4.6.0
+Standards-Version: 4.6.1
Homepage: https://libgit2.github.com/
Vcs-Git: https://salsa.debian.org/debian/libgit2.git
Vcs-Browser: https://salsa.debian.org/debian/libgit2
@@ -26,14 +26,13 @@ Package: libgit2-dev
Architecture: any
Section: libdevel
Multi-Arch: same
-Depends: libgit2-1.4 (= ${binary:Version}),
+Depends: libgit2-1.5 (= ${binary:Version}),
zlib1g-dev,
libmbedtls-dev,
libssh2-1-dev,
libhttp-parser-dev,
- libpcre3-dev,
- ${shlibs:Depends},
- ${misc:Depends}
+ libpcre2-dev,
+ ${misc:Depends},
Description: low-level Git library (development files)
libgit2 is a portable, pure C implementation of the Git
distributed version control system core methods provided as a
@@ -41,12 +40,12 @@ Description: low-level Git library (development files)
.
This package contains the development files for libgit2.
-Package: libgit2-1.4
+Package: libgit2-1.5
Architecture: any
Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Depends: ${shlibs:Depends},
- ${misc:Depends}
+ ${misc:Depends},
Description: low-level Git library
libgit2 is a portable, pure C implementation of the Git
distributed version control system core methods provided as a
@@ -54,9 +53,9 @@ Description: low-level Git library
Package: libgit2-fixtures
Architecture: all
+Multi-Arch: foreign
Pre-Depends: ${misc:Pre-Depends}
-Depends: ${shlibs:Depends},
- ${misc:Depends}
+Depends: ${misc:Depends},
Description: low-level Git library - test suite examples
libgit2 is a portable, pure C implementation of the Git
distributed version control system core methods provided as a
diff --git a/debian/copyright b/debian/copyright
index 92ce25f38..0138f748d 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -2,136 +2,84 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: libgit2
Source: https://libgit2.github.com/
Files-Excluded: deps/*
+Comment: No bundled dependencies are required to build libgit2
Files: *
-Copyright: 2009-2012, the libgit2 contributors
+Copyright: 2009-2022, the libgit2 contributors
License: GPL-2 with linking exception, origin admission
-Files: cmake/Modules/FindGSSAPI.cmake
-Copyright: 2013, Andreas Schneider
-License: BSD-2-clause
-
-Files: debian/*
-Copyright: 2011-2015, Russell Sim
- 2020, Utkarsh Gupta
-License: GPL-2+
-
Files: examples/*
+ src/util/rand.c
Copyright: Public Domain
License: CC0-1.0
-Files: include/git2/stdint.h
-Copyright: 2006, Alexander Chemeris
-License: BSD-3-clause-modified
-
-Files: src/khash.h
-Copyright: 2008, 2009, 2011, Attractive Chaos
-License: MIT
-
-Files: src/tsort.c
-Copyright: 2010, Christopher Swenson
- 2011, Vicent Marti
-License: MIT
-
-Files: src/path.c
-Copyright: 2008, The Android Open Source Project
-License: BSD-2-clause
-
-Files: src/util.c
-Copyright: 2009, Public Software Group e. V., Berlin, Germany
- 1990, Regents of the University of California.
-License: MIT and BSD-3-clause
-
-Files: src/xdiff/*
-Copyright: 2003, Davide Libenzi
-License: LGPL-2.1+
-
-Files: src/xdiff/xmerge.c
-Copyright: 2003-2006, Davide Libenzi
- 2003-2006, Johannes E. Schindelin
-License: LGPL-2.1+
-
-Files: src/xdiff/xpatience.c
-Copyright: 2003-2009, Davide Libenzi
- 2003-2009, Johannes E. Schindelin
-License: LGPL-2.1+
-
-Files: src/xdiff/xhistogram.c
-Copyright: 2010, Google Inc and others from JGit's IP log.
-License: EDL-1.0
-
-Files: src/win32/posix_w32.c
-Copyright: 1999 - 2012, The PHP Group
-License: PHP-3.01
-
Files: tests/clar/*
Copyright: 2011, Vicent Marti
License: MIT
-Files: tests/clar.h tests/clar.c tests/generate.py
-Copyright: Vicent Marti
-License: ISC
+Files: src/libgit2/xdiff/*
+ src/libgit2/xdiff/xdiffi.c
+ src/libgit2/xdiff/xdiffi.h
+ src/libgit2/xdiff/xemit.c
+ src/libgit2/xdiff/xemit.h
+ src/libgit2/xdiff/xinclude.h
+ src/libgit2/xdiff/xmacros.h
+ src/libgit2/xdiff/xmerge.c
+ src/libgit2/xdiff/xpatience.c
+ src/libgit2/xdiff/xprepare.c
+ src/libgit2/xdiff/xprepare.h
+ src/libgit2/xdiff/xtypes.h
+ src/libgit2/xdiff/xutils.c
+ src/libgit2/xdiff/xutils.h
+Copyright: 2003, Davide Libenzi
+ 2003-2016, Davide Libenzi, Johannes E. Schindelin
+License: LGPL-2.1+
-Files: tests/refs/normalize.c
-Copyright: 2009, Google Inc.
-License: BSD-3-clause-jgit
+Files: src/libgit2/xdiff/xhistogram.c
+Copyright: 2009-2010, Google Inc
+License: BSD-3-clause
-Files: src/date.c
-Copyright: 2005, Linus Torvalds
-License: GPL-2 with linking exception
- .
- Note that the only valid version of the GPL as far as this project
- is concerned is _this_ particular version of the license (ie v2, not
- v2.2 or v3.x or whatever), unless explicitly otherwise stated.
- .
- LINKING EXCEPTION
- .
- In addition to the permissions in the GNU General Public License,
- the authors give you unlimited permission to link the compiled
- version of this library into combinations with other programs,
- and to distribute those combinations without any restriction
- coming from the use of this file. (The General Public License
- restrictions do apply in other respects; for example, they cover
- modification of the file, and distribution when not linked into
- a combined executable.)
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+Files: src/util/util.c
+ tests/libgit2/refs/normalize.c
+Copyright: 2009-2022, the libgit2 contributors
+ 1990, Regents of the University of California
+ 2009, Google Inc.
+License: BSD-3-clause
-License: GPL-2 with linking exception, origin admission
- libgit2 is Copyright (C) 2009-2011 the libgit2 contributors,
- unless otherwise stated. See the AUTHORS file for details.
- .
- Note that the only valid version of the GPL as far as this project
- is concerned is _this_ particular version of the license (ie v2, not
- v2.2 or v3.x or whatever), unless explicitly otherwise stated.
- .
- LINKING EXCEPTION
- .
- In addition to the permissions in the GNU General Public License,
- the authors give you unlimited permission to link the compiled
- version of this library into combinations with other programs,
- and to distribute those combinations without any restriction
- coming from the use of this file. (The General Public License
- restrictions do apply in other respects; for example, they cover
- modification of the file, and distribution when not linked into
- a combined executable.)
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
- .
- ----------------------------------------------------------------------
- .
- The priority queue implementation is based on code licensed under the
- Apache 2.0 license:
- .
- Copyright 2010 Volkan Yazıcı
- Copyright 2006-2010 The Apache Software Foundation
- .
- The full text of the Apache 2.0 license is available at:
- .
- http://www.apache.org/licenses/LICENSE-2.0
+Files: src/util/fs_path.c
+ src/util/hash/rfc6234/sha.h
+Copyright: 2008, The Android Open Source Project
+ 2011, IETF Trust
+ the libgit2 contributors
+License: BSD-2-clause
+Files: src/util/khash.h
+ src/util/utf8.c
+Copyright: 2008-2011, Attractive Chaos
+ 2009, Public Software Group e. V., Berlin, Germany
+ the libgit2 contributors
+License: MIT
+
+Files: src/libgit2/streams/openssl_dynamic.h
+Copyright: 1995-1998, Eric Young
+ 2005, Nokia
+ 2002, Sun Microsystems, Inc
+ 1998-2007, The OpenSSL Project
+ the libgit2 contributors
+License: OpenSSL or SSLeay
+
+Files: cmake/FindGSSAPI.cmake
+Copyright: 2013, Andreas Schneider
+License: BSD-3-clause
+
+Files: include/git2/stdint.h
+Copyright: 2006-2008, Alexander Chemeris
+License: BSD-3-clause-modified
+
+Files: debian/*
+Copyright: 2011-2015, Russell Sim
+ 2020, Utkarsh Gupta
+License: GPL-2+
License: BSD-2-clause
All rights reserved.
@@ -159,7 +107,6 @@ License: BSD-2-clause
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-
License: BSD-3-clause
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -212,39 +159,6 @@ License: BSD-3-clause-modified
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-License: BSD-3-clause-jgit
- Redistribution and use in source and binary forms, with or
- without modification, are permitted provided that the following
- conditions are met:
- .
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- .
- - Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- .
- - Neither the name of the Git Development Community nor the
- names of its contributors may be used to endorse or promote
- products derived from this software without specific prior
- written permission.
- .
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
License: CC0-1.0
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
@@ -253,77 +167,39 @@ License: CC0-1.0
The full text of the CC0 1.0 Universal license is available on Debian systems
in /usr/share/common-licenses/CC0-1.0
-
-License: ISC
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
+License: GPL-2 with linking exception, origin admission
+ libgit2 is Copyright (C) 2009-2011 the libgit2 contributors,
+ unless otherwise stated. See the AUTHORS file for details.
.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-License: LGPL-2.1+
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
+ Note that the only valid version of the GPL as far as this project
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+ LINKING EXCEPTION
.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
-
-
-License: EDL-1.0
- This program and the accompanying materials are made available
- under the terms of the Eclipse Distribution License v1.0 which
- accompanies this distribution, is reproduced below, and is
- available at http://www.eclipse.org/org/documents/edl-v10.php
+ In addition to the permissions in the GNU General Public License,
+ the authors give you unlimited permission to link the compiled
+ version of this library into combinations with other programs,
+ and to distribute those combinations without any restriction
+ coming from the use of this file. (The General Public License
+ restrictions do apply in other respects; for example, they cover
+ modification of the file, and distribution when not linked into
+ a combined executable.)
.
- All rights reserved.
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
.
- Redistribution and use in source and binary forms, with or
- without modification, are permitted provided that the following
- conditions are met:
+ ----------------------------------------------------------------------
.
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
+ The priority queue implementation is based on code licensed under the
+ Apache 2.0 license:
.
- - Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
+ Copyright 2010 Volkan Yazıcı
+ Copyright 2006-2010 The Apache Software Foundation
.
- - Neither the name of the Eclipse Foundation, Inc. nor the
- names of its contributors may be used to endorse or promote
- products derived from this software without specific prior
- written permission.
+ The full text of the Apache 2.0 license is available at:
.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+ http://www.apache.org/licenses/LICENSE-2.0
License: GPL-2+
This package is free software; you can redistribute it and/or modify
@@ -342,6 +218,21 @@ License: GPL-2+
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+License: LGPL-2.1+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ .
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -362,55 +253,90 @@ License: MIT
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
-License: PHP-3.01
+License: OpenSSL
Redistribution and use in source and binary forms, with or without
- modification, is permitted provided that the following conditions
+ modification, are permitted provided that the following conditions
are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ openssl-core@openssl.org.
+ 5. Products derived from this software may not be called "OpenSSL"
+ nor may "OpenSSL" appear in their names without prior written
+ permission of the OpenSSL Project.
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/)"
.
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- .
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- .
- 3. The name "PHP" must not be used to endorse or promote products
- derived from this software without prior written permission. For
- written permission, please contact group@php.net.
- .
- 4. Products derived from this software may not be called "PHP", nor
- may "PHP" appear in their name, without prior written permission
- from group@php.net. You may indicate that your software works in
- conjunction with PHP by saying "Foo for PHP" instead of calling
- it "PHP Foo" or "phpfoo"
- .
- 5. The PHP Group may publish revised and/or new versions of the
- license from time to time. Each version will be given a
- distinguishing version number.
- Once covered code has been published under a particular version
- of the license, you may always continue to use it under the terms
- of that version. You may also choose to use such covered code
- under the terms of any subsequent version of the license
- published by the PHP Group. No one other than the PHP Group has
- the right to modify the terms applicable to covered code created
- under this License.
- .
- 6. Redistributions of any form whatsoever must retain the following
- acknowledgment:
- "This product includes PHP software, freely available from
- ".
- .
- THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
- ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
- DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
+ ====================================================================
+ This product includes cryptographic software written by Eric Young
+ (eay@cryptsoft.com). This product includes software written by Tim
+ Hudson (tjh@cryptsoft.com).
+
+License: SSLeay
+ This library is free for commercial and non-commercial use as long as
+ the following conditions are adhered to. The following conditions
+ apply to all code found in this distribution, be it the RC4, RSA,
+ lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ included with this distribution is covered by the same copyright terms
+ except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ .
+ Copyright remains Eric Young's, and as such any Copyright notices in
+ the code are not to be removed.
+ If this package is used in a product, Eric Young should be given attribution
+ as the author of the parts of the library used.
+ This can be in the form of a textual message at program startup or
+ in documentation (online or textual) provided with the package.
+ .
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ "This product includes cryptographic software written by
+ Eric Young (eay@cryptsoft.com)"
+ The word 'cryptographic' can be left out if the routines from the library
+ being used are not cryptographic related :-).
+ 4. If you include any Windows specific code (or a derivative thereof) from
+ the apps directory (application code) you must include an acknowledgement:
+ "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ .
+ THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
diff --git a/debian/libgit2-1.4.symbols b/debian/libgit2-1.4.symbols
deleted file mode 100644
index b4d01f1a3..000000000
--- a/debian/libgit2-1.4.symbols
+++ /dev/null
@@ -1,933 +0,0 @@
-libgit2.so.1.4 libgit2-1.4 #MINVER#
- git_annotated_commit_free@Base 1.4
- git_annotated_commit_from_fetchhead@Base 1.4
- git_annotated_commit_from_ref@Base 1.4
- git_annotated_commit_from_revspec@Base 1.4
- git_annotated_commit_id@Base 1.4
- git_annotated_commit_lookup@Base 1.4
- git_annotated_commit_ref@Base 1.4
- git_apply@Base 1.4
- git_apply_options_init@Base 1.4
- git_apply_to_tree@Base 1.4
- git_attr_add_macro@Base 1.4
- git_attr_cache_flush@Base 1.4
- git_attr_foreach@Base 1.4
- git_attr_foreach_ext@Base 1.4
- git_attr_get@Base 1.4
- git_attr_get_ext@Base 1.4
- git_attr_get_many@Base 1.4
- git_attr_get_many_ext@Base 1.4
- git_attr_value@Base 1.4
- git_blame_buffer@Base 1.4
- git_blame_file@Base 1.4
- git_blame_free@Base 1.4
- git_blame_get_hunk_byindex@Base 1.4
- git_blame_get_hunk_byline@Base 1.4
- git_blame_get_hunk_count@Base 1.4
- git_blame_init_options@Base 1.4
- git_blame_options_init@Base 1.4
- git_blob_create_from_buffer@Base 1.4
- git_blob_create_from_disk@Base 1.4
- git_blob_create_from_stream@Base 1.4
- git_blob_create_from_stream_commit@Base 1.4
- git_blob_create_from_workdir@Base 1.4
- git_blob_create_frombuffer@Base 1.4
- git_blob_create_fromdisk@Base 1.4
- git_blob_create_fromstream@Base 1.4
- git_blob_create_fromstream_commit@Base 1.4
- git_blob_create_fromworkdir@Base 1.4
- git_blob_data_is_binary@Base 1.4
- git_blob_dup@Base 1.4
- git_blob_filter@Base 1.4
- git_blob_filter_options_init@Base 1.4
- git_blob_filtered_content@Base 1.4
- git_blob_free@Base 1.4
- git_blob_id@Base 1.4
- git_blob_is_binary@Base 1.4
- git_blob_lookup@Base 1.4
- git_blob_lookup_prefix@Base 1.4
- git_blob_owner@Base 1.4
- git_blob_rawcontent@Base 1.4
- git_blob_rawsize@Base 1.4
- git_branch_create@Base 1.4
- git_branch_create_from_annotated@Base 1.4
- git_branch_delete@Base 1.4
- git_branch_is_checked_out@Base 1.4
- git_branch_is_head@Base 1.4
- git_branch_iterator_free@Base 1.4
- git_branch_iterator_new@Base 1.4
- git_branch_lookup@Base 1.4
- git_branch_move@Base 1.4
- git_branch_name@Base 1.4
- git_branch_name_is_valid@Base 1.4
- git_branch_next@Base 1.4
- git_branch_remote_name@Base 1.4
- git_branch_set_upstream@Base 1.4
- git_branch_upstream@Base 1.4
- git_branch_upstream_merge@Base 1.4
- git_branch_upstream_name@Base 1.4
- git_branch_upstream_remote@Base 1.4
- git_buf_contains_nul@Base 1.4
- git_buf_dispose@Base 1.4
- git_buf_free@Base 1.4
- git_buf_grow@Base 1.4
- git_buf_is_binary@Base 1.4
- git_buf_set@Base 1.4
- git_checkout_head@Base 1.4
- git_checkout_index@Base 1.4
- git_checkout_init_options@Base 1.4
- git_checkout_options_init@Base 1.4
- git_checkout_tree@Base 1.4
- git_cherrypick@Base 1.4
- git_cherrypick_commit@Base 1.4
- git_cherrypick_init_options@Base 1.4
- git_cherrypick_options_init@Base 1.4
- git_clone@Base 1.4
- git_clone_init_options@Base 1.4
- git_clone_options_init@Base 1.4
- git_commit_amend@Base 1.4
- git_commit_author@Base 1.4
- git_commit_author_with_mailmap@Base 1.4
- git_commit_body@Base 1.4
- git_commit_committer@Base 1.4
- git_commit_committer_with_mailmap@Base 1.4
- git_commit_create@Base 1.4
- git_commit_create_buffer@Base 1.4
- git_commit_create_from_callback@Base 1.4
- git_commit_create_from_ids@Base 1.4
- git_commit_create_v@Base 1.4
- git_commit_create_with_signature@Base 1.4
- git_commit_dup@Base 1.4
- git_commit_extract_signature@Base 1.4
- git_commit_free@Base 1.4
- git_commit_graph_free@Base 1.4
- git_commit_graph_open@Base 1.4
- git_commit_graph_writer_add_index_file@Base 1.4
- git_commit_graph_writer_add_revwalk@Base 1.4
- git_commit_graph_writer_commit@Base 1.4
- git_commit_graph_writer_dump@Base 1.4
- git_commit_graph_writer_free@Base 1.4
- git_commit_graph_writer_new@Base 1.4
- git_commit_graph_writer_options_init@Base 1.4
- git_commit_header_field@Base 1.4
- git_commit_id@Base 1.4
- git_commit_lookup@Base 1.4
- git_commit_lookup_prefix@Base 1.4
- git_commit_message@Base 1.4
- git_commit_message_encoding@Base 1.4
- git_commit_message_raw@Base 1.4
- git_commit_nth_gen_ancestor@Base 1.4
- git_commit_owner@Base 1.4
- git_commit_parent@Base 1.4
- git_commit_parent_id@Base 1.4
- git_commit_parentcount@Base 1.4
- git_commit_raw_header@Base 1.4
- git_commit_summary@Base 1.4
- git_commit_time@Base 1.4
- git_commit_time_offset@Base 1.4
- git_commit_tree@Base 1.4
- git_commit_tree_id@Base 1.4
- git_config_add_backend@Base 1.4
- git_config_add_file_ondisk@Base 1.4
- git_config_backend_foreach_match@Base 1.4
- git_config_delete_entry@Base 1.4
- git_config_delete_multivar@Base 1.4
- git_config_entry_free@Base 1.4
- git_config_find_global@Base 1.4
- git_config_find_programdata@Base 1.4
- git_config_find_system@Base 1.4
- git_config_find_xdg@Base 1.4
- git_config_foreach@Base 1.4
- git_config_foreach_match@Base 1.4
- git_config_free@Base 1.4
- git_config_get_bool@Base 1.4
- git_config_get_entry@Base 1.4
- git_config_get_int32@Base 1.4
- git_config_get_int64@Base 1.4
- git_config_get_mapped@Base 1.4
- git_config_get_multivar_foreach@Base 1.4
- git_config_get_path@Base 1.4
- git_config_get_string@Base 1.4
- git_config_get_string_buf@Base 1.4
- git_config_init_backend@Base 1.4
- git_config_iterator_free@Base 1.4
- git_config_iterator_glob_new@Base 1.4
- git_config_iterator_new@Base 1.4
- git_config_lock@Base 1.4
- git_config_lookup_map_value@Base 1.4
- git_config_multivar_iterator_new@Base 1.4
- git_config_new@Base 1.4
- git_config_next@Base 1.4
- git_config_open_default@Base 1.4
- git_config_open_global@Base 1.4
- git_config_open_level@Base 1.4
- git_config_open_ondisk@Base 1.4
- git_config_parse_bool@Base 1.4
- git_config_parse_int32@Base 1.4
- git_config_parse_int64@Base 1.4
- git_config_parse_path@Base 1.4
- git_config_set_bool@Base 1.4
- git_config_set_int32@Base 1.4
- git_config_set_int64@Base 1.4
- git_config_set_multivar@Base 1.4
- git_config_set_string@Base 1.4
- git_config_snapshot@Base 1.4
- git_config_unlock@Base 1.4
- git_cred_default_new@Base 1.4
- git_cred_free@Base 1.4
- git_cred_get_username@Base 1.4
- git_cred_has_username@Base 1.4
- git_cred_ssh_custom_new@Base 1.4
- git_cred_ssh_interactive_new@Base 1.4
- git_cred_ssh_key_from_agent@Base 1.4
- git_cred_ssh_key_memory_new@Base 1.4
- git_cred_ssh_key_new@Base 1.4
- git_cred_username_new@Base 1.4
- git_cred_userpass@Base 1.4
- git_cred_userpass_plaintext_new@Base 1.4
- git_credential_default_new@Base 1.4
- git_credential_free@Base 1.4
- git_credential_get_username@Base 1.4
- git_credential_has_username@Base 1.4
- git_credential_ssh_custom_new@Base 1.4
- git_credential_ssh_interactive_new@Base 1.4
- git_credential_ssh_key_from_agent@Base 1.4
- git_credential_ssh_key_memory_new@Base 1.4
- git_credential_ssh_key_new@Base 1.4
- git_credential_username_new@Base 1.4
- git_credential_userpass@Base 1.4
- git_credential_userpass_plaintext_new@Base 1.4
- git_describe_commit@Base 1.4
- git_describe_format@Base 1.4
- git_describe_format_options_init@Base 1.4
- git_describe_init_format_options@Base 1.4
- git_describe_init_options@Base 1.4
- git_describe_options_init@Base 1.4
- git_describe_result_free@Base 1.4
- git_describe_workdir@Base 1.4
- git_diff_blob_to_buffer@Base 1.4
- git_diff_blobs@Base 1.4
- git_diff_buffers@Base 1.4
- git_diff_commit_as_email@Base 1.4
- git_diff_find_init_options@Base 1.4
- git_diff_find_options_init@Base 1.4
- git_diff_find_similar@Base 1.4
- git_diff_foreach@Base 1.4
- git_diff_format_email@Base 1.4
- git_diff_format_email_init_options@Base 1.4
- git_diff_format_email_options_init@Base 1.4
- git_diff_free@Base 1.4
- git_diff_from_buffer@Base 1.4
- git_diff_get_delta@Base 1.4
- git_diff_get_perfdata@Base 1.4
- git_diff_get_stats@Base 1.4
- git_diff_index_to_index@Base 1.4
- git_diff_index_to_workdir@Base 1.4
- git_diff_init_options@Base 1.4
- git_diff_is_sorted_icase@Base 1.4
- git_diff_merge@Base 1.4
- git_diff_num_deltas@Base 1.4
- git_diff_num_deltas_of_type@Base 1.4
- git_diff_options_init@Base 1.4
- git_diff_patchid@Base 1.4
- git_diff_patchid_options_init@Base 1.4
- git_diff_print@Base 1.4
- git_diff_print_callback__to_buf@Base 1.4
- git_diff_print_callback__to_file_handle@Base 1.4
- git_diff_stats_deletions@Base 1.4
- git_diff_stats_files_changed@Base 1.4
- git_diff_stats_free@Base 1.4
- git_diff_stats_insertions@Base 1.4
- git_diff_stats_to_buf@Base 1.4
- git_diff_status_char@Base 1.4
- git_diff_to_buf@Base 1.4
- git_diff_tree_to_index@Base 1.4
- git_diff_tree_to_tree@Base 1.4
- git_diff_tree_to_workdir@Base 1.4
- git_diff_tree_to_workdir_with_index@Base 1.4
- git_email_create_from_commit@Base 1.4
- git_email_create_from_diff@Base 1.4
- git_error_clear@Base 1.4
- git_error_last@Base 1.4
- git_error_set_oom@Base 1.4
- git_error_set_str@Base 1.4
- git_fetch_init_options@Base 1.4
- git_fetch_options_init@Base 1.4
- git_filter_init@Base 1.4
- git_filter_list_apply_to_blob@Base 1.4
- git_filter_list_apply_to_buffer@Base 1.4
- git_filter_list_apply_to_data@Base 1.4
- git_filter_list_apply_to_file@Base 1.4
- git_filter_list_contains@Base 1.4
- git_filter_list_free@Base 1.4
- git_filter_list_length@Base 1.4
- git_filter_list_load@Base 1.4
- git_filter_list_load_ext@Base 1.4
- git_filter_list_new@Base 1.4
- git_filter_list_push@Base 1.4
- git_filter_list_stream_blob@Base 1.4
- git_filter_list_stream_buffer@Base 1.4
- git_filter_list_stream_data@Base 1.4
- git_filter_list_stream_file@Base 1.4
- git_filter_lookup@Base 1.4
- git_filter_register@Base 1.4
- git_filter_source_filemode@Base 1.4
- git_filter_source_flags@Base 1.4
- git_filter_source_id@Base 1.4
- git_filter_source_mode@Base 1.4
- git_filter_source_path@Base 1.4
- git_filter_source_repo@Base 1.4
- git_filter_unregister@Base 1.4
- git_graph_ahead_behind@Base 1.4
- git_graph_descendant_of@Base 1.4
- git_graph_reachable_from_any@Base 1.4
- git_hashsig_compare@Base 1.4
- git_hashsig_create@Base 1.4
- git_hashsig_create_fromfile@Base 1.4
- git_hashsig_free@Base 1.4
- git_ignore_add_rule@Base 1.4
- git_ignore_clear_internal_rules@Base 1.4
- git_ignore_path_is_ignored@Base 1.4
- git_index_add@Base 1.4
- git_index_add_all@Base 1.4
- git_index_add_bypath@Base 1.4
- git_index_add_from_buffer@Base 1.4
- git_index_add_frombuffer@Base 1.4
- git_index_caps@Base 1.4
- git_index_checksum@Base 1.4
- git_index_clear@Base 1.4
- git_index_conflict_add@Base 1.4
- git_index_conflict_cleanup@Base 1.4
- git_index_conflict_get@Base 1.4
- git_index_conflict_iterator_free@Base 1.4
- git_index_conflict_iterator_new@Base 1.4
- git_index_conflict_next@Base 1.4
- git_index_conflict_remove@Base 1.4
- git_index_entry_is_conflict@Base 1.4
- git_index_entry_stage@Base 1.4
- git_index_entrycount@Base 1.4
- git_index_find@Base 1.4
- git_index_find_prefix@Base 1.4
- git_index_free@Base 1.4
- git_index_get_byindex@Base 1.4
- git_index_get_bypath@Base 1.4
- git_index_has_conflicts@Base 1.4
- git_index_iterator_free@Base 1.4
- git_index_iterator_new@Base 1.4
- git_index_iterator_next@Base 1.4
- git_index_name_add@Base 1.4
- git_index_name_clear@Base 1.4
- git_index_name_entrycount@Base 1.4
- git_index_name_get_byindex@Base 1.4
- git_index_new@Base 1.4
- git_index_open@Base 1.4
- git_index_owner@Base 1.4
- git_index_path@Base 1.4
- git_index_read@Base 1.4
- git_index_read_tree@Base 1.4
- git_index_remove@Base 1.4
- git_index_remove_all@Base 1.4
- git_index_remove_bypath@Base 1.4
- git_index_remove_directory@Base 1.4
- git_index_reuc_add@Base 1.4
- git_index_reuc_clear@Base 1.4
- git_index_reuc_entrycount@Base 1.4
- git_index_reuc_find@Base 1.4
- git_index_reuc_get_byindex@Base 1.4
- git_index_reuc_get_bypath@Base 1.4
- git_index_reuc_remove@Base 1.4
- git_index_set_caps@Base 1.4
- git_index_set_version@Base 1.4
- git_index_update_all@Base 1.4
- git_index_version@Base 1.4
- git_index_write@Base 1.4
- git_index_write_tree@Base 1.4
- git_index_write_tree_to@Base 1.4
- git_indexer_append@Base 1.4
- git_indexer_commit@Base 1.4
- git_indexer_free@Base 1.4
- git_indexer_hash@Base 1.4
- git_indexer_init_options@Base 1.4
- git_indexer_name@Base 1.4
- git_indexer_new@Base 1.4
- git_indexer_options_init@Base 1.4
- git_libgit2_features@Base 1.4
- git_libgit2_init@Base 1.4
- git_libgit2_opts@Base 1.4
- git_libgit2_shutdown@Base 1.4
- git_libgit2_version@Base 1.4
- git_mailmap_add_entry@Base 1.4
- git_mailmap_free@Base 1.4
- git_mailmap_from_buffer@Base 1.4
- git_mailmap_from_repository@Base 1.4
- git_mailmap_new@Base 1.4
- git_mailmap_resolve@Base 1.4
- git_mailmap_resolve_signature@Base 1.4
- git_mempack_dump@Base 1.4
- git_mempack_new@Base 1.4
- git_mempack_reset@Base 1.4
- git_merge@Base 1.4
- git_merge_analysis@Base 1.4
- git_merge_analysis_for_ref@Base 1.4
- git_merge_base@Base 1.4
- git_merge_base_many@Base 1.4
- git_merge_base_octopus@Base 1.4
- git_merge_bases@Base 1.4
- git_merge_bases_many@Base 1.4
- git_merge_commits@Base 1.4
- git_merge_driver_lookup@Base 1.4
- git_merge_driver_register@Base 1.4
- git_merge_driver_source_ancestor@Base 1.4
- git_merge_driver_source_file_options@Base 1.4
- git_merge_driver_source_ours@Base 1.4
- git_merge_driver_source_repo@Base 1.4
- git_merge_driver_source_theirs@Base 1.4
- git_merge_driver_unregister@Base 1.4
- git_merge_file@Base 1.4
- git_merge_file_from_index@Base 1.4
- git_merge_file_init_input@Base 1.4
- git_merge_file_init_options@Base 1.4
- git_merge_file_input_init@Base 1.4
- git_merge_file_options_init@Base 1.4
- git_merge_file_result_free@Base 1.4
- git_merge_init_options@Base 1.4
- git_merge_options_init@Base 1.4
- git_merge_trees@Base 1.4
- git_message_prettify@Base 1.4
- git_message_trailer_array_free@Base 1.4
- git_message_trailers@Base 1.4
- git_midx_writer_add@Base 1.4
- git_midx_writer_commit@Base 1.4
- git_midx_writer_dump@Base 1.4
- git_midx_writer_free@Base 1.4
- git_midx_writer_new@Base 1.4
- git_note_author@Base 1.4
- git_note_commit_create@Base 1.4
- git_note_commit_iterator_new@Base 1.4
- git_note_commit_read@Base 1.4
- git_note_commit_remove@Base 1.4
- git_note_committer@Base 1.4
- git_note_create@Base 1.4
- git_note_default_ref@Base 1.4
- git_note_foreach@Base 1.4
- git_note_free@Base 1.4
- git_note_id@Base 1.4
- git_note_iterator_free@Base 1.4
- git_note_iterator_new@Base 1.4
- git_note_message@Base 1.4
- git_note_next@Base 1.4
- git_note_read@Base 1.4
- git_note_remove@Base 1.4
- git_object__size@Base 1.4
- git_object_dup@Base 1.4
- git_object_free@Base 1.4
- git_object_id@Base 1.4
- git_object_lookup@Base 1.4
- git_object_lookup_bypath@Base 1.4
- git_object_lookup_prefix@Base 1.4
- git_object_owner@Base 1.4
- git_object_peel@Base 1.4
- git_object_rawcontent_is_valid@Base 1.4
- git_object_short_id@Base 1.4
- git_object_string2type@Base 1.4
- git_object_type2string@Base 1.4
- git_object_type@Base 1.4
- git_object_typeisloose@Base 1.4
- git_odb_add_alternate@Base 1.4
- git_odb_add_backend@Base 1.4
- git_odb_add_disk_alternate@Base 1.4
- git_odb_backend_data_alloc@Base 1.4
- git_odb_backend_data_free@Base 1.4
- git_odb_backend_loose@Base 1.4
- git_odb_backend_malloc@Base 1.4
- git_odb_backend_one_pack@Base 1.4
- git_odb_backend_pack@Base 1.4
- git_odb_exists@Base 1.4
- git_odb_exists_ext@Base 1.4
- git_odb_exists_prefix@Base 1.4
- git_odb_expand_ids@Base 1.4
- git_odb_foreach@Base 1.4
- git_odb_free@Base 1.4
- git_odb_get_backend@Base 1.4
- git_odb_hash@Base 1.4
- git_odb_hashfile@Base 1.4
- git_odb_init_backend@Base 1.4
- git_odb_new@Base 1.4
- git_odb_num_backends@Base 1.4
- git_odb_object_data@Base 1.4
- git_odb_object_dup@Base 1.4
- git_odb_object_free@Base 1.4
- git_odb_object_id@Base 1.4
- git_odb_object_size@Base 1.4
- git_odb_object_type@Base 1.4
- git_odb_open@Base 1.4
- git_odb_open_rstream@Base 1.4
- git_odb_open_wstream@Base 1.4
- git_odb_read@Base 1.4
- git_odb_read_header@Base 1.4
- git_odb_read_prefix@Base 1.4
- git_odb_refresh@Base 1.4
- git_odb_set_commit_graph@Base 1.4
- git_odb_stream_finalize_write@Base 1.4
- git_odb_stream_free@Base 1.4
- git_odb_stream_read@Base 1.4
- git_odb_stream_write@Base 1.4
- git_odb_write@Base 1.4
- git_odb_write_multi_pack_index@Base 1.4
- git_odb_write_pack@Base 1.4
- git_oid_cmp@Base 1.4
- git_oid_cpy@Base 1.4
- git_oid_equal@Base 1.4
- git_oid_fmt@Base 1.4
- git_oid_fromraw@Base 1.4
- git_oid_fromstr@Base 1.4
- git_oid_fromstrn@Base 1.4
- git_oid_fromstrp@Base 1.4
- git_oid_is_zero@Base 1.4
- git_oid_iszero@Base 1.4
- git_oid_ncmp@Base 1.4
- git_oid_nfmt@Base 1.4
- git_oid_pathfmt@Base 1.4
- git_oid_shorten_add@Base 1.4
- git_oid_shorten_free@Base 1.4
- git_oid_shorten_new@Base 1.4
- git_oid_strcmp@Base 1.4
- git_oid_streq@Base 1.4
- git_oid_tostr@Base 1.4
- git_oid_tostr_s@Base 1.4
- git_oidarray_dispose@Base 1.4
- git_oidarray_free@Base 1.4
- git_openssl_set_locking@Base 1.4
- git_packbuilder_foreach@Base 1.4
- git_packbuilder_free@Base 1.4
- git_packbuilder_hash@Base 1.4
- git_packbuilder_insert@Base 1.4
- git_packbuilder_insert_commit@Base 1.4
- git_packbuilder_insert_recur@Base 1.4
- git_packbuilder_insert_tree@Base 1.4
- git_packbuilder_insert_walk@Base 1.4
- git_packbuilder_name@Base 1.4
- git_packbuilder_new@Base 1.4
- git_packbuilder_object_count@Base 1.4
- git_packbuilder_set_callbacks@Base 1.4
- git_packbuilder_set_threads@Base 1.4
- git_packbuilder_write@Base 1.4
- git_packbuilder_write_buf@Base 1.4
- git_packbuilder_written@Base 1.4
- git_patch_free@Base 1.4
- git_patch_from_blob_and_buffer@Base 1.4
- git_patch_from_blobs@Base 1.4
- git_patch_from_buffers@Base 1.4
- git_patch_from_diff@Base 1.4
- git_patch_get_delta@Base 1.4
- git_patch_get_hunk@Base 1.4
- git_patch_get_line_in_hunk@Base 1.4
- git_patch_line_stats@Base 1.4
- git_patch_num_hunks@Base 1.4
- git_patch_num_lines_in_hunk@Base 1.4
- git_patch_owner@Base 1.4
- git_patch_print@Base 1.4
- git_patch_size@Base 1.4
- git_patch_to_buf@Base 1.4
- git_path_is_gitfile@Base 1.4
- git_pathspec_free@Base 1.4
- git_pathspec_match_diff@Base 1.4
- git_pathspec_match_index@Base 1.4
- git_pathspec_match_list_diff_entry@Base 1.4
- git_pathspec_match_list_entry@Base 1.4
- git_pathspec_match_list_entrycount@Base 1.4
- git_pathspec_match_list_failed_entry@Base 1.4
- git_pathspec_match_list_failed_entrycount@Base 1.4
- git_pathspec_match_list_free@Base 1.4
- git_pathspec_match_tree@Base 1.4
- git_pathspec_match_workdir@Base 1.4
- git_pathspec_matches_path@Base 1.4
- git_pathspec_new@Base 1.4
- git_proxy_init_options@Base 1.4
- git_proxy_options_init@Base 1.4
- git_push_init_options@Base 1.4
- git_push_options_init@Base 1.4
- git_rebase_abort@Base 1.4
- git_rebase_commit@Base 1.4
- git_rebase_finish@Base 1.4
- git_rebase_free@Base 1.4
- git_rebase_init@Base 1.4
- git_rebase_init_options@Base 1.4
- git_rebase_inmemory_index@Base 1.4
- git_rebase_next@Base 1.4
- git_rebase_onto_id@Base 1.4
- git_rebase_onto_name@Base 1.4
- git_rebase_open@Base 1.4
- git_rebase_operation_byindex@Base 1.4
- git_rebase_operation_current@Base 1.4
- git_rebase_operation_entrycount@Base 1.4
- git_rebase_options_init@Base 1.4
- git_rebase_orig_head_id@Base 1.4
- git_rebase_orig_head_name@Base 1.4
- git_refdb_backend_fs@Base 1.4
- git_refdb_compress@Base 1.4
- git_refdb_free@Base 1.4
- git_refdb_init_backend@Base 1.4
- git_refdb_new@Base 1.4
- git_refdb_open@Base 1.4
- git_refdb_set_backend@Base 1.4
- git_reference__alloc@Base 1.4
- git_reference__alloc_symbolic@Base 1.4
- git_reference_cmp@Base 1.4
- git_reference_create@Base 1.4
- git_reference_create_matching@Base 1.4
- git_reference_delete@Base 1.4
- git_reference_dup@Base 1.4
- git_reference_dwim@Base 1.4
- git_reference_ensure_log@Base 1.4
- git_reference_foreach@Base 1.4
- git_reference_foreach_glob@Base 1.4
- git_reference_foreach_name@Base 1.4
- git_reference_free@Base 1.4
- git_reference_has_log@Base 1.4
- git_reference_is_branch@Base 1.4
- git_reference_is_note@Base 1.4
- git_reference_is_remote@Base 1.4
- git_reference_is_tag@Base 1.4
- git_reference_is_valid_name@Base 1.4
- git_reference_iterator_free@Base 1.4
- git_reference_iterator_glob_new@Base 1.4
- git_reference_iterator_new@Base 1.4
- git_reference_list@Base 1.4
- git_reference_lookup@Base 1.4
- git_reference_name@Base 1.4
- git_reference_name_is_valid@Base 1.4
- git_reference_name_to_id@Base 1.4
- git_reference_next@Base 1.4
- git_reference_next_name@Base 1.4
- git_reference_normalize_name@Base 1.4
- git_reference_owner@Base 1.4
- git_reference_peel@Base 1.4
- git_reference_remove@Base 1.4
- git_reference_rename@Base 1.4
- git_reference_resolve@Base 1.4
- git_reference_set_target@Base 1.4
- git_reference_shorthand@Base 1.4
- git_reference_symbolic_create@Base 1.4
- git_reference_symbolic_create_matching@Base 1.4
- git_reference_symbolic_set_target@Base 1.4
- git_reference_symbolic_target@Base 1.4
- git_reference_target@Base 1.4
- git_reference_target_peel@Base 1.4
- git_reference_type@Base 1.4
- git_reflog_append@Base 1.4
- git_reflog_delete@Base 1.4
- git_reflog_drop@Base 1.4
- git_reflog_entry__free@Base 1.4
- git_reflog_entry_byindex@Base 1.4
- git_reflog_entry_committer@Base 1.4
- git_reflog_entry_id_new@Base 1.4
- git_reflog_entry_id_old@Base 1.4
- git_reflog_entry_message@Base 1.4
- git_reflog_entrycount@Base 1.4
- git_reflog_free@Base 1.4
- git_reflog_read@Base 1.4
- git_reflog_rename@Base 1.4
- git_reflog_write@Base 1.4
- git_refspec_direction@Base 1.4
- git_refspec_dst@Base 1.4
- git_refspec_dst_matches@Base 1.4
- git_refspec_force@Base 1.4
- git_refspec_free@Base 1.4
- git_refspec_parse@Base 1.4
- git_refspec_rtransform@Base 1.4
- git_refspec_src@Base 1.4
- git_refspec_src_matches@Base 1.4
- git_refspec_string@Base 1.4
- git_refspec_transform@Base 1.4
- git_remote_add_fetch@Base 1.4
- git_remote_add_push@Base 1.4
- git_remote_autotag@Base 1.4
- git_remote_connect@Base 1.4
- git_remote_connect_ext@Base 1.4
- git_remote_connect_options_init@Base 1.4
- git_remote_connected@Base 1.4
- git_remote_create@Base 1.4
- git_remote_create_anonymous@Base 1.4
- git_remote_create_detached@Base 1.4
- git_remote_create_init_options@Base 1.4
- git_remote_create_options_init@Base 1.4
- git_remote_create_with_fetchspec@Base 1.4
- git_remote_create_with_opts@Base 1.4
- git_remote_default_branch@Base 1.4
- git_remote_delete@Base 1.4
- git_remote_disconnect@Base 1.4
- git_remote_download@Base 1.4
- git_remote_dup@Base 1.4
- git_remote_fetch@Base 1.4
- git_remote_free@Base 1.4
- git_remote_get_fetch_refspecs@Base 1.4
- git_remote_get_push_refspecs@Base 1.4
- git_remote_get_refspec@Base 1.4
- git_remote_init_callbacks@Base 1.4
- git_remote_is_valid_name@Base 1.4
- git_remote_list@Base 1.4
- git_remote_lookup@Base 1.4
- git_remote_ls@Base 1.4
- git_remote_name@Base 1.4
- git_remote_name_is_valid@Base 1.4
- git_remote_owner@Base 1.4
- git_remote_prune@Base 1.4
- git_remote_prune_refs@Base 1.4
- git_remote_push@Base 1.4
- git_remote_pushurl@Base 1.4
- git_remote_refspec_count@Base 1.4
- git_remote_rename@Base 1.4
- git_remote_set_autotag@Base 1.4
- git_remote_set_instance_pushurl@Base 1.4
- git_remote_set_instance_url@Base 1.4
- git_remote_set_pushurl@Base 1.4
- git_remote_set_url@Base 1.4
- git_remote_stats@Base 1.4
- git_remote_stop@Base 1.4
- git_remote_update_tips@Base 1.4
- git_remote_upload@Base 1.4
- git_remote_url@Base 1.4
- git_repository__cleanup@Base 1.4
- git_repository_commondir@Base 1.4
- git_repository_config@Base 1.4
- git_repository_config_snapshot@Base 1.4
- git_repository_detach_head@Base 1.4
- git_repository_discover@Base 1.4
- git_repository_fetchhead_foreach@Base 1.4
- git_repository_free@Base 1.4
- git_repository_get_namespace@Base 1.4
- git_repository_hashfile@Base 1.4
- git_repository_head@Base 1.4
- git_repository_head_detached@Base 1.4
- git_repository_head_detached_for_worktree@Base 1.4
- git_repository_head_for_worktree@Base 1.4
- git_repository_head_unborn@Base 1.4
- git_repository_ident@Base 1.4
- git_repository_index@Base 1.4
- git_repository_init@Base 1.4
- git_repository_init_ext@Base 1.4
- git_repository_init_init_options@Base 1.4
- git_repository_init_options_init@Base 1.4
- git_repository_is_bare@Base 1.4
- git_repository_is_empty@Base 1.4
- git_repository_is_shallow@Base 1.4
- git_repository_is_worktree@Base 1.4
- git_repository_item_path@Base 1.4
- git_repository_mergehead_foreach@Base 1.4
- git_repository_message@Base 1.4
- git_repository_message_remove@Base 1.4
- git_repository_new@Base 1.4
- git_repository_odb@Base 1.4
- git_repository_open@Base 1.4
- git_repository_open_bare@Base 1.4
- git_repository_open_ext@Base 1.4
- git_repository_open_from_worktree@Base 1.4
- git_repository_path@Base 1.4
- git_repository_refdb@Base 1.4
- git_repository_reinit_filesystem@Base 1.4
- git_repository_set_bare@Base 1.4
- git_repository_set_config@Base 1.4
- git_repository_set_head@Base 1.4
- git_repository_set_head_detached@Base 1.4
- git_repository_set_head_detached_from_annotated@Base 1.4
- git_repository_set_ident@Base 1.4
- git_repository_set_index@Base 1.4
- git_repository_set_namespace@Base 1.4
- git_repository_set_odb@Base 1.4
- git_repository_set_refdb@Base 1.4
- git_repository_set_workdir@Base 1.4
- git_repository_state@Base 1.4
- git_repository_state_cleanup@Base 1.4
- git_repository_submodule_cache_all@Base 1.4
- git_repository_submodule_cache_clear@Base 1.4
- git_repository_workdir@Base 1.4
- git_repository_wrap_odb@Base 1.4
- git_reset@Base 1.4
- git_reset_default@Base 1.4
- git_reset_from_annotated@Base 1.4
- git_revert@Base 1.4
- git_revert_commit@Base 1.4
- git_revert_init_options@Base 1.4
- git_revert_options_init@Base 1.4
- git_revparse@Base 1.4
- git_revparse_ext@Base 1.4
- git_revparse_single@Base 1.4
- git_revwalk_add_hide_cb@Base 1.4
- git_revwalk_free@Base 1.4
- git_revwalk_hide@Base 1.4
- git_revwalk_hide_glob@Base 1.4
- git_revwalk_hide_head@Base 1.4
- git_revwalk_hide_ref@Base 1.4
- git_revwalk_new@Base 1.4
- git_revwalk_next@Base 1.4
- git_revwalk_push@Base 1.4
- git_revwalk_push_glob@Base 1.4
- git_revwalk_push_head@Base 1.4
- git_revwalk_push_range@Base 1.4
- git_revwalk_push_ref@Base 1.4
- git_revwalk_repository@Base 1.4
- git_revwalk_reset@Base 1.4
- git_revwalk_simplify_first_parent@Base 1.4
- git_revwalk_sorting@Base 1.4
- git_signature_default@Base 1.4
- git_signature_dup@Base 1.4
- git_signature_free@Base 1.4
- git_signature_from_buffer@Base 1.4
- git_signature_new@Base 1.4
- git_signature_now@Base 1.4
- git_smart_subtransport_git@Base 1.4
- git_smart_subtransport_http@Base 1.4
- git_smart_subtransport_ssh@Base 1.4
- git_stash_apply@Base 1.4
- git_stash_apply_init_options@Base 1.4
- git_stash_apply_options_init@Base 1.4
- git_stash_drop@Base 1.4
- git_stash_foreach@Base 1.4
- git_stash_pop@Base 1.4
- git_stash_save@Base 1.4
- git_status_byindex@Base 1.4
- git_status_file@Base 1.4
- git_status_foreach@Base 1.4
- git_status_foreach_ext@Base 1.4
- git_status_init_options@Base 1.4
- git_status_list_entrycount@Base 1.4
- git_status_list_free@Base 1.4
- git_status_list_get_perfdata@Base 1.4
- git_status_list_new@Base 1.4
- git_status_options_init@Base 1.4
- git_status_should_ignore@Base 1.4
- git_strarray_copy@Base 1.4
- git_strarray_dispose@Base 1.4
- git_strarray_free@Base 1.4
- git_stream_register@Base 1.4
- git_stream_register_tls@Base 1.4
- git_submodule_add_finalize@Base 1.4
- git_submodule_add_setup@Base 1.4
- git_submodule_add_to_index@Base 1.4
- git_submodule_branch@Base 1.4
- git_submodule_clone@Base 1.4
- git_submodule_dup@Base 1.4
- git_submodule_fetch_recurse_submodules@Base 1.4
- git_submodule_foreach@Base 1.4
- git_submodule_free@Base 1.4
- git_submodule_head_id@Base 1.4
- git_submodule_ignore@Base 1.4
- git_submodule_index_id@Base 1.4
- git_submodule_init@Base 1.4
- git_submodule_location@Base 1.4
- git_submodule_lookup@Base 1.4
- git_submodule_name@Base 1.4
- git_submodule_open@Base 1.4
- git_submodule_owner@Base 1.4
- git_submodule_path@Base 1.4
- git_submodule_reload@Base 1.4
- git_submodule_repo_init@Base 1.4
- git_submodule_resolve_url@Base 1.4
- git_submodule_set_branch@Base 1.4
- git_submodule_set_fetch_recurse_submodules@Base 1.4
- git_submodule_set_ignore@Base 1.4
- git_submodule_set_update@Base 1.4
- git_submodule_set_url@Base 1.4
- git_submodule_status@Base 1.4
- git_submodule_sync@Base 1.4
- git_submodule_update@Base 1.4
- git_submodule_update_init_options@Base 1.4
- git_submodule_update_options_init@Base 1.4
- git_submodule_update_strategy@Base 1.4
- git_submodule_url@Base 1.4
- git_submodule_wd_id@Base 1.4
- git_tag_annotation_create@Base 1.4
- git_tag_create@Base 1.4
- git_tag_create_from_buffer@Base 1.4
- git_tag_create_frombuffer@Base 1.4
- git_tag_create_lightweight@Base 1.4
- git_tag_delete@Base 1.4
- git_tag_dup@Base 1.4
- git_tag_foreach@Base 1.4
- git_tag_free@Base 1.4
- git_tag_id@Base 1.4
- git_tag_list@Base 1.4
- git_tag_list_match@Base 1.4
- git_tag_lookup@Base 1.4
- git_tag_lookup_prefix@Base 1.4
- git_tag_message@Base 1.4
- git_tag_name@Base 1.4
- git_tag_name_is_valid@Base 1.4
- git_tag_owner@Base 1.4
- git_tag_peel@Base 1.4
- git_tag_tagger@Base 1.4
- git_tag_target@Base 1.4
- git_tag_target_id@Base 1.4
- git_tag_target_type@Base 1.4
- git_trace_set@Base 1.4
- git_transaction_commit@Base 1.4
- git_transaction_free@Base 1.4
- git_transaction_lock_ref@Base 1.4
- git_transaction_new@Base 1.4
- git_transaction_remove@Base 1.4
- git_transaction_set_reflog@Base 1.4
- git_transaction_set_symbolic_target@Base 1.4
- git_transaction_set_target@Base 1.4
- git_transport_init@Base 1.4
- git_transport_local@Base 1.4
- git_transport_new@Base 1.4
- git_transport_register@Base 1.4
- git_transport_smart@Base 1.4
- git_transport_smart_certificate_check@Base 1.4
- git_transport_smart_credentials@Base 1.4
- git_transport_ssh_with_paths@Base 1.4
- git_transport_unregister@Base 1.4
- git_tree_create_updated@Base 1.4
- git_tree_dup@Base 1.4
- git_tree_entry_byid@Base 1.4
- git_tree_entry_byindex@Base 1.4
- git_tree_entry_byname@Base 1.4
- git_tree_entry_bypath@Base 1.4
- git_tree_entry_cmp@Base 1.4
- git_tree_entry_dup@Base 1.4
- git_tree_entry_filemode@Base 1.4
- git_tree_entry_filemode_raw@Base 1.4
- git_tree_entry_free@Base 1.4
- git_tree_entry_id@Base 1.4
- git_tree_entry_name@Base 1.4
- git_tree_entry_to_object@Base 1.4
- git_tree_entry_type@Base 1.4
- git_tree_entrycount@Base 1.4
- git_tree_free@Base 1.4
- git_tree_id@Base 1.4
- git_tree_lookup@Base 1.4
- git_tree_lookup_prefix@Base 1.4
- git_tree_owner@Base 1.4
- git_tree_walk@Base 1.4
- git_treebuilder_clear@Base 1.4
- git_treebuilder_entrycount@Base 1.4
- git_treebuilder_filter@Base 1.4
- git_treebuilder_free@Base 1.4
- git_treebuilder_get@Base 1.4
- git_treebuilder_insert@Base 1.4
- git_treebuilder_new@Base 1.4
- git_treebuilder_remove@Base 1.4
- git_treebuilder_write@Base 1.4
- git_treebuilder_write_with_buffer@Base 1.4
- git_worktree_add@Base 1.4
- git_worktree_add_init_options@Base 1.4
- git_worktree_add_options_init@Base 1.4
- git_worktree_free@Base 1.4
- git_worktree_is_locked@Base 1.4
- git_worktree_is_prunable@Base 1.4
- git_worktree_list@Base 1.4
- git_worktree_lock@Base 1.4
- git_worktree_lookup@Base 1.4
- git_worktree_name@Base 1.4
- git_worktree_open_from_repository@Base 1.4
- git_worktree_path@Base 1.4
- git_worktree_prune@Base 1.4
- git_worktree_prune_init_options@Base 1.4
- git_worktree_prune_options_init@Base 1.4
- git_worktree_unlock@Base 1.4
- git_worktree_validate@Base 1.4
- giterr_clear@Base 1.4
- giterr_last@Base 1.4
- giterr_set_oom@Base 1.4
- giterr_set_str@Base 1.4
diff --git a/debian/libgit2-1.4.install b/debian/libgit2-1.5.install
similarity index 100%
rename from debian/libgit2-1.4.install
rename to debian/libgit2-1.5.install
diff --git a/debian/libgit2-1.5.symbols b/debian/libgit2-1.5.symbols
new file mode 100644
index 000000000..661f4df0f
--- /dev/null
+++ b/debian/libgit2-1.5.symbols
@@ -0,0 +1,938 @@
+libgit2.so.1.5 libgit2-1.5 #MINVER#
+* Build-Depends-Package: libgit2-dev
+ git_annotated_commit_free@Base 1.5.0
+ git_annotated_commit_from_fetchhead@Base 1.5.0
+ git_annotated_commit_from_ref@Base 1.5.0
+ git_annotated_commit_from_revspec@Base 1.5.0
+ git_annotated_commit_id@Base 1.5.0
+ git_annotated_commit_lookup@Base 1.5.0
+ git_annotated_commit_ref@Base 1.5.0
+ git_apply@Base 1.5.0
+ git_apply_options_init@Base 1.5.0
+ git_apply_to_tree@Base 1.5.0
+ git_attr_add_macro@Base 1.5.0
+ git_attr_cache_flush@Base 1.5.0
+ git_attr_foreach@Base 1.5.0
+ git_attr_foreach_ext@Base 1.5.0
+ git_attr_get@Base 1.5.0
+ git_attr_get_ext@Base 1.5.0
+ git_attr_get_many@Base 1.5.0
+ git_attr_get_many_ext@Base 1.5.0
+ git_attr_value@Base 1.5.0
+ git_blame_buffer@Base 1.5.0
+ git_blame_file@Base 1.5.0
+ git_blame_free@Base 1.5.0
+ git_blame_get_hunk_byindex@Base 1.5.0
+ git_blame_get_hunk_byline@Base 1.5.0
+ git_blame_get_hunk_count@Base 1.5.0
+ git_blame_init_options@Base 1.5.0
+ git_blame_options_init@Base 1.5.0
+ git_blob_create_from_buffer@Base 1.5.0
+ git_blob_create_from_disk@Base 1.5.0
+ git_blob_create_from_stream@Base 1.5.0
+ git_blob_create_from_stream_commit@Base 1.5.0
+ git_blob_create_from_workdir@Base 1.5.0
+ git_blob_create_frombuffer@Base 1.5.0
+ git_blob_create_fromdisk@Base 1.5.0
+ git_blob_create_fromstream@Base 1.5.0
+ git_blob_create_fromstream_commit@Base 1.5.0
+ git_blob_create_fromworkdir@Base 1.5.0
+ git_blob_data_is_binary@Base 1.5.0
+ git_blob_dup@Base 1.5.0
+ git_blob_filter@Base 1.5.0
+ git_blob_filter_options_init@Base 1.5.0
+ git_blob_filtered_content@Base 1.5.0
+ git_blob_free@Base 1.5.0
+ git_blob_id@Base 1.5.0
+ git_blob_is_binary@Base 1.5.0
+ git_blob_lookup@Base 1.5.0
+ git_blob_lookup_prefix@Base 1.5.0
+ git_blob_owner@Base 1.5.0
+ git_blob_rawcontent@Base 1.5.0
+ git_blob_rawsize@Base 1.5.0
+ git_branch_create@Base 1.5.0
+ git_branch_create_from_annotated@Base 1.5.0
+ git_branch_delete@Base 1.5.0
+ git_branch_is_checked_out@Base 1.5.0
+ git_branch_is_head@Base 1.5.0
+ git_branch_iterator_free@Base 1.5.0
+ git_branch_iterator_new@Base 1.5.0
+ git_branch_lookup@Base 1.5.0
+ git_branch_move@Base 1.5.0
+ git_branch_name@Base 1.5.0
+ git_branch_name_is_valid@Base 1.5.0
+ git_branch_next@Base 1.5.0
+ git_branch_remote_name@Base 1.5.0
+ git_branch_set_upstream@Base 1.5.0
+ git_branch_upstream@Base 1.5.0
+ git_branch_upstream_merge@Base 1.5.0
+ git_branch_upstream_name@Base 1.5.0
+ git_branch_upstream_remote@Base 1.5.0
+ git_buf_contains_nul@Base 1.5.0
+ git_buf_dispose@Base 1.5.0
+ git_buf_free@Base 1.5.0
+ git_buf_grow@Base 1.5.0
+ git_buf_is_binary@Base 1.5.0
+ git_buf_set@Base 1.5.0
+ git_checkout_head@Base 1.5.0
+ git_checkout_index@Base 1.5.0
+ git_checkout_init_options@Base 1.5.0
+ git_checkout_options_init@Base 1.5.0
+ git_checkout_tree@Base 1.5.0
+ git_cherrypick@Base 1.5.0
+ git_cherrypick_commit@Base 1.5.0
+ git_cherrypick_init_options@Base 1.5.0
+ git_cherrypick_options_init@Base 1.5.0
+ git_clone@Base 1.5.0
+ git_clone_init_options@Base 1.5.0
+ git_clone_options_init@Base 1.5.0
+ git_commit_amend@Base 1.5.0
+ git_commit_author@Base 1.5.0
+ git_commit_author_with_mailmap@Base 1.5.0
+ git_commit_body@Base 1.5.0
+ git_commit_committer@Base 1.5.0
+ git_commit_committer_with_mailmap@Base 1.5.0
+ git_commit_create@Base 1.5.0
+ git_commit_create_buffer@Base 1.5.0
+ git_commit_create_from_callback@Base 1.5.0
+ git_commit_create_from_ids@Base 1.5.0
+ git_commit_create_v@Base 1.5.0
+ git_commit_create_with_signature@Base 1.5.0
+ git_commit_dup@Base 1.5.0
+ git_commit_extract_signature@Base 1.5.0
+ git_commit_free@Base 1.5.0
+ git_commit_graph_free@Base 1.5.0
+ git_commit_graph_open@Base 1.5.0
+ git_commit_graph_writer_add_index_file@Base 1.5.0
+ git_commit_graph_writer_add_revwalk@Base 1.5.0
+ git_commit_graph_writer_commit@Base 1.5.0
+ git_commit_graph_writer_dump@Base 1.5.0
+ git_commit_graph_writer_free@Base 1.5.0
+ git_commit_graph_writer_new@Base 1.5.0
+ git_commit_graph_writer_options_init@Base 1.5.0
+ git_commit_header_field@Base 1.5.0
+ git_commit_id@Base 1.5.0
+ git_commit_lookup@Base 1.5.0
+ git_commit_lookup_prefix@Base 1.5.0
+ git_commit_message@Base 1.5.0
+ git_commit_message_encoding@Base 1.5.0
+ git_commit_message_raw@Base 1.5.0
+ git_commit_nth_gen_ancestor@Base 1.5.0
+ git_commit_owner@Base 1.5.0
+ git_commit_parent@Base 1.5.0
+ git_commit_parent_id@Base 1.5.0
+ git_commit_parentcount@Base 1.5.0
+ git_commit_raw_header@Base 1.5.0
+ git_commit_summary@Base 1.5.0
+ git_commit_time@Base 1.5.0
+ git_commit_time_offset@Base 1.5.0
+ git_commit_tree@Base 1.5.0
+ git_commit_tree_id@Base 1.5.0
+ git_config_add_backend@Base 1.5.0
+ git_config_add_file_ondisk@Base 1.5.0
+ git_config_backend_foreach_match@Base 1.5.0
+ git_config_delete_entry@Base 1.5.0
+ git_config_delete_multivar@Base 1.5.0
+ git_config_entry_free@Base 1.5.0
+ git_config_find_global@Base 1.5.0
+ git_config_find_programdata@Base 1.5.0
+ git_config_find_system@Base 1.5.0
+ git_config_find_xdg@Base 1.5.0
+ git_config_foreach@Base 1.5.0
+ git_config_foreach_match@Base 1.5.0
+ git_config_free@Base 1.5.0
+ git_config_get_bool@Base 1.5.0
+ git_config_get_entry@Base 1.5.0
+ git_config_get_int32@Base 1.5.0
+ git_config_get_int64@Base 1.5.0
+ git_config_get_mapped@Base 1.5.0
+ git_config_get_multivar_foreach@Base 1.5.0
+ git_config_get_path@Base 1.5.0
+ git_config_get_string@Base 1.5.0
+ git_config_get_string_buf@Base 1.5.0
+ git_config_init_backend@Base 1.5.0
+ git_config_iterator_free@Base 1.5.0
+ git_config_iterator_glob_new@Base 1.5.0
+ git_config_iterator_new@Base 1.5.0
+ git_config_lock@Base 1.5.0
+ git_config_lookup_map_value@Base 1.5.0
+ git_config_multivar_iterator_new@Base 1.5.0
+ git_config_new@Base 1.5.0
+ git_config_next@Base 1.5.0
+ git_config_open_default@Base 1.5.0
+ git_config_open_global@Base 1.5.0
+ git_config_open_level@Base 1.5.0
+ git_config_open_ondisk@Base 1.5.0
+ git_config_parse_bool@Base 1.5.0
+ git_config_parse_int32@Base 1.5.0
+ git_config_parse_int64@Base 1.5.0
+ git_config_parse_path@Base 1.5.0
+ git_config_set_bool@Base 1.5.0
+ git_config_set_int32@Base 1.5.0
+ git_config_set_int64@Base 1.5.0
+ git_config_set_multivar@Base 1.5.0
+ git_config_set_string@Base 1.5.0
+ git_config_snapshot@Base 1.5.0
+ git_config_unlock@Base 1.5.0
+ git_cred_default_new@Base 1.5.0
+ git_cred_free@Base 1.5.0
+ git_cred_get_username@Base 1.5.0
+ git_cred_has_username@Base 1.5.0
+ git_cred_ssh_custom_new@Base 1.5.0
+ git_cred_ssh_interactive_new@Base 1.5.0
+ git_cred_ssh_key_from_agent@Base 1.5.0
+ git_cred_ssh_key_memory_new@Base 1.5.0
+ git_cred_ssh_key_new@Base 1.5.0
+ git_cred_username_new@Base 1.5.0
+ git_cred_userpass@Base 1.5.0
+ git_cred_userpass_plaintext_new@Base 1.5.0
+ git_credential_default_new@Base 1.5.0
+ git_credential_free@Base 1.5.0
+ git_credential_get_username@Base 1.5.0
+ git_credential_has_username@Base 1.5.0
+ git_credential_ssh_custom_new@Base 1.5.0
+ git_credential_ssh_interactive_new@Base 1.5.0
+ git_credential_ssh_key_from_agent@Base 1.5.0
+ git_credential_ssh_key_memory_new@Base 1.5.0
+ git_credential_ssh_key_new@Base 1.5.0
+ git_credential_username_new@Base 1.5.0
+ git_credential_userpass@Base 1.5.0
+ git_credential_userpass_plaintext_new@Base 1.5.0
+ git_describe_commit@Base 1.5.0
+ git_describe_format@Base 1.5.0
+ git_describe_format_options_init@Base 1.5.0
+ git_describe_init_format_options@Base 1.5.0
+ git_describe_init_options@Base 1.5.0
+ git_describe_options_init@Base 1.5.0
+ git_describe_result_free@Base 1.5.0
+ git_describe_workdir@Base 1.5.0
+ git_diff_blob_to_buffer@Base 1.5.0
+ git_diff_blobs@Base 1.5.0
+ git_diff_buffers@Base 1.5.0
+ git_diff_commit_as_email@Base 1.5.0
+ git_diff_find_init_options@Base 1.5.0
+ git_diff_find_options_init@Base 1.5.0
+ git_diff_find_similar@Base 1.5.0
+ git_diff_foreach@Base 1.5.0
+ git_diff_format_email@Base 1.5.0
+ git_diff_format_email_init_options@Base 1.5.0
+ git_diff_format_email_options_init@Base 1.5.0
+ git_diff_free@Base 1.5.0
+ git_diff_from_buffer@Base 1.5.0
+ git_diff_get_delta@Base 1.5.0
+ git_diff_get_perfdata@Base 1.5.0
+ git_diff_get_stats@Base 1.5.0
+ git_diff_index_to_index@Base 1.5.0
+ git_diff_index_to_workdir@Base 1.5.0
+ git_diff_init_options@Base 1.5.0
+ git_diff_is_sorted_icase@Base 1.5.0
+ git_diff_merge@Base 1.5.0
+ git_diff_num_deltas@Base 1.5.0
+ git_diff_num_deltas_of_type@Base 1.5.0
+ git_diff_options_init@Base 1.5.0
+ git_diff_patchid@Base 1.5.0
+ git_diff_patchid_options_init@Base 1.5.0
+ git_diff_print@Base 1.5.0
+ git_diff_print_callback__to_buf@Base 1.5.0
+ git_diff_print_callback__to_file_handle@Base 1.5.0
+ git_diff_stats_deletions@Base 1.5.0
+ git_diff_stats_files_changed@Base 1.5.0
+ git_diff_stats_free@Base 1.5.0
+ git_diff_stats_insertions@Base 1.5.0
+ git_diff_stats_to_buf@Base 1.5.0
+ git_diff_status_char@Base 1.5.0
+ git_diff_to_buf@Base 1.5.0
+ git_diff_tree_to_index@Base 1.5.0
+ git_diff_tree_to_tree@Base 1.5.0
+ git_diff_tree_to_workdir@Base 1.5.0
+ git_diff_tree_to_workdir_with_index@Base 1.5.0
+ git_email_create_from_commit@Base 1.5.0
+ git_email_create_from_diff@Base 1.5.0
+ git_error_clear@Base 1.5.0
+ git_error_last@Base 1.5.0
+ git_error_set@Base 1.5.0
+ git_error_set_oom@Base 1.5.0
+ git_error_set_str@Base 1.5.0
+ git_fetch_init_options@Base 1.5.0
+ git_fetch_options_init@Base 1.5.0
+ git_filter_init@Base 1.5.0
+ git_filter_list_apply_to_blob@Base 1.5.0
+ git_filter_list_apply_to_buffer@Base 1.5.0
+ git_filter_list_apply_to_data@Base 1.5.0
+ git_filter_list_apply_to_file@Base 1.5.0
+ git_filter_list_contains@Base 1.5.0
+ git_filter_list_free@Base 1.5.0
+ git_filter_list_length@Base 1.5.0
+ git_filter_list_load@Base 1.5.0
+ git_filter_list_load_ext@Base 1.5.0
+ git_filter_list_new@Base 1.5.0
+ git_filter_list_push@Base 1.5.0
+ git_filter_list_stream_blob@Base 1.5.0
+ git_filter_list_stream_buffer@Base 1.5.0
+ git_filter_list_stream_data@Base 1.5.0
+ git_filter_list_stream_file@Base 1.5.0
+ git_filter_lookup@Base 1.5.0
+ git_filter_register@Base 1.5.0
+ git_filter_source_filemode@Base 1.5.0
+ git_filter_source_flags@Base 1.5.0
+ git_filter_source_id@Base 1.5.0
+ git_filter_source_mode@Base 1.5.0
+ git_filter_source_path@Base 1.5.0
+ git_filter_source_repo@Base 1.5.0
+ git_filter_unregister@Base 1.5.0
+ git_graph_ahead_behind@Base 1.5.0
+ git_graph_descendant_of@Base 1.5.0
+ git_graph_reachable_from_any@Base 1.5.0
+ git_hashsig_compare@Base 1.5.0
+ git_hashsig_create@Base 1.5.0
+ git_hashsig_create_fromfile@Base 1.5.0
+ git_hashsig_free@Base 1.5.0
+ git_ignore_add_rule@Base 1.5.0
+ git_ignore_clear_internal_rules@Base 1.5.0
+ git_ignore_path_is_ignored@Base 1.5.0
+ git_index_add@Base 1.5.0
+ git_index_add_all@Base 1.5.0
+ git_index_add_bypath@Base 1.5.0
+ git_index_add_from_buffer@Base 1.5.0
+ git_index_add_frombuffer@Base 1.5.0
+ git_index_caps@Base 1.5.0
+ git_index_checksum@Base 1.5.0
+ git_index_clear@Base 1.5.0
+ git_index_conflict_add@Base 1.5.0
+ git_index_conflict_cleanup@Base 1.5.0
+ git_index_conflict_get@Base 1.5.0
+ git_index_conflict_iterator_free@Base 1.5.0
+ git_index_conflict_iterator_new@Base 1.5.0
+ git_index_conflict_next@Base 1.5.0
+ git_index_conflict_remove@Base 1.5.0
+ git_index_entry_is_conflict@Base 1.5.0
+ git_index_entry_stage@Base 1.5.0
+ git_index_entrycount@Base 1.5.0
+ git_index_find@Base 1.5.0
+ git_index_find_prefix@Base 1.5.0
+ git_index_free@Base 1.5.0
+ git_index_get_byindex@Base 1.5.0
+ git_index_get_bypath@Base 1.5.0
+ git_index_has_conflicts@Base 1.5.0
+ git_index_iterator_free@Base 1.5.0
+ git_index_iterator_new@Base 1.5.0
+ git_index_iterator_next@Base 1.5.0
+ git_index_name_add@Base 1.5.0
+ git_index_name_clear@Base 1.5.0
+ git_index_name_entrycount@Base 1.5.0
+ git_index_name_get_byindex@Base 1.5.0
+ git_index_new@Base 1.5.0
+ git_index_open@Base 1.5.0
+ git_index_owner@Base 1.5.0
+ git_index_path@Base 1.5.0
+ git_index_read@Base 1.5.0
+ git_index_read_tree@Base 1.5.0
+ git_index_remove@Base 1.5.0
+ git_index_remove_all@Base 1.5.0
+ git_index_remove_bypath@Base 1.5.0
+ git_index_remove_directory@Base 1.5.0
+ git_index_reuc_add@Base 1.5.0
+ git_index_reuc_clear@Base 1.5.0
+ git_index_reuc_entrycount@Base 1.5.0
+ git_index_reuc_find@Base 1.5.0
+ git_index_reuc_get_byindex@Base 1.5.0
+ git_index_reuc_get_bypath@Base 1.5.0
+ git_index_reuc_remove@Base 1.5.0
+ git_index_set_caps@Base 1.5.0
+ git_index_set_version@Base 1.5.0
+ git_index_update_all@Base 1.5.0
+ git_index_version@Base 1.5.0
+ git_index_write@Base 1.5.0
+ git_index_write_tree@Base 1.5.0
+ git_index_write_tree_to@Base 1.5.0
+ git_indexer_append@Base 1.5.0
+ git_indexer_commit@Base 1.5.0
+ git_indexer_free@Base 1.5.0
+ git_indexer_hash@Base 1.5.0
+ git_indexer_init_options@Base 1.5.0
+ git_indexer_name@Base 1.5.0
+ git_indexer_new@Base 1.5.0
+ git_indexer_options_init@Base 1.5.0
+ git_libgit2_features@Base 1.5.0
+ git_libgit2_init@Base 1.5.0
+ git_libgit2_opts@Base 1.5.0
+ git_libgit2_prerelease@Base 1.5.0
+ git_libgit2_shutdown@Base 1.5.0
+ git_libgit2_version@Base 1.5.0
+ git_mailmap_add_entry@Base 1.5.0
+ git_mailmap_free@Base 1.5.0
+ git_mailmap_from_buffer@Base 1.5.0
+ git_mailmap_from_repository@Base 1.5.0
+ git_mailmap_new@Base 1.5.0
+ git_mailmap_resolve@Base 1.5.0
+ git_mailmap_resolve_signature@Base 1.5.0
+ git_mempack_dump@Base 1.5.0
+ git_mempack_new@Base 1.5.0
+ git_mempack_reset@Base 1.5.0
+ git_merge@Base 1.5.0
+ git_merge_analysis@Base 1.5.0
+ git_merge_analysis_for_ref@Base 1.5.0
+ git_merge_base@Base 1.5.0
+ git_merge_base_many@Base 1.5.0
+ git_merge_base_octopus@Base 1.5.0
+ git_merge_bases@Base 1.5.0
+ git_merge_bases_many@Base 1.5.0
+ git_merge_commits@Base 1.5.0
+ git_merge_driver_lookup@Base 1.5.0
+ git_merge_driver_register@Base 1.5.0
+ git_merge_driver_source_ancestor@Base 1.5.0
+ git_merge_driver_source_file_options@Base 1.5.0
+ git_merge_driver_source_ours@Base 1.5.0
+ git_merge_driver_source_repo@Base 1.5.0
+ git_merge_driver_source_theirs@Base 1.5.0
+ git_merge_driver_unregister@Base 1.5.0
+ git_merge_file@Base 1.5.0
+ git_merge_file_from_index@Base 1.5.0
+ git_merge_file_init_input@Base 1.5.0
+ git_merge_file_init_options@Base 1.5.0
+ git_merge_file_input_init@Base 1.5.0
+ git_merge_file_options_init@Base 1.5.0
+ git_merge_file_result_free@Base 1.5.0
+ git_merge_init_options@Base 1.5.0
+ git_merge_options_init@Base 1.5.0
+ git_merge_trees@Base 1.5.0
+ git_message_prettify@Base 1.5.0
+ git_message_trailer_array_free@Base 1.5.0
+ git_message_trailers@Base 1.5.0
+ git_midx_writer_add@Base 1.5.0
+ git_midx_writer_commit@Base 1.5.0
+ git_midx_writer_dump@Base 1.5.0
+ git_midx_writer_free@Base 1.5.0
+ git_midx_writer_new@Base 1.5.0
+ git_note_author@Base 1.5.0
+ git_note_commit_create@Base 1.5.0
+ git_note_commit_iterator_new@Base 1.5.0
+ git_note_commit_read@Base 1.5.0
+ git_note_commit_remove@Base 1.5.0
+ git_note_committer@Base 1.5.0
+ git_note_create@Base 1.5.0
+ git_note_default_ref@Base 1.5.0
+ git_note_foreach@Base 1.5.0
+ git_note_free@Base 1.5.0
+ git_note_id@Base 1.5.0
+ git_note_iterator_free@Base 1.5.0
+ git_note_iterator_new@Base 1.5.0
+ git_note_message@Base 1.5.0
+ git_note_next@Base 1.5.0
+ git_note_read@Base 1.5.0
+ git_note_remove@Base 1.5.0
+ git_object__size@Base 1.5.0
+ git_object_dup@Base 1.5.0
+ git_object_free@Base 1.5.0
+ git_object_id@Base 1.5.0
+ git_object_lookup@Base 1.5.0
+ git_object_lookup_bypath@Base 1.5.0
+ git_object_lookup_prefix@Base 1.5.0
+ git_object_owner@Base 1.5.0
+ git_object_peel@Base 1.5.0
+ git_object_rawcontent_is_valid@Base 1.5.0
+ git_object_short_id@Base 1.5.0
+ git_object_string2type@Base 1.5.0
+ git_object_type2string@Base 1.5.0
+ git_object_type@Base 1.5.0
+ git_object_typeisloose@Base 1.5.0
+ git_odb_add_alternate@Base 1.5.0
+ git_odb_add_backend@Base 1.5.0
+ git_odb_add_disk_alternate@Base 1.5.0
+ git_odb_backend_data_alloc@Base 1.5.0
+ git_odb_backend_data_free@Base 1.5.0
+ git_odb_backend_loose@Base 1.5.0
+ git_odb_backend_malloc@Base 1.5.0
+ git_odb_backend_one_pack@Base 1.5.0
+ git_odb_backend_pack@Base 1.5.0
+ git_odb_exists@Base 1.5.0
+ git_odb_exists_ext@Base 1.5.0
+ git_odb_exists_prefix@Base 1.5.0
+ git_odb_expand_ids@Base 1.5.0
+ git_odb_foreach@Base 1.5.0
+ git_odb_free@Base 1.5.0
+ git_odb_get_backend@Base 1.5.0
+ git_odb_hash@Base 1.5.0
+ git_odb_hashfile@Base 1.5.0
+ git_odb_init_backend@Base 1.5.0
+ git_odb_new@Base 1.5.0
+ git_odb_num_backends@Base 1.5.0
+ git_odb_object_data@Base 1.5.0
+ git_odb_object_dup@Base 1.5.0
+ git_odb_object_free@Base 1.5.0
+ git_odb_object_id@Base 1.5.0
+ git_odb_object_size@Base 1.5.0
+ git_odb_object_type@Base 1.5.0
+ git_odb_open@Base 1.5.0
+ git_odb_open_rstream@Base 1.5.0
+ git_odb_open_wstream@Base 1.5.0
+ git_odb_read@Base 1.5.0
+ git_odb_read_header@Base 1.5.0
+ git_odb_read_prefix@Base 1.5.0
+ git_odb_refresh@Base 1.5.0
+ git_odb_set_commit_graph@Base 1.5.0
+ git_odb_stream_finalize_write@Base 1.5.0
+ git_odb_stream_free@Base 1.5.0
+ git_odb_stream_read@Base 1.5.0
+ git_odb_stream_write@Base 1.5.0
+ git_odb_write@Base 1.5.0
+ git_odb_write_multi_pack_index@Base 1.5.0
+ git_odb_write_pack@Base 1.5.0
+ git_oid_cmp@Base 1.5.0
+ git_oid_cpy@Base 1.5.0
+ git_oid_equal@Base 1.5.0
+ git_oid_fmt@Base 1.5.0
+ git_oid_fromraw@Base 1.5.0
+ git_oid_fromstr@Base 1.5.0
+ git_oid_fromstrn@Base 1.5.0
+ git_oid_fromstrp@Base 1.5.0
+ git_oid_is_zero@Base 1.5.0
+ git_oid_iszero@Base 1.5.0
+ git_oid_ncmp@Base 1.5.0
+ git_oid_nfmt@Base 1.5.0
+ git_oid_pathfmt@Base 1.5.0
+ git_oid_shorten_add@Base 1.5.0
+ git_oid_shorten_free@Base 1.5.0
+ git_oid_shorten_new@Base 1.5.0
+ git_oid_strcmp@Base 1.5.0
+ git_oid_streq@Base 1.5.0
+ git_oid_tostr@Base 1.5.0
+ git_oid_tostr_s@Base 1.5.0
+ git_oidarray_dispose@Base 1.5.0
+ git_oidarray_free@Base 1.5.0
+ git_openssl_set_locking@Base 1.5.0
+ git_packbuilder_foreach@Base 1.5.0
+ git_packbuilder_free@Base 1.5.0
+ git_packbuilder_hash@Base 1.5.0
+ git_packbuilder_insert@Base 1.5.0
+ git_packbuilder_insert_commit@Base 1.5.0
+ git_packbuilder_insert_recur@Base 1.5.0
+ git_packbuilder_insert_tree@Base 1.5.0
+ git_packbuilder_insert_walk@Base 1.5.0
+ git_packbuilder_name@Base 1.5.0
+ git_packbuilder_new@Base 1.5.0
+ git_packbuilder_object_count@Base 1.5.0
+ git_packbuilder_set_callbacks@Base 1.5.0
+ git_packbuilder_set_threads@Base 1.5.0
+ git_packbuilder_write@Base 1.5.0
+ git_packbuilder_write_buf@Base 1.5.0
+ git_packbuilder_written@Base 1.5.0
+ git_patch_free@Base 1.5.0
+ git_patch_from_blob_and_buffer@Base 1.5.0
+ git_patch_from_blobs@Base 1.5.0
+ git_patch_from_buffers@Base 1.5.0
+ git_patch_from_diff@Base 1.5.0
+ git_patch_get_delta@Base 1.5.0
+ git_patch_get_hunk@Base 1.5.0
+ git_patch_get_line_in_hunk@Base 1.5.0
+ git_patch_line_stats@Base 1.5.0
+ git_patch_num_hunks@Base 1.5.0
+ git_patch_num_lines_in_hunk@Base 1.5.0
+ git_patch_owner@Base 1.5.0
+ git_patch_print@Base 1.5.0
+ git_patch_size@Base 1.5.0
+ git_patch_to_buf@Base 1.5.0
+ git_path_is_gitfile@Base 1.5.0
+ git_pathspec_free@Base 1.5.0
+ git_pathspec_match_diff@Base 1.5.0
+ git_pathspec_match_index@Base 1.5.0
+ git_pathspec_match_list_diff_entry@Base 1.5.0
+ git_pathspec_match_list_entry@Base 1.5.0
+ git_pathspec_match_list_entrycount@Base 1.5.0
+ git_pathspec_match_list_failed_entry@Base 1.5.0
+ git_pathspec_match_list_failed_entrycount@Base 1.5.0
+ git_pathspec_match_list_free@Base 1.5.0
+ git_pathspec_match_tree@Base 1.5.0
+ git_pathspec_match_workdir@Base 1.5.0
+ git_pathspec_matches_path@Base 1.5.0
+ git_pathspec_new@Base 1.5.0
+ git_proxy_init_options@Base 1.5.0
+ git_proxy_options_init@Base 1.5.0
+ git_push_init_options@Base 1.5.0
+ git_push_options_init@Base 1.5.0
+ git_rebase_abort@Base 1.5.0
+ git_rebase_commit@Base 1.5.0
+ git_rebase_finish@Base 1.5.0
+ git_rebase_free@Base 1.5.0
+ git_rebase_init@Base 1.5.0
+ git_rebase_init_options@Base 1.5.0
+ git_rebase_inmemory_index@Base 1.5.0
+ git_rebase_next@Base 1.5.0
+ git_rebase_onto_id@Base 1.5.0
+ git_rebase_onto_name@Base 1.5.0
+ git_rebase_open@Base 1.5.0
+ git_rebase_operation_byindex@Base 1.5.0
+ git_rebase_operation_current@Base 1.5.0
+ git_rebase_operation_entrycount@Base 1.5.0
+ git_rebase_options_init@Base 1.5.0
+ git_rebase_orig_head_id@Base 1.5.0
+ git_rebase_orig_head_name@Base 1.5.0
+ git_refdb_backend_fs@Base 1.5.0
+ git_refdb_compress@Base 1.5.0
+ git_refdb_free@Base 1.5.0
+ git_refdb_init_backend@Base 1.5.0
+ git_refdb_new@Base 1.5.0
+ git_refdb_open@Base 1.5.0
+ git_refdb_set_backend@Base 1.5.0
+ git_reference__alloc@Base 1.5.0
+ git_reference__alloc_symbolic@Base 1.5.0
+ git_reference_cmp@Base 1.5.0
+ git_reference_create@Base 1.5.0
+ git_reference_create_matching@Base 1.5.0
+ git_reference_delete@Base 1.5.0
+ git_reference_dup@Base 1.5.0
+ git_reference_dwim@Base 1.5.0
+ git_reference_ensure_log@Base 1.5.0
+ git_reference_foreach@Base 1.5.0
+ git_reference_foreach_glob@Base 1.5.0
+ git_reference_foreach_name@Base 1.5.0
+ git_reference_free@Base 1.5.0
+ git_reference_has_log@Base 1.5.0
+ git_reference_is_branch@Base 1.5.0
+ git_reference_is_note@Base 1.5.0
+ git_reference_is_remote@Base 1.5.0
+ git_reference_is_tag@Base 1.5.0
+ git_reference_is_valid_name@Base 1.5.0
+ git_reference_iterator_free@Base 1.5.0
+ git_reference_iterator_glob_new@Base 1.5.0
+ git_reference_iterator_new@Base 1.5.0
+ git_reference_list@Base 1.5.0
+ git_reference_lookup@Base 1.5.0
+ git_reference_name@Base 1.5.0
+ git_reference_name_is_valid@Base 1.5.0
+ git_reference_name_to_id@Base 1.5.0
+ git_reference_next@Base 1.5.0
+ git_reference_next_name@Base 1.5.0
+ git_reference_normalize_name@Base 1.5.0
+ git_reference_owner@Base 1.5.0
+ git_reference_peel@Base 1.5.0
+ git_reference_remove@Base 1.5.0
+ git_reference_rename@Base 1.5.0
+ git_reference_resolve@Base 1.5.0
+ git_reference_set_target@Base 1.5.0
+ git_reference_shorthand@Base 1.5.0
+ git_reference_symbolic_create@Base 1.5.0
+ git_reference_symbolic_create_matching@Base 1.5.0
+ git_reference_symbolic_set_target@Base 1.5.0
+ git_reference_symbolic_target@Base 1.5.0
+ git_reference_target@Base 1.5.0
+ git_reference_target_peel@Base 1.5.0
+ git_reference_type@Base 1.5.0
+ git_reflog_append@Base 1.5.0
+ git_reflog_delete@Base 1.5.0
+ git_reflog_drop@Base 1.5.0
+ git_reflog_entry__free@Base 1.5.0
+ git_reflog_entry_byindex@Base 1.5.0
+ git_reflog_entry_committer@Base 1.5.0
+ git_reflog_entry_id_new@Base 1.5.0
+ git_reflog_entry_id_old@Base 1.5.0
+ git_reflog_entry_message@Base 1.5.0
+ git_reflog_entrycount@Base 1.5.0
+ git_reflog_free@Base 1.5.0
+ git_reflog_read@Base 1.5.0
+ git_reflog_rename@Base 1.5.0
+ git_reflog_write@Base 1.5.0
+ git_refspec_direction@Base 1.5.0
+ git_refspec_dst@Base 1.5.0
+ git_refspec_dst_matches@Base 1.5.0
+ git_refspec_force@Base 1.5.0
+ git_refspec_free@Base 1.5.0
+ git_refspec_parse@Base 1.5.0
+ git_refspec_rtransform@Base 1.5.0
+ git_refspec_src@Base 1.5.0
+ git_refspec_src_matches@Base 1.5.0
+ git_refspec_string@Base 1.5.0
+ git_refspec_transform@Base 1.5.0
+ git_remote_add_fetch@Base 1.5.0
+ git_remote_add_push@Base 1.5.0
+ git_remote_autotag@Base 1.5.0
+ git_remote_connect@Base 1.5.0
+ git_remote_connect_ext@Base 1.5.0
+ git_remote_connect_options_dispose@Base 1.5.0
+ git_remote_connect_options_init@Base 1.5.0
+ git_remote_connected@Base 1.5.0
+ git_remote_create@Base 1.5.0
+ git_remote_create_anonymous@Base 1.5.0
+ git_remote_create_detached@Base 1.5.0
+ git_remote_create_init_options@Base 1.5.0
+ git_remote_create_options_init@Base 1.5.0
+ git_remote_create_with_fetchspec@Base 1.5.0
+ git_remote_create_with_opts@Base 1.5.0
+ git_remote_default_branch@Base 1.5.0
+ git_remote_delete@Base 1.5.0
+ git_remote_disconnect@Base 1.5.0
+ git_remote_download@Base 1.5.0
+ git_remote_dup@Base 1.5.0
+ git_remote_fetch@Base 1.5.0
+ git_remote_free@Base 1.5.0
+ git_remote_get_fetch_refspecs@Base 1.5.0
+ git_remote_get_push_refspecs@Base 1.5.0
+ git_remote_get_refspec@Base 1.5.0
+ git_remote_init_callbacks@Base 1.5.0
+ git_remote_is_valid_name@Base 1.5.0
+ git_remote_list@Base 1.5.0
+ git_remote_lookup@Base 1.5.0
+ git_remote_ls@Base 1.5.0
+ git_remote_name@Base 1.5.0
+ git_remote_name_is_valid@Base 1.5.0
+ git_remote_owner@Base 1.5.0
+ git_remote_prune@Base 1.5.0
+ git_remote_prune_refs@Base 1.5.0
+ git_remote_push@Base 1.5.0
+ git_remote_pushurl@Base 1.5.0
+ git_remote_refspec_count@Base 1.5.0
+ git_remote_rename@Base 1.5.0
+ git_remote_set_autotag@Base 1.5.0
+ git_remote_set_instance_pushurl@Base 1.5.0
+ git_remote_set_instance_url@Base 1.5.0
+ git_remote_set_pushurl@Base 1.5.0
+ git_remote_set_url@Base 1.5.0
+ git_remote_stats@Base 1.5.0
+ git_remote_stop@Base 1.5.0
+ git_remote_update_tips@Base 1.5.0
+ git_remote_upload@Base 1.5.0
+ git_remote_url@Base 1.5.0
+ git_repository__cleanup@Base 1.5.0
+ git_repository_commondir@Base 1.5.0
+ git_repository_config@Base 1.5.0
+ git_repository_config_snapshot@Base 1.5.0
+ git_repository_detach_head@Base 1.5.0
+ git_repository_discover@Base 1.5.0
+ git_repository_fetchhead_foreach@Base 1.5.0
+ git_repository_free@Base 1.5.0
+ git_repository_get_namespace@Base 1.5.0
+ git_repository_hashfile@Base 1.5.0
+ git_repository_head@Base 1.5.0
+ git_repository_head_detached@Base 1.5.0
+ git_repository_head_detached_for_worktree@Base 1.5.0
+ git_repository_head_for_worktree@Base 1.5.0
+ git_repository_head_unborn@Base 1.5.0
+ git_repository_ident@Base 1.5.0
+ git_repository_index@Base 1.5.0
+ git_repository_init@Base 1.5.0
+ git_repository_init_ext@Base 1.5.0
+ git_repository_init_init_options@Base 1.5.0
+ git_repository_init_options_init@Base 1.5.0
+ git_repository_is_bare@Base 1.5.0
+ git_repository_is_empty@Base 1.5.0
+ git_repository_is_shallow@Base 1.5.0
+ git_repository_is_worktree@Base 1.5.0
+ git_repository_item_path@Base 1.5.0
+ git_repository_mergehead_foreach@Base 1.5.0
+ git_repository_message@Base 1.5.0
+ git_repository_message_remove@Base 1.5.0
+ git_repository_new@Base 1.5.0
+ git_repository_odb@Base 1.5.0
+ git_repository_open@Base 1.5.0
+ git_repository_open_bare@Base 1.5.0
+ git_repository_open_ext@Base 1.5.0
+ git_repository_open_from_worktree@Base 1.5.0
+ git_repository_path@Base 1.5.0
+ git_repository_refdb@Base 1.5.0
+ git_repository_reinit_filesystem@Base 1.5.0
+ git_repository_set_bare@Base 1.5.0
+ git_repository_set_config@Base 1.5.0
+ git_repository_set_head@Base 1.5.0
+ git_repository_set_head_detached@Base 1.5.0
+ git_repository_set_head_detached_from_annotated@Base 1.5.0
+ git_repository_set_ident@Base 1.5.0
+ git_repository_set_index@Base 1.5.0
+ git_repository_set_namespace@Base 1.5.0
+ git_repository_set_odb@Base 1.5.0
+ git_repository_set_refdb@Base 1.5.0
+ git_repository_set_workdir@Base 1.5.0
+ git_repository_state@Base 1.5.0
+ git_repository_state_cleanup@Base 1.5.0
+ git_repository_submodule_cache_all@Base 1.5.0
+ git_repository_submodule_cache_clear@Base 1.5.0
+ git_repository_workdir@Base 1.5.0
+ git_repository_wrap_odb@Base 1.5.0
+ git_reset@Base 1.5.0
+ git_reset_default@Base 1.5.0
+ git_reset_from_annotated@Base 1.5.0
+ git_revert@Base 1.5.0
+ git_revert_commit@Base 1.5.0
+ git_revert_init_options@Base 1.5.0
+ git_revert_options_init@Base 1.5.0
+ git_revparse@Base 1.5.0
+ git_revparse_ext@Base 1.5.0
+ git_revparse_single@Base 1.5.0
+ git_revwalk_add_hide_cb@Base 1.5.0
+ git_revwalk_free@Base 1.5.0
+ git_revwalk_hide@Base 1.5.0
+ git_revwalk_hide_glob@Base 1.5.0
+ git_revwalk_hide_head@Base 1.5.0
+ git_revwalk_hide_ref@Base 1.5.0
+ git_revwalk_new@Base 1.5.0
+ git_revwalk_next@Base 1.5.0
+ git_revwalk_push@Base 1.5.0
+ git_revwalk_push_glob@Base 1.5.0
+ git_revwalk_push_head@Base 1.5.0
+ git_revwalk_push_range@Base 1.5.0
+ git_revwalk_push_ref@Base 1.5.0
+ git_revwalk_repository@Base 1.5.0
+ git_revwalk_reset@Base 1.5.0
+ git_revwalk_simplify_first_parent@Base 1.5.0
+ git_revwalk_sorting@Base 1.5.0
+ git_signature_default@Base 1.5.0
+ git_signature_dup@Base 1.5.0
+ git_signature_free@Base 1.5.0
+ git_signature_from_buffer@Base 1.5.0
+ git_signature_new@Base 1.5.0
+ git_signature_now@Base 1.5.0
+ git_smart_subtransport_git@Base 1.5.0
+ git_smart_subtransport_http@Base 1.5.0
+ git_smart_subtransport_ssh@Base 1.5.0
+ git_stash_apply@Base 1.5.0
+ git_stash_apply_init_options@Base 1.5.0
+ git_stash_apply_options_init@Base 1.5.0
+ git_stash_drop@Base 1.5.0
+ git_stash_foreach@Base 1.5.0
+ git_stash_pop@Base 1.5.0
+ git_stash_save@Base 1.5.0
+ git_status_byindex@Base 1.5.0
+ git_status_file@Base 1.5.0
+ git_status_foreach@Base 1.5.0
+ git_status_foreach_ext@Base 1.5.0
+ git_status_init_options@Base 1.5.0
+ git_status_list_entrycount@Base 1.5.0
+ git_status_list_free@Base 1.5.0
+ git_status_list_get_perfdata@Base 1.5.0
+ git_status_list_new@Base 1.5.0
+ git_status_options_init@Base 1.5.0
+ git_status_should_ignore@Base 1.5.0
+ git_strarray_copy@Base 1.5.0
+ git_strarray_dispose@Base 1.5.0
+ git_strarray_free@Base 1.5.0
+ git_stream_register@Base 1.5.0
+ git_stream_register_tls@Base 1.5.0
+ git_submodule_add_finalize@Base 1.5.0
+ git_submodule_add_setup@Base 1.5.0
+ git_submodule_add_to_index@Base 1.5.0
+ git_submodule_branch@Base 1.5.0
+ git_submodule_clone@Base 1.5.0
+ git_submodule_dup@Base 1.5.0
+ git_submodule_fetch_recurse_submodules@Base 1.5.0
+ git_submodule_foreach@Base 1.5.0
+ git_submodule_free@Base 1.5.0
+ git_submodule_head_id@Base 1.5.0
+ git_submodule_ignore@Base 1.5.0
+ git_submodule_index_id@Base 1.5.0
+ git_submodule_init@Base 1.5.0
+ git_submodule_location@Base 1.5.0
+ git_submodule_lookup@Base 1.5.0
+ git_submodule_name@Base 1.5.0
+ git_submodule_open@Base 1.5.0
+ git_submodule_owner@Base 1.5.0
+ git_submodule_path@Base 1.5.0
+ git_submodule_reload@Base 1.5.0
+ git_submodule_repo_init@Base 1.5.0
+ git_submodule_resolve_url@Base 1.5.0
+ git_submodule_set_branch@Base 1.5.0
+ git_submodule_set_fetch_recurse_submodules@Base 1.5.0
+ git_submodule_set_ignore@Base 1.5.0
+ git_submodule_set_update@Base 1.5.0
+ git_submodule_set_url@Base 1.5.0
+ git_submodule_status@Base 1.5.0
+ git_submodule_sync@Base 1.5.0
+ git_submodule_update@Base 1.5.0
+ git_submodule_update_init_options@Base 1.5.0
+ git_submodule_update_options_init@Base 1.5.0
+ git_submodule_update_strategy@Base 1.5.0
+ git_submodule_url@Base 1.5.0
+ git_submodule_wd_id@Base 1.5.0
+ git_tag_annotation_create@Base 1.5.0
+ git_tag_create@Base 1.5.0
+ git_tag_create_from_buffer@Base 1.5.0
+ git_tag_create_frombuffer@Base 1.5.0
+ git_tag_create_lightweight@Base 1.5.0
+ git_tag_delete@Base 1.5.0
+ git_tag_dup@Base 1.5.0
+ git_tag_foreach@Base 1.5.0
+ git_tag_free@Base 1.5.0
+ git_tag_id@Base 1.5.0
+ git_tag_list@Base 1.5.0
+ git_tag_list_match@Base 1.5.0
+ git_tag_lookup@Base 1.5.0
+ git_tag_lookup_prefix@Base 1.5.0
+ git_tag_message@Base 1.5.0
+ git_tag_name@Base 1.5.0
+ git_tag_name_is_valid@Base 1.5.0
+ git_tag_owner@Base 1.5.0
+ git_tag_peel@Base 1.5.0
+ git_tag_tagger@Base 1.5.0
+ git_tag_target@Base 1.5.0
+ git_tag_target_id@Base 1.5.0
+ git_tag_target_type@Base 1.5.0
+ git_trace_set@Base 1.5.0
+ git_transaction_commit@Base 1.5.0
+ git_transaction_free@Base 1.5.0
+ git_transaction_lock_ref@Base 1.5.0
+ git_transaction_new@Base 1.5.0
+ git_transaction_remove@Base 1.5.0
+ git_transaction_set_reflog@Base 1.5.0
+ git_transaction_set_symbolic_target@Base 1.5.0
+ git_transaction_set_target@Base 1.5.0
+ git_transport_init@Base 1.5.0
+ git_transport_local@Base 1.5.0
+ git_transport_new@Base 1.5.0
+ git_transport_register@Base 1.5.0
+ git_transport_remote_connect_options@Base 1.5.0
+ git_transport_smart@Base 1.5.0
+ git_transport_smart_certificate_check@Base 1.5.0
+ git_transport_smart_credentials@Base 1.5.0
+ git_transport_ssh_with_paths@Base 1.5.0
+ git_transport_unregister@Base 1.5.0
+ git_tree_create_updated@Base 1.5.0
+ git_tree_dup@Base 1.5.0
+ git_tree_entry_byid@Base 1.5.0
+ git_tree_entry_byindex@Base 1.5.0
+ git_tree_entry_byname@Base 1.5.0
+ git_tree_entry_bypath@Base 1.5.0
+ git_tree_entry_cmp@Base 1.5.0
+ git_tree_entry_dup@Base 1.5.0
+ git_tree_entry_filemode@Base 1.5.0
+ git_tree_entry_filemode_raw@Base 1.5.0
+ git_tree_entry_free@Base 1.5.0
+ git_tree_entry_id@Base 1.5.0
+ git_tree_entry_name@Base 1.5.0
+ git_tree_entry_to_object@Base 1.5.0
+ git_tree_entry_type@Base 1.5.0
+ git_tree_entrycount@Base 1.5.0
+ git_tree_free@Base 1.5.0
+ git_tree_id@Base 1.5.0
+ git_tree_lookup@Base 1.5.0
+ git_tree_lookup_prefix@Base 1.5.0
+ git_tree_owner@Base 1.5.0
+ git_tree_walk@Base 1.5.0
+ git_treebuilder_clear@Base 1.5.0
+ git_treebuilder_entrycount@Base 1.5.0
+ git_treebuilder_filter@Base 1.5.0
+ git_treebuilder_free@Base 1.5.0
+ git_treebuilder_get@Base 1.5.0
+ git_treebuilder_insert@Base 1.5.0
+ git_treebuilder_new@Base 1.5.0
+ git_treebuilder_remove@Base 1.5.0
+ git_treebuilder_write@Base 1.5.0
+ git_treebuilder_write_with_buffer@Base 1.5.0
+ git_worktree_add@Base 1.5.0
+ git_worktree_add_init_options@Base 1.5.0
+ git_worktree_add_options_init@Base 1.5.0
+ git_worktree_free@Base 1.5.0
+ git_worktree_is_locked@Base 1.5.0
+ git_worktree_is_prunable@Base 1.5.0
+ git_worktree_list@Base 1.5.0
+ git_worktree_lock@Base 1.5.0
+ git_worktree_lookup@Base 1.5.0
+ git_worktree_name@Base 1.5.0
+ git_worktree_open_from_repository@Base 1.5.0
+ git_worktree_path@Base 1.5.0
+ git_worktree_prune@Base 1.5.0
+ git_worktree_prune_init_options@Base 1.5.0
+ git_worktree_prune_options_init@Base 1.5.0
+ git_worktree_unlock@Base 1.5.0
+ git_worktree_validate@Base 1.5.0
+ giterr_clear@Base 1.5.0
+ giterr_last@Base 1.5.0
+ giterr_set_oom@Base 1.5.0
+ giterr_set_str@Base 1.5.0
diff --git a/debian/libgit2-fixtures.lintian-overrides b/debian/libgit2-fixtures.lintian-overrides
new file mode 100644
index 000000000..24bd4fbcd
--- /dev/null
+++ b/debian/libgit2-fixtures.lintian-overrides
@@ -0,0 +1,2 @@
+libgit2-fixtures: executable-not-elf-or-script [usr/share/doc/libgit2-fixtures/examples/*]
+libgit2-fixtures: package-contains-vcs-control-file [usr/share/doc/libgit2-fixtures/examples/*]
diff --git a/debian/patches/disable-flaky-stat-tests.patch b/debian/patches/disable-flaky-stat-tests.patch
new file mode 100644
index 000000000..0923b5c1e
--- /dev/null
+++ b/debian/patches/disable-flaky-stat-tests.patch
@@ -0,0 +1,132 @@
+From: =?utf-8?q?Timo_R=C3=B6hling?=
+Date: Wed, 31 Aug 2022 15:24:06 +0200
+Subject: Ignore test failures because of stat()
+
+---
+ tests/libgit2/repo/init.c | 14 ++++++++------
+ tests/libgit2/repo/template.c | 19 +++++++++++--------
+ tests/util/copy.c | 12 ++++++++----
+ tests/util/mkdir.c | 2 ++
+ 4 files changed, 29 insertions(+), 18 deletions(-)
+
+diff --git a/tests/libgit2/repo/init.c b/tests/libgit2/repo/init.c
+index 7cf6742..aec1ec6 100644
+--- a/tests/libgit2/repo/init.c
++++ b/tests/libgit2/repo/init.c
+@@ -424,12 +424,14 @@ void test_repo_init__extended_1(void)
+ cl_assert(!git_repository_is_empty(g_repo));
+
+ cl_git_pass(git_fs_path_lstat(git_repository_path(g_repo), &st));
+- cl_assert(S_ISDIR(st.st_mode));
+- if (cl_is_chmod_supported())
+- cl_assert((S_ISGID & st.st_mode) == S_ISGID);
+- else
+- cl_assert((S_ISGID & st.st_mode) == 0);
+-
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ {
++ cl_assert(S_ISDIR(st.st_mode));
++ if (cl_is_chmod_supported())
++ cl_assert((S_ISGID & st.st_mode) == S_ISGID);
++ else
++ cl_assert((S_ISGID & st.st_mode) == 0);
++ }
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD"));
+ cl_assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC);
+ cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref));
+diff --git a/tests/libgit2/repo/template.c b/tests/libgit2/repo/template.c
+index e8fe266..f771f4e 100644
+--- a/tests/libgit2/repo/template.c
++++ b/tests/libgit2/repo/template.c
+@@ -72,8 +72,8 @@ static void assert_hooks_match(
+ CLEAR_FOR_CORE_FILEMODE(expected_mode);
+ CLEAR_FOR_CORE_FILEMODE(st.st_mode);
+ }
+-
+- cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
+ }
+
+ git_str_dispose(&expected);
+@@ -97,14 +97,17 @@ static void assert_mode_seems_okay(
+ expect_setgid = false;
+ }
+
+- if (S_ISGID != 0)
+- cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0);
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ {
++ if (S_ISGID != 0)
++ cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0);
+
+- cl_assert_equal_b(
+- GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode));
++ cl_assert_equal_b(
++ GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode));
+
+- cl_assert_equal_i_fmt(
+- GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o");
++ cl_assert_equal_i_fmt(
++ GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o");
++ }
+ }
+
+ static void setup_repo(const char *name, git_repository_init_options *opts)
+diff --git a/tests/util/copy.c b/tests/util/copy.c
+index 2613730..1b74f0d 100644
+--- a/tests/util/copy.c
++++ b/tests/util/copy.c
+@@ -12,7 +12,8 @@ void test_copy__file(void)
+ cl_git_pass(git_futils_cp("copy_me", "copy_me_two", 0664));
+
+ cl_git_pass(git_fs_path_lstat("copy_me_two", &st));
+- cl_assert(S_ISREG(st.st_mode));
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ cl_assert(S_ISREG(st.st_mode));
+
+ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
+ cl_assert_equal_sz(strlen(content), (size_t)st.st_size);
+@@ -39,7 +40,8 @@ void test_copy__file_in_dir(void)
+ 0664));
+
+ cl_git_pass(git_fs_path_lstat("an_dir/second_dir/and_more/copy_me_two", &st));
+- cl_assert(S_ISREG(st.st_mode));
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ cl_assert(S_ISREG(st.st_mode));
+
+ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
+ cl_assert_equal_sz(strlen(content), (size_t)st.st_size);
+@@ -103,7 +105,8 @@ void test_copy__tree(void)
+
+ memset(&st, 0, sizeof(struct stat));
+ cl_git_pass(git_fs_path_lstat("t1/c/f3", &st));
+- cl_assert(S_ISREG(st.st_mode));
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ cl_assert(S_ISREG(st.st_mode));
+
+ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
+ cl_assert_equal_sz(strlen(content), (size_t)st.st_size);
+@@ -111,7 +114,8 @@ void test_copy__tree(void)
+ #ifndef GIT_WIN32
+ memset(&st, 0, sizeof(struct stat));
+ cl_git_pass(git_fs_path_lstat("t1/c/d/l1", &st));
+- cl_assert(S_ISLNK(st.st_mode));
++ if (!cl_is_env_set("GITTEST_FLAKY_STAT"))
++ cl_assert(S_ISLNK(st.st_mode));
+ #endif
+
+ cl_git_pass(git_futils_rmdir_r("t1", NULL, GIT_RMDIR_REMOVE_FILES));
+diff --git a/tests/util/mkdir.c b/tests/util/mkdir.c
+index 8658eec..1c944e7 100644
+--- a/tests/util/mkdir.c
++++ b/tests/util/mkdir.c
+@@ -160,6 +160,8 @@ static void check_mode_at_line(
+ expected &= 0600;
+ actual &= 0600;
+ }
++ if (cl_is_env_set("GITTEST_FLAKY_STAT"))
++ return;
+
+ clar__assert_equal(
+ file, func, line, "expected_mode != actual_mode", 1,
diff --git a/debian/patches/disable-online-tests.patch b/debian/patches/disable-online-tests.patch
index 273cc6e60..e513af1ab 100644
--- a/debian/patches/disable-online-tests.patch
+++ b/debian/patches/disable-online-tests.patch
@@ -1,28 +1,33 @@
-Skip tests that needs an active internet connection
+From: Utkarsh Gupta
+Date: Sun, 28 Aug 2022 17:12:49 +0200
+Subject: disable-online-tests
---- a/tests/CMakeLists.txt
-+++ b/tests/CMakeLists.txt
-@@ -68,15 +68,15 @@
- endif()
- endfunction(ADD_CLAR_TEST)
-
--add_clar_test(offline -v -xonline)
-+#add_clar_test(offline -v -xonline)
- add_clar_test(invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
--add_clar_test(online -v -sonline -xonline::customcert)
--add_clar_test(online_customcert -v -sonline::customcert)
--add_clar_test(gitdaemon -v -sonline::push)
--add_clar_test(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
--add_clar_test(proxy -v -sonline::clone::proxy)
--add_clar_test(auth_clone -v -sonline::clone::cred)
--add_clar_test(auth_clone_and_push -v -sonline::clone::push -sonline::push)
-+#add_clar_test(online -v -sonline -xonline::customcert)
-+#add_clar_test(online_customcert -v -sonline::customcert)
-+#add_clar_test(gitdaemon -v -sonline::push)
-+#add_clar_test(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
-+#add_clar_test(proxy -v -sonline::clone::proxy)
-+#add_clar_test(auth_clone -v -sonline::clone::cred)
-+#add_clar_test(auth_clone_and_push -v -sonline::clone::push -sonline::push)
-
- #
- # Header file validation project: ensure that we do not publish any sloppy
+Skip tests that needs an active internet connection
+---
+ tests/libgit2/CMakeLists.txt | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/tests/libgit2/CMakeLists.txt b/tests/libgit2/CMakeLists.txt
+index 27f421a..213076f 100644
+--- a/tests/libgit2/CMakeLists.txt
++++ b/tests/libgit2/CMakeLists.txt
+@@ -66,10 +66,12 @@ endif()
+ include(AddClarTest)
+ add_clar_test(libgit2_tests offline -v -xonline)
+ add_clar_test(libgit2_tests invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
+-add_clar_test(libgit2_tests online -v -sonline -xonline::customcert)
+-add_clar_test(libgit2_tests online_customcert -v -sonline::customcert)
+-add_clar_test(libgit2_tests gitdaemon -v -sonline::push)
+-add_clar_test(libgit2_tests ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
+-add_clar_test(libgit2_tests proxy -v -sonline::clone::proxy)
+-add_clar_test(libgit2_tests auth_clone -v -sonline::clone::cred)
+-add_clar_test(libgit2_tests auth_clone_and_push -v -sonline::clone::push -sonline::push)
++if(NOT DISABLE_ONLINE_TESTS)
++ add_clar_test(libgit2_tests online -v -sonline -xonline::customcert)
++ add_clar_test(libgit2_tests online_customcert -v -sonline::customcert)
++ add_clar_test(libgit2_tests gitdaemon -v -sonline::push)
++ add_clar_test(libgit2_tests ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
++ add_clar_test(libgit2_tests proxy -v -sonline::clone::proxy)
++ add_clar_test(libgit2_tests auth_clone -v -sonline::clone::cred)
++ add_clar_test(libgit2_tests auth_clone_and_push -v -sonline::clone::push -sonline::push)
++endif()
diff --git a/debian/patches/enable-repro-builds.patch b/debian/patches/enable-repro-builds.patch
deleted file mode 100644
index cbac4bdc9..000000000
--- a/debian/patches/enable-repro-builds.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-Description: Enable reproducible builds by default.
-Author: Utkarsh Gupta
-
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -54,7 +54,7 @@
- option(USE_NTLMCLIENT "Enable NTLM support on Unix." ON)
- endif()
-
-- option(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF)
-+ option(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" ON)
- endif()
-
- if(APPLE)
diff --git a/debian/patches/fix-unit-tests.patch b/debian/patches/fix-unit-tests.patch
new file mode 100644
index 000000000..35f45fc17
--- /dev/null
+++ b/debian/patches/fix-unit-tests.patch
@@ -0,0 +1,135 @@
+From: =?utf-8?q?Timo_R=C3=B6hling?=
+Date: Sun, 28 Aug 2022 17:20:01 +0200
+Subject: Fix unit tests
+
+---
+ tests/libgit2/CMakeLists.txt | 2 +-
+ tests/libgit2/network/url/parse.c | 67 ++++-----------------------------------
+ 2 files changed, 7 insertions(+), 62 deletions(-)
+
+diff --git a/tests/libgit2/CMakeLists.txt b/tests/libgit2/CMakeLists.txt
+index 213076f..9a56bd7 100644
+--- a/tests/libgit2/CMakeLists.txt
++++ b/tests/libgit2/CMakeLists.txt
+@@ -65,7 +65,7 @@ endif()
+
+ include(AddClarTest)
+ add_clar_test(libgit2_tests offline -v -xonline)
+-add_clar_test(libgit2_tests invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
++add_clar_test(libgit2_tests invasive -v -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
+ if(NOT DISABLE_ONLINE_TESTS)
+ add_clar_test(libgit2_tests online -v -sonline -xonline::customcert)
+ add_clar_test(libgit2_tests online_customcert -v -sonline::customcert)
+diff --git a/tests/libgit2/network/url/parse.c b/tests/libgit2/network/url/parse.c
+index 8149ba5..729302e 100644
+--- a/tests/libgit2/network/url/parse.c
++++ b/tests/libgit2/network/url/parse.c
+@@ -65,14 +65,7 @@ void test_network_url_parse__hostname_implied_root_custom_port(void)
+
+ void test_network_url_parse__hostname_implied_root_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://example.com:"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "example.com");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://example.com:"));
+ }
+
+ void test_network_url_parse__hostname_encoded_password(void)
+@@ -131,14 +124,7 @@ void test_network_url_parse__hostname_port(void)
+
+ void test_network_url_parse__hostname_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "example.com");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/resource");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://example.com:/resource"));
+ }
+
+ void test_network_url_parse__hostname_user_port(void)
+@@ -221,14 +207,7 @@ void test_network_url_parse__ipv4_implied_root_custom_port(void)
+
+ void test_network_url_parse__ipv4_implied_root_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "192.168.1.1");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://192.168.1.1:"));
+ }
+
+ void test_network_url_parse__ipv4_encoded_password(void)
+@@ -285,14 +264,7 @@ void test_network_url_parse__ipv4_port(void)
+
+ void test_network_url_parse__ipv4_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:/resource"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "192.168.1.1");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/resource");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://192.168.1.1:/resource"));
+ }
+
+ void test_network_url_parse__ipv4_user_port(void)
+@@ -373,27 +345,7 @@ void test_network_url_parse__ipv6_implied_root_custom_port(void)
+
+ void test_network_url_parse__ipv6_implied_root_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+-}
+-
+-void test_network_url_parse__ipv6_encoded_password(void)
+-{
+- cl_git_pass(git_net_url_parse(&conndata,
+- "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/"));
+- cl_assert_equal_s(conndata.scheme, "https");
+- cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+- cl_assert_equal_s(conndata.port, "1234");
+- cl_assert_equal_s(conndata.path, "/");
+- cl_assert_equal_s(conndata.username, "user");
+- cl_assert_equal_s(conndata.password, "pass/is@bad");
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:"));
+ }
+
+ void test_network_url_parse__ipv6_user(void)
+@@ -437,14 +389,7 @@ void test_network_url_parse__ipv6_port(void)
+
+ void test_network_url_parse__ipv6_empty_port(void)
+ {
+- cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource"));
+- cl_assert_equal_s(conndata.scheme, "http");
+- cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+- cl_assert_equal_s(conndata.port, "80");
+- cl_assert_equal_s(conndata.path, "/resource");
+- cl_assert_equal_p(conndata.username, NULL);
+- cl_assert_equal_p(conndata.password, NULL);
+- cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
++ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource"));
+ }
+
+ void test_network_url_parse__ipv6_user_port(void)
diff --git a/debian/patches/handle-bashism.patch b/debian/patches/handle-bashism.patch
new file mode 100644
index 000000000..8b7ced027
--- /dev/null
+++ b/debian/patches/handle-bashism.patch
@@ -0,0 +1,18 @@
+From: =?utf-8?q?Timo_R=C3=B6hling?=
+Date: Sun, 28 Aug 2022 17:42:55 +0200
+Subject: Use bash for shell script with bashisms
+
+---
+ tests/resources/push.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/resources/push.sh b/tests/resources/push.sh
+index 3e77fb5..54ef3dd 100644
+--- a/tests/resources/push.sh
++++ b/tests/resources/push.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/bin/bash
+ #creates push_src repo for libgit2 push tests.
+ set -eu
+
diff --git a/debian/patches/series b/debian/patches/series
index 17ca6dffb..06fdaee68 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,4 @@
disable-online-tests.patch
-enable-repro-builds.patch
+fix-unit-tests.patch
+handle-bashism.patch
+disable-flaky-stat-tests.patch
diff --git a/debian/rules b/debian/rules
index f2ebe3158..d28ff4865 100755
--- a/debian/rules
+++ b/debian/rules
@@ -2,70 +2,52 @@
# -*- makefile -*-
# This rules file has 2 streams, the build-debian-devel stream builds
-# the static library and the bulid-debian-release builds the dynamic
+# the static library and the build-debian-release builds the dynamic
# library.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
-DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
-TEST_TMPDIR := $(CURDIR)/tmp-test
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
-DPKG_EXPORT_BUILDFLAGS = 1
-include /usr/share/dpkg/buildflags.mk
-override_dh_auto_configure:
- dh_auto_configure --builddirectory=build-debian-release -- \
- -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \
- -DUSE_OPENSSL:BOOL=OFF \
- -DUSE_HTTPS=mbedTLS \
- -DUSE_SSH=ON \
- -DCERT_LOCATION=/etc/ssl/certs/ca-certificates.crt \
- -DUSE_CURL_SSL:BOOL=ON \
- -DUSE_GSSAPI:BOOL=ON \
- -DTHREADSAFE:BOOL=ON \
- -DBUILD_CLAR:BOOL=ON \
- -DUSE_NTLMCLIENT=OFF \
- -DENABLE_REPRODUCIBLE_BUILDS=ON \
- -DUSE_HTTP_PARSER=system \
- -DLIB_INSTALL_DIR:STRING=lib/$(DEB_HOST_MULTIARCH)
-
- dh_auto_configure --builddirectory=build-debian-devel -- \
- -DCMAKE_BUILD_TYPE:STRING=Release \
- -DTHREADSAFE:BOOL=ON \
- -DUSE_HTTPS=mbedTLS \
- -DUSE_SSH=ON \
- -DCERT_LOCATION=/etc/ssl/certs/ca-certificates.crt \
- -DUSE_CURL_SSL:BOOL=ON \
- -DUSE_GSSAPI:BOOL=ON \
- -DBUILD_CLAR:BOOL=OFF \
- -DBUILD_SHARED_LIBS:BOOL=OFF \
- -DUSE_NTLMCLIENT=OFF \
- -DENABLE_REPRODUCIBLE_BUILDS=ON \
- -DUSE_HTTP_PARSER=system \
- -DLIB_INSTALL_DIR:STRING=lib/$(DEB_HOST_MULTIARCH)
+BUILD_TESTS = $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),OFF,ON)
+COMMON_CMAKE_FLAGS = \
+ -DBUILD_CLI=OFF \
+ -DBUILD_TESTS=$(BUILD_TESTS) \
+ -DCERT_LOCATION=/etc/ssl/certs/ca-certificates.crt \
+ -DDISABLE_ONLINE_TESTS=ON \
+ -DENABLE_REPRODUCIBLE_BUILDS=ON \
+ -DREGEX_BACKEND=pcre2 \
+ -DUSE_GSSAPI=ON \
+ -DUSE_HTTPS=mbedTLS \
+ -DUSE_HTTP_PARSER=system \
+ -DUSE_NTLMCLIENT=OFF \
+ -DUSE_SSH=ON
-override_dh_makeshlibs:
- dh_makeshlibs -V
-
-override_dh_auto_build:
- dh_auto_build --builddirectory=build-debian-release
- dh_auto_build --builddirectory=build-debian-devel
-
-override_dh_auto_install:
- dh_auto_install --builddirectory=build-debian-release
- dh_auto_install --builddirectory=build-debian-devel
-
-override_dh_auto_test:
- mkdir -p build-debian-release/tmp
- dh_auto_test --builddirectory=build-debian-release
- mkdir -p build-debian-devel/tmp
- dh_auto_test --builddirectory=build-debian-devel
-
-override_dh_installexamples:
- dh_installexamples --exclude .gitignore
+# The stat() in the Git fs layer has some issues
+export GITTEST_FLAKY_STAT = true
%:
- dh $@ --buildsystem cmake --dbgsym-migration='libgit2-dbg (<< 0.26.0+dfsg.1-1~)' --builddirectory=build-debian-release
- dh $@ --buildsystem cmake --builddirectory=build-debian-devel
+ dh $@ --buildsystem=cmake
+
+override_dh_auto_configure:
+ dh_auto_configure --builddirectory=build-debian-devel -- \
+ -DBUILD_SHARED_LIBS=OFF \
+ $(COMMON_CMAKE_FLAGS)
+ dh_auto_configure --builddirectory=build-debian-release -- \
+ -DBUILD_SHARED_LIBS=ON \
+ $(COMMON_CMAKE_FLAGS)
+
+override_dh_auto_build:
+ dh_auto_build --builddirectory=build-debian-devel
+ dh_auto_build --builddirectory=build-debian-release
+
+override_dh_auto_install:
+ dh_auto_install --builddirectory=build-debian-devel
+ dh_auto_install --builddirectory=build-debian-release
+
+override_dh_auto_test:
+ dh_auto_test --builddirectory=build-debian-devel
+ dh_auto_test --builddirectory=build-debian-release
+
diff --git a/debian/watch b/debian/watch
index 9e850b32d..65b8013d8 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,5 @@
-version=3
-opts=compression=xz,repack,filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/libgit2-$1\.tar\.gz/,dversionmangle=s/\+dfsg\d*$//,repacksuffix=+dfsg.1 \
- https://github.com/libgit2/libgit2/releases .*/v?([\d.]*)\.tar\.gz
+version=4
+opts=filenamemangle=s%(?:.*?)?v?(\d[\d.]*@ARCHIVE_EXT@)%@PACKAGE@-$1%,\
+ repack,dversionmangle=auto,repacksuffix=+ds \
+ https://github.com/libgit2/libgit2/tags (?:.*?/)?v?@ANY_VERSION@@ARCHIVE_EXT@
+
diff --git a/docs/changelog.md b/docs/changelog.md
index 32a67d2c7..989800a11 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,39 +1,79 @@
-v1.4.3
-------
+v1.5
+----
-🔒 This is a security release to provide compatibility with git's changes to address [CVE 2022-24765](https://github.blog/2022-04-12-git-security-vulnerability-announced/).
-
-**libgit2 is not directly affected** by this vulnerability, because libgit2 does not directly invoke any executable. But we are providing these changes as a security release for any users that use libgit2 for repository discovery and then _also_ use git on that repository. In this release, we will now validate that the user opening the repository is the same user that owns the on-disk repository. This is to match git's behavior.
-
-In addition, we are providing several correctness fixes where invalid input can lead to a crash. These may prevent possible denial of service attacks. At this time there are not known exploits to these issues.
-
-Full list of changes:
-
-* Validate repository directory ownership (v1.4) by @ethomson in https://github.com/libgit2/libgit2/pull/6267
-* midx: Fix an undefined behavior (left-shift signed overflow) by @lhchavez in https://github.com/libgit2/libgit2/pull/6260
-* fetch: support OID refspec without dst by @ethomson in https://github.com/libgit2/libgit2/pull/6251
-* Fix crash when regenerating a patch with unquoted spaces in filename by @jorio in https://github.com/libgit2/libgit2/pull/6244
-
-All users of the v1.4 release line are recommended to upgrade.
-
-**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.4.2...v1.4.3
-
-v1.4.2
-------
-
-This is a bugfix release with the following changes:
+This is release v1.5.0, "Stubentiger". This release adds the basis for an experimental CLI, continues preparing for SHA256 support, adds a benchmarking utility, and has numerous new features and bugfixes.
+## What's Changed
+### New features
+* The beginnings of a git-compatible CLI for testing and benchmarking by @ethomson in https://github.com/libgit2/libgit2/pull/6133
+* Add `clone` support to the CLI @ethomson in https://github.com/libgit2/libgit2/pull/6274
+* A benchmarking suite to compare libgit2 functionality against git by @ethomson in https://github.com/libgit2/libgit2/pull/6235
+* SHA256: add a SHA256 implementation backend by @ethomson in https://github.com/libgit2/libgit2/pull/6144
+* SHA256: support dynamically loaded openssl by @ethomson in https://github.com/libgit2/libgit2/pull/6258
+* Transport: introduce `git_transport_smart_remote_connect_options` by @lhchavez in https://github.com/libgit2/libgit2/pull/6278
+### Bug fixes
+* Free parent and ref in lg2_commit before returning. by @apnadkarni in https://github.com/libgit2/libgit2/pull/6219
+* xdiff: use xdl_free not free by @ethomson in https://github.com/libgit2/libgit2/pull/6223
* remote: do store the update_tips callback error value by @carlosmn in https://github.com/libgit2/libgit2/pull/6226
* win32: `find_system_dirs` does not return `GIT_ENOTFOUND` by @ethomson in https://github.com/libgit2/libgit2/pull/6228
+* Some minor fixes for issues discovered by coverity by @ethomson in https://github.com/libgit2/libgit2/pull/6238
+* Fix a string concatenation bug when validating extensions by @bierbaum in https://github.com/libgit2/libgit2/pull/6246
+* fetch: support OID refspec without dst by @ethomson in https://github.com/libgit2/libgit2/pull/6251
+* Fix crash when regenerating a patch with unquoted spaces in filename by @jorio in https://github.com/libgit2/libgit2/pull/6244
+* midx: Fix an undefined behavior (left-shift signed overflow) by @lhchavez in https://github.com/libgit2/libgit2/pull/6260
+* Validate repository directory ownership by @ethomson in https://github.com/libgit2/libgit2/pull/6266
+* midx: fix large offset table check. by @ccstolley in https://github.com/libgit2/libgit2/pull/6309
+* midx: do not verify the checksum on load by @carlosmn in https://github.com/libgit2/libgit2/pull/6291
+* revparse: Remove error-prone, redundant test by @dongcarl in https://github.com/libgit2/libgit2/pull/6299
+* refs: fix missing error message by @zawata in https://github.com/libgit2/libgit2/pull/6305
+* CLI: progress updates by @ethomson in https://github.com/libgit2/libgit2/pull/6319
+* A couple of simplications around mwindow by @carlosmn in https://github.com/libgit2/libgit2/pull/6288
+* config: update config entry iteration lifecycle by @ethomson in https://github.com/libgit2/libgit2/pull/6320
+* repo: allow administrator to own the configuration by @ethomson in https://github.com/libgit2/libgit2/pull/6321
+* filter: Fix Segfault by @zawata in https://github.com/libgit2/libgit2/pull/6303
+* ntlmclient: LibreSSL 3.5 removed HMAC_CTX_cleanup by @vishwin in https://github.com/libgit2/libgit2/pull/6340
+* Fix internal git_sysdir_find* function usage within public git_config_find* functions by @kcsaul in https://github.com/libgit2/libgit2/pull/6335
+* fix interactive rebase detect. by @i-tengfei in https://github.com/libgit2/libgit2/pull/6334
+* cmake: drop posix dependency from pcre* detection by @jpalus in https://github.com/libgit2/libgit2/pull/6333
+* Fix erroneously lax configuration ownership checks by @ethomson in https://github.com/libgit2/libgit2/pull/6341
+* pack: don't pretend we support pack files v3 by @ethomson in https://github.com/libgit2/libgit2/pull/6347
+* Fix creation of branches and tags with invalid names by @lya001 in https://github.com/libgit2/libgit2/pull/6348
+### Security fixes
+* Fixes for CVE 2022-29187 by @ethomson in https://github.com/libgit2/libgit2/pull/6349
+* zlib: update bundled zlib to v1.2.12 by @ethomson in https://github.com/libgit2/libgit2/pull/6350
+### Code cleanups
+* sha256: refactoring in preparation for sha256 by @ethomson in https://github.com/libgit2/libgit2/pull/6265
+* remote: Delete a now-inexistent API declaration by @lhchavez in https://github.com/libgit2/libgit2/pull/6276
+* Fix missing include by @cschlack in https://github.com/libgit2/libgit2/pull/6277
+### Build and CI improvements
+* meta: show build status for v1.3 and v1.4 branches by @ethomson in https://github.com/libgit2/libgit2/pull/6216
+* cmake: Fix package name for system http-parser by @mgorny in https://github.com/libgit2/libgit2/pull/6217
+* meta: update version number to v1.5.0-alpha by @ethomson in https://github.com/libgit2/libgit2/pull/6220
+* cmake: export libraries needed to compile against libgit2 by @ethomson in https://github.com/libgit2/libgit2/pull/6239
+* clone: update bitbucket tests by @ethomson in https://github.com/libgit2/libgit2/pull/6252
+* diff: don't stat empty file on arm32 (flaky test) by @ethomson in https://github.com/libgit2/libgit2/pull/6259
+* tests: support flaky stat by @ethomson in https://github.com/libgit2/libgit2/pull/6262
+* Include test results data in CI by @ethomson in https://github.com/libgit2/libgit2/pull/6306
+* Add a .clang-format with our style by @ethomson in https://github.com/libgit2/libgit2/pull/6023
+* CI: limits actions scheduled workflows to the main repo by @ethomson in https://github.com/libgit2/libgit2/pull/6342
+* ci: update dockerfiles for mbedTLS new url by @ethomson in https://github.com/libgit2/libgit2/pull/6343
+### Documentation improvements
+* Add Pharo to language bindings by @theseion in https://github.com/libgit2/libgit2/pull/6310
+* Add link to Tcl bindings for libgit2 by @apnadkarni in https://github.com/libgit2/libgit2/pull/6318
+* fix couple of typos by @SkinnyMind in https://github.com/libgit2/libgit2/pull/6287
+* update documentation for default status options by @ethomson in https://github.com/libgit2/libgit2/pull/6322
-v1.4.1
-------
+## New Contributors
+* @bierbaum made their first contribution in https://github.com/libgit2/libgit2/pull/6246
+* @dongcarl made their first contribution in https://github.com/libgit2/libgit2/pull/6299
+* @SkinnyMind made their first contribution in https://github.com/libgit2/libgit2/pull/6287
+* @zawata made their first contribution in https://github.com/libgit2/libgit2/pull/6305
+* @vishwin made their first contribution in https://github.com/libgit2/libgit2/pull/6340
+* @i-tengfei made their first contribution in https://github.com/libgit2/libgit2/pull/6334
+* @jpalus made their first contribution in https://github.com/libgit2/libgit2/pull/6333
+* @lya001 made their first contribution in https://github.com/libgit2/libgit2/pull/6348
-This is a bugfix release with the following changes:
-
-* xdiff: use xdl_free not free by @ethomson
-* cmake: Fix package name for system http-parser by @mgorny
-* Free parent and ref in lg2_commit before returning by @apnadkarni
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.4.0...v1.5.0
v1.4
----
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 235e72ada..8e38c7d4e 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,3 +1,5 @@
+# examples: code usage examples of libgit2
+
file(GLOB SRC_EXAMPLES *.c *.h)
add_executable(lg2 ${SRC_EXAMPLES})
@@ -10,7 +12,7 @@ target_include_directories(lg2 PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_
target_include_directories(lg2 SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
if(WIN32 OR ANDROID)
- target_link_libraries(lg2 git2)
+ target_link_libraries(lg2 libgit2package)
else()
- target_link_libraries(lg2 git2 pthread)
+ target_link_libraries(lg2 libgit2package pthread)
endif()
diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt
index eaa490fd9..a2c19ed40 100644
--- a/fuzzers/CMakeLists.txt
+++ b/fuzzers/CMakeLists.txt
@@ -1,3 +1,5 @@
+# fuzzers: libFuzzer and standalone fuzzing utilities
+
if(BUILD_FUZZERS AND NOT USE_STANDALONE_FUZZERS)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link")
add_c_flag(-fsanitize=fuzzer)
diff --git a/fuzzers/packfile_fuzzer.c b/fuzzers/packfile_fuzzer.c
index 6002fa1de..23ecaf80f 100644
--- a/fuzzers/packfile_fuzzer.c
+++ b/fuzzers/packfile_fuzzer.c
@@ -94,7 +94,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
fprintf(stderr, "Failed to compute the SHA1 hash\n");
abort();
}
- if (git_indexer_append(indexer, &oid, sizeof(oid), &stats) < 0) {
+ if (git_indexer_append(indexer, &oid.id, GIT_OID_RAWSZ, &stats) < 0) {
goto cleanup;
}
}
diff --git a/include/git2/branch.h b/include/git2/branch.h
index 36a393d10..27c6fa157 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -129,8 +129,8 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
* See `git_tag_create()` for rules about valid names.
*
* Note that if the move succeeds, the old reference object will not
- + be valid anymore, and should be freed immediately by the user using
- + `git_reference_free()`.
+ * be valid anymore, and should be freed immediately by the user using
+ * `git_reference_free()`.
*
* @param out New reference object for the updated name.
*
diff --git a/include/git2/common.h b/include/git2/common.h
index b8c4ad531..c3e3e7b4e 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -121,6 +121,17 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_libgit2_version(int *major, int *minor, int *rev);
+/**
+ * Return the prerelease state of the libgit2 library currently being
+ * used. For nightly builds during active development, this will be
+ * "alpha". Releases may have a "beta" or release candidate ("rc1",
+ * "rc2", etc) prerelease. For a final release, this function returns
+ * NULL.
+ *
+ * @return the name of the prerelease state or NULL
+ */
+GIT_EXTERN(const char *) git_libgit2_prerelease(void);
+
/**
* Combinations of these values describe the features with which libgit2
* was compiled
diff --git a/include/git2/config.h b/include/git2/config.h
index a5486a4c9..cfab0c757 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -122,7 +122,7 @@ typedef struct {
* global configuration file.
*
* This method will not guess the path to the xdg compatible
- * config file (.config/git/config).
+ * config file (`.config/git/config`).
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a global configuration file has been found. Its path will be stored in `out`.
@@ -149,8 +149,8 @@ GIT_EXTERN(int) git_config_find_xdg(git_buf *out);
/**
* Locate the path to the system configuration file
*
- * If /etc/gitconfig doesn't exist, it will look for
- * %PROGRAMFILES%\Git\etc\gitconfig.
+ * If `/etc/gitconfig` doesn't exist, it will look for
+ * `%PROGRAMFILES%\Git\etc\gitconfig`.
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a system configuration file has been
@@ -161,7 +161,7 @@ GIT_EXTERN(int) git_config_find_system(git_buf *out);
/**
* Locate the path to the configuration file in ProgramData
*
- * Look for the file in %PROGRAMDATA%\Git\config used by portable git.
+ * Look for the file in `%PROGRAMDATA%\Git\config` used by portable git.
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a ProgramData configuration file has been
@@ -449,8 +449,8 @@ GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, cons
/**
* Return the current entry and advance the iterator
*
- * The pointers returned by this function are valid until the iterator
- * is freed.
+ * The pointers returned by this function are valid until the next call
+ * to `git_config_next` or until the iterator is freed.
*
* @param entry pointer to store the entry
* @param iter the iterator
diff --git a/include/git2/deprecated.h b/include/git2/deprecated.h
index f73d7da61..c32abeeb7 100644
--- a/include/git2/deprecated.h
+++ b/include/git2/deprecated.h
@@ -436,6 +436,8 @@ GIT_EXTERN(int) git_diff_format_email_options_init(
#define GITERR_WORKTREE GIT_ERROR_WORKTREE
#define GITERR_SHA1 GIT_ERROR_SHA1
+#define GIT_ERROR_SHA1 GIT_ERROR_SHA
+
/**
* Return the last `git_error` object that was generated for the
* current thread. This is an alias of `git_error_last` and is
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 16712f988..a61964bbb 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -107,7 +107,7 @@ typedef enum {
GIT_ERROR_FILESYSTEM,
GIT_ERROR_PATCH,
GIT_ERROR_WORKTREE,
- GIT_ERROR_SHA1,
+ GIT_ERROR_SHA,
GIT_ERROR_HTTP,
GIT_ERROR_INTERNAL
} git_error_t;
@@ -131,7 +131,8 @@ GIT_EXTERN(const git_error *) git_error_last(void);
GIT_EXTERN(void) git_error_clear(void);
/**
- * Set the error message string for this thread.
+ * Set the error message string for this thread, using `printf`-style
+ * formatting.
*
* This function is public so that custom ODB backends and the like can
* relay an error message through libgit2. Most regular users of libgit2
@@ -144,7 +145,20 @@ GIT_EXTERN(void) git_error_clear(void);
*
* @param error_class One of the `git_error_t` enum above describing the
* general subsystem that is responsible for the error.
- * @param string The formatted error message to keep
+ * @param fmt The `printf`-style format string; subsequent arguments must
+ * be the arguments for the format string.
+ */
+GIT_EXTERN(void) git_error_set(int error_class, const char *fmt, ...)
+ GIT_FORMAT_PRINTF(2, 3);
+
+/**
+ * Set the error message string for this thread. This function is like
+ * `git_error_set` but takes a static string instead of a `printf`-style
+ * format.
+ *
+ * @param error_class One of the `git_error_t` enum above describing the
+ * general subsystem that is responsible for the error.
+ * @param string The error message to keep
* @return 0 on success or -1 on failure
*/
GIT_EXTERN(int) git_error_set_str(int error_class, const char *string);
diff --git a/include/git2/merge.h b/include/git2/merge.h
index e90941a49..fcce5594d 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -603,7 +603,7 @@ GIT_EXTERN(int) git_merge_commits(
* completes, resolve any conflicts and prepare a commit.
*
* For compatibility with git, the repository is put into a merging
- * state. Once the commit is done (or if the uses wishes to abort),
+ * state. Once the commit is done (or if the user wishes to abort),
* you should clear this state by calling
* `git_repository_state_cleanup()`.
*
diff --git a/include/git2/status.h b/include/git2/status.h
index d8f9663b4..bb28e875b 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -227,13 +227,16 @@ typedef struct {
/**
* The `show` value is one of the `git_status_show_t` constants that
- * control which files to scan and in what order.
+ * control which files to scan and in what order. The default is
+ * `GIT_STATUS_SHOW_INDEX_AND_WORKDIR`.
*/
git_status_show_t show;
/**
* The `flags` value is an OR'ed combination of the
- * `git_status_opt_t` values above.
+ * `git_status_opt_t` values above. The default is
+ * `GIT_STATUS_OPT_DEFAULTS`, which matches git's default
+ * behavior.
*/
unsigned int flags;
diff --git a/include/git2/sys/remote.h b/include/git2/sys/remote.h
index dd243ca55..0eae9234d 100644
--- a/include/git2/sys/remote.h
+++ b/include/git2/sys/remote.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_sys_git_remote_h
#define INCLUDE_sys_git_remote_h
+#include "git2/remote.h"
+
/**
* @file git2/sys/remote.h
* @brief Low-level remote functionality for custom transports
@@ -26,6 +28,19 @@ typedef enum {
GIT_REMOTE_CAPABILITY_REACHABLE_OID = (1 << 1),
} git_remote_capability_t;
+/**
+ * Disposes libgit2-initialized fields from a git_remote_connect_options.
+ * This should only be used for git_remote_connect_options returned by
+ * git_transport_remote_connect_options.
+ *
+ * Note that this does not free the `git_remote_connect_options` itself, just
+ * the memory pointed to by it.
+ *
+ * @param opts The `git_remote_connect_options` struct to dispose.
+ */
+GIT_EXTERN(void) git_remote_connect_options_dispose(
+ git_remote_connect_options *opts);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h
index f0c2a3eab..06ae7079f 100644
--- a/include/git2/sys/transport.h
+++ b/include/git2/sys/transport.h
@@ -9,10 +9,11 @@
#define INCLUDE_sys_git_transport_h
#include "git2/net.h"
+#include "git2/proxy.h"
+#include "git2/remote.h"
+#include "git2/strarray.h"
#include "git2/transport.h"
#include "git2/types.h"
-#include "git2/strarray.h"
-#include "git2/proxy.h"
/**
* @file git2/sys/transport.h
@@ -261,14 +262,17 @@ GIT_EXTERN(int) git_transport_smart_certificate_check(git_transport *transport,
GIT_EXTERN(int) git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods);
/**
- * Get a copy of the proxy options
+ * Get a copy of the remote connect options
*
- * The url is copied and must be freed by the caller.
+ * All data is copied and must be freed by the caller by calling
+ * `git_remote_connect_options_dispose`.
*
* @param out options struct to fill
* @param transport the transport to extract the data from.
*/
-GIT_EXTERN(int) git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport);
+GIT_EXTERN(int) git_transport_remote_connect_options(
+ git_remote_connect_options *out,
+ git_transport *transport);
/*
*** End of base transport interface ***
diff --git a/include/git2/version.h b/include/git2/version.h
index 980f70b69..d591904fd 100644
--- a/include/git2/version.h
+++ b/include/git2/version.h
@@ -7,12 +7,33 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
-#define LIBGIT2_VERSION "1.4.3"
-#define LIBGIT2_VER_MAJOR 1
-#define LIBGIT2_VER_MINOR 4
-#define LIBGIT2_VER_REVISION 3
-#define LIBGIT2_VER_PATCH 0
+/**
+ * The version string for libgit2. This string follows semantic
+ * versioning (v2) guidelines.
+ */
+#define LIBGIT2_VERSION "1.5.0"
-#define LIBGIT2_SOVERSION "1.4"
+/** The major version number for this version of libgit2. */
+#define LIBGIT2_VER_MAJOR 1
+
+/** The minor version number for this version of libgit2. */
+#define LIBGIT2_VER_MINOR 5
+
+/** The revision ("teeny") version number for this version of libgit2. */
+#define LIBGIT2_VER_REVISION 0
+
+/** The Windows DLL patch number for this version of libgit2. */
+#define LIBGIT2_VER_PATCH 0
+
+/**
+ * The prerelease string for this version of libgit2. For development
+ * (nightly) builds, this will be "alpha". For prereleases, this will be
+ * a prerelease name like "beta" or "rc1". For final releases, this will
+ * be `NULL`.
+ */
+#define LIBGIT2_VER_PRERELEASE NULL
+
+/** The library ABI soversion for this version of libgit2. */
+#define LIBGIT2_SOVERSION "1.5"
#endif
diff --git a/package.json b/package.json
index 5caa47aea..8676fe513 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "libgit2",
- "version": "1.4.3",
+ "version": "1.5.0",
"repo": "https://github.com/libgit2/libgit2",
"description": " A cross-platform, linkable library implementation of Git that you can use in your application.",
"install": "mkdir build && cd build && cmake .. && cmake --build ."
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e7b54d036..d16cfe538 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,12 +1,22 @@
-add_library(git2internal OBJECT)
-set_target_properties(git2internal PROPERTIES C_STANDARD 90)
-set_target_properties(git2internal PROPERTIES C_EXTENSIONS OFF)
+# The main libgit2 source tree: this CMakeLists.txt identifies platform
+# support and includes the subprojects that make up core libgit2 support.
+#
+# Optional build configuration settings
+#
if(DEPRECATE_HARD)
add_definitions(-DGIT_DEPRECATE_HARD)
endif()
+if(USE_LEAK_CHECKER STREQUAL "valgrind")
+ add_definitions(-DVALGRIND)
+endif()
+
+#
+# Optional debugging functionality
+#
+
if(DEBUG_POOL)
set(GIT_DEBUG_POOL 1)
endif()
@@ -22,29 +32,32 @@ if(DEBUG_STRICT_OPEN)
endif()
add_feature_info(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
+#
+# Optional feature enablement
+#
-include(PkgBuildConfig)
-include(SanitizeBool)
+include(SelectGSSAPI)
+include(SelectHTTPSBackend)
+include(SelectHashes)
+include(SelectHTTPParser)
+include(SelectRegex)
+include(SelectSSH)
+include(SelectWinHTTP)
+include(SelectZlib)
-# This variable will contain the libraries we need to put into
-# libgit2.pc's Requires.private. That is, what we're linking to or
-# what someone who's statically linking us needs to link to.
-set(LIBGIT2_PC_REQUIRES "")
-# This will be set later if we use the system's http-parser library or
-# use iconv (OSX) and will be written to the Libs.private field in the
-# pc file.
-set(LIBGIT2_PC_LIBS "")
+#
+# Platform support
+#
-set(LIBGIT2_INCLUDES
- "${CMAKE_CURRENT_BINARY_DIR}"
- "${PROJECT_SOURCE_DIR}/src"
- "${PROJECT_SOURCE_DIR}/include")
+# futimes/futimens
if(HAVE_FUTIMENS)
set(GIT_USE_FUTIMENS 1)
endif ()
add_feature_info(futimens GIT_USE_FUTIMENS "futimens support")
+# qsort
+
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" GIT_QSORT_R_BSD)
@@ -55,69 +68,85 @@ check_prototype_definition(qsort_r
check_function_exists(qsort_s GIT_QSORT_S)
+# random / entropy data
+
check_function_exists(getentropy GIT_RAND_GETENTROPY)
+check_function_exists(getloadavg GIT_RAND_GETLOADAVG)
-# Find required dependencies
+# determine architecture of the machine
-if(WIN32)
- list(APPEND LIBGIT2_SYSTEM_LIBS ws2_32)
-elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
- list(APPEND LIBGIT2_SYSTEM_LIBS socket nsl)
- list(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
-elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku")
- list(APPEND LIBGIT2_SYSTEM_LIBS network)
- list(APPEND LIBGIT2_PC_LIBS "-lnetwork")
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(GIT_ARCH_64 1)
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set(GIT_ARCH_32 1)
+elseif(CMAKE_SIZEOF_VOID_P)
+ message(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
+else()
+ message(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
endif()
+# nanosecond mtime/ctime support
+
+if(USE_NSEC)
+ set(GIT_USE_NSEC 1)
+endif()
+
+# high-resolution stat support
+
+if(HAVE_STRUCT_STAT_ST_MTIM)
+ set(GIT_USE_STAT_MTIM 1)
+elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+ set(GIT_USE_STAT_MTIMESPEC 1)
+elseif(HAVE_STRUCT_STAT_ST_MTIME_NSEC)
+ set(GIT_USE_STAT_MTIME_NSEC 1)
+endif()
+
+# realtime support
+
check_library_exists(rt clock_gettime "time.h" NEED_LIBRT)
if(NEED_LIBRT)
list(APPEND LIBGIT2_SYSTEM_LIBS rt)
list(APPEND LIBGIT2_PC_LIBS "-lrt")
endif()
+# platform libraries
+
+if(WIN32)
+ list(APPEND LIBGIT2_SYSTEM_LIBS ws2_32)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+ list(APPEND LIBGIT2_SYSTEM_LIBS socket nsl)
+ list(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "Haiku")
+ list(APPEND LIBGIT2_SYSTEM_LIBS gnu network)
+ list(APPEND LIBGIT2_PC_LIBS "-lgnu -lnetwork")
+endif()
+
+if(AMIGA)
+ add_definitions(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
+endif()
+
+# threads
+
if(USE_THREADS)
- list(APPEND LIBGIT2_SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
- list(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
+ if(NOT WIN32)
+ find_package(Threads REQUIRED)
+ list(APPEND LIBGIT2_SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
+ list(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ set(GIT_THREADS 1)
endif()
add_feature_info(threadsafe USE_THREADS "threadsafe support")
+#
+# Optional bundled features
+#
-if(WIN32 AND EMBED_SSH_PATH)
- file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
- list(SORT SRC_SSH)
- target_sources(git2internal PRIVATE ${SRC_SSH})
-
- list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include")
- file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
- set(GIT_SSH 1)
-endif()
-
-include(SelectHTTPSBackend)
-include(SelectHashes)
-include(SelectHTTPParser)
-include(SelectRegex)
-include(SelectSSH)
-include(SelectWinHTTP)
-include(SelectZlib)
-
-
-if(USE_SHA1 STREQUAL "CollisionDetection")
- file(GLOB SRC_SHA1 hash/sha1/collisiondetect.* hash/sha1/sha1dc/*)
-elseif(USE_SHA1 STREQUAL "OpenSSL")
- file(GLOB SRC_SHA1 hash/sha1/openssl.*)
-elseif(USE_SHA1 STREQUAL "CommonCrypto")
- file(GLOB SRC_SHA1 hash/sha1/common_crypto.*)
-elseif(USE_SHA1 STREQUAL "mbedTLS")
- file(GLOB SRC_SHA1 hash/sha1/mbedtls.*)
-elseif(USE_SHA1 STREQUAL "Win32")
- file(GLOB SRC_SHA1 hash/sha1/win32.*)
-elseif(USE_SHA1 STREQUAL "Generic")
- file(GLOB SRC_SHA1 hash/sha1/generic.*)
-endif()
-list(APPEND SRC_SHA1 "hash/sha1.h")
-target_sources(git2internal PRIVATE ${SRC_SHA1})
-
-# Optional external dependency: ntlmclient
+# ntlmclient
if(USE_NTLMCLIENT)
set(GIT_NTLM 1)
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/ntlmclient" "${PROJECT_BINARY_DIR}/deps/ntlmclient")
@@ -126,11 +155,10 @@ if(USE_NTLMCLIENT)
endif()
add_feature_info(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
-# Optional external dependency: GSSAPI
+#
+# Optional external dependencies
-include(SelectGSSAPI)
-
-# Optional external dependency: iconv
+# iconv
if(USE_ICONV)
find_package(Iconv)
endif()
@@ -142,166 +170,28 @@ if(ICONV_FOUND)
endif()
add_feature_info(iconv GIT_USE_ICONV "iconv encoding conversion support")
-
-if(USE_THREADS)
- if(NOT WIN32)
- find_package(Threads REQUIRED)
- endif()
-
- set(GIT_THREADS 1)
-endif()
-
-if(USE_NSEC)
- set(GIT_USE_NSEC 1)
-endif()
-
-if(HAVE_STRUCT_STAT_ST_MTIM)
- set(GIT_USE_STAT_MTIM 1)
-elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC)
- set(GIT_USE_STAT_MTIMESPEC 1)
-elseif(HAVE_STRUCT_STAT_ST_MTIME_NSEC)
- set(GIT_USE_STAT_MTIME_NSEC 1)
-endif()
-
-target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
-
-# Collect sourcefiles
-file(GLOB SRC_H
- "${PROJECT_SOURCE_DIR}/include/git2.h"
- "${PROJECT_SOURCE_DIR}/include/git2/*.h"
- "${PROJECT_SOURCE_DIR}/include/git2/sys/*.h")
-list(SORT SRC_H)
-target_sources(git2internal PRIVATE ${SRC_H})
-
-# On Windows use specific platform sources
-if(WIN32 AND NOT CYGWIN)
- set(WIN_RC "win32/git2.rc")
-
- file(GLOB SRC_OS win32/*.c win32/*.h)
- list(SORT SRC_OS)
- target_sources(git2internal PRIVATE ${SRC_OS})
-elseif(AMIGA)
- target_compile_definitions(git2internal PRIVATE NO_ADDRINFO NO_READDIR_R NO_MMAP)
-else()
- file(GLOB SRC_OS unix/*.c unix/*.h)
- list(SORT SRC_OS)
- target_sources(git2internal PRIVATE ${SRC_OS})
-endif()
-
-if(USE_LEAK_CHECKER STREQUAL "valgrind")
- target_compile_definitions(git2internal PRIVATE VALGRIND)
-endif()
-
-file(GLOB SRC_GIT2 *.c *.h
- allocators/*.c allocators/*.h
- streams/*.c streams/*.h
- transports/*.c transports/*.h
- xdiff/*.c xdiff/*.h)
-list(SORT SRC_GIT2)
-target_sources(git2internal PRIVATE ${SRC_GIT2})
-
-if(APPLE)
- # The old Secure Transport API has been deprecated in macOS 10.15.
- set_source_files_properties(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
-endif()
-
-# the xdiff dependency is not (yet) warning-free, disable warnings as
-# errors for the xdiff sources until we've sorted them out
-if(MSVC)
- set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
- set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
- set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
- set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
- set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
- set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
-else()
- set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
- set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
- set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
- set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
- set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
-endif()
-
-# Determine architecture of the machine
-if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(GIT_ARCH_64 1)
-elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
- set(GIT_ARCH_32 1)
-elseif(CMAKE_SIZEOF_VOID_P)
- message(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
-else()
- message(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
-endif()
+#
+# Configure support
+#
configure_file(features.h.in git2/sys/features.h)
-ide_split_sources(git2internal)
-list(APPEND LIBGIT2_OBJECTS $ ${LIBGIT2_DEPENDENCY_OBJECTS})
+#
+# Include child projects
+#
-target_include_directories(git2internal PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${PROJECT_SOURCE_DIR}/include)
-target_include_directories(git2internal SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
+add_subdirectory(libgit2)
+add_subdirectory(util)
+if(BUILD_CLI)
+ add_subdirectory(cli)
+endif()
+
+# re-export these to the root so that peer projects (tests, fuzzers,
+# examples) can use them
set(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
set(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
set(LIBGIT2_DEPENDENCY_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES} PARENT_SCOPE)
set(LIBGIT2_DEPENDENCY_OBJECTS ${LIBGIT2_DEPENDENCY_OBJECTS} PARENT_SCOPE)
set(LIBGIT2_SYSTEM_INCLUDES ${LIBGIT2_SYSTEM_INCLUDES} PARENT_SCOPE)
set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE)
-
-if(XCODE_VERSION)
- # This is required for Xcode to actually link the libgit2 library
- # when using only object libraries.
- file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.c "")
- list(APPEND LIBGIT2_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/dummy.c)
-endif()
-
-# Compile and link libgit2
-add_library(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
-target_link_libraries(git2 ${LIBGIT2_SYSTEM_LIBS})
-
-set_target_properties(git2 PROPERTIES C_STANDARD 90)
-set_target_properties(git2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
-set_target_properties(git2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
-set_target_properties(git2 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
-
-# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
-# Win64+MSVC+static libs = linker error
-if(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
- set_target_properties(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
-endif()
-
-ide_split_sources(git2)
-
-if(SONAME)
- set_target_properties(git2 PROPERTIES VERSION ${libgit2_VERSION})
- set_target_properties(git2 PROPERTIES SOVERSION "${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
- if(LIBGIT2_FILENAME)
- target_compile_definitions(git2 PRIVATE LIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
- set_target_properties(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
- elseif(DEFINED LIBGIT2_PREFIX)
- set_target_properties(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
- endif()
-endif()
-
-pkg_build_config(NAME libgit2
- VERSION ${libgit2_VERSION}
- DESCRIPTION "The git library, take 2"
- LIBS_SELF git2
- PRIVATE_LIBS ${LIBGIT2_PC_LIBS}
- REQUIRES ${LIBGIT2_PC_REQUIRES}
-)
-
-if(MSVC_IDE)
- # Precompiled headers
- set_target_properties(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
- set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
-endif()
-
-# Install
-install(TARGETS git2
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-)
-install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-install(FILES ${PROJECT_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 000000000..10b86c1dc
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,12 @@
+# libgit2 sources
+
+This is the source that makes up the core of libgit2 and its related
+projects.
+
+* `cli`
+ A git-compatible command-line interface that uses libgit2.
+* `libgit2`
+ This is the libgit2 project, a cross-platform, linkable library
+ implementation of Git that you can use in your application.
+* `util`
+ A shared utility library for these projects.
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
new file mode 100644
index 000000000..4f347e93f
--- /dev/null
+++ b/src/cli/CMakeLists.txt
@@ -0,0 +1,53 @@
+set(CLI_INCLUDES
+ "${libgit2_BINARY_DIR}/src"
+ "${libgit2_SOURCE_DIR}/src/util"
+ "${libgit2_SOURCE_DIR}/src/cli"
+ "${libgit2_SOURCE_DIR}/include")
+
+if(WIN32 AND NOT CYGWIN)
+ file(GLOB CLI_SRC_OS win32/*.c)
+ list(SORT CLI_SRC_OS)
+else()
+ file(GLOB CLI_SRC_OS unix/*.c)
+ list(SORT CLI_SRC_OS)
+endif()
+
+file(GLOB CLI_SRC_C *.c *.h)
+list(SORT CLI_SRC_C)
+
+#
+# The CLI currently needs to be statically linked against libgit2 because
+# the utility library uses libgit2's thread-local error buffers. TODO:
+# remove this dependency and allow us to dynamically link against libgit2.
+#
+
+if(BUILD_CLI STREQUAL "dynamic")
+ set(CLI_LIBGIT2_LIBRARY libgit2package)
+else()
+ set(CLI_LIBGIT2_OBJECTS $)
+endif()
+
+#
+# Compile and link the CLI
+#
+
+add_executable(git2_cli ${CLI_SRC_C} ${CLI_SRC_OS} ${CLI_OBJECTS}
+ $
+ ${CLI_LIBGIT2_OBJECTS}
+ ${LIBGIT2_DEPENDENCY_OBJECTS})
+target_link_libraries(git2_cli ${CLI_LIBGIT2_LIBRARY} ${LIBGIT2_SYSTEM_LIBS})
+
+set_target_properties(git2_cli PROPERTIES C_STANDARD 90)
+set_target_properties(git2_cli PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
+
+ide_split_sources(git2_cli)
+
+target_include_directories(git2_cli PRIVATE ${CLI_INCLUDES})
+
+if(MSVC_IDE)
+ # Precompiled headers
+ set_target_properties(git2_cli PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
+ set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
+endif()
+
+install(TARGETS git2_cli RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/cli/README.md b/src/cli/README.md
new file mode 100644
index 000000000..3087c39c4
--- /dev/null
+++ b/src/cli/README.md
@@ -0,0 +1,26 @@
+# cli
+
+A git-compatible command-line interface that uses libgit2.
+
+## Adding commands
+
+1. Individual commands have a `main`-like top-level entrypoint. For example:
+
+ ```c
+ int cmd_help(int argc, char **argv)
+ ```
+
+ Although this is the same signature as `main`, commands are not built as
+ individual standalone executables, they'll be linked into the main cli.
+ (Though there may be an option for command executables to be built as
+ standalone executables in the future.)
+
+2. Commands are prototyped in `cmd.h` and added to `main.c`'s list of
+ commands (`cli_cmds[]`). Commands should be specified with their name,
+ entrypoint and a brief description that can be printed in `git help`.
+ This is done because commands are linked into the main cli.
+
+3. Commands should accept a `--help` option that displays their help
+ information. This will be shown when a user runs ` --help` and
+ when a user runs `help `.
+
diff --git a/src/hash/sha1/generic.h b/src/cli/cli.h
similarity index 52%
rename from src/hash/sha1/generic.h
rename to src/cli/cli.h
index 53fc0823e..7dede6785 100644
--- a/src/hash/sha1/generic.h
+++ b/src/cli/cli.h
@@ -5,15 +5,16 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hash_sha1_generic_h__
-#define INCLUDE_hash_sha1_generic_h__
+#ifndef CLI_cli_h__
+#define CLI_cli_h__
-#include "hash/sha1.h"
+#define PROGRAM_NAME "git2"
-struct git_hash_sha1_ctx {
- uint64_t size;
- unsigned int H[5];
- unsigned int W[16];
-};
+#include "git2_util.h"
-#endif
+#include "error.h"
+#include "opt.h"
+#include "opt_usage.h"
+#include "sighandler.h"
+
+#endif /* CLI_cli_h__ */
diff --git a/src/cli/cmd.c b/src/cli/cmd.c
new file mode 100644
index 000000000..2a7e71cdb
--- /dev/null
+++ b/src/cli/cmd.c
@@ -0,0 +1,21 @@
+/*
+ * 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 "cli.h"
+#include "cmd.h"
+
+const cli_cmd_spec *cli_cmd_spec_byname(const char *name)
+{
+ const cli_cmd_spec *cmd;
+
+ for (cmd = cli_cmds; cmd->name; cmd++) {
+ if (!strcmp(cmd->name, name))
+ return cmd;
+ }
+
+ return NULL;
+}
diff --git a/src/cli/cmd.h b/src/cli/cmd.h
new file mode 100644
index 000000000..8b1a1b38f
--- /dev/null
+++ b/src/cli/cmd.h
@@ -0,0 +1,33 @@
+/*
+ * 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 CLI_cmd_h__
+#define CLI_cmd_h__
+
+/* Command definitions */
+typedef struct {
+ const char *name;
+ int (*fn)(int argc, char **argv);
+ const char *desc;
+} cli_cmd_spec;
+
+/* Options that are common to all commands (eg --help, --git-dir) */
+extern const cli_opt_spec cli_common_opts[];
+
+/* All the commands supported by the CLI */
+extern const cli_cmd_spec cli_cmds[];
+
+/* Find a command by name */
+extern const cli_cmd_spec *cli_cmd_spec_byname(const char *name);
+
+/* Commands */
+extern int cmd_cat_file(int argc, char **argv);
+extern int cmd_clone(int argc, char **argv);
+extern int cmd_hash_object(int argc, char **argv);
+extern int cmd_help(int argc, char **argv);
+
+#endif /* CLI_cmd_h__ */
diff --git a/src/cli/cmd_cat_file.c b/src/cli/cmd_cat_file.c
new file mode 100644
index 000000000..fb53a722b
--- /dev/null
+++ b/src/cli/cmd_cat_file.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+#include "cli.h"
+#include "cmd.h"
+
+#define COMMAND_NAME "cat-file"
+
+typedef enum {
+ DISPLAY_CONTENT = 0,
+ DISPLAY_EXISTS,
+ DISPLAY_PRETTY,
+ DISPLAY_SIZE,
+ DISPLAY_TYPE
+} display_t;
+
+static int show_help;
+static int display = DISPLAY_CONTENT;
+static char *type_name, *object_spec;
+
+static const cli_opt_spec opts[] = {
+ { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
+ CLI_OPT_USAGE_HIDDEN | CLI_OPT_USAGE_STOP_PARSING, NULL,
+ "display help about the " COMMAND_NAME " command" },
+
+ { CLI_OPT_TYPE_SWITCH, NULL, 't', &display, DISPLAY_TYPE,
+ CLI_OPT_USAGE_REQUIRED, NULL, "display the type of the object" },
+ { CLI_OPT_TYPE_SWITCH, NULL, 's', &display, DISPLAY_SIZE,
+ CLI_OPT_USAGE_CHOICE, NULL, "display the size of the object" },
+ { CLI_OPT_TYPE_SWITCH, NULL, 'e', &display, DISPLAY_EXISTS,
+ CLI_OPT_USAGE_CHOICE, NULL, "displays nothing unless the object is corrupt" },
+ { CLI_OPT_TYPE_SWITCH, NULL, 'p', &display, DISPLAY_PRETTY,
+ CLI_OPT_USAGE_CHOICE, NULL, "pretty-print the object" },
+ { CLI_OPT_TYPE_ARG, "type", 0, &type_name, 0,
+ CLI_OPT_USAGE_CHOICE, "type", "the type of object to display" },
+ { CLI_OPT_TYPE_ARG, "object", 0, &object_spec, 0,
+ CLI_OPT_USAGE_REQUIRED, "object", "the object to display" },
+ { 0 },
+};
+
+static void print_help(void)
+{
+ cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
+ printf("\n");
+
+ printf("Display the content for the given object in the repository.\n");
+ printf("\n");
+
+ printf("Options:\n");
+
+ cli_opt_help_fprint(stdout, opts);
+}
+
+static int print_odb(git_object *object, display_t display)
+{
+ git_odb *odb = NULL;
+ git_odb_object *odb_object = NULL;
+ const unsigned char *content;
+ git_object_size_t size;
+ int ret = 0;
+
+ /*
+ * Our parsed blobs retain the raw content; all other objects are
+ * parsed into a working representation. To get the raw content,
+ * we need to do an ODB lookup. (Thankfully, this should be cached
+ * in-memory from our last call.)
+ */
+ if (git_object_type(object) == GIT_OBJECT_BLOB) {
+ content = git_blob_rawcontent((git_blob *)object);
+ size = git_blob_rawsize((git_blob *)object);
+ } else {
+ if (git_repository_odb(&odb, git_object_owner(object)) < 0 ||
+ git_odb_read(&odb_object, odb, git_object_id(object)) < 0) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ content = git_odb_object_data(odb_object);
+ size = git_odb_object_size(odb_object);
+ }
+
+ switch (display) {
+ case DISPLAY_SIZE:
+ if (printf("%" PRIu64 "\n", size) < 0)
+ ret = cli_error_os();
+ break;
+ case DISPLAY_CONTENT:
+ if (p_write(fileno(stdout), content, (size_t)size) < 0)
+ ret = cli_error_os();
+ break;
+ default:
+ GIT_ASSERT(0);
+ }
+
+done:
+ git_odb_object_free(odb_object);
+ git_odb_free(odb);
+ return ret;
+}
+
+static int print_type(git_object *object)
+{
+ if (printf("%s\n", git_object_type2string(git_object_type(object))) < 0)
+ return cli_error_os();
+
+ return 0;
+}
+
+static int print_pretty(git_object *object)
+{
+ const git_tree_entry *entry;
+ size_t i, count;
+
+ /*
+ * Only trees are stored in an unreadable format and benefit from
+ * pretty-printing.
+ */
+ if (git_object_type(object) != GIT_OBJECT_TREE)
+ return print_odb(object, DISPLAY_CONTENT);
+
+ for (i = 0, count = git_tree_entrycount((git_tree *)object); i < count; i++) {
+ entry = git_tree_entry_byindex((git_tree *)object, i);
+
+ if (printf("%06o %s %s\t%s\n",
+ git_tree_entry_filemode_raw(entry),
+ git_object_type2string(git_tree_entry_type(entry)),
+ git_oid_tostr_s(git_tree_entry_id(entry)),
+ git_tree_entry_name(entry)) < 0)
+ return cli_error_os();
+ }
+
+ return 0;
+}
+
+int cmd_cat_file(int argc, char **argv)
+{
+ git_repository *repo = NULL;
+ git_object *object = NULL;
+ git_object_t type;
+ cli_opt invalid_opt;
+ int giterr, ret = 0;
+
+ if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
+ return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
+
+ if (show_help) {
+ print_help();
+ return 0;
+ }
+
+ if (git_repository_open_ext(&repo, ".", GIT_REPOSITORY_OPEN_FROM_ENV, NULL) < 0)
+ return cli_error_git();
+
+ if ((giterr = git_revparse_single(&object, repo, object_spec)) < 0) {
+ if (display == DISPLAY_EXISTS && giterr == GIT_ENOTFOUND)
+ ret = 1;
+ else
+ ret = cli_error_git();
+
+ goto done;
+ }
+
+ if (type_name) {
+ git_object *peeled;
+
+ if ((type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID) {
+ ret = cli_error_usage("invalid object type '%s'", type_name);
+ goto done;
+ }
+
+ if (git_object_peel(&peeled, object, type) < 0) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ git_object_free(object);
+ object = peeled;
+ }
+
+ switch (display) {
+ case DISPLAY_EXISTS:
+ ret = 0;
+ break;
+ case DISPLAY_TYPE:
+ ret = print_type(object);
+ break;
+ case DISPLAY_PRETTY:
+ ret = print_pretty(object);
+ break;
+ default:
+ ret = print_odb(object, display);
+ break;
+ }
+
+done:
+ git_object_free(object);
+ git_repository_free(repo);
+ return ret;
+}
diff --git a/src/cli/cmd_clone.c b/src/cli/cmd_clone.c
new file mode 100644
index 000000000..a382b5875
--- /dev/null
+++ b/src/cli/cmd_clone.c
@@ -0,0 +1,176 @@
+/*
+ * 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
+#include
+#include "cli.h"
+#include "cmd.h"
+#include "error.h"
+#include "sighandler.h"
+#include "progress.h"
+
+#include "fs_path.h"
+#include "futils.h"
+
+#define COMMAND_NAME "clone"
+
+static char *branch, *remote_path, *local_path;
+static int show_help, quiet, checkout = 1, bare;
+static bool local_path_exists;
+static cli_progress progress = CLI_PROGRESS_INIT;
+
+static const cli_opt_spec opts[] = {
+ { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
+ CLI_OPT_USAGE_HIDDEN | CLI_OPT_USAGE_STOP_PARSING, NULL,
+ "display help about the " COMMAND_NAME " command" },
+
+ { CLI_OPT_TYPE_SWITCH, "quiet", 'q', &quiet, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "display the type of the object" },
+ { CLI_OPT_TYPE_SWITCH, "no-checkout", 'n', &checkout, 0,
+ CLI_OPT_USAGE_DEFAULT, NULL, "don't checkout HEAD" },
+ { CLI_OPT_TYPE_SWITCH, "bare", 0, &bare, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "don't create a working directory" },
+ { CLI_OPT_TYPE_VALUE, "branch", 'b', &branch, 0,
+ CLI_OPT_USAGE_DEFAULT, "name", "branch to check out" },
+ { CLI_OPT_TYPE_LITERAL },
+ { CLI_OPT_TYPE_ARG, "repository", 0, &remote_path, 0,
+ CLI_OPT_USAGE_REQUIRED, "repository", "repository path" },
+ { CLI_OPT_TYPE_ARG, "directory", 0, &local_path, 0,
+ CLI_OPT_USAGE_DEFAULT, "directory", "directory to clone into" },
+ { 0 }
+};
+
+static void print_help(void)
+{
+ cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
+ printf("\n");
+
+ printf("Clone a repository into a new directory.\n");
+ printf("\n");
+
+ printf("Options:\n");
+
+ cli_opt_help_fprint(stdout, opts);
+}
+
+static char *compute_local_path(const char *orig_path)
+{
+ const char *slash;
+ char *local_path;
+
+ if ((slash = strrchr(orig_path, '/')) == NULL &&
+ (slash = strrchr(orig_path, '\\')) == NULL)
+ local_path = git__strdup(orig_path);
+ else
+ local_path = git__strdup(slash + 1);
+
+ return local_path;
+}
+
+static bool validate_local_path(const char *path)
+{
+ if (!git_fs_path_exists(path))
+ return false;
+
+ if (!git_fs_path_isdir(path) || !git_fs_path_is_empty_dir(path)) {
+ fprintf(stderr, "fatal: destination path '%s' already exists and is not an empty directory.\n",
+ path);
+ exit(128);
+ }
+
+ return true;
+}
+
+static void cleanup(void)
+{
+ int rmdir_flags = GIT_RMDIR_REMOVE_FILES;
+
+ cli_progress_abort(&progress);
+
+ if (local_path_exists)
+ rmdir_flags |= GIT_RMDIR_SKIP_ROOT;
+
+ if (!git_fs_path_isdir(local_path))
+ return;
+
+ git_futils_rmdir_r(local_path, NULL, rmdir_flags);
+}
+
+static void interrupt_cleanup(void)
+{
+ cleanup();
+ exit(130);
+}
+
+int cmd_clone(int argc, char **argv)
+{
+ git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
+ git_repository *repo = NULL;
+ cli_opt invalid_opt;
+ char *computed_path = NULL;
+ int ret = 0;
+
+ if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
+ return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
+
+ if (show_help) {
+ print_help();
+ return 0;
+ }
+
+ if (!remote_path) {
+ ret = cli_error_usage("you must specify a repository to clone");
+ goto done;
+ }
+
+ if (bare)
+ clone_opts.bare = 1;
+
+ if (branch)
+ clone_opts.checkout_branch = branch;
+
+ if (!checkout)
+ clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
+
+ if (!local_path)
+ local_path = computed_path = compute_local_path(remote_path);
+
+ local_path_exists = validate_local_path(local_path);
+
+ cli_sighandler_set_interrupt(interrupt_cleanup);
+
+ if (!local_path_exists &&
+ git_futils_mkdir(local_path, 0777, 0) < 0) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ if (!quiet) {
+ clone_opts.fetch_opts.callbacks.sideband_progress = cli_progress_fetch_sideband;
+ clone_opts.fetch_opts.callbacks.transfer_progress = cli_progress_fetch_transfer;
+ clone_opts.fetch_opts.callbacks.payload = &progress;
+
+ clone_opts.checkout_opts.progress_cb = cli_progress_checkout;
+ clone_opts.checkout_opts.progress_payload = &progress;
+
+ printf("Cloning into '%s'...\n", local_path);
+ }
+
+ if (git_clone(&repo, remote_path, local_path, &clone_opts) < 0) {
+ cleanup();
+ ret = cli_error_git();
+ goto done;
+ }
+
+ cli_progress_finish(&progress);
+
+done:
+ cli_progress_dispose(&progress);
+ git__free(computed_path);
+ git_repository_free(repo);
+ return ret;
+}
diff --git a/src/cli/cmd_hash_object.c b/src/cli/cmd_hash_object.c
new file mode 100644
index 000000000..5cfe9146a
--- /dev/null
+++ b/src/cli/cmd_hash_object.c
@@ -0,0 +1,135 @@
+/*
+ * 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
+#include "cli.h"
+#include "cmd.h"
+
+#include "futils.h"
+
+#define COMMAND_NAME "hash-object"
+
+static int show_help;
+static char *type_name;
+static int write_object, read_stdin, literally;
+static char **filenames;
+
+static const cli_opt_spec opts[] = {
+ { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
+ CLI_OPT_USAGE_HIDDEN | CLI_OPT_USAGE_STOP_PARSING, NULL,
+ "display help about the " COMMAND_NAME " command" },
+
+ { CLI_OPT_TYPE_VALUE, NULL, 't', &type_name, 0,
+ CLI_OPT_USAGE_DEFAULT, "type", "the type of object to hash (default: \"blob\")" },
+ { CLI_OPT_TYPE_SWITCH, NULL, 'w', &write_object, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "write the object to the object database" },
+ { CLI_OPT_TYPE_SWITCH, "literally", 0, &literally, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "do not validate the object contents" },
+ { CLI_OPT_TYPE_SWITCH, "stdin", 0, &read_stdin, 1,
+ CLI_OPT_USAGE_REQUIRED, NULL, "read content from stdin" },
+ { CLI_OPT_TYPE_ARGS, "file", 0, &filenames, 0,
+ CLI_OPT_USAGE_CHOICE, "file", "the file (or files) to read and hash" },
+ { 0 },
+};
+
+static void print_help(void)
+{
+ cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
+ printf("\n");
+
+ printf("Compute the object ID for a given file and optionally write that file\nto the object database.\n");
+ printf("\n");
+
+ printf("Options:\n");
+
+ cli_opt_help_fprint(stdout, opts);
+}
+
+static int hash_buf(git_odb *odb, git_str *buf, git_object_t type)
+{
+ git_oid oid;
+
+ if (!literally) {
+ int valid = 0;
+
+ if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, type) < 0 || !valid)
+ return cli_error_git();
+ }
+
+ if (write_object) {
+ if (git_odb_write(&oid, odb, buf->ptr, buf->size, type) < 0)
+ return cli_error_git();
+ } else {
+ if (git_odb_hash(&oid, buf->ptr, buf->size, type) < 0)
+ return cli_error_git();
+ }
+
+ if (printf("%s\n", git_oid_tostr_s(&oid)) < 0)
+ return cli_error_os();
+
+ return 0;
+}
+
+int cmd_hash_object(int argc, char **argv)
+{
+ git_repository *repo = NULL;
+ git_odb *odb = NULL;
+ git_str buf = GIT_STR_INIT;
+ cli_opt invalid_opt;
+ git_object_t type = GIT_OBJECT_BLOB;
+ char **filename;
+ int ret = 0;
+
+ if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
+ return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
+
+ if (show_help) {
+ print_help();
+ return 0;
+ }
+
+ if (type_name && (type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
+ return cli_error_usage("invalid object type '%s'", type_name);
+
+ if (write_object &&
+ (git_repository_open_ext(&repo, ".", GIT_REPOSITORY_OPEN_FROM_ENV, NULL) < 0 ||
+ git_repository_odb(&odb, repo) < 0)) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ /*
+ * TODO: we're reading blobs, we shouldn't pull them all into main
+ * memory, we should just stream them into the odb instead.
+ * (Or create a `git_odb_writefile` API.)
+ */
+ if (read_stdin) {
+ if (git_futils_readbuffer_fd_full(&buf, fileno(stdin)) < 0) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ if ((ret = hash_buf(odb, &buf, type)) != 0)
+ goto done;
+ } else {
+ for (filename = filenames; *filename; filename++) {
+ if (git_futils_readbuffer(&buf, *filename) < 0) {
+ ret = cli_error_git();
+ goto done;
+ }
+
+ if ((ret = hash_buf(odb, &buf, type)) != 0)
+ goto done;
+ }
+ }
+
+done:
+ git_str_dispose(&buf);
+ git_odb_free(odb);
+ git_repository_free(repo);
+ return ret;
+}
diff --git a/src/cli/cmd_help.c b/src/cli/cmd_help.c
new file mode 100644
index 000000000..7ee982242
--- /dev/null
+++ b/src/cli/cmd_help.c
@@ -0,0 +1,86 @@
+/*
+ * 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
+#include
+#include "cli.h"
+#include "cmd.h"
+
+#define COMMAND_NAME "help"
+
+static char *command;
+static int show_help;
+
+static const cli_opt_spec opts[] = {
+ { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
+ CLI_OPT_USAGE_HIDDEN, NULL, "display help about the help command" },
+ { CLI_OPT_TYPE_ARG, "command", 0, &command, 0,
+ CLI_OPT_USAGE_DEFAULT, "command", "the command to show help for" },
+ { 0 },
+};
+
+static int print_help(void)
+{
+ cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
+ printf("\n");
+
+ printf("Display help information about %s. If a command is specified, help\n", PROGRAM_NAME);
+ printf("about that command will be shown. Otherwise, general information about\n");
+ printf("%s will be shown, including the commands available.\n", PROGRAM_NAME);
+
+ return 0;
+}
+
+static int print_commands(void)
+{
+ const cli_cmd_spec *cmd;
+
+ cli_opt_usage_fprint(stdout, PROGRAM_NAME, NULL, cli_common_opts);
+ printf("\n");
+
+ printf("These are the %s commands available:\n\n", PROGRAM_NAME);
+
+ for (cmd = cli_cmds; cmd->name; cmd++)
+ printf(" %-11s %s\n", cmd->name, cmd->desc);
+
+ printf("\nSee '%s help ' for more information on a specific command.\n", PROGRAM_NAME);
+
+ return 0;
+}
+
+int cmd_help(int argc, char **argv)
+{
+ char *fake_args[2];
+ const cli_cmd_spec *cmd;
+ cli_opt invalid_opt;
+
+ if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
+ return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
+
+ /* Show the meta-help */
+ if (show_help)
+ return print_help();
+
+ /* We were not asked to show help for a specific command. */
+ if (!command)
+ return print_commands();
+
+ /*
+ * If we were asked for help for a command (eg, `help `),
+ * delegate back to that command's `--help` option. This lets
+ * commands own their help. Emulate the command-line arguments
+ * that would invoke ` --help` and invoke that command.
+ */
+ fake_args[0] = command;
+ fake_args[1] = "--help";
+
+ if ((cmd = cli_cmd_spec_byname(command)) == NULL)
+ return cli_error("'%s' is not a %s command. See '%s help'.",
+ command, PROGRAM_NAME, PROGRAM_NAME);
+
+ return cmd->fn(2, fake_args);
+}
diff --git a/src/cli/error.h b/src/cli/error.h
new file mode 100644
index 000000000..cce7a54c0
--- /dev/null
+++ b/src/cli/error.h
@@ -0,0 +1,51 @@
+/*
+ * 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 CLI_error_h__
+#define CLI_error_h__
+
+#include "cli.h"
+#include
+
+#define CLI_EXIT_OK 0
+#define CLI_EXIT_ERROR 1
+#define CLI_EXIT_OS 128
+#define CLI_EXIT_GIT 128
+#define CLI_EXIT_USAGE 129
+
+#define cli_error__print(fmt) do { \
+ va_list ap; \
+ va_start(ap, fmt); \
+ fprintf(stderr, "%s: ", PROGRAM_NAME); \
+ vfprintf(stderr, fmt, ap); \
+ fprintf(stderr, "\n"); \
+ va_end(ap); \
+ } while(0)
+
+GIT_INLINE(int) cli_error(const char *fmt, ...)
+{
+ cli_error__print(fmt);
+ return CLI_EXIT_ERROR;
+}
+
+GIT_INLINE(int) cli_error_usage(const char *fmt, ...)
+{
+ cli_error__print(fmt);
+ return CLI_EXIT_USAGE;
+}
+
+GIT_INLINE(int) cli_error_git(void)
+{
+ const git_error *err = git_error_last();
+ fprintf(stderr, "%s: %s\n", PROGRAM_NAME,
+ err ? err->message : "unknown error");
+ return CLI_EXIT_GIT;
+}
+
+#define cli_error_os() (perror(PROGRAM_NAME), CLI_EXIT_OS)
+
+#endif /* CLI_error_h__ */
diff --git a/src/cli/main.c b/src/cli/main.c
new file mode 100644
index 000000000..cbfc50eec
--- /dev/null
+++ b/src/cli/main.c
@@ -0,0 +1,106 @@
+/*
+ * 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
+#include
+#include "cli.h"
+#include "cmd.h"
+
+static int show_help = 0;
+static int show_version = 0;
+static char *command = NULL;
+static char **args = NULL;
+
+const cli_opt_spec cli_common_opts[] = {
+ { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "display help information" },
+ { CLI_OPT_TYPE_SWITCH, "version", 0, &show_version, 1,
+ CLI_OPT_USAGE_DEFAULT, NULL, "display the version" },
+ { CLI_OPT_TYPE_ARG, "command", 0, &command, 0,
+ CLI_OPT_USAGE_REQUIRED, "command", "the command to run" },
+ { CLI_OPT_TYPE_ARGS, "args", 0, &args, 0,
+ CLI_OPT_USAGE_DEFAULT, "args", "arguments for the command" },
+ { 0 }
+};
+
+const cli_cmd_spec cli_cmds[] = {
+ { "cat-file", cmd_cat_file, "Display an object in the repository" },
+ { "clone", cmd_clone, "Clone a repository into a new directory" },
+ { "hash-object", cmd_hash_object, "Hash a raw object and product its object ID" },
+ { "help", cmd_help, "Display help information" },
+ { NULL }
+};
+
+int main(int argc, char **argv)
+{
+ const cli_cmd_spec *cmd;
+ cli_opt_parser optparser;
+ cli_opt opt;
+ char *help_args[3] = { NULL };
+ int help_args_len;
+ int args_len = 0;
+ int ret = 0;
+
+ if (git_libgit2_init() < 0) {
+ cli_error("failed to initialize libgit2");
+ exit(CLI_EXIT_GIT);
+ }
+
+ cli_opt_parser_init(&optparser, cli_common_opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU);
+
+ /* Parse the top-level (common) options and command information */
+ while (cli_opt_parser_next(&opt, &optparser)) {
+ if (!opt.spec) {
+ cli_opt_status_fprint(stderr, PROGRAM_NAME, &opt);
+ cli_opt_usage_fprint(stderr, PROGRAM_NAME, NULL, cli_common_opts);
+ ret = CLI_EXIT_USAGE;
+ goto done;
+ }
+
+ /*
+ * When we see a command, stop parsing and capture the
+ * remaining arguments as args for the command itself.
+ */
+ if (command) {
+ args = &argv[optparser.idx];
+ args_len = (int)(argc - optparser.idx);
+ break;
+ }
+ }
+
+ if (show_version) {
+ printf("%s version %s\n", PROGRAM_NAME, LIBGIT2_VERSION);
+ goto done;
+ }
+
+ /*
+ * If `--help ` is specified, delegate to that command's
+ * `--help` option. If no command is specified, run the `help`
+ * command. Do this by updating the args to emulate that behavior.
+ */
+ if (!command || show_help) {
+ help_args[0] = command ? (char *)command : "help";
+ help_args[1] = command ? "--help" : NULL;
+ help_args_len = command ? 2 : 1;
+
+ command = help_args[0];
+ args = help_args;
+ args_len = help_args_len;
+ }
+
+ if ((cmd = cli_cmd_spec_byname(command)) == NULL) {
+ ret = cli_error("'%s' is not a %s command. See '%s help'.",
+ command, PROGRAM_NAME, PROGRAM_NAME);
+ goto done;
+ }
+
+ ret = cmd->fn(args_len, args);
+
+done:
+ git_libgit2_shutdown();
+ return ret;
+}
diff --git a/src/cli/opt.c b/src/cli/opt.c
new file mode 100644
index 000000000..72df5877f
--- /dev/null
+++ b/src/cli/opt.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c), Edward Thomson
+ * All rights reserved.
+ *
+ * This file is part of adopt, distributed under the MIT license.
+ * For full terms and conditions, see the included LICENSE file.
+ *
+ * THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT.
+ *
+ * This file was produced by using the `rename.pl` script included with
+ * adopt. The command-line specified was:
+ *
+ * ./rename.pl cli_opt --filename=opt --include=cli.h --inline=GIT_INLINE --header-guard=CLI_opt_h__ --lowercase-status --without-usage
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "cli.h"
+#include "opt.h"
+
+#ifdef _WIN32
+# include
+#else
+# include
+# include
+#endif
+
+#ifdef _MSC_VER
+# define alloca _alloca
+#endif
+
+#define spec_is_option_type(x) \
+ ((x)->type == CLI_OPT_TYPE_BOOL || \
+ (x)->type == CLI_OPT_TYPE_SWITCH || \
+ (x)->type == CLI_OPT_TYPE_VALUE)
+
+GIT_INLINE(const cli_opt_spec *) spec_for_long(
+ int *is_negated,
+ int *has_value,
+ const char **value,
+ const cli_opt_parser *parser,
+ const char *arg)
+{
+ const cli_opt_spec *spec;
+ char *eql;
+ size_t eql_pos;
+
+ eql = strchr(arg, '=');
+ eql_pos = (eql = strchr(arg, '=')) ? (size_t)(eql - arg) : strlen(arg);
+
+ for (spec = parser->specs; spec->type; ++spec) {
+ /* Handle -- (everything after this is literal) */
+ if (spec->type == CLI_OPT_TYPE_LITERAL && arg[0] == '\0')
+ return spec;
+
+ /* Handle --no-option arguments for bool types */
+ if (spec->type == CLI_OPT_TYPE_BOOL &&
+ strncmp(arg, "no-", 3) == 0 &&
+ strcmp(arg + 3, spec->name) == 0) {
+ *is_negated = 1;
+ return spec;
+ }
+
+ /* Handle the typical --option arguments */
+ if (spec_is_option_type(spec) &&
+ spec->name &&
+ strcmp(arg, spec->name) == 0)
+ return spec;
+
+ /* Handle --option=value arguments */
+ if (spec->type == CLI_OPT_TYPE_VALUE &&
+ eql &&
+ strncmp(arg, spec->name, eql_pos) == 0 &&
+ spec->name[eql_pos] == '\0') {
+ *has_value = 1;
+ *value = arg[eql_pos + 1] ? &arg[eql_pos + 1] : NULL;
+ return spec;
+ }
+ }
+
+ return NULL;
+}
+
+GIT_INLINE(const cli_opt_spec *) spec_for_short(
+ const char **value,
+ const cli_opt_parser *parser,
+ const char *arg)
+{
+ const cli_opt_spec *spec;
+
+ for (spec = parser->specs; spec->type; ++spec) {
+ /* Handle -svalue short options with a value */
+ if (spec->type == CLI_OPT_TYPE_VALUE &&
+ arg[0] == spec->alias &&
+ arg[1] != '\0') {
+ *value = &arg[1];
+ return spec;
+ }
+
+ /* Handle typical -s short options */
+ if (arg[0] == spec->alias) {
+ *value = NULL;
+ return spec;
+ }
+ }
+
+ return NULL;
+}
+
+GIT_INLINE(const cli_opt_spec *) spec_for_arg(cli_opt_parser *parser)
+{
+ const cli_opt_spec *spec;
+ size_t args = 0;
+
+ for (spec = parser->specs; spec->type; ++spec) {
+ if (spec->type == CLI_OPT_TYPE_ARG) {
+ if (args == parser->arg_idx) {
+ parser->arg_idx++;
+ return spec;
+ }
+
+ args++;
+ }
+
+ if (spec->type == CLI_OPT_TYPE_ARGS && args == parser->arg_idx)
+ return spec;
+ }
+
+ return NULL;
+}
+
+GIT_INLINE(int) spec_is_choice(const cli_opt_spec *spec)
+{
+ return ((spec + 1)->type &&
+ ((spec + 1)->usage & CLI_OPT_USAGE_CHOICE));
+}
+
+/*
+ * If we have a choice with switches and bare arguments, and we see
+ * the switch, then we no longer expect the bare argument.
+ */
+GIT_INLINE(void) consume_choices(const cli_opt_spec *spec, cli_opt_parser *parser)
+{
+ /* back up to the beginning of the choices */
+ while (spec->type && (spec->usage & CLI_OPT_USAGE_CHOICE))
+ --spec;
+
+ if (!spec_is_choice(spec))
+ return;
+
+ do {
+ if (spec->type == CLI_OPT_TYPE_ARG)
+ parser->arg_idx++;
+ ++spec;
+ } while(spec->type && (spec->usage & CLI_OPT_USAGE_CHOICE));
+}
+
+static cli_opt_status_t parse_long(cli_opt *opt, cli_opt_parser *parser)
+{
+ const cli_opt_spec *spec;
+ char *arg = parser->args[parser->idx++];
+ const char *value = NULL;
+ int is_negated = 0, has_value = 0;
+
+ opt->arg = arg;
+
+ if ((spec = spec_for_long(&is_negated, &has_value, &value, parser, &arg[2])) == NULL) {
+ opt->spec = NULL;
+ opt->status = CLI_OPT_STATUS_UNKNOWN_OPTION;
+ goto done;
+ }
+
+ opt->spec = spec;
+
+ /* Future options parsed as literal */
+ if (spec->type == CLI_OPT_TYPE_LITERAL)
+ parser->in_literal = 1;
+
+ /* --bool or --no-bool */
+ else if (spec->type == CLI_OPT_TYPE_BOOL && spec->value)
+ *((int *)spec->value) = !is_negated;
+
+ /* --accumulate */
+ else if (spec->type == CLI_OPT_TYPE_ACCUMULATOR && spec->value)
+ *((int *)spec->value) += spec->switch_value ? spec->switch_value : 1;
+
+ /* --switch */
+ else if (spec->type == CLI_OPT_TYPE_SWITCH && spec->value)
+ *((int *)spec->value) = spec->switch_value;
+
+ /* Parse values as "--foo=bar" or "--foo bar" */
+ else if (spec->type == CLI_OPT_TYPE_VALUE) {
+ if (has_value)
+ opt->value = (char *)value;
+ else if ((parser->idx + 1) <= parser->args_len)
+ opt->value = parser->args[parser->idx++];
+
+ if (spec->value)
+ *((char **)spec->value) = opt->value;
+ }
+
+ /* Required argument was not provided */
+ if (spec->type == CLI_OPT_TYPE_VALUE &&
+ !opt->value &&
+ !(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL))
+ opt->status = CLI_OPT_STATUS_MISSING_VALUE;
+ else
+ opt->status = CLI_OPT_STATUS_OK;
+
+ consume_choices(opt->spec, parser);
+
+done:
+ return opt->status;
+}
+
+static cli_opt_status_t parse_short(cli_opt *opt, cli_opt_parser *parser)
+{
+ const cli_opt_spec *spec;
+ char *arg = parser->args[parser->idx++];
+ const char *value;
+
+ opt->arg = arg;
+
+ if ((spec = spec_for_short(&value, parser, &arg[1 + parser->in_short])) == NULL) {
+ opt->spec = NULL;
+ opt->status = CLI_OPT_STATUS_UNKNOWN_OPTION;
+ goto done;
+ }
+
+ opt->spec = spec;
+
+ if (spec->type == CLI_OPT_TYPE_BOOL && spec->value)
+ *((int *)spec->value) = 1;
+
+ else if (spec->type == CLI_OPT_TYPE_ACCUMULATOR && spec->value)
+ *((int *)spec->value) += spec->switch_value ? spec->switch_value : 1;
+
+ else if (spec->type == CLI_OPT_TYPE_SWITCH && spec->value)
+ *((int *)spec->value) = spec->switch_value;
+
+ /* Parse values as "-ifoo" or "-i foo" */
+ else if (spec->type == CLI_OPT_TYPE_VALUE) {
+ if (value)
+ opt->value = (char *)value;
+ else if ((parser->idx + 1) <= parser->args_len)
+ opt->value = parser->args[parser->idx++];
+
+ if (spec->value)
+ *((char **)spec->value) = opt->value;
+ }
+
+ /*
+ * Handle compressed short arguments, like "-fbcd"; see if there's
+ * another character after the one we processed. If not, advance
+ * the parser index.
+ */
+ if (spec->type != CLI_OPT_TYPE_VALUE && arg[2 + parser->in_short] != '\0') {
+ parser->in_short++;
+ parser->idx--;
+ } else {
+ parser->in_short = 0;
+ }
+
+ /* Required argument was not provided */
+ if (spec->type == CLI_OPT_TYPE_VALUE && !opt->value)
+ opt->status = CLI_OPT_STATUS_MISSING_VALUE;
+ else
+ opt->status = CLI_OPT_STATUS_OK;
+
+ consume_choices(opt->spec, parser);
+
+done:
+ return opt->status;
+}
+
+static cli_opt_status_t parse_arg(cli_opt *opt, cli_opt_parser *parser)
+{
+ const cli_opt_spec *spec = spec_for_arg(parser);
+
+ opt->spec = spec;
+ opt->arg = parser->args[parser->idx];
+
+ if (!spec) {
+ parser->idx++;
+ opt->status = CLI_OPT_STATUS_UNKNOWN_OPTION;
+ } else if (spec->type == CLI_OPT_TYPE_ARGS) {
+ if (spec->value)
+ *((char ***)spec->value) = &parser->args[parser->idx];
+
+ /*
+ * We have started a list of arguments; the remainder of
+ * given arguments need not be examined.
+ */
+ parser->in_args = (parser->args_len - parser->idx);
+ parser->idx = parser->args_len;
+ opt->args_len = parser->in_args;
+ opt->status = CLI_OPT_STATUS_OK;
+ } else {
+ if (spec->value)
+ *((char **)spec->value) = parser->args[parser->idx];
+
+ parser->idx++;
+ opt->status = CLI_OPT_STATUS_OK;
+ }
+
+ return opt->status;
+}
+
+static int support_gnu_style(unsigned int flags)
+{
+ if ((flags & CLI_OPT_PARSE_FORCE_GNU) != 0)
+ return 1;
+
+ if ((flags & CLI_OPT_PARSE_GNU) == 0)
+ return 0;
+
+ /* TODO: Windows */
+#if defined(_WIN32) && defined(UNICODE)
+ if (_wgetenv(L"POSIXLY_CORRECT") != NULL)
+ return 0;
+#else
+ if (getenv("POSIXLY_CORRECT") != NULL)
+ return 0;
+#endif
+
+ return 1;
+}
+
+void cli_opt_parser_init(
+ cli_opt_parser *parser,
+ const cli_opt_spec specs[],
+ char **args,
+ size_t args_len,
+ unsigned int flags)
+{
+ assert(parser);
+
+ memset(parser, 0x0, sizeof(cli_opt_parser));
+
+ parser->specs = specs;
+ parser->args = args;
+ parser->args_len = args_len;
+ parser->flags = flags;
+
+ parser->needs_sort = support_gnu_style(flags);
+}
+
+GIT_INLINE(const cli_opt_spec *) spec_for_sort(
+ int *needs_value,
+ const cli_opt_parser *parser,
+ const char *arg)
+{
+ int is_negated, has_value = 0;
+ const char *value;
+ const cli_opt_spec *spec = NULL;
+ size_t idx = 0;
+
+ *needs_value = 0;
+
+ if (strncmp(arg, "--", 2) == 0) {
+ spec = spec_for_long(&is_negated, &has_value, &value, parser, &arg[2]);
+ *needs_value = !has_value;
+ }
+
+ else if (strncmp(arg, "-", 1) == 0) {
+ spec = spec_for_short(&value, parser, &arg[1]);
+
+ /*
+ * Advance through compressed short arguments to see if
+ * the last one has a value, eg "-xvffilename".
+ */
+ while (spec && !value && arg[1 + ++idx] != '\0')
+ spec = spec_for_short(&value, parser, &arg[1 + idx]);
+
+ *needs_value = (value == NULL);
+ }
+
+ return spec;
+}
+
+/*
+ * Some parsers allow for handling arguments like "file1 --help file2";
+ * this is done by re-sorting the arguments in-place; emulate that.
+ */
+static int sort_gnu_style(cli_opt_parser *parser)
+{
+ size_t i, j, insert_idx = parser->idx, offset;
+ const cli_opt_spec *spec;
+ char *option, *value;
+ int needs_value, changed = 0;
+
+ parser->needs_sort = 0;
+
+ for (i = parser->idx; i < parser->args_len; i++) {
+ spec = spec_for_sort(&needs_value, parser, parser->args[i]);
+
+ /* Not a "-" or "--" prefixed option. No change. */
+ if (!spec)
+ continue;
+
+ /* A "--" alone means remaining args are literal. */
+ if (spec->type == CLI_OPT_TYPE_LITERAL)
+ break;
+
+ option = parser->args[i];
+
+ /*
+ * If the argument is a value type and doesn't already
+ * have a value (eg "--foo=bar" or "-fbar") then we need
+ * to copy the next argument as its value.
+ */
+ if (spec->type == CLI_OPT_TYPE_VALUE && needs_value) {
+ /*
+ * A required value is not provided; set parser
+ * index to this value so that we fail on it.
+ */
+ if (i + 1 >= parser->args_len) {
+ parser->idx = i;
+ return 1;
+ }
+
+ value = parser->args[i + 1];
+ offset = 1;
+ } else {
+ value = NULL;
+ offset = 0;
+ }
+
+ /* Caller error if args[0] is an option. */
+ if (i == 0)
+ return 0;
+
+ /* Shift args up one (or two) and insert the option */
+ for (j = i; j > insert_idx; j--)
+ parser->args[j + offset] = parser->args[j - 1];
+
+ parser->args[insert_idx] = option;
+
+ if (value)
+ parser->args[insert_idx + 1] = value;
+
+ insert_idx += (1 + offset);
+ i += offset;
+
+ changed = 1;
+ }
+
+ return changed;
+}
+
+cli_opt_status_t cli_opt_parser_next(cli_opt *opt, cli_opt_parser *parser)
+{
+ assert(opt && parser);
+
+ memset(opt, 0x0, sizeof(cli_opt));
+
+ if (parser->idx >= parser->args_len) {
+ opt->args_len = parser->in_args;
+ return CLI_OPT_STATUS_DONE;
+ }
+
+ /* Handle options in long form, those beginning with "--" */
+ if (strncmp(parser->args[parser->idx], "--", 2) == 0 &&
+ !parser->in_short &&
+ !parser->in_literal)
+ return parse_long(opt, parser);
+
+ /* Handle options in short form, those beginning with "-" */
+ else if (parser->in_short ||
+ (strncmp(parser->args[parser->idx], "-", 1) == 0 &&
+ !parser->in_literal))
+ return parse_short(opt, parser);
+
+ /*
+ * We've reached the first "bare" argument. In POSIX mode, all
+ * remaining items on the command line are arguments. In GNU
+ * mode, there may be long or short options after this. Sort any
+ * options up to this position then re-parse the current position.
+ */
+ if (parser->needs_sort && sort_gnu_style(parser))
+ return cli_opt_parser_next(opt, parser);
+
+ return parse_arg(opt, parser);
+}
+
+GIT_INLINE(int) spec_included(const cli_opt_spec **specs, const cli_opt_spec *spec)
+{
+ const cli_opt_spec **i;
+
+ for (i = specs; *i; ++i) {
+ if (spec == *i)
+ return 1;
+ }
+
+ return 0;
+}
+
+static cli_opt_status_t validate_required(
+ cli_opt *opt,
+ const cli_opt_spec specs[],
+ const cli_opt_spec **given_specs)
+{
+ const cli_opt_spec *spec, *required;
+ int given;
+
+ /*
+ * Iterate over the possible specs to identify requirements and
+ * ensure that those have been given on the command-line.
+ * Note that we can have required *choices*, where one in a
+ * list of choices must be specified.
+ */
+ for (spec = specs, required = NULL, given = 0; spec->type; ++spec) {
+ if (!required && (spec->usage & CLI_OPT_USAGE_REQUIRED)) {
+ required = spec;
+ given = 0;
+ } else if (!required) {
+ continue;
+ }
+
+ if (!given)
+ given = spec_included(given_specs, spec);
+
+ /*
+ * Validate the requirement unless we're in a required
+ * choice. In that case, keep the required state and
+ * validate at the end of the choice list.
+ */
+ if (!spec_is_choice(spec)) {
+ if (!given) {
+ opt->spec = required;
+ opt->status = CLI_OPT_STATUS_MISSING_ARGUMENT;
+ break;
+ }
+
+ required = NULL;
+ given = 0;
+ }
+ }
+
+ return opt->status;
+}
+
+cli_opt_status_t cli_opt_parse(
+ cli_opt *opt,
+ const cli_opt_spec specs[],
+ char **args,
+ size_t args_len,
+ unsigned int flags)
+{
+ cli_opt_parser parser;
+ const cli_opt_spec **given_specs;
+ size_t given_idx = 0;
+
+ cli_opt_parser_init(&parser, specs, args, args_len, flags);
+
+ given_specs = alloca(sizeof(const cli_opt_spec *) * (args_len + 1));
+
+ while (cli_opt_parser_next(opt, &parser)) {
+ if (opt->status != CLI_OPT_STATUS_OK &&
+ opt->status != CLI_OPT_STATUS_DONE)
+ return opt->status;
+
+ if ((opt->spec->usage & CLI_OPT_USAGE_STOP_PARSING))
+ return (opt->status = CLI_OPT_STATUS_DONE);
+
+ given_specs[given_idx++] = opt->spec;
+ }
+
+ given_specs[given_idx] = NULL;
+
+ return validate_required(opt, specs, given_specs);
+}
+
+static int spec_name_fprint(FILE *file, const cli_opt_spec *spec)
+{
+ int error;
+
+ if (spec->type == CLI_OPT_TYPE_ARG)
+ error = fprintf(file, "%s", spec->value_name);
+ else if (spec->type == CLI_OPT_TYPE_ARGS)
+ error = fprintf(file, "%s", spec->value_name);
+ else if (spec->alias && !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
+ error = fprintf(file, "-%c", spec->alias);
+ else
+ error = fprintf(file, "--%s", spec->name);
+
+ return error;
+}
+
+int cli_opt_status_fprint(
+ FILE *file,
+ const char *command,
+ const cli_opt *opt)
+{
+ const cli_opt_spec *choice;
+ int error;
+
+ if (command && (error = fprintf(file, "%s: ", command)) < 0)
+ return error;
+
+ switch (opt->status) {
+ case CLI_OPT_STATUS_DONE:
+ error = fprintf(file, "finished processing arguments (no error)\n");
+ break;
+ case CLI_OPT_STATUS_OK:
+ error = fprintf(file, "no error\n");
+ break;
+ case CLI_OPT_STATUS_UNKNOWN_OPTION:
+ error = fprintf(file, "unknown option: %s\n", opt->arg);
+ break;
+ case CLI_OPT_STATUS_MISSING_VALUE:
+ if ((error = fprintf(file, "argument '")) < 0 ||
+ (error = spec_name_fprint(file, opt->spec)) < 0 ||
+ (error = fprintf(file, "' requires a value.\n")) < 0)
+ break;
+ break;
+ case CLI_OPT_STATUS_MISSING_ARGUMENT:
+ if (spec_is_choice(opt->spec)) {
+ int is_choice = 1;
+
+ if (spec_is_choice((opt->spec)+1))
+ error = fprintf(file, "one of");
+ else
+ error = fprintf(file, "either");
+
+ if (error < 0)
+ break;
+
+ for (choice = opt->spec; is_choice; ++choice) {
+ is_choice = spec_is_choice(choice);
+
+ if (!is_choice)
+ error = fprintf(file, " or");
+ else if (choice != opt->spec)
+ error = fprintf(file, ",");
+
+ if ((error < 0) ||
+ (error = fprintf(file, " '")) < 0 ||
+ (error = spec_name_fprint(file, choice)) < 0 ||
+ (error = fprintf(file, "'")) < 0)
+ break;
+
+ if (!spec_is_choice(choice))
+ break;
+ }
+
+ if ((error < 0) ||
+ (error = fprintf(file, " is required.\n")) < 0)
+ break;
+ } else {
+ if ((error = fprintf(file, "argument '")) < 0 ||
+ (error = spec_name_fprint(file, opt->spec)) < 0 ||
+ (error = fprintf(file, "' is required.\n")) < 0)
+ break;
+ }
+
+ break;
+ default:
+ error = fprintf(file, "unknown status: %d\n", opt->status);
+ break;
+ }
+
+ return error;
+}
+
diff --git a/src/cli/opt.h b/src/cli/opt.h
new file mode 100644
index 000000000..6c1d4603e
--- /dev/null
+++ b/src/cli/opt.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c), Edward Thomson
+ * All rights reserved.
+ *
+ * This file is part of adopt, distributed under the MIT license.
+ * For full terms and conditions, see the included LICENSE file.
+ *
+ * THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT.
+ *
+ * This file was produced by using the `rename.pl` script included with
+ * adopt. The command-line specified was:
+ *
+ * ./rename.pl cli_opt --filename=opt --include=cli.h --inline=GIT_INLINE --header-guard=CLI_opt_h__ --lowercase-status --without-usage
+ */
+
+#ifndef CLI_opt_h__
+#define CLI_opt_h__
+
+#include
+#include
+
+/**
+ * The type of argument to be parsed.
+ */
+typedef enum {
+ CLI_OPT_TYPE_NONE = 0,
+
+ /**
+ * An option that, when specified, sets a given value to true.
+ * This is useful for options like "--debug". A negation
+ * option (beginning with "no-") is implicitly specified; for
+ * example "--no-debug". The `value` pointer in the returned
+ * option will be set to `1` when this is specified, and set to
+ * `0` when the negation "no-" option is specified.
+ */
+ CLI_OPT_TYPE_BOOL,
+
+ /**
+ * An option that, when specified, sets the given `value` pointer
+ * to the specified `switch_value`. This is useful for booleans
+ * where you do not want the implicit negation that comes with an
+ * `CLI_OPT_TYPE_BOOL`, or for switches that multiplex a value, like
+ * setting a mode. For example, `--read` may set the `value` to
+ * `MODE_READ` and `--write` may set the `value` to `MODE_WRITE`.
+ */
+ CLI_OPT_TYPE_SWITCH,
+
+ /**
+ * An option that, when specified, increments the given
+ * `value` by the given `switch_value`. This can be specified
+ * multiple times to continue to increment the `value`.
+ * (For example, "-vvv" to set verbosity to 3.)
+ */
+ CLI_OPT_TYPE_ACCUMULATOR,
+
+ /**
+ * An option that takes a value, for example `-n value`,
+ * `-nvalue`, `--name value` or `--name=value`.
+ */
+ CLI_OPT_TYPE_VALUE,
+
+ /**
+ * A bare "--" that indicates that arguments following this are
+ * literal. This allows callers to specify things that might
+ * otherwise look like options, for example to operate on a file
+ * named "-rf" then you can invoke "program -- -rf" to treat
+ * "-rf" as an argument not an option.
+ */
+ CLI_OPT_TYPE_LITERAL,
+
+ /**
+ * A single argument, not an option. When options are exhausted,
+ * arguments will be matches in the order that they're specified
+ * in the spec list. For example, if two `CLI_OPT_TYPE_ARGS` are
+ * specified, `input_file` and `output_file`, then the first bare
+ * argument on the command line will be `input_file` and the
+ * second will be `output_file`.
+ */
+ CLI_OPT_TYPE_ARG,
+
+ /**
+ * A collection of arguments. This is useful when you want to take
+ * a list of arguments, for example, multiple paths. When specified,
+ * the value will be set to the first argument in the list.
+ */
+ CLI_OPT_TYPE_ARGS,
+} cli_opt_type_t;
+
+/**
+ * Additional information about an option, including parsing
+ * restrictions and usage information to be displayed to the end-user.
+ */
+typedef enum {
+ /** Defaults for the argument. */
+ CLI_OPT_USAGE_DEFAULT = 0,
+
+ /** This argument is required. */
+ CLI_OPT_USAGE_REQUIRED = (1u << 0),
+
+ /**
+ * This is a multiple choice argument, combined with the previous
+ * argument. For example, when the previous argument is `-f` and
+ * this optional is applied to an argument of type `-b` then one
+ * of `-f` or `-b` may be specified.
+ */
+ CLI_OPT_USAGE_CHOICE = (1u << 1),
+
+ /**
+ * This argument short-circuits the remainder of parsing.
+ * Useful for arguments like `--help`.
+ */
+ CLI_OPT_USAGE_STOP_PARSING = (1u << 2),
+
+ /** The argument's value is optional ("-n" or "-n foo") */
+ CLI_OPT_USAGE_VALUE_OPTIONAL = (1u << 3),
+
+ /** This argument should not be displayed in usage. */
+ CLI_OPT_USAGE_HIDDEN = (1u << 4),
+
+ /** In usage, show the long format instead of the abbreviated format. */
+ CLI_OPT_USAGE_SHOW_LONG = (1u << 5),
+} cli_opt_usage_t;
+
+typedef enum {
+ /** Default parsing behavior. */
+ CLI_OPT_PARSE_DEFAULT = 0,
+
+ /**
+ * Parse with GNU `getopt_long` style behavior, where options can
+ * be intermixed with arguments at any position (for example,
+ * "file1 --help file2".) Like `getopt_long`, this can mutate the
+ * arguments given.
+ */
+ CLI_OPT_PARSE_GNU = (1u << 0),
+
+ /**
+ * Force GNU `getopt_long` style behavior; the `POSIXLY_CORRECT`
+ * environment variable is ignored.
+ */
+ CLI_OPT_PARSE_FORCE_GNU = (1u << 1),
+} cli_opt_flag_t;
+
+/** Specification for an available option. */
+typedef struct cli_opt_spec {
+ /** Type of option expected. */
+ cli_opt_type_t type;
+
+ /** Name of the long option. */
+ const char *name;
+
+ /** The alias is the short (one-character) option alias. */
+ const char alias;
+
+ /**
+ * If this spec is of type `CLI_OPT_TYPE_BOOL`, this is a pointer
+ * to an `int` that will be set to `1` if the option is specified.
+ *
+ * If this spec is of type `CLI_OPT_TYPE_SWITCH`, this is a pointer
+ * to an `int` that will be set to the opt's `switch_value` (below)
+ * when this option is specified.
+ *
+ * If this spec is of type `CLI_OPT_TYPE_ACCUMULATOR`, this is a
+ * pointer to an `int` that will be incremented by the opt's
+ * `switch_value` (below). If no `switch_value` is provided then
+ * the value will be incremented by 1.
+ *
+ * If this spec is of type `CLI_OPT_TYPE_VALUE`,
+ * `CLI_OPT_TYPE_VALUE_OPTIONAL`, or `CLI_OPT_TYPE_ARG`, this is
+ * a pointer to a `char *` that will be set to the value
+ * specified on the command line.
+ *
+ * If this spec is of type `CLI_OPT_TYPE_ARGS`, this is a pointer
+ * to a `char **` that will be set to the remaining values
+ * specified on the command line.
+ */
+ void *value;
+
+ /**
+ * If this spec is of type `CLI_OPT_TYPE_SWITCH`, this is the value
+ * to set in the option's `value` pointer when it is specified. If
+ * this spec is of type `CLI_OPT_TYPE_ACCUMULATOR`, this is the value
+ * to increment in the option's `value` pointer when it is
+ * specified. This is ignored for other opt types.
+ */
+ int switch_value;
+
+ /**
+ * Optional usage flags that change parsing behavior and how
+ * usage information is shown to the end-user.
+ */
+ uint32_t usage;
+
+ /**
+ * The name of the value, provided when creating usage information.
+ * This is required only for the functions that display usage
+ * information and only when a spec is of type `CLI_OPT_TYPE_VALUE,
+ * `CLI_OPT_TYPE_ARG` or `CLI_OPT_TYPE_ARGS``.
+ */
+ const char *value_name;
+
+ /**
+ * Optional short description of the option to display to the
+ * end-user. This is only used when creating usage information.
+ */
+ const char *help;
+} cli_opt_spec;
+
+/** Return value for `cli_opt_parser_next`. */
+typedef enum {
+ /** Parsing is complete; there are no more arguments. */
+ CLI_OPT_STATUS_DONE = 0,
+
+ /**
+ * This argument was parsed correctly; the `opt` structure is
+ * populated and the value pointer has been set.
+ */
+ CLI_OPT_STATUS_OK = 1,
+
+ /**
+ * The argument could not be parsed correctly, it does not match
+ * any of the specifications provided.
+ */
+ CLI_OPT_STATUS_UNKNOWN_OPTION = 2,
+
+ /**
+ * The argument matched a spec of type `CLI_OPT_VALUE`, but no value
+ * was provided.
+ */
+ CLI_OPT_STATUS_MISSING_VALUE = 3,
+
+ /** A required argument was not provided. */
+ CLI_OPT_STATUS_MISSING_ARGUMENT = 4,
+} cli_opt_status_t;
+
+/** An option provided on the command-line. */
+typedef struct cli_opt {
+ /** The status of parsing the most recent argument. */
+ cli_opt_status_t status;
+
+ /**
+ * The specification that was provided on the command-line, or
+ * `NULL` if the argument did not match an `cli_opt_spec`.
+ */
+ const cli_opt_spec *spec;
+
+ /**
+ * The argument as it was specified on the command-line, including
+ * dashes, eg, `-f` or `--foo`.
+ */
+ char *arg;
+
+ /**
+ * If the spec is of type `CLI_OPT_VALUE` or `CLI_OPT_VALUE_OPTIONAL`,
+ * this is the value provided to the argument.
+ */
+ char *value;
+
+ /**
+ * If the argument is of type `CLI_OPT_ARGS`, this is the number of
+ * arguments remaining. This value is persisted even when parsing
+ * is complete and `status` == `CLI_OPT_STATUS_DONE`.
+ */
+ size_t args_len;
+} cli_opt;
+
+/* The internal parser state. Callers should not modify this structure. */
+typedef struct cli_opt_parser {
+ const cli_opt_spec *specs;
+ char **args;
+ size_t args_len;
+ unsigned int flags;
+
+ /* Parser state */
+ size_t idx;
+ size_t arg_idx;
+ size_t in_args;
+ size_t in_short;
+ int needs_sort : 1,
+ in_literal : 1;
+} cli_opt_parser;
+
+/**
+ * Parses all the command-line arguments and updates all the options using
+ * the pointers provided. Parsing stops on any invalid argument and
+ * information about the failure will be provided in the opt argument.
+ *
+ * This is the simplest way to parse options; it handles the initialization
+ * (`parser_init`) and looping (`parser_next`).
+ *
+ * @param opt The The `cli_opt` information that failed parsing
+ * @param specs A NULL-terminated array of `cli_opt_spec`s that can be parsed
+ * @param args The arguments that will be parsed
+ * @param args_len The length of arguments to be parsed
+ * @param flags The `cli_opt_flag_t flags for parsing
+ */
+cli_opt_status_t cli_opt_parse(
+ cli_opt *opt,
+ const cli_opt_spec specs[],
+ char **args,
+ size_t args_len,
+ unsigned int flags);
+
+/**
+ * Initializes a parser that parses the given arguments according to the
+ * given specifications.
+ *
+ * @param parser The `cli_opt_parser` that will be initialized
+ * @param specs A NULL-terminated array of `cli_opt_spec`s that can be parsed
+ * @param args The arguments that will be parsed
+ * @param args_len The length of arguments to be parsed
+ * @param flags The `cli_opt_flag_t flags for parsing
+ */
+void cli_opt_parser_init(
+ cli_opt_parser *parser,
+ const cli_opt_spec specs[],
+ char **args,
+ size_t args_len,
+ unsigned int flags);
+
+/**
+ * Parses the next command-line argument and places the information about
+ * the argument into the given `opt` data.
+ *
+ * @param opt The `cli_opt` information parsed from the argument
+ * @param parser An `cli_opt_parser` that has been initialized with
+ * `cli_opt_parser_init`
+ * @return true if the caller should continue iterating, or 0 if there are
+ * no arguments left to process.
+ */
+cli_opt_status_t cli_opt_parser_next(
+ cli_opt *opt,
+ cli_opt_parser *parser);
+
+/**
+ * Prints the status after parsing the most recent argument. This is
+ * useful for printing an error message when an unknown argument was
+ * specified, or when an argument was specified without a value.
+ *
+ * @param file The file to print information to
+ * @param command The name of the command to use when printing (optional)
+ * @param opt The option that failed to parse
+ * @return 0 on success, -1 on failure
+ */
+int cli_opt_status_fprint(
+ FILE *file,
+ const char *command,
+ const cli_opt *opt);
+
+#endif /* CLI_opt_h__ */
diff --git a/src/cli/opt_usage.c b/src/cli/opt_usage.c
new file mode 100644
index 000000000..478b41631
--- /dev/null
+++ b/src/cli/opt_usage.c
@@ -0,0 +1,194 @@
+/*
+ * 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 "cli.h"
+#include "str.h"
+
+static int print_spec_name(git_str *out, const cli_opt_spec *spec)
+{
+ if (spec->type == CLI_OPT_TYPE_VALUE && spec->alias &&
+ !(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL) &&
+ !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
+ return git_str_printf(out, "-%c <%s>", spec->alias, spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_VALUE && spec->alias &&
+ !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
+ return git_str_printf(out, "-%c [<%s>]", spec->alias, spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_VALUE &&
+ !(spec->usage & CLI_OPT_USAGE_VALUE_OPTIONAL))
+ return git_str_printf(out, "--%s[=<%s>]", spec->name, spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_VALUE)
+ return git_str_printf(out, "--%s=<%s>", spec->name, spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_ARG)
+ return git_str_printf(out, "<%s>", spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_ARGS)
+ return git_str_printf(out, "<%s>...", spec->value_name);
+ if (spec->type == CLI_OPT_TYPE_LITERAL)
+ return git_str_printf(out, "--");
+ if (spec->alias && !(spec->usage & CLI_OPT_USAGE_SHOW_LONG))
+ return git_str_printf(out, "-%c", spec->alias);
+ if (spec->name)
+ return git_str_printf(out, "--%s", spec->name);
+
+ GIT_ASSERT(0);
+}
+
+/*
+ * This is similar to adopt's function, but modified to understand
+ * that we have a command ("git") and a "subcommand" ("checkout").
+ * It also understands a terminal's line length and wrap appropriately,
+ * using a `git_str` for storage.
+ */
+int cli_opt_usage_fprint(
+ FILE *file,
+ const char *command,
+ const char *subcommand,
+ const cli_opt_spec specs[])
+{
+ git_str usage = GIT_BUF_INIT, opt = GIT_BUF_INIT;
+ const cli_opt_spec *spec;
+ size_t i, prefixlen, linelen;
+ bool choice = false, next_choice = false, optional = false;
+ int error;
+
+ /* TODO: query actual console width. */
+ int console_width = 80;
+
+ if ((error = git_str_printf(&usage, "usage: %s", command)) < 0)
+ goto done;
+
+ if (subcommand &&
+ (error = git_str_printf(&usage, " %s", subcommand)) < 0)
+ goto done;
+
+ linelen = git_str_len(&usage);
+ prefixlen = linelen + 1;
+
+ for (spec = specs; spec->type; ++spec) {
+ if (!choice)
+ optional = !(spec->usage & CLI_OPT_USAGE_REQUIRED);
+
+ next_choice = !!((spec + 1)->usage & CLI_OPT_USAGE_CHOICE);
+
+ if (spec->usage & CLI_OPT_USAGE_HIDDEN)
+ continue;
+
+ if (choice)
+ git_str_putc(&opt, '|');
+ else
+ git_str_clear(&opt);
+
+ if (optional && !choice)
+ git_str_putc(&opt, '[');
+ if (!optional && !choice && next_choice)
+ git_str_putc(&opt, '(');
+
+ if ((error = print_spec_name(&opt, spec)) < 0)
+ goto done;
+
+ if (!optional && choice && !next_choice)
+ git_str_putc(&opt, ')');
+ else if (optional && !next_choice)
+ git_str_putc(&opt, ']');
+
+ if ((choice = next_choice))
+ continue;
+
+ if (git_str_oom(&opt)) {
+ error = -1;
+ goto done;
+ }
+
+ if (linelen > prefixlen &&
+ console_width > 0 &&
+ linelen + git_str_len(&opt) + 1 > (size_t)console_width) {
+ git_str_putc(&usage, '\n');
+
+ for (i = 0; i < prefixlen; i++)
+ git_str_putc(&usage, ' ');
+
+ linelen = prefixlen;
+ } else {
+ git_str_putc(&usage, ' ');
+ linelen += git_str_len(&opt) + 1;
+ }
+
+ git_str_puts(&usage, git_str_cstr(&opt));
+
+ if (git_str_oom(&usage)) {
+ error = -1;
+ goto done;
+ }
+ }
+
+ error = fprintf(file, "%s\n", git_str_cstr(&usage));
+
+done:
+ error = (error < 0) ? -1 : 0;
+
+ git_str_dispose(&usage);
+ git_str_dispose(&opt);
+ return error;
+}
+
+int cli_opt_usage_error(
+ const char *subcommand,
+ const cli_opt_spec specs[],
+ const cli_opt *invalid_opt)
+{
+ cli_opt_status_fprint(stderr, PROGRAM_NAME, invalid_opt);
+ cli_opt_usage_fprint(stderr, PROGRAM_NAME, subcommand, specs);
+ return CLI_EXIT_USAGE;
+}
+
+int cli_opt_help_fprint(
+ FILE *file,
+ const cli_opt_spec specs[])
+{
+ git_str help = GIT_BUF_INIT;
+ const cli_opt_spec *spec;
+ int error = 0;
+
+ /* Display required arguments first */
+ for (spec = specs; spec->type; ++spec) {
+ if (! (spec->usage & CLI_OPT_USAGE_REQUIRED) ||
+ (spec->usage & CLI_OPT_USAGE_HIDDEN))
+ continue;
+
+ git_str_printf(&help, " ");
+
+ if ((error = print_spec_name(&help, spec)) < 0)
+ goto done;
+
+ git_str_printf(&help, ": %s\n", spec->help);
+ }
+
+ /* Display the remaining arguments */
+ for (spec = specs; spec->type; ++spec) {
+ if ((spec->usage & CLI_OPT_USAGE_REQUIRED) ||
+ (spec->usage & CLI_OPT_USAGE_HIDDEN))
+ continue;
+
+ git_str_printf(&help, " ");
+
+ if ((error = print_spec_name(&help, spec)) < 0)
+ goto done;
+
+ git_str_printf(&help, ": %s\n", spec->help);
+
+ }
+
+ if (git_str_oom(&help) ||
+ p_write(fileno(file), help.ptr, help.size) < 0)
+ error = -1;
+
+done:
+ error = (error < 0) ? -1 : 0;
+
+ git_str_dispose(&help);
+ return error;
+}
+
diff --git a/src/cli/opt_usage.h b/src/cli/opt_usage.h
new file mode 100644
index 000000000..c752494e1
--- /dev/null
+++ b/src/cli/opt_usage.h
@@ -0,0 +1,35 @@
+/*
+ * 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 CLI_opt_usage_h__
+#define CLI_opt_usage_h__
+
+/**
+ * Prints usage information to the given file handle.
+ *
+ * @param file The file to print information to
+ * @param command The name of the command to use when printing
+ * @param subcommand The name of the subcommand (eg "checkout") to use when printing, or NULL to skip
+ * @param specs The specifications allowed by the command
+ * @return 0 on success, -1 on failure
+ */
+int cli_opt_usage_fprint(
+ FILE *file,
+ const char *command,
+ const char *subcommand,
+ const cli_opt_spec specs[]);
+
+int cli_opt_usage_error(
+ const char *subcommand,
+ const cli_opt_spec specs[],
+ const cli_opt *invalid_opt);
+
+int cli_opt_help_fprint(
+ FILE *file,
+ const cli_opt_spec specs[]);
+
+#endif /* CLI_opt_usage_h__ */
diff --git a/src/cli/progress.c b/src/cli/progress.c
new file mode 100644
index 000000000..ba52655e7
--- /dev/null
+++ b/src/cli/progress.c
@@ -0,0 +1,345 @@
+/*
+ * 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
+#include
+#include
+
+#include "progress.h"
+#include "error.h"
+
+/*
+ * Show updates to the percentage and number of objects received
+ * separately from the throughput to give an accurate progress while
+ * avoiding too much noise on the screen.
+ */
+#define PROGRESS_UPDATE_TIME 0.10
+#define THROUGHPUT_UPDATE_TIME 1.00
+
+#define is_nl(c) ((c) == '\r' || (c) == '\n')
+
+#define return_os_error(msg) do { \
+ git_error_set(GIT_ERROR_OS, "%s", msg); return -1; } while(0)
+
+GIT_INLINE(size_t) no_nl_len(const char *str, size_t len)
+{
+ size_t i = 0;
+
+ while (i < len && !is_nl(str[i]))
+ i++;
+
+ return i;
+}
+
+GIT_INLINE(size_t) nl_len(bool *has_nl, const char *str, size_t len)
+{
+ size_t i = no_nl_len(str, len);
+
+ *has_nl = false;
+
+ while (i < len && is_nl(str[i])) {
+ *has_nl = true;
+ i++;
+ }
+
+ return i;
+}
+
+static int progress_write(cli_progress *progress, bool force, git_str *line)
+{
+ bool has_nl;
+ size_t no_nl = no_nl_len(line->ptr, line->size);
+ size_t nl = nl_len(&has_nl, line->ptr + no_nl, line->size - no_nl);
+ double now = git__timer();
+ size_t i;
+
+ /* Avoid spamming the console with progress updates */
+ if (!force && line->ptr[line->size - 1] != '\n' && progress->last_update) {
+ if (now - progress->last_update < PROGRESS_UPDATE_TIME) {
+ git_str_clear(&progress->deferred);
+ git_str_put(&progress->deferred, line->ptr, line->size);
+ return git_str_oom(&progress->deferred) ? -1 : 0;
+ }
+ }
+
+ /*
+ * If there's something on this line already (eg, a progress line
+ * with only a trailing `\r` that we'll print over) then we need
+ * to really print over it in case we're writing a shorter line.
+ */
+ if (printf("%.*s", (int)no_nl, line->ptr) < 0)
+ return_os_error("could not print status");
+
+ if (progress->onscreen.size) {
+ for (i = no_nl; i < progress->onscreen.size; i++) {
+ if (printf(" ") < 0)
+ return_os_error("could not print status");
+ }
+ }
+
+ if (printf("%.*s", (int)nl, line->ptr + no_nl) < 0 ||
+ fflush(stdout) != 0)
+ return_os_error("could not print status");
+
+ git_str_clear(&progress->onscreen);
+
+ if (line->ptr[line->size - 1] == '\n') {
+ progress->last_update = 0;
+ } else {
+ git_str_put(&progress->onscreen, line->ptr, line->size);
+ progress->last_update = now;
+ }
+
+ git_str_clear(&progress->deferred);
+ return git_str_oom(&progress->onscreen) ? -1 : 0;
+}
+
+static int progress_printf(cli_progress *progress, bool force, const char *fmt, ...)
+ GIT_FORMAT_PRINTF(3, 4);
+
+int progress_printf(cli_progress *progress, bool force, const char *fmt, ...)
+{
+ git_str buf = GIT_BUF_INIT;
+ va_list ap;
+ int error;
+
+ va_start(ap, fmt);
+ error = git_str_vprintf(&buf, fmt, ap);
+ va_end(ap);
+
+ if (error < 0)
+ return error;
+
+ error = progress_write(progress, force, &buf);
+
+ git_str_dispose(&buf);
+ return error;
+}
+
+static int progress_complete(cli_progress *progress)
+{
+ if (progress->deferred.size)
+ progress_write(progress, true, &progress->deferred);
+
+ if (progress->onscreen.size)
+ if (printf("\n") < 0)
+ return_os_error("could not print status");
+
+ git_str_clear(&progress->deferred);
+ git_str_clear(&progress->onscreen);
+ progress->last_update = 0;
+ progress->action_start = 0;
+ progress->action_finish = 0;
+
+ return 0;
+}
+
+GIT_INLINE(int) percent(size_t completed, size_t total)
+{
+ if (total == 0)
+ return (completed == 0) ? 100 : 0;
+
+ return (int)(((double)completed / (double)total) * 100);
+}
+
+int cli_progress_fetch_sideband(const char *str, int len, void *payload)
+{
+ cli_progress *progress = (cli_progress *)payload;
+ size_t remain;
+
+ if (len <= 0)
+ return 0;
+
+ /* Accumulate the sideband data, then print it line-at-a-time. */
+ if (git_str_put(&progress->sideband, str, len) < 0)
+ return -1;
+
+ str = progress->sideband.ptr;
+ remain = progress->sideband.size;
+
+ while (remain) {
+ bool has_nl;
+ size_t line_len = nl_len(&has_nl, str, remain);
+
+ if (!has_nl)
+ break;
+
+ if (line_len < INT_MAX) {
+ int error = progress_printf(progress, true,
+ "remote: %.*s", (int)line_len, str);
+
+ if (error < 0)
+ return error;
+ }
+
+ str += line_len;
+ remain -= line_len;
+ }
+
+ git_str_consume_bytes(&progress->sideband, (progress->sideband.size - remain));
+
+ return 0;
+}
+
+static int fetch_receiving(
+ cli_progress *progress,
+ const git_indexer_progress *stats)
+{
+ char *recv_units[] = { "B", "KiB", "MiB", "GiB", "TiB", NULL };
+ char *rate_units[] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", NULL };
+
+ double now, recv_len, rate, elapsed;
+ size_t recv_unit_idx = 0, rate_unit_idx = 0;
+ bool done = (stats->received_objects == stats->total_objects);
+
+ if (!progress->action_start)
+ progress->action_start = git__timer();
+
+ if (done && progress->action_finish)
+ now = progress->action_finish;
+ else if (done)
+ progress->action_finish = now = git__timer();
+ else
+ now = git__timer();
+
+ if (progress->throughput_update &&
+ now - progress->throughput_update < THROUGHPUT_UPDATE_TIME) {
+ elapsed = progress->throughput_update -
+ progress->action_start;
+ recv_len = progress->throughput_bytes;
+ } else {
+ elapsed = now - progress->action_start;
+ recv_len = (double)stats->received_bytes;
+
+ progress->throughput_update = now;
+ progress->throughput_bytes = recv_len;
+ }
+
+ rate = elapsed ? recv_len / elapsed : 0;
+
+ while (recv_len > 1024 && recv_units[recv_unit_idx+1]) {
+ recv_len /= 1024;
+ recv_unit_idx++;
+ }
+
+ while (rate > 1024 && rate_units[rate_unit_idx+1]) {
+ rate /= 1024;
+ rate_unit_idx++;
+ }
+
+ return progress_printf(progress, false,
+ "Receiving objects: %3d%% (%d/%d), %.2f %s | %.2f %s%s\r",
+ percent(stats->received_objects, stats->total_objects),
+ stats->received_objects,
+ stats->total_objects,
+ recv_len, recv_units[recv_unit_idx],
+ rate, rate_units[rate_unit_idx],
+ done ? ", done." : "");
+}
+
+static int fetch_resolving(
+ cli_progress *progress,
+ const git_indexer_progress *stats)
+{
+ bool done = (stats->indexed_deltas == stats->total_deltas);
+
+ return progress_printf(progress, false,
+ "Resolving deltas: %3d%% (%d/%d)%s\r",
+ percent(stats->indexed_deltas, stats->total_deltas),
+ stats->indexed_deltas, stats->total_deltas,
+ done ? ", done." : "");
+}
+
+int cli_progress_fetch_transfer(const git_indexer_progress *stats, void *payload)
+{
+ cli_progress *progress = (cli_progress *)payload;
+ int error = 0;
+
+ switch (progress->action) {
+ case CLI_PROGRESS_NONE:
+ progress->action = CLI_PROGRESS_RECEIVING;
+ /* fall through */
+
+ case CLI_PROGRESS_RECEIVING:
+ if ((error = fetch_receiving(progress, stats)) < 0)
+ break;
+
+ /*
+ * Upgrade from receiving to resolving; do this after the
+ * final call to cli_progress_fetch_receiving (above) to
+ * ensure that we've printed a final "done" string after
+ * any sideband data.
+ */
+ if (!stats->indexed_deltas)
+ break;
+
+ progress_complete(progress);
+ progress->action = CLI_PROGRESS_RESOLVING;
+ /* fall through */
+
+ case CLI_PROGRESS_RESOLVING:
+ error = fetch_resolving(progress, stats);
+ break;
+
+ default:
+ /* should not be reached */
+ GIT_ASSERT(!"unexpected progress state");
+ }
+
+ return error;
+}
+
+void cli_progress_checkout(
+ const char *path,
+ size_t completed_steps,
+ size_t total_steps,
+ void *payload)
+{
+ cli_progress *progress = (cli_progress *)payload;
+ bool done = (completed_steps == total_steps);
+
+ GIT_UNUSED(path);
+
+ if (progress->action != CLI_PROGRESS_CHECKING_OUT) {
+ progress_complete(progress);
+ progress->action = CLI_PROGRESS_CHECKING_OUT;
+ }
+
+ progress_printf(progress, false,
+ "Checking out files: %3d%% (%" PRIuZ "/%" PRIuZ ")%s\r",
+ percent(completed_steps, total_steps),
+ completed_steps, total_steps,
+ done ? ", done." : "");
+}
+
+int cli_progress_abort(cli_progress *progress)
+{
+ if (progress->onscreen.size > 0 && printf("\n") < 0)
+ return_os_error("could not print status");
+
+ return 0;
+}
+
+int cli_progress_finish(cli_progress *progress)
+{
+ int error = progress->action ? progress_complete(progress) : 0;
+
+ progress->action = 0;
+ return error;
+}
+
+void cli_progress_dispose(cli_progress *progress)
+{
+ if (progress == NULL)
+ return;
+
+ git_str_dispose(&progress->sideband);
+ git_str_dispose(&progress->onscreen);
+ git_str_dispose(&progress->deferred);
+
+ memset(progress, 0, sizeof(cli_progress));
+}
diff --git a/src/cli/progress.h b/src/cli/progress.h
new file mode 100644
index 000000000..7a445ec29
--- /dev/null
+++ b/src/cli/progress.h
@@ -0,0 +1,117 @@
+/*
+ * 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 CLI_progress_h__
+#define CLI_progress_h__
+
+#include
+#include "str.h"
+
+/*
+ * A general purpose set of progress printing functions. An individual
+ * `cli_progress` object is capable of displaying progress for a single
+ * function, even if that function displays multiple pieces of progress
+ * (like `git_clone`). `cli_progress_finish` should be called after
+ * any function invocation to re-set state.
+ */
+
+typedef enum {
+ CLI_PROGRESS_NONE,
+ CLI_PROGRESS_RECEIVING,
+ CLI_PROGRESS_RESOLVING,
+ CLI_PROGRESS_CHECKING_OUT
+} cli_progress_t;
+
+typedef struct {
+ cli_progress_t action;
+
+ /* Actions may time themselves (eg fetch) but are not required to */
+ double action_start;
+ double action_finish;
+
+ /* Last console update, avoid too frequent updates. */
+ double last_update;
+
+ /* Accumulators for partial output and deferred updates. */
+ git_str sideband;
+ git_str onscreen;
+ git_str deferred;
+
+ /* Last update about throughput */
+ double throughput_update;
+ double throughput_bytes;
+} cli_progress;
+
+#define CLI_PROGRESS_INIT { 0 }
+
+/**
+ * Prints sideband data from fetch to the console. Suitable for a
+ * `sideband_progress` callback for `git_fetch_options`.
+ *
+ * @param str The sideband string
+ * @param len The length of the sideband string
+ * @param payload A pointer to the cli_progress
+ * @return 0 on success, -1 on failure
+ */
+extern int cli_progress_fetch_sideband(
+ const char *str,
+ int len,
+ void *payload);
+
+/**
+ * Prints fetch transfer statistics to the console. Suitable for a
+ * `transfer_progress` callback for `git_fetch_options`.
+ *
+ * @param stats The indexer stats
+ * @param payload A pointer to the cli_progress
+ * @return 0 on success, -1 on failure
+ */
+extern int cli_progress_fetch_transfer(
+ const git_indexer_progress *stats,
+ void *payload);
+
+/**
+ * Prints checkout progress to the console. Suitable for a
+ * `progress_cb` callback for `git_checkout_options`.
+ *
+ * @param path The path being written
+ * @param completed_steps The completed checkout steps
+ * @param total_steps The total number of checkout steps
+ * @param payload A pointer to the cli_progress
+ */
+extern void cli_progress_checkout(
+ const char *path,
+ size_t completed_steps,
+ size_t total_steps,
+ void *payload);
+
+/**
+ * Stop displaying progress quickly; suitable for stopping an application
+ * quickly. Does not display any lines that were buffered, just gets the
+ * console back to a sensible place.
+ *
+ * @param progress The progress information
+ * @return 0 on success, -1 on failure
+ */
+extern int cli_progress_abort(cli_progress *progress);
+
+/**
+ * Finishes displaying progress; flushes any buffered output.
+ *
+ * @param progress The progress information
+ * @return 0 on success, -1 on failure
+ */
+extern int cli_progress_finish(cli_progress *progress);
+
+/**
+ * Disposes the progress information.
+ *
+ * @param progress The progress information
+ */
+extern void cli_progress_dispose(cli_progress *progress);
+
+#endif /* CLI_progress_h__ */
diff --git a/src/cli/sighandler.h b/src/cli/sighandler.h
new file mode 100644
index 000000000..877223e02
--- /dev/null
+++ b/src/cli/sighandler.h
@@ -0,0 +1,20 @@
+/*
+ * 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 CLI_sighandler_h__
+#define CLI_sighandler_h__
+
+/**
+ * Sets up a signal handler that will run when the process is interrupted
+ * (via SIGINT on POSIX or Control-C or Control-Break on Windows).
+ *
+ * @param handler The function to run on interrupt
+ * @return 0 on success, -1 on failure
+ */
+int cli_sighandler_set_interrupt(void (*handler)(void));
+
+#endif /* CLI_sighandler_h__ */
diff --git a/src/cli/unix/sighandler.c b/src/cli/unix/sighandler.c
new file mode 100644
index 000000000..6b4982d48
--- /dev/null
+++ b/src/cli/unix/sighandler.c
@@ -0,0 +1,36 @@
+/*
+ * 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
+#include
+#include "git2_util.h"
+#include "cli.h"
+
+static void (*interrupt_handler)(void) = NULL;
+
+static void interrupt_proxy(int signal)
+{
+ GIT_UNUSED(signal);
+ interrupt_handler();
+}
+
+int cli_sighandler_set_interrupt(void (*handler)(void))
+{
+ void (*result)(int);
+
+ if ((interrupt_handler = handler) != NULL)
+ result = signal(SIGINT, interrupt_proxy);
+ else
+ result = signal(SIGINT, SIG_DFL);
+
+ if (result == SIG_ERR) {
+ git_error_set(GIT_ERROR_OS, "could not set signal handler");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/win32/precompiled.c b/src/cli/win32/precompiled.c
similarity index 100%
rename from src/win32/precompiled.c
rename to src/cli/win32/precompiled.c
diff --git a/src/cli/win32/precompiled.h b/src/cli/win32/precompiled.h
new file mode 100644
index 000000000..b0309b864
--- /dev/null
+++ b/src/cli/win32/precompiled.h
@@ -0,0 +1,3 @@
+#include
+
+#include "cli.h"
diff --git a/src/cli/win32/sighandler.c b/src/cli/win32/sighandler.c
new file mode 100644
index 000000000..cc0b64640
--- /dev/null
+++ b/src/cli/win32/sighandler.c
@@ -0,0 +1,37 @@
+/*
+ * 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 "git2_util.h"
+#include
+
+#include "cli.h"
+
+static void (*interrupt_handler)(void) = NULL;
+
+static BOOL WINAPI interrupt_proxy(DWORD signal)
+{
+ GIT_UNUSED(signal);
+ interrupt_handler();
+ return TRUE;
+}
+
+int cli_sighandler_set_interrupt(void (*handler)(void))
+{
+ BOOL result;
+
+ if ((interrupt_handler = handler) != NULL)
+ result = SetConsoleCtrlHandler(interrupt_proxy, FALSE);
+ else
+ result = SetConsoleCtrlHandler(NULL, FALSE);
+
+ if (!result) {
+ git_error_set(GIT_ERROR_OS, "could not set control control handler");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/features.h.in b/src/features.h.in
index f920135da..fbf0cab60 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -46,8 +46,17 @@
#cmakedefine GIT_SHA1_WIN32 1
#cmakedefine GIT_SHA1_COMMON_CRYPTO 1
#cmakedefine GIT_SHA1_OPENSSL 1
+#cmakedefine GIT_SHA1_OPENSSL_DYNAMIC 1
#cmakedefine GIT_SHA1_MBEDTLS 1
+#cmakedefine GIT_SHA256_BUILTIN 1
+#cmakedefine GIT_SHA256_WIN32 1
+#cmakedefine GIT_SHA256_COMMON_CRYPTO 1
+#cmakedefine GIT_SHA256_OPENSSL 1
+#cmakedefine GIT_SHA256_OPENSSL_DYNAMIC 1
+#cmakedefine GIT_SHA256_MBEDTLS 1
+
#cmakedefine GIT_RAND_GETENTROPY 1
+#cmakedefine GIT_RAND_GETLOADAVG 1
#endif
diff --git a/src/hash/sha1.h b/src/hash/sha1.h
deleted file mode 100644
index 4b4dae3f8..000000000
--- a/src/hash/sha1.h
+++ /dev/null
@@ -1,40 +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_hash_sha1_h__
-#define INCLUDE_hash_sha1_h__
-
-#include "common.h"
-
-typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
-
-#if defined(GIT_SHA1_COLLISIONDETECT)
-# include "sha1/collisiondetect.h"
-#elif defined(GIT_SHA1_COMMON_CRYPTO)
-# include "sha1/common_crypto.h"
-#elif defined(GIT_SHA1_OPENSSL)
-# include "sha1/openssl.h"
-#elif defined(GIT_SHA1_WIN32)
-# include "sha1/win32.h"
-#elif defined(GIT_SHA1_MBEDTLS)
-# include "sha1/mbedtls.h"
-#else
-# include "sha1/generic.h"
-#endif
-
-#define GIT_HASH_SHA1_SIZE 20
-
-int git_hash_sha1_global_init(void);
-
-int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx);
-void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx);
-
-int git_hash_sha1_init(git_hash_sha1_ctx *c);
-int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len);
-int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *c);
-
-#endif
diff --git a/src/hash/sha1/generic.c b/src/hash/sha1/generic.c
deleted file mode 100644
index 85b34c578..000000000
--- a/src/hash/sha1/generic.c
+++ /dev/null
@@ -1,300 +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 "generic.h"
-
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-
-/*
- * Force usage of rol or ror by selecting the one with the smaller constant.
- * It _can_ generate slightly smaller code (a constant of 1 is special), but
- * perhaps more importantly it's possibly faster on any uarch that does a
- * rotate with a loop.
- */
-
-#define SHA_ASM(op, x, n) (__extension__ ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; }))
-#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
-#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
-
-#else
-
-#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
-#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
-#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
-
-#endif
-
-/*
- * If you have 32 registers or more, the compiler can (and should)
- * try to change the array[] accesses into registers. However, on
- * machines with less than ~25 registers, that won't really work,
- * and at least gcc will make an unholy mess of it.
- *
- * So to avoid that mess which just slows things down, we force
- * the stores to memory to actually happen (we might be better off
- * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
- * suggested by Artur Skawina - that will also make gcc unable to
- * try to do the silly "optimize away loads" part because it won't
- * see what the value will be).
- *
- * Ben Herrenschmidt reports that on PPC, the C version comes close
- * to the optimized asm with this (ie on PPC you don't want that
- * 'volatile', since there are lots of registers).
- *
- * On ARM we get the best code generation by forcing a full memory barrier
- * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
- * the stack frame size simply explode and performance goes down the drain.
- */
-
-#if defined(__i386__) || defined(__x86_64__)
- #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
-#elif defined(__GNUC__) && defined(__arm__)
- #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
-#else
- #define setW(x, val) (W(x) = (val))
-#endif
-
-/*
- * Performance might be improved if the CPU architecture is OK with
- * unaligned 32-bit loads and a fast ntohl() is available.
- * Otherwise fall back to byte loads and shifts which is portable,
- * and is faster on architectures with memory alignment issues.
- */
-
-#if defined(__i386__) || defined(__x86_64__) || \
- defined(_M_IX86) || defined(_M_X64) || \
- defined(__ppc__) || defined(__ppc64__) || \
- defined(__powerpc__) || defined(__powerpc64__) || \
- defined(__s390__) || defined(__s390x__)
-
-#define get_be32(p) ntohl(*(const unsigned int *)(p))
-#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
-
-#else
-
-#define get_be32(p) ( \
- (*((const unsigned char *)(p) + 0) << 24) | \
- (*((const unsigned char *)(p) + 1) << 16) | \
- (*((const unsigned char *)(p) + 2) << 8) | \
- (*((const unsigned char *)(p) + 3) << 0) )
-#define put_be32(p, v) do { \
- unsigned int __v = (v); \
- *((unsigned char *)(p) + 0) = __v >> 24; \
- *((unsigned char *)(p) + 1) = __v >> 16; \
- *((unsigned char *)(p) + 2) = __v >> 8; \
- *((unsigned char *)(p) + 3) = __v >> 0; } while (0)
-
-#endif
-
-/* This "rolls" over the 512-bit array */
-#define W(x) (array[(x)&15])
-
-/*
- * Where do we get the source from? The first 16 iterations get it from
- * the input data, the next mix it from the 512-bit array.
- */
-#define SHA_SRC(t) get_be32(data + t)
-#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
-
-#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
- unsigned int TEMP = input(t); setW(t, TEMP); \
- E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
- B = SHA_ROR(B, 2); } while (0)
-
-#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
-#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
-#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
-#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
-#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E )
-
-static void hash__block(git_hash_sha1_ctx *ctx, const unsigned int *data)
-{
- unsigned int A,B,C,D,E;
- unsigned int array[16];
-
- A = ctx->H[0];
- B = ctx->H[1];
- C = ctx->H[2];
- D = ctx->H[3];
- E = ctx->H[4];
-
- /* Round 1 - iterations 0-16 take their input from 'data' */
- T_0_15( 0, A, B, C, D, E);
- T_0_15( 1, E, A, B, C, D);
- T_0_15( 2, D, E, A, B, C);
- T_0_15( 3, C, D, E, A, B);
- T_0_15( 4, B, C, D, E, A);
- T_0_15( 5, A, B, C, D, E);
- T_0_15( 6, E, A, B, C, D);
- T_0_15( 7, D, E, A, B, C);
- T_0_15( 8, C, D, E, A, B);
- T_0_15( 9, B, C, D, E, A);
- T_0_15(10, A, B, C, D, E);
- T_0_15(11, E, A, B, C, D);
- T_0_15(12, D, E, A, B, C);
- T_0_15(13, C, D, E, A, B);
- T_0_15(14, B, C, D, E, A);
- T_0_15(15, A, B, C, D, E);
-
- /* Round 1 - tail. Input from 512-bit mixing array */
- T_16_19(16, E, A, B, C, D);
- T_16_19(17, D, E, A, B, C);
- T_16_19(18, C, D, E, A, B);
- T_16_19(19, B, C, D, E, A);
-
- /* Round 2 */
- T_20_39(20, A, B, C, D, E);
- T_20_39(21, E, A, B, C, D);
- T_20_39(22, D, E, A, B, C);
- T_20_39(23, C, D, E, A, B);
- T_20_39(24, B, C, D, E, A);
- T_20_39(25, A, B, C, D, E);
- T_20_39(26, E, A, B, C, D);
- T_20_39(27, D, E, A, B, C);
- T_20_39(28, C, D, E, A, B);
- T_20_39(29, B, C, D, E, A);
- T_20_39(30, A, B, C, D, E);
- T_20_39(31, E, A, B, C, D);
- T_20_39(32, D, E, A, B, C);
- T_20_39(33, C, D, E, A, B);
- T_20_39(34, B, C, D, E, A);
- T_20_39(35, A, B, C, D, E);
- T_20_39(36, E, A, B, C, D);
- T_20_39(37, D, E, A, B, C);
- T_20_39(38, C, D, E, A, B);
- T_20_39(39, B, C, D, E, A);
-
- /* Round 3 */
- T_40_59(40, A, B, C, D, E);
- T_40_59(41, E, A, B, C, D);
- T_40_59(42, D, E, A, B, C);
- T_40_59(43, C, D, E, A, B);
- T_40_59(44, B, C, D, E, A);
- T_40_59(45, A, B, C, D, E);
- T_40_59(46, E, A, B, C, D);
- T_40_59(47, D, E, A, B, C);
- T_40_59(48, C, D, E, A, B);
- T_40_59(49, B, C, D, E, A);
- T_40_59(50, A, B, C, D, E);
- T_40_59(51, E, A, B, C, D);
- T_40_59(52, D, E, A, B, C);
- T_40_59(53, C, D, E, A, B);
- T_40_59(54, B, C, D, E, A);
- T_40_59(55, A, B, C, D, E);
- T_40_59(56, E, A, B, C, D);
- T_40_59(57, D, E, A, B, C);
- T_40_59(58, C, D, E, A, B);
- T_40_59(59, B, C, D, E, A);
-
- /* Round 4 */
- T_60_79(60, A, B, C, D, E);
- T_60_79(61, E, A, B, C, D);
- T_60_79(62, D, E, A, B, C);
- T_60_79(63, C, D, E, A, B);
- T_60_79(64, B, C, D, E, A);
- T_60_79(65, A, B, C, D, E);
- T_60_79(66, E, A, B, C, D);
- T_60_79(67, D, E, A, B, C);
- T_60_79(68, C, D, E, A, B);
- T_60_79(69, B, C, D, E, A);
- T_60_79(70, A, B, C, D, E);
- T_60_79(71, E, A, B, C, D);
- T_60_79(72, D, E, A, B, C);
- T_60_79(73, C, D, E, A, B);
- T_60_79(74, B, C, D, E, A);
- T_60_79(75, A, B, C, D, E);
- T_60_79(76, E, A, B, C, D);
- T_60_79(77, D, E, A, B, C);
- T_60_79(78, C, D, E, A, B);
- T_60_79(79, B, C, D, E, A);
-
- ctx->H[0] += A;
- ctx->H[1] += B;
- ctx->H[2] += C;
- ctx->H[3] += D;
- ctx->H[4] += E;
-}
-
-int git_hash_sha1_global_init(void)
-{
- return 0;
-}
-
-int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
-{
- return git_hash_sha1_init(ctx);
-}
-
-void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
-{
- GIT_UNUSED(ctx);
-}
-
-int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
-{
- ctx->size = 0;
-
- /* Initialize H with the magic constants (see FIPS180 for constants) */
- ctx->H[0] = 0x67452301;
- ctx->H[1] = 0xefcdab89;
- ctx->H[2] = 0x98badcfe;
- ctx->H[3] = 0x10325476;
- ctx->H[4] = 0xc3d2e1f0;
-
- return 0;
-}
-
-int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
-{
- unsigned int lenW = ctx->size & 63;
-
- ctx->size += len;
-
- /* Read the data into W and process blocks as they get full */
- if (lenW) {
- unsigned int left = 64 - lenW;
- if (len < left)
- left = (unsigned int)len;
- memcpy(lenW + (char *)ctx->W, data, left);
- lenW = (lenW + left) & 63;
- len -= left;
- data = ((const char *)data + left);
- if (lenW)
- return 0;
- hash__block(ctx, ctx->W);
- }
- while (len >= 64) {
- hash__block(ctx, data);
- data = ((const char *)data + 64);
- len -= 64;
- }
- if (len)
- memcpy(ctx->W, data, len);
-
- return 0;
-}
-
-int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
-{
- static const unsigned char pad[64] = { 0x80 };
- unsigned int padlen[2];
- int i;
-
- /* Pad with a binary 1 (ie 0x80), then zeroes, then length */
- padlen[0] = htonl((uint32_t)(ctx->size >> 29));
- padlen[1] = htonl((uint32_t)(ctx->size << 3));
-
- i = ctx->size & 63;
- git_hash_sha1_update(ctx, pad, 1+ (63 & (55 - i)));
- git_hash_sha1_update(ctx, padlen, 8);
-
- /* Output hash */
- for (i = 0; i < 5; i++)
- put_be32(out + i*4, ctx->H[i]);
-
- return 0;
-}
diff --git a/src/hash/sha1/openssl.c b/src/hash/sha1/openssl.c
deleted file mode 100644
index 64bf99b3c..000000000
--- a/src/hash/sha1/openssl.c
+++ /dev/null
@@ -1,59 +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 "openssl.h"
-
-int git_hash_sha1_global_init(void)
-{
- return 0;
-}
-
-int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
-{
- return git_hash_sha1_init(ctx);
-}
-
-void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
-{
- GIT_UNUSED(ctx);
-}
-
-int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
-{
- GIT_ASSERT_ARG(ctx);
-
- if (SHA1_Init(&ctx->c) != 1) {
- git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context");
- return -1;
- }
-
- return 0;
-}
-
-int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
-{
- GIT_ASSERT_ARG(ctx);
-
- if (SHA1_Update(&ctx->c, data, len) != 1) {
- git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash");
- return -1;
- }
-
- return 0;
-}
-
-int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
-{
- GIT_ASSERT_ARG(ctx);
-
- if (SHA1_Final(out, &ctx->c) != 1) {
- git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash");
- return -1;
- }
-
- return 0;
-}
diff --git a/src/hash/sha1/win32.c b/src/hash/sha1/win32.c
deleted file mode 100644
index b89dfbad8..000000000
--- a/src/hash/sha1/win32.c
+++ /dev/null
@@ -1,333 +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 "win32.h"
-
-#include "runtime.h"
-
-#include
-#include
-
-#define GIT_HASH_CNG_DLL_NAME "bcrypt.dll"
-
-/* BCRYPT_SHA1_ALGORITHM */
-#define GIT_HASH_CNG_HASH_TYPE L"SHA1"
-
-/* BCRYPT_OBJECT_LENGTH */
-#define GIT_HASH_CNG_HASH_OBJECT_LEN L"ObjectLength"
-
-/* BCRYPT_HASH_REUSEABLE_FLAGS */
-#define GIT_HASH_CNG_HASH_REUSABLE 0x00000020
-
-static git_hash_prov hash_prov = {0};
-
-/* Hash initialization */
-
-/* Initialize CNG, if available */
-GIT_INLINE(int) hash_cng_prov_init(void)
-{
- char dll_path[MAX_PATH];
- DWORD dll_path_len, size_len;
-
- /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */
- if (!git_has_win32_version(6, 0, 1)) {
- git_error_set(GIT_ERROR_SHA1, "CryptoNG is not supported on this platform");
- return -1;
- }
-
- /* Load bcrypt.dll explicitly from the system directory */
- if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 ||
- dll_path_len > MAX_PATH ||
- StringCchCat(dll_path, MAX_PATH, "\\") < 0 ||
- StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 ||
- (hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) {
- git_error_set(GIT_ERROR_SHA1, "CryptoNG library could not be loaded");
- return -1;
- }
-
- /* Load the function addresses */
- if ((hash_prov.prov.cng.open_algorithm_provider = (hash_win32_cng_open_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptOpenAlgorithmProvider")) == NULL ||
- (hash_prov.prov.cng.get_property = (hash_win32_cng_get_property_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptGetProperty")) == NULL ||
- (hash_prov.prov.cng.create_hash = (hash_win32_cng_create_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCreateHash")) == NULL ||
- (hash_prov.prov.cng.finish_hash = (hash_win32_cng_finish_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptFinishHash")) == NULL ||
- (hash_prov.prov.cng.hash_data = (hash_win32_cng_hash_data_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptHashData")) == NULL ||
- (hash_prov.prov.cng.destroy_hash = (hash_win32_cng_destroy_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptDestroyHash")) == NULL ||
- (hash_prov.prov.cng.close_algorithm_provider = (hash_win32_cng_close_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCloseAlgorithmProvider")) == NULL) {
- FreeLibrary(hash_prov.prov.cng.dll);
-
- git_error_set(GIT_ERROR_OS, "CryptoNG functions could not be loaded");
- return -1;
- }
-
- /* Load the SHA1 algorithm */
- if (hash_prov.prov.cng.open_algorithm_provider(&hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0) {
- FreeLibrary(hash_prov.prov.cng.dll);
-
- git_error_set(GIT_ERROR_OS, "algorithm provider could not be initialized");
- return -1;
- }
-
- /* Get storage space for the hash object */
- if (hash_prov.prov.cng.get_property(hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_prov.prov.cng.hash_object_size, sizeof(DWORD), &size_len, 0) < 0) {
- hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0);
- FreeLibrary(hash_prov.prov.cng.dll);
-
- git_error_set(GIT_ERROR_OS, "algorithm handle could not be found");
- return -1;
- }
-
- hash_prov.type = CNG;
- return 0;
-}
-
-GIT_INLINE(void) hash_cng_prov_shutdown(void)
-{
- hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0);
- FreeLibrary(hash_prov.prov.cng.dll);
-
- hash_prov.type = INVALID;
-}
-
-/* Initialize CryptoAPI */
-GIT_INLINE(int) hash_cryptoapi_prov_init()
-{
- if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
- git_error_set(GIT_ERROR_OS, "legacy hash context could not be started");
- return -1;
- }
-
- hash_prov.type = CRYPTOAPI;
- return 0;
-}
-
-GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void)
-{
- CryptReleaseContext(hash_prov.prov.cryptoapi.handle, 0);
-
- hash_prov.type = INVALID;
-}
-
-static void sha1_shutdown(void)
-{
- if (hash_prov.type == CNG)
- hash_cng_prov_shutdown();
- else if(hash_prov.type == CRYPTOAPI)
- hash_cryptoapi_prov_shutdown();
-}
-
-int git_hash_sha1_global_init(void)
-{
- int error = 0;
-
- if (hash_prov.type != INVALID)
- return 0;
-
- if ((error = hash_cng_prov_init()) < 0)
- error = hash_cryptoapi_prov_init();
-
- if (!error)
- error = git_runtime_shutdown_register(sha1_shutdown);
-
- return error;
-}
-
-/* CryptoAPI: available in Windows XP and newer */
-
-GIT_INLINE(int) hash_ctx_cryptoapi_init(git_hash_sha1_ctx *ctx)
-{
- ctx->type = CRYPTOAPI;
- ctx->prov = &hash_prov;
-
- return git_hash_sha1_init(ctx);
-}
-
-GIT_INLINE(int) hash_cryptoapi_init(git_hash_sha1_ctx *ctx)
-{
- if (ctx->ctx.cryptoapi.valid)
- CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
-
- if (!CryptCreateHash(ctx->prov->prov.cryptoapi.handle, CALG_SHA1, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) {
- ctx->ctx.cryptoapi.valid = 0;
- git_error_set(GIT_ERROR_OS, "legacy hash implementation could not be created");
- return -1;
- }
-
- ctx->ctx.cryptoapi.valid = 1;
- return 0;
-}
-
-GIT_INLINE(int) hash_cryptoapi_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len)
-{
- const BYTE *data = (BYTE *)_data;
-
- GIT_ASSERT(ctx->ctx.cryptoapi.valid);
-
- while (len > 0) {
- DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len;
-
- if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0)) {
- git_error_set(GIT_ERROR_OS, "legacy hash data could not be updated");
- return -1;
- }
-
- data += chunk;
- len -= chunk;
- }
-
- return 0;
-}
-
-GIT_INLINE(int) hash_cryptoapi_final(unsigned char *out, git_hash_sha1_ctx *ctx)
-{
- DWORD len = GIT_HASH_SHA1_SIZE;
- int error = 0;
-
- GIT_ASSERT(ctx->ctx.cryptoapi.valid);
-
- if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out, &len, 0)) {
- git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished");
- error = -1;
- }
-
- CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
- ctx->ctx.cryptoapi.valid = 0;
-
- return error;
-}
-
-GIT_INLINE(void) hash_ctx_cryptoapi_cleanup(git_hash_sha1_ctx *ctx)
-{
- if (ctx->ctx.cryptoapi.valid)
- CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
-}
-
-/* CNG: Available in Windows Server 2008 and newer */
-
-GIT_INLINE(int) hash_ctx_cng_init(git_hash_sha1_ctx *ctx)
-{
- if ((ctx->ctx.cng.hash_object = git__malloc(hash_prov.prov.cng.hash_object_size)) == NULL)
- return -1;
-
- if (hash_prov.prov.cng.create_hash(hash_prov.prov.cng.handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_prov.prov.cng.hash_object_size, NULL, 0, 0) < 0) {
- git__free(ctx->ctx.cng.hash_object);
-
- git_error_set(GIT_ERROR_OS, "hash implementation could not be created");
- return -1;
- }
-
- ctx->type = CNG;
- ctx->prov = &hash_prov;
-
- return 0;
-}
-
-GIT_INLINE(int) hash_cng_init(git_hash_sha1_ctx *ctx)
-{
- BYTE hash[GIT_OID_RAWSZ];
-
- if (!ctx->ctx.cng.updated)
- return 0;
-
- /* CNG needs to be finished to restart */
- if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, GIT_OID_RAWSZ, 0) < 0) {
- git_error_set(GIT_ERROR_OS, "hash implementation could not be finished");
- return -1;
- }
-
- ctx->ctx.cng.updated = 0;
-
- return 0;
-}
-
-GIT_INLINE(int) hash_cng_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len)
-{
- PBYTE data = (PBYTE)_data;
-
- while (len > 0) {
- ULONG chunk = (len > ULONG_MAX) ? ULONG_MAX : (ULONG)len;
-
- if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0) {
- git_error_set(GIT_ERROR_OS, "hash could not be updated");
- return -1;
- }
-
- data += chunk;
- len -= chunk;
- }
-
- return 0;
-}
-
-GIT_INLINE(int) hash_cng_final(unsigned char *out, git_hash_sha1_ctx *ctx)
-{
- if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out, GIT_HASH_SHA1_SIZE, 0) < 0) {
- git_error_set(GIT_ERROR_OS, "hash could not be finished");
- return -1;
- }
-
- ctx->ctx.cng.updated = 0;
-
- return 0;
-}
-
-GIT_INLINE(void) hash_ctx_cng_cleanup(git_hash_sha1_ctx *ctx)
-{
- ctx->prov->prov.cng.destroy_hash(ctx->ctx.cng.hash_handle);
- git__free(ctx->ctx.cng.hash_object);
-}
-
-/* Indirection between CryptoAPI and CNG */
-
-int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
-{
- int error = 0;
-
- GIT_ASSERT_ARG(ctx);
-
- /*
- * When compiled with GIT_THREADS, the global hash_prov data is
- * initialized with git_libgit2_init. Otherwise, it must be initialized
- * at first use.
- */
- if (hash_prov.type == INVALID && (error = git_hash_sha1_global_init()) < 0)
- return error;
-
- memset(ctx, 0x0, sizeof(git_hash_sha1_ctx));
-
- return (hash_prov.type == CNG) ? hash_ctx_cng_init(ctx) : hash_ctx_cryptoapi_init(ctx);
-}
-
-int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
-{
- GIT_ASSERT_ARG(ctx);
- GIT_ASSERT_ARG(ctx->type);
- return (ctx->type == CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx);
-}
-
-int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
-{
- GIT_ASSERT_ARG(ctx);
- GIT_ASSERT_ARG(ctx->type);
- return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len);
-}
-
-int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
-{
- GIT_ASSERT_ARG(ctx);
- GIT_ASSERT_ARG(ctx->type);
- return (ctx->type == CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx);
-}
-
-void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
-{
- if (!ctx)
- return;
- else if (ctx->type == CNG)
- hash_ctx_cng_cleanup(ctx);
- else if(ctx->type == CRYPTOAPI)
- hash_ctx_cryptoapi_cleanup(ctx);
-}
diff --git a/src/hash/sha1/win32.h b/src/hash/sha1/win32.h
deleted file mode 100644
index 791d20a42..000000000
--- a/src/hash/sha1/win32.h
+++ /dev/null
@@ -1,128 +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_hash_sha1_win32_h__
-#define INCLUDE_hash_sha1_win32_h__
-
-#include "hash/sha1.h"
-
-#include
-#include
-
-enum hash_win32_prov_type {
- INVALID = 0,
- CRYPTOAPI,
- CNG
-};
-
-/*
- * CryptoAPI is available for hashing on Windows XP and newer.
- */
-
-struct hash_cryptoapi_prov {
- HCRYPTPROV handle;
-};
-
-/*
- * CNG (bcrypt.dll) is significantly more performant than CryptoAPI and is
- * preferred, however it is only available on Windows 2008 and newer and
- * must therefore be dynamically loaded, and we must inline constants that
- * would not exist when building in pre-Windows 2008 environments.
- */
-
-/* Function declarations for CNG */
-typedef NTSTATUS (WINAPI *hash_win32_cng_open_algorithm_provider_fn)(
- HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm,
- LPCWSTR pszAlgId,
- LPCWSTR pszImplementation,
- DWORD dwFlags);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_get_property_fn)(
- HANDLE /* BCRYPT_HANDLE */ hObject,
- LPCWSTR pszProperty,
- PUCHAR pbOutput,
- ULONG cbOutput,
- ULONG *pcbResult,
- ULONG dwFlags);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_create_hash_fn)(
- HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm,
- HANDLE /* BCRYPT_HASH_HANDLE */ *phHash,
- PUCHAR pbHashObject, ULONG cbHashObject,
- PUCHAR pbSecret,
- ULONG cbSecret,
- ULONG dwFlags);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_finish_hash_fn)(
- HANDLE /* BCRYPT_HASH_HANDLE */ hHash,
- PUCHAR pbOutput,
- ULONG cbOutput,
- ULONG dwFlags);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_hash_data_fn)(
- HANDLE /* BCRYPT_HASH_HANDLE */ hHash,
- PUCHAR pbInput,
- ULONG cbInput,
- ULONG dwFlags);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_destroy_hash_fn)(
- HANDLE /* BCRYPT_HASH_HANDLE */ hHash);
-
-typedef NTSTATUS (WINAPI *hash_win32_cng_close_algorithm_provider_fn)(
- HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm,
- ULONG dwFlags);
-
-struct hash_cng_prov {
- /* DLL for CNG */
- HINSTANCE dll;
-
- /* Function pointers for CNG */
- hash_win32_cng_open_algorithm_provider_fn open_algorithm_provider;
- hash_win32_cng_get_property_fn get_property;
- hash_win32_cng_create_hash_fn create_hash;
- hash_win32_cng_finish_hash_fn finish_hash;
- hash_win32_cng_hash_data_fn hash_data;
- hash_win32_cng_destroy_hash_fn destroy_hash;
- hash_win32_cng_close_algorithm_provider_fn close_algorithm_provider;
-
- HANDLE /* BCRYPT_ALG_HANDLE */ handle;
- DWORD hash_object_size;
-};
-
-typedef struct {
- enum hash_win32_prov_type type;
-
- union {
- struct hash_cryptoapi_prov cryptoapi;
- struct hash_cng_prov cng;
- } prov;
-} git_hash_prov;
-
-/* Hash contexts */
-
-struct hash_cryptoapi_ctx {
- bool valid;
- HCRYPTHASH hash_handle;
-};
-
-struct hash_cng_ctx {
- bool updated;
- HANDLE /* BCRYPT_HASH_HANDLE */ hash_handle;
- PBYTE hash_object;
-};
-
-struct git_hash_sha1_ctx {
- enum hash_win32_prov_type type;
- git_hash_prov *prov;
-
- union {
- struct hash_cryptoapi_ctx cryptoapi;
- struct hash_cng_ctx cng;
- } ctx;
-};
-
-#endif
diff --git a/src/libgit2/CMakeLists.txt b/src/libgit2/CMakeLists.txt
new file mode 100644
index 000000000..0c7ddddba
--- /dev/null
+++ b/src/libgit2/CMakeLists.txt
@@ -0,0 +1,131 @@
+# libgit2: the shared library: this CMakeLists.txt compiles the core
+# git library functionality.
+
+add_library(libgit2 OBJECT)
+set_target_properties(libgit2 PROPERTIES C_STANDARD 90)
+set_target_properties(libgit2 PROPERTIES C_EXTENSIONS OFF)
+
+include(PkgBuildConfig)
+
+set(LIBGIT2_INCLUDES
+ "${PROJECT_BINARY_DIR}/src"
+ "${PROJECT_SOURCE_DIR}/src/libgit2"
+ "${PROJECT_SOURCE_DIR}/src/util"
+ "${PROJECT_SOURCE_DIR}/include")
+
+if(WIN32 AND EMBED_SSH_PATH)
+ file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
+ list(SORT SRC_SSH)
+ target_sources(libgit2 PRIVATE ${SRC_SSH})
+
+ list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include")
+ file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
+ set(GIT_SSH 1)
+endif()
+
+# Collect sourcefiles
+file(GLOB SRC_H
+ "${PROJECT_SOURCE_DIR}/include/git2.h"
+ "${PROJECT_SOURCE_DIR}/include/git2/*.h"
+ "${PROJECT_SOURCE_DIR}/include/git2/sys/*.h")
+list(SORT SRC_H)
+target_sources(libgit2 PRIVATE ${SRC_H})
+
+file(GLOB SRC_GIT2 *.c *.h
+ streams/*.c streams/*.h
+ transports/*.c transports/*.h
+ xdiff/*.c xdiff/*.h)
+list(SORT SRC_GIT2)
+target_sources(libgit2 PRIVATE ${SRC_GIT2})
+
+if(WIN32 AND NOT CYGWIN)
+ # Add resource information on Windows
+ set(SRC_RC "git2.rc")
+endif()
+
+if(APPLE)
+ # The old Secure Transport API has been deprecated in macOS 10.15.
+ set_source_files_properties(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
+endif()
+
+# the xdiff dependency is not (yet) warning-free, disable warnings
+# as errors for the xdiff sources until we've sorted them out
+if(MSVC)
+ set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
+ set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
+ set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
+ set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
+ set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
+ set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
+else()
+ set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
+ set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
+ set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+ set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+ set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
+endif()
+
+ide_split_sources(libgit2)
+list(APPEND LIBGIT2_OBJECTS $ $ ${LIBGIT2_DEPENDENCY_OBJECTS})
+
+target_include_directories(libgit2 PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${PROJECT_SOURCE_DIR}/include)
+target_include_directories(libgit2 SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
+
+set(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
+set(LIBGIT2_DEPENDENCY_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_DEPENDENCY_OBJECTS ${LIBGIT2_DEPENDENCY_OBJECTS} PARENT_SCOPE)
+set(LIBGIT2_SYSTEM_INCLUDES ${LIBGIT2_SYSTEM_INCLUDES} PARENT_SCOPE)
+set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE)
+
+#
+# Compile and link libgit2
+#
+
+add_library(libgit2package ${SRC_RC} ${LIBGIT2_OBJECTS})
+target_link_libraries(libgit2package ${LIBGIT2_SYSTEM_LIBS})
+
+set_target_properties(libgit2package PROPERTIES C_STANDARD 90)
+set_target_properties(libgit2package PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+set_target_properties(libgit2package PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+set_target_properties(libgit2package PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+
+# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
+# Win64+MSVC+static libs = linker error
+if(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
+ set_target_properties(libgit2package PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
+endif()
+
+ide_split_sources(libgit2package)
+
+if(SONAME)
+ set_target_properties(libgit2package PROPERTIES VERSION ${libgit2_VERSION})
+ set_target_properties(libgit2package PROPERTIES SOVERSION "${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}")
+ if(LIBGIT2_FILENAME)
+ target_compile_definitions(libgit2package PRIVATE LIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
+ set_target_properties(libgit2package PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
+ elseif(DEFINED LIBGIT2_PREFIX)
+ set_target_properties(libgit2package PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
+ endif()
+endif()
+
+pkg_build_config(NAME libgit2
+ VERSION ${libgit2_VERSION}
+ DESCRIPTION "The git library, take 2"
+ LIBS_SELF git2
+ PRIVATE_LIBS ${LIBGIT2_PC_LIBS}
+ REQUIRES ${LIBGIT2_PC_REQUIRES})
+
+if(MSVC_IDE)
+ # Precompiled headers
+ set_target_properties(libgit2package PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
+ set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
+endif()
+
+# Install
+install(TARGETS libgit2package
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+install(FILES ${PROJECT_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/annotated_commit.c b/src/libgit2/annotated_commit.c
similarity index 100%
rename from src/annotated_commit.c
rename to src/libgit2/annotated_commit.c
diff --git a/src/annotated_commit.h b/src/libgit2/annotated_commit.h
similarity index 100%
rename from src/annotated_commit.h
rename to src/libgit2/annotated_commit.h
diff --git a/src/apply.c b/src/libgit2/apply.c
similarity index 100%
rename from src/apply.c
rename to src/libgit2/apply.c
diff --git a/src/apply.h b/src/libgit2/apply.h
similarity index 100%
rename from src/apply.h
rename to src/libgit2/apply.h
diff --git a/src/attr.c b/src/libgit2/attr.c
similarity index 100%
rename from src/attr.c
rename to src/libgit2/attr.c
diff --git a/src/attr.h b/src/libgit2/attr.h
similarity index 100%
rename from src/attr.h
rename to src/libgit2/attr.h
diff --git a/src/attr_file.c b/src/libgit2/attr_file.c
similarity index 100%
rename from src/attr_file.c
rename to src/libgit2/attr_file.c
diff --git a/src/attr_file.h b/src/libgit2/attr_file.h
similarity index 100%
rename from src/attr_file.h
rename to src/libgit2/attr_file.h
diff --git a/src/attrcache.c b/src/libgit2/attrcache.c
similarity index 100%
rename from src/attrcache.c
rename to src/libgit2/attrcache.c
diff --git a/src/attrcache.h b/src/libgit2/attrcache.h
similarity index 100%
rename from src/attrcache.h
rename to src/libgit2/attrcache.h
diff --git a/src/blame.c b/src/libgit2/blame.c
similarity index 100%
rename from src/blame.c
rename to src/libgit2/blame.c
diff --git a/src/blame.h b/src/libgit2/blame.h
similarity index 100%
rename from src/blame.h
rename to src/libgit2/blame.h
diff --git a/src/blame_git.c b/src/libgit2/blame_git.c
similarity index 100%
rename from src/blame_git.c
rename to src/libgit2/blame_git.c
diff --git a/src/blame_git.h b/src/libgit2/blame_git.h
similarity index 100%
rename from src/blame_git.h
rename to src/libgit2/blame_git.h
diff --git a/src/blob.c b/src/libgit2/blob.c
similarity index 99%
rename from src/blob.c
rename to src/libgit2/blob.c
index 19ce8b3b5..b1680d3a8 100644
--- a/src/blob.c
+++ b/src/libgit2/blob.c
@@ -101,7 +101,7 @@ static int write_file_stream(
git_oid *id, git_odb *odb, const char *path, git_object_size_t file_size)
{
int fd, error;
- char buffer[FILEIO_BUFSIZE];
+ char buffer[GIT_BUFSIZE_FILEIO];
git_odb_stream *stream = NULL;
ssize_t read_len = -1;
git_object_size_t written = 0;
diff --git a/src/blob.h b/src/libgit2/blob.h
similarity index 100%
rename from src/blob.h
rename to src/libgit2/blob.h
diff --git a/src/branch.c b/src/libgit2/branch.c
similarity index 98%
rename from src/branch.c
rename to src/libgit2/branch.c
index 2e29af99d..2dd7d2bb4 100644
--- a/src/branch.c
+++ b/src/libgit2/branch.c
@@ -53,6 +53,17 @@ static int not_a_local_branch(const char *reference_name)
return -1;
}
+static bool branch_name_is_valid(const char *branch_name)
+{
+ /*
+ * Discourage branch name starting with dash,
+ * https://github.com/git/git/commit/6348624010888b
+ * and discourage HEAD as branch name,
+ * https://github.com/git/git/commit/a625b092cc5994
+ */
+ return branch_name[0] != '-' && git__strcmp(branch_name, "HEAD");
+}
+
static int create_branch(
git_reference **ref_out,
git_repository *repository,
@@ -73,8 +84,8 @@ static int create_branch(
GIT_ASSERT_ARG(ref_out);
GIT_ASSERT_ARG(git_commit_owner(commit) == repository);
- if (!git__strcmp(branch_name, "HEAD")) {
- git_error_set(GIT_ERROR_REFERENCE, "'HEAD' is not a valid branch name");
+ if (!branch_name_is_valid(branch_name)) {
+ git_error_set(GIT_ERROR_REFERENCE, "'%s' is not a valid branch name", branch_name);
error = -1;
goto cleanup;
}
@@ -797,13 +808,7 @@ int git_branch_name_is_valid(int *valid, const char *name)
*valid = 0;
- /*
- * Discourage branch name starting with dash,
- * https://github.com/git/git/commit/6348624010888b
- * and discourage HEAD as branch name,
- * https://github.com/git/git/commit/a625b092cc5994
- */
- if (!name || name[0] == '-' || !git__strcmp(name, "HEAD"))
+ if (!name || !branch_name_is_valid(name))
goto done;
if ((error = git_str_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
diff --git a/src/branch.h b/src/libgit2/branch.h
similarity index 100%
rename from src/branch.h
rename to src/libgit2/branch.h
diff --git a/src/buf.c b/src/libgit2/buf.c
similarity index 100%
rename from src/buf.c
rename to src/libgit2/buf.c
diff --git a/src/buf.h b/src/libgit2/buf.h
similarity index 100%
rename from src/buf.h
rename to src/libgit2/buf.h
diff --git a/src/cache.c b/src/libgit2/cache.c
similarity index 100%
rename from src/cache.c
rename to src/libgit2/cache.c
diff --git a/src/cache.h b/src/libgit2/cache.h
similarity index 100%
rename from src/cache.h
rename to src/libgit2/cache.h
diff --git a/src/checkout.c b/src/libgit2/checkout.c
similarity index 100%
rename from src/checkout.c
rename to src/libgit2/checkout.c
diff --git a/src/checkout.h b/src/libgit2/checkout.h
similarity index 100%
rename from src/checkout.h
rename to src/libgit2/checkout.h
diff --git a/src/cherrypick.c b/src/libgit2/cherrypick.c
similarity index 100%
rename from src/cherrypick.c
rename to src/libgit2/cherrypick.c
diff --git a/src/clone.c b/src/libgit2/clone.c
similarity index 100%
rename from src/clone.c
rename to src/libgit2/clone.c
diff --git a/src/clone.h b/src/libgit2/clone.h
similarity index 100%
rename from src/clone.h
rename to src/libgit2/clone.h
diff --git a/src/commit.c b/src/libgit2/commit.c
similarity index 100%
rename from src/commit.c
rename to src/libgit2/commit.c
diff --git a/src/commit.h b/src/libgit2/commit.h
similarity index 100%
rename from src/commit.h
rename to src/libgit2/commit.h
diff --git a/src/commit_graph.c b/src/libgit2/commit_graph.c
similarity index 97%
rename from src/commit_graph.c
rename to src/libgit2/commit_graph.c
index 70e866b92..10947acec 100644
--- a/src/commit_graph.c
+++ b/src/libgit2/commit_graph.c
@@ -138,7 +138,7 @@ static int commit_graph_parse_oid_lookup(
struct git_commit_graph_chunk *chunk_oid_lookup)
{
uint32_t i;
- git_oid *oid, *prev_oid, zero_oid = {{0}};
+ unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
if (chunk_oid_lookup->offset == 0)
return commit_graph_error("missing OID Lookup chunk");
@@ -147,10 +147,10 @@ static int commit_graph_parse_oid_lookup(
if (chunk_oid_lookup->length != file->num_commits * GIT_OID_RAWSZ)
return commit_graph_error("OID Lookup chunk has wrong length");
- file->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
- prev_oid = &zero_oid;
- for (i = 0; i < file->num_commits; ++i, ++oid) {
- if (git_oid_cmp(prev_oid, oid) >= 0)
+ file->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
+ prev_oid = zero_oid;
+ for (i = 0; i < file->num_commits; ++i, oid += GIT_OID_RAWSZ) {
+ if (git_oid_raw_cmp(prev_oid, oid) >= 0)
return commit_graph_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
@@ -437,7 +437,7 @@ static int git_commit_graph_entry_get_byindex(
}
commit_data = file->commit_data + pos * (GIT_OID_RAWSZ + 4 * sizeof(uint32_t));
- git_oid_cpy(&e->tree_oid, (const git_oid *)commit_data);
+ git_oid_fromraw(&e->tree_oid, commit_data);
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ)));
e->parent_indices[1] = ntohl(
*((uint32_t *)(commit_data + GIT_OID_RAWSZ + sizeof(uint32_t))));
@@ -470,7 +470,8 @@ static int git_commit_graph_entry_get_byindex(
e->parent_count++;
}
}
- git_oid_cpy(&e->sha1, &file->oid_lookup[pos]);
+
+ git_oid_fromraw(&e->sha1, &file->oid_lookup[pos * GIT_OID_RAWSZ]);
return 0;
}
@@ -514,7 +515,7 @@ int git_commit_graph_entry_find(
{
int pos, found = 0;
uint32_t hi, lo;
- const git_oid *current = NULL;
+ const unsigned char *current = NULL;
GIT_ASSERT_ARG(e);
GIT_ASSERT_ARG(file);
@@ -528,26 +529,25 @@ int git_commit_graph_entry_find(
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
- current = file->oid_lookup + pos;
+ current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)file->num_commits) {
- current = file->oid_lookup + pos;
+ current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
- if (!git_oid_ncmp(short_oid, current, len))
+ if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)file->num_commits) {
/* Check for ambiguousity */
- const git_oid *next = current + 1;
+ const unsigned char *next = current + GIT_OID_RAWSZ;
- if (!git_oid_ncmp(short_oid, next, len)) {
+ if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
- }
}
if (!found)
@@ -1019,7 +1019,9 @@ static int commit_graph_write(
/* Fill the OID Lookup table. */
git_vector_foreach (&w->commits, i, packed_commit) {
error = git_str_put(&oid_lookup,
- (const char *)&packed_commit->sha1, sizeof(git_oid));
+ (const char *)&packed_commit->sha1.id,
+ GIT_OID_RAWSZ);
+
if (error < 0)
goto cleanup;
}
@@ -1034,8 +1036,9 @@ static int commit_graph_write(
unsigned int parentcount = (unsigned int)git_array_size(packed_commit->parents);
error = git_str_put(&commit_data,
- (const char *)&packed_commit->tree_oid,
- sizeof(git_oid));
+ (const char *)&packed_commit->tree_oid.id,
+ GIT_OID_RAWSZ);
+
if (error < 0)
goto cleanup;
diff --git a/src/commit_graph.h b/src/libgit2/commit_graph.h
similarity index 99%
rename from src/commit_graph.h
rename to src/libgit2/commit_graph.h
index 45e125b9e..b78ab8177 100644
--- a/src/commit_graph.h
+++ b/src/libgit2/commit_graph.h
@@ -36,7 +36,7 @@ typedef struct git_commit_graph_file {
uint32_t num_commits;
/* The OID Lookup table. */
- git_oid *oid_lookup;
+ unsigned char *oid_lookup;
/*
* The Commit Data table. Each entry contains the OID of the commit followed
diff --git a/src/commit_list.c b/src/libgit2/commit_list.c
similarity index 100%
rename from src/commit_list.c
rename to src/libgit2/commit_list.c
diff --git a/src/commit_list.h b/src/libgit2/commit_list.h
similarity index 100%
rename from src/commit_list.h
rename to src/libgit2/commit_list.h
diff --git a/src/libgit2/common.h b/src/libgit2/common.h
new file mode 100644
index 000000000..bb9ec5ac1
--- /dev/null
+++ b/src/libgit2/common.h
@@ -0,0 +1,55 @@
+/*
+ * 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_common_h__
+#define INCLUDE_common_h__
+
+#include "git2_util.h"
+#include "errors.h"
+
+/*
+* Include the declarations for deprecated functions; this ensures
+* that they're decorated with the proper extern/visibility attributes.
+*/
+#include "git2/deprecated.h"
+
+#include "posix.h"
+
+/**
+ * Initialize a structure with a version.
+ */
+GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
+{
+ memset(structure, 0, len);
+ *((int*)structure) = version;
+}
+#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
+
+#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \
+ TYPE _tmpl = TPL; \
+ GIT_ERROR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \
+ memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
+
+/**
+ * Check a versioned structure for validity
+ */
+GIT_INLINE(int) git_error__check_version(const void *structure, unsigned int expected_max, const char *name)
+{
+ unsigned int actual;
+
+ if (!structure)
+ return 0;
+
+ actual = *(const unsigned int*)structure;
+ if (actual > 0 && actual <= expected_max)
+ return 0;
+
+ git_error_set(GIT_ERROR_INVALID, "invalid version %d on %s", actual, name);
+ return -1;
+}
+#define GIT_ERROR_CHECK_VERSION(S,V,N) if (git_error__check_version(S,V,N) < 0) return -1
+
+#endif
diff --git a/src/config.c b/src/libgit2/config.c
similarity index 99%
rename from src/config.c
rename to src/libgit2/config.c
index 6bd59f2a5..5c366e221 100644
--- a/src/config.c
+++ b/src/libgit2/config.c
@@ -1137,7 +1137,7 @@ int git_config__find_global(git_str *path)
int git_config_find_xdg(git_buf *path)
{
- GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_global_file, GIT_CONFIG_FILENAME_XDG);
+ GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_xdg_file, GIT_CONFIG_FILENAME_XDG);
}
int git_config__find_xdg(git_str *path)
@@ -1147,7 +1147,7 @@ int git_config__find_xdg(git_str *path)
int git_config_find_system(git_buf *path)
{
- GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_global_file, GIT_CONFIG_FILENAME_SYSTEM);
+ GIT_BUF_WRAP_PRIVATE(path, git_sysdir_find_system_file, GIT_CONFIG_FILENAME_SYSTEM);
}
int git_config__find_system(git_str *path)
@@ -1170,10 +1170,13 @@ int git_config_find_programdata(git_buf *path)
int git_config__find_programdata(git_str *path)
{
+ git_fs_path_owner_t owner_level =
+ GIT_FS_PATH_OWNER_CURRENT_USER |
+ GIT_FS_PATH_OWNER_ADMINISTRATOR;
bool is_safe;
if (git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
- git_fs_path_owner_is_system_or_current_user(&is_safe, path->ptr) < 0)
+ git_fs_path_owner_is(&is_safe, path->ptr, owner_level) < 0)
return -1;
if (!is_safe) {
diff --git a/src/config.h b/src/libgit2/config.h
similarity index 100%
rename from src/config.h
rename to src/libgit2/config.h
diff --git a/src/config_backend.h b/src/libgit2/config_backend.h
similarity index 100%
rename from src/config_backend.h
rename to src/libgit2/config_backend.h
diff --git a/src/config_cache.c b/src/libgit2/config_cache.c
similarity index 100%
rename from src/config_cache.c
rename to src/libgit2/config_cache.c
diff --git a/src/config_entries.c b/src/libgit2/config_entries.c
similarity index 100%
rename from src/config_entries.c
rename to src/libgit2/config_entries.c
diff --git a/src/config_entries.h b/src/libgit2/config_entries.h
similarity index 100%
rename from src/config_entries.h
rename to src/libgit2/config_entries.h
diff --git a/src/config_file.c b/src/libgit2/config_file.c
similarity index 100%
rename from src/config_file.c
rename to src/libgit2/config_file.c
diff --git a/src/config_mem.c b/src/libgit2/config_mem.c
similarity index 100%
rename from src/config_mem.c
rename to src/libgit2/config_mem.c
diff --git a/src/config_parse.c b/src/libgit2/config_parse.c
similarity index 100%
rename from src/config_parse.c
rename to src/libgit2/config_parse.c
diff --git a/src/config_parse.h b/src/libgit2/config_parse.h
similarity index 100%
rename from src/config_parse.h
rename to src/libgit2/config_parse.h
diff --git a/src/config_snapshot.c b/src/libgit2/config_snapshot.c
similarity index 100%
rename from src/config_snapshot.c
rename to src/libgit2/config_snapshot.c
diff --git a/src/crlf.c b/src/libgit2/crlf.c
similarity index 100%
rename from src/crlf.c
rename to src/libgit2/crlf.c
diff --git a/src/delta.c b/src/libgit2/delta.c
similarity index 100%
rename from src/delta.c
rename to src/libgit2/delta.c
diff --git a/src/delta.h b/src/libgit2/delta.h
similarity index 100%
rename from src/delta.h
rename to src/libgit2/delta.h
diff --git a/src/describe.c b/src/libgit2/describe.c
similarity index 100%
rename from src/describe.c
rename to src/libgit2/describe.c
diff --git a/src/diff.c b/src/libgit2/diff.c
similarity index 100%
rename from src/diff.c
rename to src/libgit2/diff.c
diff --git a/src/diff.h b/src/libgit2/diff.h
similarity index 100%
rename from src/diff.h
rename to src/libgit2/diff.h
diff --git a/src/diff_driver.c b/src/libgit2/diff_driver.c
similarity index 100%
rename from src/diff_driver.c
rename to src/libgit2/diff_driver.c
diff --git a/src/diff_driver.h b/src/libgit2/diff_driver.h
similarity index 100%
rename from src/diff_driver.h
rename to src/libgit2/diff_driver.h
diff --git a/src/diff_file.c b/src/libgit2/diff_file.c
similarity index 100%
rename from src/diff_file.c
rename to src/libgit2/diff_file.c
diff --git a/src/diff_file.h b/src/libgit2/diff_file.h
similarity index 100%
rename from src/diff_file.h
rename to src/libgit2/diff_file.h
diff --git a/src/diff_generate.c b/src/libgit2/diff_generate.c
similarity index 100%
rename from src/diff_generate.c
rename to src/libgit2/diff_generate.c
diff --git a/src/diff_generate.h b/src/libgit2/diff_generate.h
similarity index 100%
rename from src/diff_generate.h
rename to src/libgit2/diff_generate.h
diff --git a/src/diff_parse.c b/src/libgit2/diff_parse.c
similarity index 100%
rename from src/diff_parse.c
rename to src/libgit2/diff_parse.c
diff --git a/src/diff_parse.h b/src/libgit2/diff_parse.h
similarity index 100%
rename from src/diff_parse.h
rename to src/libgit2/diff_parse.h
diff --git a/src/diff_print.c b/src/libgit2/diff_print.c
similarity index 100%
rename from src/diff_print.c
rename to src/libgit2/diff_print.c
diff --git a/src/diff_stats.c b/src/libgit2/diff_stats.c
similarity index 100%
rename from src/diff_stats.c
rename to src/libgit2/diff_stats.c
diff --git a/src/diff_stats.h b/src/libgit2/diff_stats.h
similarity index 100%
rename from src/diff_stats.h
rename to src/libgit2/diff_stats.h
diff --git a/src/diff_tform.c b/src/libgit2/diff_tform.c
similarity index 100%
rename from src/diff_tform.c
rename to src/libgit2/diff_tform.c
diff --git a/src/diff_tform.h b/src/libgit2/diff_tform.h
similarity index 100%
rename from src/diff_tform.h
rename to src/libgit2/diff_tform.h
diff --git a/src/diff_xdiff.c b/src/libgit2/diff_xdiff.c
similarity index 99%
rename from src/diff_xdiff.c
rename to src/libgit2/diff_xdiff.c
index 3f6eccac1..5f56c5209 100644
--- a/src/diff_xdiff.c
+++ b/src/libgit2/diff_xdiff.c
@@ -11,6 +11,7 @@
#include "diff.h"
#include "diff_driver.h"
#include "patch_generate.h"
+#include "utf8.h"
static int git_xdiff_scan_int(const char **str, int *value)
{
diff --git a/src/diff_xdiff.h b/src/libgit2/diff_xdiff.h
similarity index 100%
rename from src/diff_xdiff.h
rename to src/libgit2/diff_xdiff.h
diff --git a/src/email.c b/src/libgit2/email.c
similarity index 100%
rename from src/email.c
rename to src/libgit2/email.c
diff --git a/src/email.h b/src/libgit2/email.h
similarity index 100%
rename from src/email.h
rename to src/libgit2/email.h
diff --git a/src/errors.c b/src/libgit2/errors.c
similarity index 100%
rename from src/errors.c
rename to src/libgit2/errors.c
diff --git a/src/errors.h b/src/libgit2/errors.h
similarity index 93%
rename from src/errors.h
rename to src/libgit2/errors.h
index a2f60f752..772c7bad1 100644
--- a/src/errors.h
+++ b/src/libgit2/errors.h
@@ -11,9 +11,8 @@
#include "common.h"
/*
- * Set the error message for this thread, formatting as needed.
+ * `vprintf`-style formatting for the error message for this thread.
*/
-void git_error_set(int error_class, const char *fmt, ...) GIT_FORMAT_PRINTF(2, 3);
void git_error_vset(int error_class, const char *fmt, va_list ap);
/**
diff --git a/src/fetch.c b/src/libgit2/fetch.c
similarity index 100%
rename from src/fetch.c
rename to src/libgit2/fetch.c
diff --git a/src/fetch.h b/src/libgit2/fetch.h
similarity index 100%
rename from src/fetch.h
rename to src/libgit2/fetch.h
diff --git a/src/fetchhead.c b/src/libgit2/fetchhead.c
similarity index 100%
rename from src/fetchhead.c
rename to src/libgit2/fetchhead.c
diff --git a/src/fetchhead.h b/src/libgit2/fetchhead.h
similarity index 100%
rename from src/fetchhead.h
rename to src/libgit2/fetchhead.h
diff --git a/src/filter.c b/src/libgit2/filter.c
similarity index 96%
rename from src/filter.c
rename to src/libgit2/filter.c
index 2712e8c60..80a3cae67 100644
--- a/src/filter.c
+++ b/src/libgit2/filter.c
@@ -893,6 +893,17 @@ static int buffered_stream_write(
return git_str_put(&buffered_stream->input, buffer, len);
}
+#ifndef GIT_DEPRECATE_HARD
+# define BUF_TO_STRUCT(b, s) \
+ (b)->ptr = (s)->ptr; \
+ (b)->size = (s)->size; \
+ (b)->reserved = (s)->asize;
+# define STRUCT_TO_BUF(s, b) \
+ (s)->ptr = (b)->ptr; \
+ (s)->size = (b)->size; \
+ (s)->asize = (b)->reserved;
+#endif
+
static int buffered_stream_close(git_writestream *s)
{
struct buffered_stream *buffered_stream = (struct buffered_stream *)s;
@@ -902,6 +913,25 @@ static int buffered_stream_close(git_writestream *s)
GIT_ASSERT_ARG(buffered_stream);
+#ifndef GIT_DEPRECATE_HARD
+ if (buffered_stream->write_fn == NULL) {
+ git_buf legacy_output = GIT_BUF_INIT,
+ legacy_input = GIT_BUF_INIT;
+
+ BUF_TO_STRUCT(&legacy_output, buffered_stream->output);
+ BUF_TO_STRUCT(&legacy_input, &buffered_stream->input);
+
+ error = buffered_stream->legacy_write_fn(
+ buffered_stream->filter,
+ buffered_stream->payload,
+ &legacy_output,
+ &legacy_input,
+ buffered_stream->source);
+
+ STRUCT_TO_BUF(buffered_stream->output, &legacy_output);
+ STRUCT_TO_BUF(&buffered_stream->input, &legacy_input);
+ } else
+#endif
error = buffered_stream->write_fn(
buffered_stream->filter,
buffered_stream->payload,
@@ -1085,7 +1115,7 @@ int git_filter_list_stream_file(
const char *path,
git_writestream *target)
{
- char buf[FILTERIO_BUFSIZE];
+ char buf[GIT_BUFSIZE_FILTERIO];
git_str abspath = GIT_STR_INIT;
const char *base = repo ? git_repository_workdir(repo) : NULL;
git_vector filter_streams = GIT_VECTOR_INIT;
diff --git a/src/filter.h b/src/libgit2/filter.h
similarity index 100%
rename from src/filter.h
rename to src/libgit2/filter.h
diff --git a/src/win32/git2.rc b/src/libgit2/git2.rc
similarity index 100%
rename from src/win32/git2.rc
rename to src/libgit2/git2.rc
diff --git a/src/graph.c b/src/libgit2/graph.c
similarity index 100%
rename from src/graph.c
rename to src/libgit2/graph.c
diff --git a/src/hashsig.c b/src/libgit2/hashsig.c
similarity index 100%
rename from src/hashsig.c
rename to src/libgit2/hashsig.c
diff --git a/src/ident.c b/src/libgit2/ident.c
similarity index 100%
rename from src/ident.c
rename to src/libgit2/ident.c
diff --git a/src/idxmap.c b/src/libgit2/idxmap.c
similarity index 100%
rename from src/idxmap.c
rename to src/libgit2/idxmap.c
diff --git a/src/idxmap.h b/src/libgit2/idxmap.h
similarity index 100%
rename from src/idxmap.h
rename to src/libgit2/idxmap.h
diff --git a/src/ignore.c b/src/libgit2/ignore.c
similarity index 100%
rename from src/ignore.c
rename to src/libgit2/ignore.c
diff --git a/src/ignore.h b/src/libgit2/ignore.h
similarity index 100%
rename from src/ignore.h
rename to src/libgit2/ignore.h
diff --git a/src/index.c b/src/libgit2/index.c
similarity index 99%
rename from src/index.c
rename to src/libgit2/index.c
index aa97c6421..f44c507d3 100644
--- a/src/index.c
+++ b/src/libgit2/index.c
@@ -74,7 +74,7 @@ struct entry_short {
uint32_t uid;
uint32_t gid;
uint32_t file_size;
- git_oid oid;
+ unsigned char oid[GIT_OID_RAWSZ];
uint16_t flags;
char path[1]; /* arbitrary length */
};
@@ -88,7 +88,7 @@ struct entry_long {
uint32_t uid;
uint32_t gid;
uint32_t file_size;
- git_oid oid;
+ unsigned char oid[GIT_OID_RAWSZ];
uint16_t flags;
uint16_t flags_extended;
char path[1]; /* arbitrary length */
@@ -2480,9 +2480,11 @@ static int read_entry(
entry.uid = ntohl(source.uid);
entry.gid = ntohl(source.gid);
entry.file_size = ntohl(source.file_size);
- git_oid_cpy(&entry.id, &source.oid);
entry.flags = ntohs(source.flags);
+ if (git_oid_fromraw(&entry.id, source.oid) < 0)
+ return -1;
+
if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) {
uint16_t flags_raw;
size_t flags_offset;
@@ -2803,9 +2805,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
ondisk.uid = htonl(entry->uid);
ondisk.gid = htonl(entry->gid);
ondisk.file_size = htonl((uint32_t)entry->file_size);
-
- git_oid_cpy(&ondisk.oid, &entry->id);
-
+ git_oid_raw_cpy(ondisk.oid, entry->id.id);
ondisk.flags = htons(entry->flags);
if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
diff --git a/src/index.h b/src/libgit2/index.h
similarity index 100%
rename from src/index.h
rename to src/libgit2/index.h
diff --git a/src/indexer.c b/src/libgit2/indexer.c
similarity index 99%
rename from src/indexer.c
rename to src/libgit2/indexer.c
index f9a32e7ac..afb9ce81a 100644
--- a/src/indexer.c
+++ b/src/libgit2/indexer.c
@@ -385,7 +385,7 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
size_t i;
git_array_foreach(tree->entries, i, entry)
- if (add_expected_oid(idx, entry->oid) < 0)
+ if (add_expected_oid(idx, &entry->oid) < 0)
goto out;
break;
@@ -1269,7 +1269,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
/* Write out the object names (SHA-1 hashes) */
git_vector_foreach(&idx->objects, i, entry) {
- git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
+ git_filebuf_write(&index_file, &entry->oid.id, GIT_OID_RAWSZ);
}
/* Write out the CRC32 values */
diff --git a/src/indexer.h b/src/libgit2/indexer.h
similarity index 100%
rename from src/indexer.h
rename to src/libgit2/indexer.h
diff --git a/src/iterator.c b/src/libgit2/iterator.c
similarity index 99%
rename from src/iterator.c
rename to src/libgit2/iterator.c
index 15bb63dc8..bc6f766ce 100644
--- a/src/iterator.c
+++ b/src/libgit2/iterator.c
@@ -613,7 +613,7 @@ GIT_INLINE(int) tree_iterator_frame_push_neighbors(
break;
if ((error = git_tree_lookup(&tree,
- iter->base.repo, entry->tree_entry->oid)) < 0)
+ iter->base.repo, &entry->tree_entry->oid)) < 0)
break;
if (git_vector_insert(&parent_frame->similar_trees, tree) < 0)
@@ -659,7 +659,7 @@ GIT_INLINE(int) tree_iterator_frame_push(
int error;
if ((error = git_tree_lookup(&tree,
- iter->base.repo, entry->tree_entry->oid)) < 0 ||
+ iter->base.repo, &entry->tree_entry->oid)) < 0 ||
(error = tree_iterator_frame_init(iter, tree, entry)) < 0)
goto done;
@@ -740,7 +740,7 @@ static void tree_iterator_set_current(
iter->entry.mode = tree_entry->attr;
iter->entry.path = iter->entry_path.ptr;
- git_oid_cpy(&iter->entry.id, tree_entry->oid);
+ git_oid_cpy(&iter->entry.id, &tree_entry->oid);
}
static int tree_iterator_advance(const git_index_entry **out, git_iterator *i)
diff --git a/src/iterator.h b/src/libgit2/iterator.h
similarity index 100%
rename from src/iterator.h
rename to src/libgit2/iterator.h
diff --git a/src/libgit2.c b/src/libgit2/libgit2.c
similarity index 99%
rename from src/libgit2.c
rename to src/libgit2/libgit2.c
index c99d5b942..2fda0722e 100644
--- a/src/libgit2.c
+++ b/src/libgit2/libgit2.c
@@ -107,6 +107,11 @@ int git_libgit2_version(int *major, int *minor, int *rev)
return 0;
}
+const char *git_libgit2_prerelease(void)
+{
+ return LIBGIT2_VER_PRERELEASE;
+}
+
int git_libgit2_features(void)
{
return 0
diff --git a/src/libgit2.h b/src/libgit2/libgit2.h
similarity index 100%
rename from src/libgit2.h
rename to src/libgit2/libgit2.h
diff --git a/src/mailmap.c b/src/libgit2/mailmap.c
similarity index 100%
rename from src/mailmap.c
rename to src/libgit2/mailmap.c
diff --git a/src/mailmap.h b/src/libgit2/mailmap.h
similarity index 100%
rename from src/mailmap.h
rename to src/libgit2/mailmap.h
diff --git a/src/merge.c b/src/libgit2/merge.c
similarity index 100%
rename from src/merge.c
rename to src/libgit2/merge.c
diff --git a/src/merge.h b/src/libgit2/merge.h
similarity index 100%
rename from src/merge.h
rename to src/libgit2/merge.h
diff --git a/src/merge_driver.c b/src/libgit2/merge_driver.c
similarity index 100%
rename from src/merge_driver.c
rename to src/libgit2/merge_driver.c
diff --git a/src/merge_driver.h b/src/libgit2/merge_driver.h
similarity index 100%
rename from src/merge_driver.h
rename to src/libgit2/merge_driver.h
diff --git a/src/merge_file.c b/src/libgit2/merge_file.c
similarity index 100%
rename from src/merge_file.c
rename to src/libgit2/merge_file.c
diff --git a/src/message.c b/src/libgit2/message.c
similarity index 100%
rename from src/message.c
rename to src/libgit2/message.c
diff --git a/src/midx.c b/src/libgit2/midx.c
similarity index 95%
rename from src/midx.c
rename to src/libgit2/midx.c
index 0092601f6..67eab9acb 100644
--- a/src/midx.c
+++ b/src/libgit2/midx.c
@@ -115,7 +115,7 @@ static int midx_parse_oid_lookup(
struct git_midx_chunk *chunk_oid_lookup)
{
uint32_t i;
- git_oid *oid, *prev_oid, zero_oid = {{0}};
+ unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
if (chunk_oid_lookup->offset == 0)
return midx_error("missing OID Lookup chunk");
@@ -124,10 +124,10 @@ static int midx_parse_oid_lookup(
if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_RAWSZ)
return midx_error("OID Lookup chunk has wrong length");
- idx->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
- prev_oid = &zero_oid;
- for (i = 0; i < idx->num_objects; ++i, ++oid) {
- if (git_oid_cmp(prev_oid, oid) >= 0)
+ idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
+ prev_oid = zero_oid;
+ for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_RAWSZ) {
+ if (git_oid_raw_cmp(prev_oid, oid) >= 0)
return midx_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
@@ -179,7 +179,6 @@ int git_midx_parse(
uint32_t i;
off64_t last_chunk_offset, chunk_offset, trailer_offset;
size_t checksum_size;
- unsigned char checksum[GIT_HASH_SHA1_SIZE];
int error;
struct git_midx_chunk chunk_packfile_names = {0},
chunk_oid_fanout = {0},
@@ -217,11 +216,6 @@ int git_midx_parse(
return midx_error("wrong index size");
memcpy(idx->checksum, data + trailer_offset, checksum_size);
- if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
- return midx_error("could not calculate signature");
- if (memcmp(checksum, idx->checksum, checksum_size) != 0)
- return midx_error("index signature mismatch");
-
chunk_hdr = data + sizeof(struct git_midx_header);
last_chunk = NULL;
for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
@@ -389,7 +383,7 @@ int git_midx_entry_find(
int pos, found = 0;
size_t pack_index;
uint32_t hi, lo;
- const git_oid *current = NULL;
+ unsigned char *current = NULL;
const unsigned char *object_offset;
off64_t offset;
@@ -403,26 +397,25 @@ int git_midx_entry_find(
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
- current = idx->oid_lookup + pos;
+ current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)idx->num_objects) {
- current = idx->oid_lookup + pos;
+ current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
- if (!git_oid_ncmp(short_oid, current, len))
+ if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) {
/* Check for ambiguousity */
- const git_oid *next = current + 1;
+ const unsigned char *next = current + GIT_OID_RAWSZ;
- if (!git_oid_ncmp(short_oid, next, len)) {
+ if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
- }
}
if (!found)
@@ -432,8 +425,8 @@ int git_midx_entry_find(
object_offset = idx->object_offsets + pos * 8;
offset = ntohl(*((uint32_t *)(object_offset + 4)));
- if (offset & 0x80000000) {
- uint32_t object_large_offsets_pos = offset & 0x7fffffff;
+ if (idx->object_large_offsets && offset & 0x80000000) {
+ uint32_t object_large_offsets_pos = (uint32_t) (offset ^ 0x80000000);
const unsigned char *object_large_offsets_index = idx->object_large_offsets;
/* Make sure we're not being sent out of bounds */
@@ -450,7 +443,7 @@ int git_midx_entry_find(
return midx_error("invalid index into the packfile names table");
e->pack_index = pack_index;
e->offset = offset;
- git_oid_cpy(&e->sha1, current);
+ git_oid_fromraw(&e->sha1, current);
return 0;
}
@@ -459,13 +452,17 @@ int git_midx_foreach_entry(
git_odb_foreach_cb cb,
void *data)
{
+ git_oid oid;
size_t i;
int error;
GIT_ASSERT_ARG(idx);
for (i = 0; i < idx->num_objects; ++i) {
- if ((error = cb(&idx->oid_lookup[i], data)) != 0)
+ if ((error = git_oid_fromraw(&oid, &idx->oid_lookup[i * GIT_OID_RAWSZ])) < 0)
+ return error;
+
+ if ((error = cb(&oid, data)) != 0)
return git_error_set_after_callback(error);
}
@@ -751,7 +748,7 @@ static int midx_write(
/* Fill the OID Lookup table. */
git_vector_foreach (&object_entries, i, entry) {
- error = git_str_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
+ error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_RAWSZ);
if (error < 0)
goto cleanup;
}
diff --git a/src/midx.h b/src/libgit2/midx.h
similarity index 98%
rename from src/midx.h
rename to src/libgit2/midx.h
index 7dd851bd3..bcb0d9a0a 100644
--- a/src/midx.h
+++ b/src/libgit2/midx.h
@@ -17,6 +17,7 @@
#include "map.h"
#include "mwindow.h"
#include "odb.h"
+#include "oid.h"
/*
* A multi-pack-index file.
@@ -40,7 +41,7 @@ typedef struct git_midx_file {
uint32_t num_objects;
/* The OID Lookup table. */
- git_oid *oid_lookup;
+ unsigned char *oid_lookup;
/* The Object Offsets table. Each entry has two 4-byte fields with the pack index and the offset. */
const unsigned char *object_offsets;
diff --git a/src/mwindow.c b/src/libgit2/mwindow.c
similarity index 95%
rename from src/mwindow.c
rename to src/libgit2/mwindow.c
index d06b7a80e..ad649490a 100644
--- a/src/mwindow.c
+++ b/src/libgit2/mwindow.c
@@ -186,13 +186,16 @@ int git_mwindow_free_all(git_mwindow_file *mwf)
}
/*
- * Check if a window 'win' contains the address 'offset'
+ * Check if a window 'win' contains both the address 'offset' and 'extra'.
+ *
+ * 'extra' is the size of the hash we're using as we always want to make sure
+ * that it's contained.
*/
-int git_mwindow_contains(git_mwindow *win, off64_t offset)
+int git_mwindow_contains(git_mwindow *win, off64_t offset, off64_t extra)
{
off64_t win_off = win->offset;
return win_off <= offset
- && offset <= (off64_t)(win_off + win->window_map.len);
+ && (offset + extra) <= (off64_t)(win_off + win->window_map.len);
}
#define GIT_MWINDOW__LRU -1
@@ -237,9 +240,7 @@ static bool git_mwindow_scan_recently_used(
* store it in the output parameter. If lru_window is NULL,
* it's the first loop, so store it as well.
*/
- if (!lru_window ||
- (comparison_sign == GIT_MWINDOW__LRU && lru_window->last_used > w->last_used) ||
- (comparison_sign == GIT_MWINDOW__MRU && lru_window->last_used < w->last_used)) {
+ if (!lru_window || (comparison_sign * w->last_used) > lru_window->last_used) {
lru_window = w;
lru_last = w_last;
found = true;
@@ -406,14 +407,13 @@ unsigned char *git_mwindow_open(
return NULL;
}
- if (!w || !(git_mwindow_contains(w, offset) && git_mwindow_contains(w, offset + extra))) {
+ if (!w || !(git_mwindow_contains(w, offset, extra))) {
if (w) {
w->inuse_cnt--;
}
for (w = mwf->windows; w; w = w->next) {
- if (git_mwindow_contains(w, offset) &&
- git_mwindow_contains(w, offset + extra))
+ if (git_mwindow_contains(w, offset, extra))
break;
}
diff --git a/src/mwindow.h b/src/libgit2/mwindow.h
similarity index 95%
rename from src/mwindow.h
rename to src/libgit2/mwindow.h
index e3a03f019..e32ab99d4 100644
--- a/src/mwindow.h
+++ b/src/libgit2/mwindow.h
@@ -38,7 +38,7 @@ typedef struct git_mwindow_ctl {
git_vector windowfiles;
} git_mwindow_ctl;
-int git_mwindow_contains(git_mwindow *win, off64_t offset);
+int git_mwindow_contains(git_mwindow *win, off64_t offset, off64_t extra);
int git_mwindow_free_all(git_mwindow_file *mwf); /* locks */
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, off64_t offset, size_t extra, unsigned int *left);
int git_mwindow_file_register(git_mwindow_file *mwf);
diff --git a/src/netops.c b/src/libgit2/netops.c
similarity index 99%
rename from src/netops.c
rename to src/libgit2/netops.c
index 0a27365b8..00640c600 100644
--- a/src/netops.c
+++ b/src/libgit2/netops.c
@@ -12,7 +12,6 @@
#include "posix.h"
#include "str.h"
-#include "http_parser.h"
#include "runtime.h"
int gitno_recv(gitno_buffer *buf)
diff --git a/src/netops.h b/src/libgit2/netops.h
similarity index 100%
rename from src/netops.h
rename to src/libgit2/netops.h
diff --git a/src/notes.c b/src/libgit2/notes.c
similarity index 100%
rename from src/notes.c
rename to src/libgit2/notes.c
diff --git a/src/notes.h b/src/libgit2/notes.h
similarity index 100%
rename from src/notes.h
rename to src/libgit2/notes.h
diff --git a/src/object.c b/src/libgit2/object.c
similarity index 99%
rename from src/object.c
rename to src/libgit2/object.c
index 7bc256fce..b828f88f6 100644
--- a/src/object.c
+++ b/src/libgit2/object.c
@@ -250,6 +250,7 @@ int git_object_lookup_prefix(
if (error < 0)
return error;
+ GIT_ASSERT(odb_obj);
error = git_object__from_odb_object(object_out, repo, odb_obj, type);
git_odb_object_free(odb_obj);
diff --git a/src/object.h b/src/libgit2/object.h
similarity index 100%
rename from src/object.h
rename to src/libgit2/object.h
diff --git a/src/object_api.c b/src/libgit2/object_api.c
similarity index 100%
rename from src/object_api.c
rename to src/libgit2/object_api.c
diff --git a/src/odb.c b/src/libgit2/odb.c
similarity index 99%
rename from src/odb.c
rename to src/libgit2/odb.c
index 14eff53c7..7b98c72ee 100644
--- a/src/odb.c
+++ b/src/libgit2/odb.c
@@ -198,7 +198,7 @@ void git_odb_object_free(git_odb_object *object)
int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
{
size_t hdr_len;
- char hdr[64], buffer[FILEIO_BUFSIZE];
+ char hdr[64], buffer[GIT_BUFSIZE_FILEIO];
git_hash_ctx ctx;
ssize_t read_len = 0;
int error = 0;
@@ -1067,7 +1067,7 @@ int git_odb_expand_ids(
int git_odb_read_header(size_t *len_p, git_object_t *type_p, git_odb *db, const git_oid *id)
{
int error;
- git_odb_object *object;
+ git_odb_object *object = NULL;
error = git_odb__read_header_or_object(&object, len_p, type_p, db, id);
diff --git a/src/odb.h b/src/libgit2/odb.h
similarity index 100%
rename from src/odb.h
rename to src/libgit2/odb.h
diff --git a/src/odb_loose.c b/src/libgit2/odb_loose.c
similarity index 100%
rename from src/odb_loose.c
rename to src/libgit2/odb_loose.c
diff --git a/src/odb_mempack.c b/src/libgit2/odb_mempack.c
similarity index 100%
rename from src/odb_mempack.c
rename to src/libgit2/odb_mempack.c
diff --git a/src/odb_pack.c b/src/libgit2/odb_pack.c
similarity index 100%
rename from src/odb_pack.c
rename to src/libgit2/odb_pack.c
diff --git a/src/offmap.c b/src/libgit2/offmap.c
similarity index 100%
rename from src/offmap.c
rename to src/libgit2/offmap.c
diff --git a/src/offmap.h b/src/libgit2/offmap.h
similarity index 100%
rename from src/offmap.h
rename to src/libgit2/offmap.h
diff --git a/src/oid.c b/src/libgit2/oid.c
similarity index 96%
rename from src/oid.c
rename to src/libgit2/oid.c
index 19061e899..fb92174ab 100644
--- a/src/oid.c
+++ b/src/libgit2/oid.c
@@ -187,8 +187,7 @@ int git_oid_fromraw(git_oid *out, const unsigned char *raw)
int git_oid_cpy(git_oid *out, const git_oid *src)
{
- memcpy(out->id, src->id, sizeof(out->id));
- return 0;
+ return git_oid_raw_cpy(out->id, src->id);
}
int git_oid_cmp(const git_oid *a, const git_oid *b)
@@ -203,25 +202,7 @@ int git_oid_equal(const git_oid *a, const git_oid *b)
int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
{
- const unsigned char *a = oid_a->id;
- const unsigned char *b = oid_b->id;
-
- if (len > GIT_OID_HEXSZ)
- len = GIT_OID_HEXSZ;
-
- while (len > 1) {
- if (*a != *b)
- return 1;
- a++;
- b++;
- len -= 2;
- };
-
- if (len)
- if ((*a ^ *b) & 0xf0)
- return 1;
-
- return 0;
+ return git_oid_raw_ncmp(oid_a->id, oid_b->id, len);
}
int git_oid_strcmp(const git_oid *oid_a, const char *str)
diff --git a/src/oid.h b/src/libgit2/oid.h
similarity index 70%
rename from src/oid.h
rename to src/libgit2/oid.h
index 5baec33e5..abae9a4b2 100644
--- a/src/oid.h
+++ b/src/libgit2/oid.h
@@ -25,11 +25,44 @@ extern const git_oid git_oid__empty_tree_sha1;
*/
char *git_oid_allocfmt(const git_oid *id);
-GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
+GIT_INLINE(int) git_oid_raw_ncmp(
+ const unsigned char *sha1,
+ const unsigned char *sha2,
+ size_t len)
+{
+ if (len > GIT_OID_HEXSZ)
+ len = GIT_OID_HEXSZ;
+
+ while (len > 1) {
+ if (*sha1 != *sha2)
+ return 1;
+ sha1++;
+ sha2++;
+ len -= 2;
+ };
+
+ if (len)
+ if ((*sha1 ^ *sha2) & 0xf0)
+ return 1;
+
+ return 0;
+}
+
+GIT_INLINE(int) git_oid_raw_cmp(
+ const unsigned char *sha1,
+ const unsigned char *sha2)
{
return memcmp(sha1, sha2, GIT_OID_RAWSZ);
}
+GIT_INLINE(int) git_oid_raw_cpy(
+ unsigned char *dst,
+ const unsigned char *src)
+{
+ memcpy(dst, src, GIT_OID_RAWSZ);
+ return 0;
+}
+
/*
* Compare two oid structures.
*
@@ -39,7 +72,7 @@ GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char
*/
GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
{
- return git_oid__hashcmp(a->id, b->id);
+ return git_oid_raw_cmp(a->id, b->id);
}
GIT_INLINE(void) git_oid__cpy_prefix(
diff --git a/src/oidarray.c b/src/libgit2/oidarray.c
similarity index 100%
rename from src/oidarray.c
rename to src/libgit2/oidarray.c
diff --git a/src/oidarray.h b/src/libgit2/oidarray.h
similarity index 100%
rename from src/oidarray.h
rename to src/libgit2/oidarray.h
diff --git a/src/oidmap.c b/src/libgit2/oidmap.c
similarity index 98%
rename from src/oidmap.c
rename to src/libgit2/oidmap.c
index 0ae8bf33e..eaf9fa051 100644
--- a/src/oidmap.c
+++ b/src/libgit2/oidmap.c
@@ -19,7 +19,7 @@ __KHASH_TYPE(oid, const git_oid *, void *)
GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
{
khint_t h;
- memcpy(&h, oid, sizeof(khint_t));
+ memcpy(&h, oid->id, sizeof(khint_t));
return h;
}
diff --git a/src/oidmap.h b/src/libgit2/oidmap.h
similarity index 100%
rename from src/oidmap.h
rename to src/libgit2/oidmap.h
diff --git a/src/pack-objects.c b/src/libgit2/pack-objects.c
similarity index 100%
rename from src/pack-objects.c
rename to src/libgit2/pack-objects.c
diff --git a/src/pack-objects.h b/src/libgit2/pack-objects.h
similarity index 100%
rename from src/pack-objects.h
rename to src/libgit2/pack-objects.h
diff --git a/src/pack.c b/src/libgit2/pack.c
similarity index 97%
rename from src/pack.c
rename to src/libgit2/pack.c
index 5c0cba7e8..16fe378bd 100644
--- a/src/pack.c
+++ b/src/libgit2/pack.c
@@ -1001,13 +1001,14 @@ int get_delta_base(
base_offset = delta_obj_offset - unsigned_base_offset;
*curpos += used;
} else if (type == GIT_OBJECT_REF_DELTA) {
+ git_oid base_oid;
+ git_oid_fromraw(&base_oid, base_info);
+
/* If we have the cooperative cache, search in it first */
if (p->has_cache) {
struct git_pack_entry *entry;
- git_oid oid;
- git_oid_fromraw(&oid, base_info);
- if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
+ if ((entry = git_oidmap_get(p->idx_cache, &base_oid)) != NULL) {
if (entry->offset == 0)
return packfile_error("delta offset is zero");
@@ -1024,7 +1025,7 @@ int get_delta_base(
}
/* The base entry _must_ be in the same pack */
- if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < 0)
+ if (pack_entry_find_offset(&base_offset, &unused, p, &base_oid, GIT_OID_HEXSZ) < 0)
return packfile_error("base entry delta is not in the same pack");
*curpos += 20;
} else
@@ -1082,7 +1083,7 @@ static int packfile_open_locked(struct git_pack_file *p)
{
struct stat st;
struct git_pack_header hdr;
- git_oid sha1;
+ unsigned char sha1[GIT_OID_RAWSZ];
unsigned char *idx_sha1;
if (pack_index_open_locked(p) < 0)
@@ -1130,12 +1131,12 @@ static int packfile_open_locked(struct git_pack_file *p)
/* Verify the pack matches its index. */
if (p->num_objects != ntohl(hdr.hdr_entries) ||
- p_pread(p->mwf.fd, sha1.id, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
+ p_pread(p->mwf.fd, sha1, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
goto cleanup;
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
- if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
+ if (git_oid_raw_cmp(sha1, idx_sha1) != 0)
goto cleanup;
if (git_mwindow_file_register(&p->mwf) < 0)
@@ -1340,10 +1341,14 @@ int git_pack_foreach_entry(
}
git_vector_free(&offsets);
- p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
+ p->oids = (unsigned char **)git_vector_detach(NULL, NULL, &oids);
}
- /* We need to copy the OIDs to another array before we relinquish the lock to avoid races. */
+ /*
+ * We need to copy the OIDs to another array before we
+ * relinquish the lock to avoid races. We can also take
+ * this opportunity to put them into normal form.
+ */
git_array_init_to_size(oids, p->num_objects);
if (!oids.ptr) {
git_mutex_unlock(&p->lock);
@@ -1357,7 +1362,7 @@ int git_pack_foreach_entry(
git_array_clear(oids);
GIT_ERROR_CHECK_ALLOC(oid);
}
- git_oid_cpy(oid, p->oids[i]);
+ git_oid_fromraw(oid, p->oids[i]);
}
git_mutex_unlock(&p->lock);
@@ -1380,7 +1385,7 @@ int git_pack_foreach_entry_offset(
{
const unsigned char *index;
off64_t current_offset;
- const git_oid *current_oid;
+ git_oid current_oid;
uint32_t i;
int error = 0;
@@ -1422,8 +1427,9 @@ int git_pack_foreach_entry_offset(
current_offset = (((off64_t)ntohl(*((uint32_t *)(large_offset_ptr + 0)))) << 32) |
ntohl(*((uint32_t *)(large_offset_ptr + 4)));
}
- current_oid = (const git_oid *)(index + 20 * i);
- if ((error = cb(current_oid, current_offset, data)) != 0) {
+
+ git_oid_fromraw(¤t_oid, (index + 20 * i));
+ if ((error = cb(¤t_oid, current_offset, data)) != 0) {
error = git_error_set_after_callback(error);
goto cleanup;
}
@@ -1431,8 +1437,8 @@ int git_pack_foreach_entry_offset(
} else {
for (i = 0; i < p->num_objects; i++) {
current_offset = ntohl(*(const uint32_t *)(index + 24 * i));
- current_oid = (const git_oid *)(index + 24 * i + 4);
- if ((error = cb(current_oid, current_offset, data)) != 0) {
+ git_oid_fromraw(¤t_oid, (index + 24 * i + 4));
+ if ((error = cb(¤t_oid, current_offset, data)) != 0) {
error = git_error_set_after_callback(error);
goto cleanup;
}
@@ -1451,7 +1457,7 @@ int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned
while (lo < hi) {
unsigned mi = (lo + hi) / 2;
- int cmp = git_oid__hashcmp(base + mi * stride, oid_prefix);
+ int cmp = git_oid_raw_cmp(base + mi * stride, oid_prefix);
if (!cmp)
return mi;
@@ -1530,7 +1536,7 @@ static int pack_entry_find_offset(
if (pos < (int)p->num_objects) {
current = index + pos * stride;
- if (!git_oid_ncmp(short_oid, (const git_oid *)current, len))
+ if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
@@ -1539,7 +1545,7 @@ static int pack_entry_find_offset(
/* Check for ambiguousity */
const unsigned char *next = current + stride;
- if (!git_oid_ncmp(short_oid, (const git_oid *)next, len)) {
+ if (!git_oid_raw_ncmp(short_oid->id, next, len)) {
found = 2;
}
}
diff --git a/src/pack.h b/src/libgit2/pack.h
similarity index 98%
rename from src/pack.h
rename to src/libgit2/pack.h
index bf279c6b6..d90588f79 100644
--- a/src/pack.h
+++ b/src/libgit2/pack.h
@@ -19,6 +19,7 @@
#include "offmap.h"
#include "oidmap.h"
#include "zstream.h"
+#include "oid.h"
/**
* Function type for callbacks from git_pack_foreach_entry_offset.
@@ -32,7 +33,7 @@ typedef int git_pack_foreach_entry_offset_cb(
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
#define PACK_VERSION 2
-#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
+#define pack_version_ok(v) ((v) == htonl(2))
struct git_pack_header {
uint32_t hdr_signature;
uint32_t hdr_version;
@@ -104,7 +105,7 @@ struct git_pack_file {
git_time_t mtime;
unsigned pack_local:1, pack_keep:1, has_cache:1;
git_oidmap *idx_cache;
- git_oid **oids;
+ unsigned char **oids;
git_pack_cache bases; /* delta base cache */
diff --git a/src/parse.c b/src/libgit2/parse.c
similarity index 100%
rename from src/parse.c
rename to src/libgit2/parse.c
diff --git a/src/parse.h b/src/libgit2/parse.h
similarity index 100%
rename from src/parse.h
rename to src/libgit2/parse.h
diff --git a/src/patch.c b/src/libgit2/patch.c
similarity index 100%
rename from src/patch.c
rename to src/libgit2/patch.c
diff --git a/src/patch.h b/src/libgit2/patch.h
similarity index 100%
rename from src/patch.h
rename to src/libgit2/patch.h
diff --git a/src/patch_generate.c b/src/libgit2/patch_generate.c
similarity index 100%
rename from src/patch_generate.c
rename to src/libgit2/patch_generate.c
diff --git a/src/patch_generate.h b/src/libgit2/patch_generate.h
similarity index 100%
rename from src/patch_generate.h
rename to src/libgit2/patch_generate.h
diff --git a/src/patch_parse.c b/src/libgit2/patch_parse.c
similarity index 100%
rename from src/patch_parse.c
rename to src/libgit2/patch_parse.c
diff --git a/src/patch_parse.h b/src/libgit2/patch_parse.h
similarity index 100%
rename from src/patch_parse.h
rename to src/libgit2/patch_parse.h
diff --git a/src/path.c b/src/libgit2/path.c
similarity index 99%
rename from src/path.c
rename to src/libgit2/path.c
index 05a3dc2cf..a19340efe 100644
--- a/src/path.c
+++ b/src/libgit2/path.c
@@ -9,6 +9,7 @@
#include "repository.h"
#include "fs_path.h"
+#include "utf8.h"
typedef struct {
git_repository *repo;
diff --git a/src/path.h b/src/libgit2/path.h
similarity index 100%
rename from src/path.h
rename to src/libgit2/path.h
diff --git a/src/pathspec.c b/src/libgit2/pathspec.c
similarity index 100%
rename from src/pathspec.c
rename to src/libgit2/pathspec.c
diff --git a/src/pathspec.h b/src/libgit2/pathspec.h
similarity index 100%
rename from src/pathspec.h
rename to src/libgit2/pathspec.h
diff --git a/src/proxy.c b/src/libgit2/proxy.c
similarity index 100%
rename from src/proxy.c
rename to src/libgit2/proxy.c
diff --git a/src/proxy.h b/src/libgit2/proxy.h
similarity index 100%
rename from src/proxy.h
rename to src/libgit2/proxy.h
diff --git a/src/push.c b/src/libgit2/push.c
similarity index 100%
rename from src/push.c
rename to src/libgit2/push.c
diff --git a/src/push.h b/src/libgit2/push.h
similarity index 100%
rename from src/push.h
rename to src/libgit2/push.h
diff --git a/src/reader.c b/src/libgit2/reader.c
similarity index 100%
rename from src/reader.c
rename to src/libgit2/reader.c
diff --git a/src/reader.h b/src/libgit2/reader.h
similarity index 100%
rename from src/reader.h
rename to src/libgit2/reader.h
diff --git a/src/rebase.c b/src/libgit2/rebase.c
similarity index 99%
rename from src/rebase.c
rename to src/libgit2/rebase.c
index 6f01d3990..5e48f0dfb 100644
--- a/src/rebase.c
+++ b/src/libgit2/rebase.c
@@ -35,6 +35,7 @@
#define ONTO_FILE "onto"
#define ONTO_NAME_FILE "onto_name"
#define QUIET_FILE "quiet"
+#define INTERACTIVE_FILE "interactive"
#define MSGNUM_FILE "msgnum"
#define END_FILE "end"
@@ -92,6 +93,7 @@ static int rebase_state_type(
git_repository *repo)
{
git_str path = GIT_STR_INIT;
+ git_str interactive_path = GIT_STR_INIT;
git_rebase_t type = GIT_REBASE_NONE;
if (git_str_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
@@ -107,7 +109,14 @@ static int rebase_state_type(
return -1;
if (git_fs_path_isdir(git_str_cstr(&path))) {
- type = GIT_REBASE_MERGE;
+ if (git_str_joinpath(&interactive_path, path.ptr, INTERACTIVE_FILE) < 0)
+ return -1;
+
+ if (git_fs_path_isfile(interactive_path.ptr))
+ type = GIT_REBASE_INTERACTIVE;
+ else
+ type = GIT_REBASE_MERGE;
+
goto done;
}
@@ -118,6 +127,7 @@ done:
*path_out = git_str_detach(&path);
git_str_dispose(&path);
+ git_str_dispose(&interactive_path);
return 0;
}
diff --git a/src/refdb.c b/src/libgit2/refdb.c
similarity index 100%
rename from src/refdb.c
rename to src/libgit2/refdb.c
diff --git a/src/refdb.h b/src/libgit2/refdb.h
similarity index 100%
rename from src/refdb.h
rename to src/libgit2/refdb.h
diff --git a/src/refdb_fs.c b/src/libgit2/refdb_fs.c
similarity index 99%
rename from src/refdb_fs.c
rename to src/libgit2/refdb_fs.c
index 95bda9404..0f49b16bb 100644
--- a/src/refdb_fs.c
+++ b/src/libgit2/refdb_fs.c
@@ -740,7 +740,7 @@ static int packed_lookup(
return 0;
}
}
- return GIT_ENOTFOUND;
+ return ref_error_notfound(ref_name);
parse_failed:
git_error_set(GIT_ERROR_REFERENCE, "corrupted packed references file");
@@ -1361,7 +1361,11 @@ static int packed_write(refdb_fs_backend *backend)
for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) {
struct packref *ref = git_sortedcache_entry(refcache, i);
- GIT_ASSERT(ref);
+
+ GIT_ASSERT_WITH_CLEANUP(ref, {
+ error = -1;
+ goto fail;
+ });
if ((error = packed_find_peel(backend, ref)) < 0)
goto fail;
diff --git a/src/reflog.c b/src/libgit2/reflog.c
similarity index 100%
rename from src/reflog.c
rename to src/libgit2/reflog.c
diff --git a/src/reflog.h b/src/libgit2/reflog.h
similarity index 100%
rename from src/reflog.h
rename to src/libgit2/reflog.h
diff --git a/src/refs.c b/src/libgit2/refs.c
similarity index 100%
rename from src/refs.c
rename to src/libgit2/refs.c
diff --git a/src/refs.h b/src/libgit2/refs.h
similarity index 100%
rename from src/refs.h
rename to src/libgit2/refs.h
diff --git a/src/refspec.c b/src/libgit2/refspec.c
similarity index 100%
rename from src/refspec.c
rename to src/libgit2/refspec.c
diff --git a/src/refspec.h b/src/libgit2/refspec.h
similarity index 100%
rename from src/refspec.h
rename to src/libgit2/refspec.h
diff --git a/src/remote.c b/src/libgit2/remote.c
similarity index 99%
rename from src/remote.c
rename to src/libgit2/remote.c
index 1a79faaab..3d0593712 100644
--- a/src/remote.c
+++ b/src/libgit2/remote.c
@@ -1830,7 +1830,7 @@ static int update_one_tip(
}
if (error == GIT_ENOTFOUND) {
- memset(&old, 0, GIT_OID_RAWSZ);
+ memset(&old, 0, sizeof(git_oid));
error = 0;
if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
diff --git a/src/remote.h b/src/libgit2/remote.h
similarity index 95%
rename from src/remote.h
rename to src/libgit2/remote.h
index ea9c7d17f..41ee58e0f 100644
--- a/src/remote.h
+++ b/src/libgit2/remote.h
@@ -11,6 +11,7 @@
#include "git2/remote.h"
#include "git2/transport.h"
+#include "git2/sys/remote.h"
#include "git2/sys/transport.h"
#include "refspec.h"
@@ -53,7 +54,6 @@ int git_remote_connect_options_normalize(
git_remote_connect_options *dst,
git_repository *repo,
const git_remote_connect_options *src);
-void git_remote_connect_options_dispose(git_remote_connect_options *opts);
int git_remote_capabilities(unsigned int *out, git_remote *remote);
diff --git a/src/repo_template.h b/src/libgit2/repo_template.h
similarity index 100%
rename from src/repo_template.h
rename to src/libgit2/repo_template.h
diff --git a/src/repository.c b/src/libgit2/repository.c
similarity index 97%
rename from src/repository.c
rename to src/libgit2/repository.c
index 6119c1c70..f761b5f32 100644
--- a/src/repository.c
+++ b/src/libgit2/repository.c
@@ -488,7 +488,7 @@ static int read_gitfile(git_str *path_out, const char *file_path)
typedef struct {
const char *repo_path;
git_str tmp;
- bool is_safe;
+ bool *is_safe;
} validate_ownership_data;
static int validate_ownership_cb(const git_config_entry *entry, void *payload)
@@ -496,49 +496,102 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
validate_ownership_data *data = payload;
if (strcmp(entry->value, "") == 0)
- data->is_safe = false;
+ *data->is_safe = false;
if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
strcmp(data->tmp.ptr, data->repo_path) == 0)
- data->is_safe = true;
+ *data->is_safe = true;
return 0;
}
-static int validate_ownership(const char *repo_path)
+static int validate_ownership_config(bool *is_safe, const char *path)
{
- git_config *config = NULL;
- validate_ownership_data data = { repo_path, GIT_STR_INIT, false };
- bool is_safe;
+ validate_ownership_data ownership_data = {
+ path, GIT_STR_INIT, is_safe
+ };
+ git_config *config;
int error;
- if ((error = git_fs_path_owner_is_current_user(&is_safe, repo_path)) < 0) {
- if (error == GIT_ENOTFOUND)
- error = 0;
+ if (load_global_config(&config) != 0)
+ return 0;
- goto done;
- }
+ error = git_config_get_multivar_foreach(config,
+ "safe.directory", NULL,
+ validate_ownership_cb,
+ &ownership_data);
- if (is_safe) {
+ git_config_free(config);
+ git_str_dispose(&ownership_data.tmp);
+
+ return error;
+}
+
+static int validate_ownership_path(bool *is_safe, const char *path)
+{
+ git_fs_path_owner_t owner_level =
+ GIT_FS_PATH_OWNER_CURRENT_USER |
+ GIT_FS_PATH_USER_IS_ADMINISTRATOR |
+ GIT_FS_PATH_OWNER_RUNNING_SUDO;
+ int error = 0;
+
+ if (path)
+ error = git_fs_path_owner_is(is_safe, path, owner_level);
+
+ if (error == GIT_ENOTFOUND) {
+ *is_safe = true;
error = 0;
- goto done;
}
- if (load_global_config(&config) == 0) {
- error = git_config_get_multivar_foreach(config, "safe.directory", NULL, validate_ownership_cb, &data);
+ return error;
+}
- if (!error && data.is_safe)
+static int validate_ownership(git_repository *repo)
+{
+ const char *validation_paths[3] = { NULL }, *path;
+ size_t validation_len = 0, i;
+ bool is_safe = false;
+ int error = 0;
+
+ /*
+ * If there's a worktree, validate the permissions to it *and*
+ * the git directory, and use the worktree as the configuration
+ * key for allowlisting the directory. In a bare setup, only
+ * look at the gitdir and use that as the allowlist. So we
+ * examine all `validation_paths` but use only the first as
+ * the configuration lookup.
+ */
+
+ if (repo->workdir)
+ validation_paths[validation_len++] = repo->workdir;
+
+ if (repo->gitlink)
+ validation_paths[validation_len++] = repo->gitlink;
+
+ validation_paths[validation_len++] = repo->gitdir;
+
+ for (i = 0; i < validation_len; i++) {
+ path = validation_paths[i];
+
+ if ((error = validate_ownership_path(&is_safe, path)) < 0)
goto done;
+
+ if (!is_safe)
+ break;
}
- git_error_set(GIT_ERROR_CONFIG,
- "repository path '%s' is not owned by current user",
- repo_path);
- error = GIT_EOWNER;
+ if (is_safe ||
+ (error = validate_ownership_config(&is_safe, validation_paths[0])) < 0)
+ goto done;
+
+ if (!is_safe) {
+ git_error_set(GIT_ERROR_CONFIG,
+ "repository path '%s' is not owned by current user",
+ path);
+ error = GIT_EOWNER;
+ }
done:
- git_config_free(config);
- git_str_dispose(&data.tmp);
return error;
}
@@ -915,7 +968,6 @@ int git_repository_open_ext(
gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
git_repository *repo = NULL;
git_config *config = NULL;
- const char *validation_path;
int version = 0;
if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
@@ -974,12 +1026,11 @@ int git_repository_open_ext(
}
/*
- * Ensure that the git directory is owned by the current user.
+ * Ensure that the git directory and worktree are
+ * owned by the current user.
*/
- validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
-
if (git_repository__validate_ownership &&
- (error = validate_ownership(validation_path)) < 0)
+ (error = validate_ownership(repo)) < 0)
goto cleanup;
cleanup:
@@ -1530,6 +1581,7 @@ static int check_valid_extension(const git_config_entry *entry, void *payload)
}
for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
+ git_str_clear(&cfg);
extension = builtin_extensions[i];
if ((error = git_str_printf(&cfg, "extensions.%s", extension)) < 0)
diff --git a/src/repository.h b/src/libgit2/repository.h
similarity index 100%
rename from src/repository.h
rename to src/libgit2/repository.h
diff --git a/src/reset.c b/src/libgit2/reset.c
similarity index 100%
rename from src/reset.c
rename to src/libgit2/reset.c
diff --git a/src/revert.c b/src/libgit2/revert.c
similarity index 100%
rename from src/revert.c
rename to src/libgit2/revert.c
diff --git a/src/revparse.c b/src/libgit2/revparse.c
similarity index 100%
rename from src/revparse.c
rename to src/libgit2/revparse.c
diff --git a/src/revwalk.c b/src/libgit2/revwalk.c
similarity index 100%
rename from src/revwalk.c
rename to src/libgit2/revwalk.c
diff --git a/src/revwalk.h b/src/libgit2/revwalk.h
similarity index 100%
rename from src/revwalk.h
rename to src/libgit2/revwalk.h
diff --git a/src/settings.h b/src/libgit2/settings.h
similarity index 100%
rename from src/settings.h
rename to src/libgit2/settings.h
diff --git a/src/signature.c b/src/libgit2/signature.c
similarity index 100%
rename from src/signature.c
rename to src/libgit2/signature.c
diff --git a/src/signature.h b/src/libgit2/signature.h
similarity index 100%
rename from src/signature.h
rename to src/libgit2/signature.h
diff --git a/src/stash.c b/src/libgit2/stash.c
similarity index 100%
rename from src/stash.c
rename to src/libgit2/stash.c
diff --git a/src/status.c b/src/libgit2/status.c
similarity index 100%
rename from src/status.c
rename to src/libgit2/status.c
diff --git a/src/status.h b/src/libgit2/status.h
similarity index 100%
rename from src/status.h
rename to src/libgit2/status.h
diff --git a/src/strarray.c b/src/libgit2/strarray.c
similarity index 100%
rename from src/strarray.c
rename to src/libgit2/strarray.c
diff --git a/src/stream.h b/src/libgit2/stream.h
similarity index 100%
rename from src/stream.h
rename to src/libgit2/stream.h
diff --git a/src/streams/mbedtls.c b/src/libgit2/streams/mbedtls.c
similarity index 100%
rename from src/streams/mbedtls.c
rename to src/libgit2/streams/mbedtls.c
diff --git a/src/streams/mbedtls.h b/src/libgit2/streams/mbedtls.h
similarity index 100%
rename from src/streams/mbedtls.h
rename to src/libgit2/streams/mbedtls.h
diff --git a/src/streams/openssl.c b/src/libgit2/streams/openssl.c
similarity index 100%
rename from src/streams/openssl.c
rename to src/libgit2/streams/openssl.c
diff --git a/src/streams/openssl.h b/src/libgit2/streams/openssl.h
similarity index 100%
rename from src/streams/openssl.h
rename to src/libgit2/streams/openssl.h
diff --git a/src/streams/openssl_dynamic.c b/src/libgit2/streams/openssl_dynamic.c
similarity index 100%
rename from src/streams/openssl_dynamic.c
rename to src/libgit2/streams/openssl_dynamic.c
diff --git a/src/streams/openssl_dynamic.h b/src/libgit2/streams/openssl_dynamic.h
similarity index 100%
rename from src/streams/openssl_dynamic.h
rename to src/libgit2/streams/openssl_dynamic.h
diff --git a/src/streams/openssl_legacy.c b/src/libgit2/streams/openssl_legacy.c
similarity index 100%
rename from src/streams/openssl_legacy.c
rename to src/libgit2/streams/openssl_legacy.c
diff --git a/src/streams/openssl_legacy.h b/src/libgit2/streams/openssl_legacy.h
similarity index 100%
rename from src/streams/openssl_legacy.h
rename to src/libgit2/streams/openssl_legacy.h
diff --git a/src/streams/registry.c b/src/libgit2/streams/registry.c
similarity index 100%
rename from src/streams/registry.c
rename to src/libgit2/streams/registry.c
diff --git a/src/streams/registry.h b/src/libgit2/streams/registry.h
similarity index 100%
rename from src/streams/registry.h
rename to src/libgit2/streams/registry.h
diff --git a/src/streams/socket.c b/src/libgit2/streams/socket.c
similarity index 100%
rename from src/streams/socket.c
rename to src/libgit2/streams/socket.c
diff --git a/src/streams/socket.h b/src/libgit2/streams/socket.h
similarity index 100%
rename from src/streams/socket.h
rename to src/libgit2/streams/socket.h
diff --git a/src/streams/stransport.c b/src/libgit2/streams/stransport.c
similarity index 100%
rename from src/streams/stransport.c
rename to src/libgit2/streams/stransport.c
diff --git a/src/streams/stransport.h b/src/libgit2/streams/stransport.h
similarity index 100%
rename from src/streams/stransport.h
rename to src/libgit2/streams/stransport.h
diff --git a/src/streams/tls.c b/src/libgit2/streams/tls.c
similarity index 100%
rename from src/streams/tls.c
rename to src/libgit2/streams/tls.c
diff --git a/src/streams/tls.h b/src/libgit2/streams/tls.h
similarity index 100%
rename from src/streams/tls.h
rename to src/libgit2/streams/tls.h
diff --git a/src/submodule.c b/src/libgit2/submodule.c
similarity index 100%
rename from src/submodule.c
rename to src/libgit2/submodule.c
diff --git a/src/submodule.h b/src/libgit2/submodule.h
similarity index 100%
rename from src/submodule.h
rename to src/libgit2/submodule.h
diff --git a/src/sysdir.c b/src/libgit2/sysdir.c
similarity index 100%
rename from src/sysdir.c
rename to src/libgit2/sysdir.c
diff --git a/src/sysdir.h b/src/libgit2/sysdir.h
similarity index 100%
rename from src/sysdir.h
rename to src/libgit2/sysdir.h
diff --git a/src/tag.c b/src/libgit2/tag.c
similarity index 98%
rename from src/tag.c
rename to src/libgit2/tag.c
index 5734106fa..792155a4b 100644
--- a/src/tag.c
+++ b/src/libgit2/tag.c
@@ -244,6 +244,15 @@ on_error:
return -1;
}
+static bool tag_name_is_valid(const char *tag_name)
+{
+ /*
+ * Discourage tag name starting with dash,
+ * https://github.com/git/git/commit/4f0accd638b8d2
+ */
+ return tag_name[0] != '-';
+}
+
static int git_tag_create__internal(
git_oid *oid,
git_repository *repo,
@@ -269,6 +278,11 @@ static int git_tag_create__internal(
return -1;
}
+ if (!tag_name_is_valid(tag_name)) {
+ git_error_set(GIT_ERROR_TAG, "'%s' is not a valid tag name", tag_name);
+ return -1;
+ }
+
error = retrieve_tag_reference_oid(oid, &ref_name, repo, tag_name);
if (error < 0 && error != GIT_ENOTFOUND)
goto cleanup;
@@ -542,11 +556,7 @@ int git_tag_name_is_valid(int *valid, const char *name)
*valid = 0;
- /*
- * Discourage tag name starting with dash,
- * https://github.com/git/git/commit/4f0accd638b8d2
- */
- if (!name || name[0] == '-')
+ if (!name || !tag_name_is_valid(name))
goto done;
if ((error = git_str_puts(&ref_name, GIT_REFS_TAGS_DIR)) < 0 ||
diff --git a/src/tag.h b/src/libgit2/tag.h
similarity index 100%
rename from src/tag.h
rename to src/libgit2/tag.h
diff --git a/src/threadstate.c b/src/libgit2/threadstate.c
similarity index 100%
rename from src/threadstate.c
rename to src/libgit2/threadstate.c
diff --git a/src/threadstate.h b/src/libgit2/threadstate.h
similarity index 100%
rename from src/threadstate.h
rename to src/libgit2/threadstate.h
diff --git a/src/trace.c b/src/libgit2/trace.c
similarity index 100%
rename from src/trace.c
rename to src/libgit2/trace.c
diff --git a/src/trace.h b/src/libgit2/trace.h
similarity index 100%
rename from src/trace.h
rename to src/libgit2/trace.h
diff --git a/src/trailer.c b/src/libgit2/trailer.c
similarity index 100%
rename from src/trailer.c
rename to src/libgit2/trailer.c
diff --git a/src/transaction.c b/src/libgit2/transaction.c
similarity index 100%
rename from src/transaction.c
rename to src/libgit2/transaction.c
diff --git a/src/transaction.h b/src/libgit2/transaction.h
similarity index 100%
rename from src/transaction.h
rename to src/libgit2/transaction.h
diff --git a/src/transport.c b/src/libgit2/transport.c
similarity index 100%
rename from src/transport.c
rename to src/libgit2/transport.c
diff --git a/src/transports/auth.c b/src/libgit2/transports/auth.c
similarity index 100%
rename from src/transports/auth.c
rename to src/libgit2/transports/auth.c
diff --git a/src/transports/auth.h b/src/libgit2/transports/auth.h
similarity index 100%
rename from src/transports/auth.h
rename to src/libgit2/transports/auth.h
diff --git a/src/transports/auth_negotiate.c b/src/libgit2/transports/auth_negotiate.c
similarity index 100%
rename from src/transports/auth_negotiate.c
rename to src/libgit2/transports/auth_negotiate.c
diff --git a/src/transports/auth_negotiate.h b/src/libgit2/transports/auth_negotiate.h
similarity index 100%
rename from src/transports/auth_negotiate.h
rename to src/libgit2/transports/auth_negotiate.h
diff --git a/src/transports/auth_ntlm.c b/src/libgit2/transports/auth_ntlm.c
similarity index 100%
rename from src/transports/auth_ntlm.c
rename to src/libgit2/transports/auth_ntlm.c
diff --git a/src/transports/auth_ntlm.h b/src/libgit2/transports/auth_ntlm.h
similarity index 100%
rename from src/transports/auth_ntlm.h
rename to src/libgit2/transports/auth_ntlm.h
diff --git a/src/transports/credential.c b/src/libgit2/transports/credential.c
similarity index 100%
rename from src/transports/credential.c
rename to src/libgit2/transports/credential.c
diff --git a/src/transports/credential_helpers.c b/src/libgit2/transports/credential_helpers.c
similarity index 100%
rename from src/transports/credential_helpers.c
rename to src/libgit2/transports/credential_helpers.c
diff --git a/src/transports/git.c b/src/libgit2/transports/git.c
similarity index 100%
rename from src/transports/git.c
rename to src/libgit2/transports/git.c
diff --git a/src/transports/http.c b/src/libgit2/transports/http.c
similarity index 100%
rename from src/transports/http.c
rename to src/libgit2/transports/http.c
diff --git a/src/transports/http.h b/src/libgit2/transports/http.h
similarity index 100%
rename from src/transports/http.h
rename to src/libgit2/transports/http.h
diff --git a/src/transports/httpclient.c b/src/libgit2/transports/httpclient.c
similarity index 99%
rename from src/transports/httpclient.c
rename to src/libgit2/transports/httpclient.c
index 75782da82..f07923ef2 100644
--- a/src/transports/httpclient.c
+++ b/src/libgit2/transports/httpclient.c
@@ -395,7 +395,7 @@ static int on_body(http_parser *parser, const char *buf, size_t len)
size_t max_len;
/* Saw data when we expected not to (eg, in consume_response_body) */
- if (ctx->output_buf == NULL && ctx->output_size == 0) {
+ if (ctx->output_buf == NULL || ctx->output_size == 0) {
ctx->parse_status = PARSE_STATUS_NO_OUTPUT;
return 0;
}
diff --git a/src/transports/httpclient.h b/src/libgit2/transports/httpclient.h
similarity index 100%
rename from src/transports/httpclient.h
rename to src/libgit2/transports/httpclient.h
diff --git a/src/transports/local.c b/src/libgit2/transports/local.c
similarity index 100%
rename from src/transports/local.c
rename to src/libgit2/transports/local.c
diff --git a/src/transports/smart.c b/src/libgit2/transports/smart.c
similarity index 97%
rename from src/transports/smart.c
rename to src/libgit2/transports/smart.c
index 801fcbe53..7f57dba2a 100644
--- a/src/transports/smart.c
+++ b/src/libgit2/transports/smart.c
@@ -425,6 +425,18 @@ int git_transport_smart_credentials(git_credential **out, git_transport *transpo
return connect_opts->callbacks.credentials(out, t->url, user, methods, connect_opts->callbacks.payload);
}
+int git_transport_remote_connect_options(
+ git_remote_connect_options *out,
+ git_transport *transport)
+{
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
+
+ GIT_ASSERT_ARG(out);
+ GIT_ASSERT_ARG(transport);
+
+ return git_remote_connect_options_dup(out, &t->connect_opts);
+}
+
int git_transport_smart(git_transport **out, git_remote *owner, void *param)
{
transport_smart *t;
diff --git a/src/transports/smart.h b/src/libgit2/transports/smart.h
similarity index 100%
rename from src/transports/smart.h
rename to src/libgit2/transports/smart.h
diff --git a/src/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c
similarity index 100%
rename from src/transports/smart_pkt.c
rename to src/libgit2/transports/smart_pkt.c
diff --git a/src/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c
similarity index 100%
rename from src/transports/smart_protocol.c
rename to src/libgit2/transports/smart_protocol.c
diff --git a/src/transports/ssh.c b/src/libgit2/transports/ssh.c
similarity index 100%
rename from src/transports/ssh.c
rename to src/libgit2/transports/ssh.c
diff --git a/src/transports/ssh.h b/src/libgit2/transports/ssh.h
similarity index 100%
rename from src/transports/ssh.h
rename to src/libgit2/transports/ssh.h
diff --git a/src/transports/winhttp.c b/src/libgit2/transports/winhttp.c
similarity index 100%
rename from src/transports/winhttp.c
rename to src/libgit2/transports/winhttp.c
diff --git a/src/tree-cache.c b/src/libgit2/tree-cache.c
similarity index 99%
rename from src/tree-cache.c
rename to src/libgit2/tree-cache.c
index 0977c92f3..cd69e7bf8 100644
--- a/src/tree-cache.c
+++ b/src/libgit2/tree-cache.c
@@ -263,7 +263,7 @@ static void write_tree(git_str *out, git_tree_cache *tree)
git_str_printf(out, "%s%c%"PRIdZ" %"PRIuZ"\n", tree->name, 0, tree->entry_count, tree->children_count);
if (tree->entry_count != -1)
- git_str_put(out, (const char *) &tree->oid, GIT_OID_RAWSZ);
+ git_str_put(out, (char *)&tree->oid.id, GIT_OID_RAWSZ);
for (i = 0; i < tree->children_count; i++)
write_tree(out, tree->children[i]);
diff --git a/src/tree-cache.h b/src/libgit2/tree-cache.h
similarity index 100%
rename from src/tree-cache.h
rename to src/libgit2/tree-cache.h
diff --git a/src/tree.c b/src/libgit2/tree.c
similarity index 97%
rename from src/tree.c
rename to src/libgit2/tree.c
index a1545dc2d..a5371fd87 100644
--- a/src/tree.c
+++ b/src/libgit2/tree.c
@@ -82,6 +82,7 @@ int git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2)
static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, const git_oid *id)
{
git_tree_entry *entry = NULL;
+ char *filename_ptr;
size_t tree_len;
TREE_ENTRY_CHECK_NAMELEN(filename_len);
@@ -95,21 +96,13 @@ static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, co
if (!entry)
return NULL;
- {
- char *filename_ptr;
- void *id_ptr;
-
- filename_ptr = ((char *) entry) + sizeof(git_tree_entry);
- memcpy(filename_ptr, filename, filename_len);
- entry->filename = filename_ptr;
-
- id_ptr = filename_ptr + filename_len + 1;
- git_oid_cpy(id_ptr, id);
- entry->oid = id_ptr;
- }
-
+ filename_ptr = ((char *) entry) + sizeof(git_tree_entry);
+ memcpy(filename_ptr, filename, filename_len);
+ entry->filename = filename_ptr;
entry->filename_len = (uint16_t)filename_len;
+ git_oid_cpy(&entry->oid, id);
+
return entry;
}
@@ -231,7 +224,7 @@ int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
GIT_ASSERT_ARG(source);
- cpy = alloc_entry(source->filename, source->filename_len, source->oid);
+ cpy = alloc_entry(source->filename, source->filename_len, &source->oid);
if (cpy == NULL)
return -1;
@@ -269,7 +262,7 @@ const char *git_tree_entry_name(const git_tree_entry *entry)
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
{
GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
- return entry->oid;
+ return &entry->oid;
}
git_object_t git_tree_entry_type(const git_tree_entry *entry)
@@ -292,7 +285,7 @@ int git_tree_entry_to_object(
GIT_ASSERT_ARG(entry);
GIT_ASSERT_ARG(object_out);
- return git_object_lookup(object_out, repo, entry->oid, GIT_OBJECT_ANY);
+ return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJECT_ANY);
}
static const git_tree_entry *entry_fromname(
@@ -331,7 +324,7 @@ const git_tree_entry *git_tree_entry_byid(
GIT_ASSERT_ARG_WITH_RETVAL(tree, NULL);
git_array_foreach(tree->entries, i, e) {
- if (memcmp(&e->oid->id, &id->id, sizeof(id->id)) == 0)
+ if (git_oid_equal(&e->oid, id))
return e;
}
@@ -432,7 +425,7 @@ int git_tree__parse_raw(void *_tree, const char *data, size_t size)
entry->attr = attr;
entry->filename_len = (uint16_t)filename_len;
entry->filename = buffer;
- entry->oid = (git_oid *) ((char *) buffer + filename_len + 1);
+ git_oid_fromraw(&entry->oid, ((unsigned char *) buffer + filename_len + 1));
}
buffer += filename_len + 1;
@@ -536,7 +529,7 @@ static int git_treebuilder__write_with_buffer(
git_str_printf(buf, "%o ", entry->attr);
git_str_put(buf, entry->filename, entry->filename_len + 1);
- git_str_put(buf, (char *)entry->oid->id, GIT_OID_RAWSZ);
+ git_str_put(buf, (char *)entry->oid.id, GIT_OID_RAWSZ);
if (git_str_oom(buf)) {
error = -1;
@@ -765,7 +758,7 @@ int git_treebuilder_new(
git_array_foreach(source->entries, i, entry_src) {
if (append_entry(
bld, entry_src->filename,
- entry_src->oid,
+ &entry_src->oid,
entry_src->attr,
false) < 0)
goto on_error;
@@ -798,7 +791,7 @@ int git_treebuilder_insert(
return error;
if ((entry = git_strmap_get(bld->map, filename)) != NULL) {
- git_oid_cpy((git_oid *) entry->oid, id);
+ git_oid_cpy(&entry->oid, id);
} else {
entry = alloc_entry(filename, strlen(filename), id);
GIT_ERROR_CHECK_ALLOC(entry);
@@ -954,7 +947,7 @@ int git_tree_entry_bypath(
return git_tree_entry_dup(entry_out, entry);
}
- if (git_tree_lookup(&subtree, root->object.repo, entry->oid) < 0)
+ if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
return -1;
error = git_tree_entry_bypath(
@@ -995,7 +988,7 @@ static int tree_walk(
git_tree *subtree;
size_t path_len = git_str_len(path);
- error = git_tree_lookup(&subtree, tree->object.repo, entry->oid);
+ error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid);
if (error < 0)
break;
diff --git a/src/tree.h b/src/libgit2/tree.h
similarity index 98%
rename from src/tree.h
rename to src/libgit2/tree.h
index 6bd9ed652..0dd963ff2 100644
--- a/src/tree.h
+++ b/src/libgit2/tree.h
@@ -19,7 +19,7 @@
struct git_tree_entry {
uint16_t attr;
uint16_t filename_len;
- const git_oid *oid;
+ git_oid oid;
const char *filename;
};
diff --git a/src/userdiff.h b/src/libgit2/userdiff.h
similarity index 100%
rename from src/userdiff.h
rename to src/libgit2/userdiff.h
diff --git a/src/worktree.c b/src/libgit2/worktree.c
similarity index 100%
rename from src/worktree.c
rename to src/libgit2/worktree.c
diff --git a/src/worktree.h b/src/libgit2/worktree.h
similarity index 100%
rename from src/worktree.h
rename to src/libgit2/worktree.h
diff --git a/src/xdiff/git-xdiff.h b/src/libgit2/xdiff/git-xdiff.h
similarity index 100%
rename from src/xdiff/git-xdiff.h
rename to src/libgit2/xdiff/git-xdiff.h
diff --git a/src/xdiff/xdiff.h b/src/libgit2/xdiff/xdiff.h
similarity index 100%
rename from src/xdiff/xdiff.h
rename to src/libgit2/xdiff/xdiff.h
diff --git a/src/xdiff/xdiffi.c b/src/libgit2/xdiff/xdiffi.c
similarity index 100%
rename from src/xdiff/xdiffi.c
rename to src/libgit2/xdiff/xdiffi.c
diff --git a/src/xdiff/xdiffi.h b/src/libgit2/xdiff/xdiffi.h
similarity index 100%
rename from src/xdiff/xdiffi.h
rename to src/libgit2/xdiff/xdiffi.h
diff --git a/src/xdiff/xemit.c b/src/libgit2/xdiff/xemit.c
similarity index 100%
rename from src/xdiff/xemit.c
rename to src/libgit2/xdiff/xemit.c
diff --git a/src/xdiff/xemit.h b/src/libgit2/xdiff/xemit.h
similarity index 100%
rename from src/xdiff/xemit.h
rename to src/libgit2/xdiff/xemit.h
diff --git a/src/xdiff/xhistogram.c b/src/libgit2/xdiff/xhistogram.c
similarity index 100%
rename from src/xdiff/xhistogram.c
rename to src/libgit2/xdiff/xhistogram.c
diff --git a/src/xdiff/xinclude.h b/src/libgit2/xdiff/xinclude.h
similarity index 100%
rename from src/xdiff/xinclude.h
rename to src/libgit2/xdiff/xinclude.h
diff --git a/src/xdiff/xmacros.h b/src/libgit2/xdiff/xmacros.h
similarity index 100%
rename from src/xdiff/xmacros.h
rename to src/libgit2/xdiff/xmacros.h
diff --git a/src/xdiff/xmerge.c b/src/libgit2/xdiff/xmerge.c
similarity index 100%
rename from src/xdiff/xmerge.c
rename to src/libgit2/xdiff/xmerge.c
diff --git a/src/xdiff/xpatience.c b/src/libgit2/xdiff/xpatience.c
similarity index 100%
rename from src/xdiff/xpatience.c
rename to src/libgit2/xdiff/xpatience.c
diff --git a/src/xdiff/xprepare.c b/src/libgit2/xdiff/xprepare.c
similarity index 100%
rename from src/xdiff/xprepare.c
rename to src/libgit2/xdiff/xprepare.c
diff --git a/src/xdiff/xprepare.h b/src/libgit2/xdiff/xprepare.h
similarity index 100%
rename from src/xdiff/xprepare.h
rename to src/libgit2/xdiff/xprepare.h
diff --git a/src/xdiff/xtypes.h b/src/libgit2/xdiff/xtypes.h
similarity index 100%
rename from src/xdiff/xtypes.h
rename to src/libgit2/xdiff/xtypes.h
diff --git a/src/xdiff/xutils.c b/src/libgit2/xdiff/xutils.c
similarity index 100%
rename from src/xdiff/xutils.c
rename to src/libgit2/xdiff/xutils.c
diff --git a/src/xdiff/xutils.h b/src/libgit2/xdiff/xutils.h
similarity index 100%
rename from src/xdiff/xutils.h
rename to src/libgit2/xdiff/xutils.h
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
new file mode 100644
index 000000000..b2833954d
--- /dev/null
+++ b/src/util/CMakeLists.txt
@@ -0,0 +1,74 @@
+# util: a shared library for common utility functions for libgit2 projects
+
+add_library(util OBJECT)
+set_target_properties(util PROPERTIES C_STANDARD 90)
+set_target_properties(util PROPERTIES C_EXTENSIONS OFF)
+
+set(UTIL_INCLUDES
+ "${PROJECT_BINARY_DIR}/src"
+ "${PROJECT_SOURCE_DIR}/src/util"
+ "${PROJECT_SOURCE_DIR}/include")
+
+file(GLOB UTIL_SRC *.c *.h allocators/*.c allocators/*.h hash.h)
+list(SORT UTIL_SRC)
+
+#
+# Platform specific sources
+#
+
+if(WIN32 AND NOT CYGWIN)
+ file(GLOB UTIL_SRC_OS win32/*.c win32/*.h)
+ list(SORT UTIL_SRC_OS)
+elseif(NOT AMIGA)
+ file(GLOB UTIL_SRC_OS unix/*.c unix/*.h)
+ list(SORT UTIL_SRC_OS)
+endif()
+
+#
+# Hash backend selection
+#
+
+if(USE_SHA1 STREQUAL "CollisionDetection")
+ file(GLOB UTIL_SRC_SHA1 hash/collisiondetect.* hash/sha1dc/*)
+ target_compile_definitions(util PRIVATE SHA1DC_NO_STANDARD_INCLUDES=1)
+ target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_SHA1_C=\"git2_util.h\")
+ target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"git2_util.h\")
+elseif(USE_SHA1 STREQUAL "OpenSSL" OR USE_SHA1 STREQUAL "OpenSSL-Dynamic")
+ file(GLOB UTIL_SRC_SHA1 hash/openssl.*)
+elseif(USE_SHA1 STREQUAL "CommonCrypto")
+ file(GLOB UTIL_SRC_SHA1 hash/common_crypto.*)
+elseif(USE_SHA1 STREQUAL "mbedTLS")
+ file(GLOB UTIL_SRC_SHA1 hash/mbedtls.*)
+elseif(USE_SHA1 STREQUAL "Win32")
+ file(GLOB UTIL_SRC_SHA1 hash/win32.*)
+else()
+ message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
+endif()
+
+list(SORT UTIL_SRC_SHA1)
+
+if(USE_SHA256 STREQUAL "Builtin")
+ file(GLOB UTIL_SRC_SHA256 hash/builtin.* hash/rfc6234/*)
+elseif(USE_SHA256 STREQUAL "OpenSSL" OR USE_SHA256 STREQUAL "OpenSSL-Dynamic")
+ file(GLOB UTIL_SRC_SHA256 hash/openssl.*)
+elseif(USE_SHA256 STREQUAL "CommonCrypto")
+ file(GLOB UTIL_SRC_SHA256 hash/common_crypto.*)
+elseif(USE_SHA256 STREQUAL "mbedTLS")
+ file(GLOB UTIL_SRC_SHA256 hash/mbedtls.*)
+elseif(USE_SHA256 STREQUAL "Win32")
+ file(GLOB UTIL_SRC_SHA256 hash/win32.*)
+else()
+ message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
+endif()
+
+list(SORT UTIL_SRC_SHA256)
+
+#
+# Build the library
+#
+
+target_sources(util PRIVATE ${UTIL_SRC} ${UTIL_SRC_OS} ${UTIL_SRC_SHA1} ${UTIL_SRC_SHA256})
+ide_split_sources(util)
+
+target_include_directories(util PRIVATE ${UTIL_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include)
+target_include_directories(util SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
diff --git a/src/alloc.c b/src/util/alloc.c
similarity index 100%
rename from src/alloc.c
rename to src/util/alloc.c
diff --git a/src/alloc.h b/src/util/alloc.h
similarity index 100%
rename from src/alloc.h
rename to src/util/alloc.h
diff --git a/src/allocators/failalloc.c b/src/util/allocators/failalloc.c
similarity index 100%
rename from src/allocators/failalloc.c
rename to src/util/allocators/failalloc.c
diff --git a/src/allocators/failalloc.h b/src/util/allocators/failalloc.h
similarity index 97%
rename from src/allocators/failalloc.h
rename to src/util/allocators/failalloc.h
index 6115e51e7..91264a0bb 100644
--- a/src/allocators/failalloc.h
+++ b/src/util/allocators/failalloc.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_failalloc_h__
#define INCLUDE_allocators_failalloc_h__
-#include "common.h"
+#include "git2_util.h"
extern void *git_failalloc_malloc(size_t len, const char *file, int line);
extern void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line);
diff --git a/src/allocators/stdalloc.c b/src/util/allocators/stdalloc.c
similarity index 100%
rename from src/allocators/stdalloc.c
rename to src/util/allocators/stdalloc.c
diff --git a/src/allocators/stdalloc.h b/src/util/allocators/stdalloc.h
similarity index 94%
rename from src/allocators/stdalloc.h
rename to src/util/allocators/stdalloc.h
index fa23fe6e3..955038cb0 100644
--- a/src/allocators/stdalloc.h
+++ b/src/util/allocators/stdalloc.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_stdalloc_h__
#define INCLUDE_allocators_stdalloc_h__
-#include "common.h"
+#include "git2_util.h"
#include "alloc.h"
diff --git a/src/allocators/win32_leakcheck.c b/src/util/allocators/win32_leakcheck.c
similarity index 100%
rename from src/allocators/win32_leakcheck.c
rename to src/util/allocators/win32_leakcheck.c
diff --git a/src/allocators/win32_leakcheck.h b/src/util/allocators/win32_leakcheck.h
similarity index 94%
rename from src/allocators/win32_leakcheck.h
rename to src/util/allocators/win32_leakcheck.h
index 089690f90..edcd9307f 100644
--- a/src/allocators/win32_leakcheck.h
+++ b/src/util/allocators/win32_leakcheck.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_win32_leakcheck_h
#define INCLUDE_allocators_win32_leakcheck_h
-#include "common.h"
+#include "git2_util.h"
#include "alloc.h"
diff --git a/src/array.h b/src/util/array.h
similarity index 99%
rename from src/array.h
rename to src/util/array.h
index e97688b36..cbab52ad1 100644
--- a/src/array.h
+++ b/src/util/array.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_array_h__
#define INCLUDE_array_h__
-#include "common.h"
+#include "git2_util.h"
/*
* Use this to declare a typesafe resizable array of items, a la:
diff --git a/src/assert_safe.h b/src/util/assert_safe.h
similarity index 79%
rename from src/assert_safe.h
rename to src/util/assert_safe.h
index 8c261100f..cc0bac551 100644
--- a/src/assert_safe.h
+++ b/src/util/assert_safe.h
@@ -24,6 +24,8 @@
# define GIT_ASSERT_WITH_RETVAL(expr, fail) assert(expr)
# define GIT_ASSERT_ARG_WITH_RETVAL(expr, fail) assert(expr)
+
+# define GIT_ASSERT_WITH_CLEANUP(expr, cleanup) assert(expr)
#else
/** Internal consistency check to stop the function. */
@@ -53,6 +55,20 @@
} \
} while(0)
+/**
+ * Go to to the given label on assertion failures; useful when you have
+ * taken a lock or otherwise need to release a resource.
+ */
+# define GIT_ASSERT_WITH_CLEANUP(expr, cleanup) \
+ GIT_ASSERT__WITH_CLEANUP(expr, GIT_ERROR_INTERNAL, "unrecoverable internal error", cleanup)
+
+# define GIT_ASSERT__WITH_CLEANUP(expr, code, msg, cleanup) do { \
+ if (!(expr)) { \
+ git_error_set(code, "%s: '%s'", msg, #expr); \
+ cleanup; \
+ } \
+ } while(0)
+
#endif /* GIT_ASSERT_HARD */
#endif
diff --git a/src/bitvec.h b/src/util/bitvec.h
similarity index 100%
rename from src/bitvec.h
rename to src/util/bitvec.h
diff --git a/src/cc-compat.h b/src/util/cc-compat.h
similarity index 100%
rename from src/cc-compat.h
rename to src/util/cc-compat.h
diff --git a/src/date.c b/src/util/date.c
similarity index 98%
rename from src/date.c
rename to src/util/date.c
index 0e5ffc96b..4d757e21a 100644
--- a/src/date.c
+++ b/src/util/date.c
@@ -1,10 +1,11 @@
/*
- * GIT - The information manager from hell
+ * Copyright (C) the libgit2 contributors. All rights reserved.
*
- * Copyright (C) Linus Torvalds, 2005
+ * 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 "common.h"
+#include "git2_util.h"
#ifndef GIT_WIN32
#include
diff --git a/src/date.h b/src/util/date.h
similarity index 100%
rename from src/date.h
rename to src/util/date.h
diff --git a/src/filebuf.c b/src/util/filebuf.c
similarity index 99%
rename from src/filebuf.c
rename to src/util/filebuf.c
index eafcba3bd..e014d43b2 100644
--- a/src/filebuf.c
+++ b/src/util/filebuf.c
@@ -65,7 +65,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
if ((flags & GIT_FILEBUF_APPEND) && git_fs_path_exists(file->path_original) == true) {
git_file source;
- char buffer[FILEIO_BUFSIZE];
+ char buffer[GIT_BUFSIZE_FILEIO];
ssize_t read_bytes;
int error = 0;
diff --git a/src/filebuf.h b/src/util/filebuf.h
similarity index 99%
rename from src/filebuf.h
rename to src/util/filebuf.h
index adbb19936..4a61ae4e3 100644
--- a/src/filebuf.h
+++ b/src/util/filebuf.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_filebuf_h__
#define INCLUDE_filebuf_h__
-#include "common.h"
+#include "git2_util.h"
#include "futils.h"
#include "hash.h"
diff --git a/src/fs_path.c b/src/util/fs_path.c
similarity index 94%
rename from src/fs_path.c
rename to src/util/fs_path.c
index a67617eca..6c87bfd01 100644
--- a/src/fs_path.c
+++ b/src/util/fs_path.c
@@ -7,8 +7,9 @@
#include "fs_path.h"
+#include "git2_util.h"
+#include "futils.h"
#include "posix.h"
-#include "repository.h"
#ifdef GIT_WIN32
#include "win32/posix.h"
#include "win32/w32_buffer.h"
@@ -21,6 +22,13 @@
#include
#include
+#define ensure_error_set(code) do { \
+ const git_error *e = git_error_last(); \
+ if (!e || !e->message) \
+ git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, \
+ "filesystem callback returned %d", code); \
+ } while(0)
+
static int dos_drive_prefix_length(const char *path)
{
int i;
@@ -101,7 +109,7 @@ int git_fs_path_basename_r(git_str *buffer, const char *path)
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
startp = ".";
- len = 1;
+ len = 1;
goto Exit;
}
@@ -113,7 +121,7 @@ int git_fs_path_basename_r(git_str *buffer, const char *path)
/* All slashes becomes "/" */
if (endp == path && *endp == '/') {
startp = "/";
- len = 1;
+ len = 1;
goto Exit;
}
@@ -185,8 +193,7 @@ int git_fs_path_dirname_r(git_str *buffer, const char *path)
if (endp - path + 1 > INT_MAX) {
git_error_set(GIT_ERROR_INVALID, "path too long");
- len = -1;
- goto Exit;
+ return -1;
}
if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
@@ -211,8 +218,7 @@ int git_fs_path_dirname_r(git_str *buffer, const char *path)
if (endp - path + 1 > INT_MAX) {
git_error_set(GIT_ERROR_INVALID, "path too long");
- len = -1;
- goto Exit;
+ return -1;
}
if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) {
@@ -530,7 +536,7 @@ int git_fs_path_walk_up(
if (!scan) {
error = cb(data, "");
if (error)
- git_error_set_after_callback(error);
+ ensure_error_set(error);
return error;
}
@@ -543,7 +549,7 @@ int git_fs_path_walk_up(
iter.ptr[scan] = oldc;
if (error) {
- git_error_set_after_callback(error);
+ ensure_error_set(error);
break;
}
@@ -563,7 +569,7 @@ int git_fs_path_walk_up(
if (!error && stop == 0 && iter.ptr[0] != '/') {
error = cb(data, "");
if (error)
- git_error_set_after_callback(error);
+ ensure_error_set(error);
}
return error;
@@ -1167,7 +1173,7 @@ int git_fs_path_direach(
/* Only set our own error if the callback did not set one already */
if (error != 0) {
if (!git_error_last())
- git_error_set_after_callback(error);
+ ensure_error_set(error);
break;
}
@@ -1779,9 +1785,9 @@ done:
return supported;
}
-static git_fs_path__mock_owner_t mock_owner = GIT_FS_PATH_MOCK_OWNER_NONE;
+static git_fs_path_owner_t mock_owner = GIT_FS_PATH_OWNER_NONE;
-void git_fs_path__set_owner(git_fs_path__mock_owner_t owner)
+void git_fs_path__set_owner(git_fs_path_owner_t owner)
{
mock_owner = owner;
}
@@ -1873,74 +1879,52 @@ static int file_owner_sid(PSID *out, const char *path)
return error;
}
-int git_fs_path_owner_is_current_user(bool *out, const char *path)
+int git_fs_path_owner_is(
+ bool *out,
+ const char *path,
+ git_fs_path_owner_t owner_type)
{
PSID owner_sid = NULL, user_sid = NULL;
- int error = -1;
+ BOOL is_admin, admin_owned;
+ int error;
if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+ *out = ((mock_owner & owner_type) != 0);
return 0;
}
- if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
- (error = current_user_sid(&user_sid)) < 0)
+ if ((error = file_owner_sid(&owner_sid, path)) < 0)
goto done;
- *out = EqualSid(owner_sid, user_sid);
- error = 0;
+ if ((owner_type & GIT_FS_PATH_OWNER_CURRENT_USER) != 0) {
+ if ((error = current_user_sid(&user_sid)) < 0)
+ goto done;
-done:
- git__free(owner_sid);
- git__free(user_sid);
- return error;
-}
-
-int git_fs_path_owner_is_system(bool *out, const char *path)
-{
- PSID owner_sid;
-
- if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
- return 0;
+ if (EqualSid(owner_sid, user_sid)) {
+ *out = true;
+ goto done;
+ }
}
- if (file_owner_sid(&owner_sid, path) < 0)
- return -1;
+ admin_owned =
+ IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
+ IsWellKnownSid(owner_sid, WinLocalSystemSid);
- *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
- IsWellKnownSid(owner_sid, WinLocalSystemSid);
-
- git__free(owner_sid);
- return 0;
-}
-
-int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
-{
- PSID owner_sid = NULL, user_sid = NULL;
- int error = -1;
-
- if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
- mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
- return 0;
- }
-
- if (file_owner_sid(&owner_sid, path) < 0)
- goto done;
-
- if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
- IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
- *out = 1;
- error = 0;
+ if (admin_owned &&
+ (owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR) != 0) {
+ *out = true;
goto done;
}
- if (current_user_sid(&user_sid) < 0)
+ if (admin_owned &&
+ (owner_type & GIT_FS_PATH_USER_IS_ADMINISTRATOR) != 0 &&
+ CheckTokenMembership(NULL, owner_sid, &is_admin) &&
+ is_admin) {
+ *out = true;
goto done;
+ }
- *out = EqualSid(owner_sid, user_sid);
- error = 0;
+ *out = false;
done:
git__free(owner_sid);
@@ -1950,12 +1934,36 @@ done:
#else
-static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len)
+static int sudo_uid_lookup(uid_t *out)
+{
+ git_str uid_str = GIT_STR_INIT;
+ int64_t uid;
+ int error;
+
+ if ((error = git__getenv(&uid_str, "SUDO_UID")) == 0 &&
+ (error = git__strntol64(&uid, uid_str.ptr, uid_str.size, NULL, 10)) == 0 &&
+ uid == (int64_t)((uid_t)uid)) {
+ *out = (uid_t)uid;
+ }
+
+ git_str_dispose(&uid_str);
+ return error;
+}
+
+int git_fs_path_owner_is(
+ bool *out,
+ const char *path,
+ git_fs_path_owner_t owner_type)
{
struct stat st;
- size_t i;
+ uid_t euid, sudo_uid;
- *out = false;
+ if (mock_owner) {
+ *out = ((mock_owner & owner_type) != 0);
+ return 0;
+ }
+
+ euid = geteuid();
if (p_lstat(path, &st) != 0) {
if (errno == ENOENT)
@@ -1965,55 +1973,42 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid
return -1;
}
- for (i = 0; i < uids_len; i++) {
- if (uids[i] == st.st_uid) {
- *out = true;
- break;
- }
- }
-
- return 0;
-}
-
-int git_fs_path_owner_is_current_user(bool *out, const char *path)
-{
- uid_t userid = geteuid();
-
- if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+ if ((owner_type & GIT_FS_PATH_OWNER_CURRENT_USER) != 0 &&
+ st.st_uid == euid) {
+ *out = true;
return 0;
}
- return fs_path_owner_is(out, path, &userid, 1);
+ if ((owner_type & GIT_FS_PATH_OWNER_ADMINISTRATOR) != 0 &&
+ st.st_uid == 0) {
+ *out = true;
+ return 0;
+ }
+
+ if ((owner_type & GIT_FS_PATH_OWNER_RUNNING_SUDO) != 0 &&
+ euid == 0 &&
+ sudo_uid_lookup(&sudo_uid) == 0 &&
+ st.st_uid == sudo_uid) {
+ *out = true;
+ return 0;
+ }
+
+ *out = false;
+ return 0;
+}
+
+#endif
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path)
+{
+ return git_fs_path_owner_is(out, path, GIT_FS_PATH_OWNER_CURRENT_USER);
}
int git_fs_path_owner_is_system(bool *out, const char *path)
{
- uid_t userid = 0;
-
- if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
- return 0;
- }
-
- return fs_path_owner_is(out, path, &userid, 1);
+ return git_fs_path_owner_is(out, path, GIT_FS_PATH_OWNER_ADMINISTRATOR);
}
-int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
-{
- uid_t userids[2] = { geteuid(), 0 };
-
- if (mock_owner) {
- *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
- mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
- return 0;
- }
-
- return fs_path_owner_is(out, path, userids, 2);
-}
-
-#endif
-
int git_fs_path_find_executable(git_str *fullpath, const char *executable)
{
#ifdef GIT_WIN32
diff --git a/src/fs_path.h b/src/util/fs_path.h
similarity index 95%
rename from src/fs_path.h
rename to src/util/fs_path.h
index 7e6a22d4f..e5ca67378 100644
--- a/src/fs_path.h
+++ b/src/util/fs_path.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_fs_path_h__
#define INCLUDE_fs_path_h__
-#include "common.h"
+#include "git2_util.h"
#include "posix.h"
#include "str.h"
@@ -732,18 +732,42 @@ int git_fs_path_normalize_slashes(git_str *out, const char *path);
bool git_fs_path_supports_symlinks(const char *dir);
typedef enum {
- GIT_FS_PATH_MOCK_OWNER_NONE = 0, /* do filesystem lookups as normal */
- GIT_FS_PATH_MOCK_OWNER_SYSTEM = 1,
- GIT_FS_PATH_MOCK_OWNER_CURRENT_USER = 2,
- GIT_FS_PATH_MOCK_OWNER_OTHER = 3
-} git_fs_path__mock_owner_t;
+ GIT_FS_PATH_OWNER_NONE = 0,
+
+ /** The file must be owned by the current user. */
+ GIT_FS_PATH_OWNER_CURRENT_USER = (1 << 0),
+
+ /** The file must be owned by the system account. */
+ GIT_FS_PATH_OWNER_ADMINISTRATOR = (1 << 1),
+
+ /**
+ * The file may be owned by a system account if the current
+ * user is in an administrator group. Windows only; this is
+ * a noop on non-Windows systems.
+ */
+ GIT_FS_PATH_USER_IS_ADMINISTRATOR = (1 << 2),
+
+ /**
+ * The file is owned by the current user, who is running `sudo`.
+ */
+ GIT_FS_PATH_OWNER_RUNNING_SUDO = (1 << 3),
+
+ /** The file may be owned by another user. */
+ GIT_FS_PATH_OWNER_OTHER = (1 << 4)
+} git_fs_path_owner_t;
/**
* Sets the mock ownership for files; subsequent calls to
- * `git_fs_path_owner_is_*` functions will return this data until cleared
- * with `GIT_FS_PATH_MOCK_OWNER_NONE`.
+ * `git_fs_path_owner_is_*` functions will return this data until
+ * cleared with `GIT_FS_PATH_OWNER_NONE`.
*/
-void git_fs_path__set_owner(git_fs_path__mock_owner_t owner);
+void git_fs_path__set_owner(git_fs_path_owner_t owner);
+
+/** Verify that the file in question is owned by the given owner. */
+int git_fs_path_owner_is(
+ bool *out,
+ const char *path,
+ git_fs_path_owner_t owner_type);
/**
* Verify that the file in question is owned by an administrator or system
@@ -757,12 +781,6 @@ int git_fs_path_owner_is_system(bool *out, const char *path);
int git_fs_path_owner_is_current_user(bool *out, const char *path);
-/**
- * Verify that the file in question is owned by an administrator or system
- * account _or_ the current user;
- */
-int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path);
-
/**
* Search the current PATH for the given executable, returning the full
* path if it is found.
diff --git a/src/futils.c b/src/util/futils.c
similarity index 96%
rename from src/futils.c
rename to src/util/futils.c
index 42c35955e..cb872de09 100644
--- a/src/futils.c
+++ b/src/util/futils.c
@@ -167,18 +167,60 @@ int git_futils_readbuffer_fd(git_str *buf, git_file fd, size_t len)
/* p_read loops internally to read len bytes */
read_size = p_read(fd, buf->ptr, len);
- if (read_size != (ssize_t)len) {
+ if (read_size < 0) {
git_error_set(GIT_ERROR_OS, "failed to read descriptor");
git_str_dispose(buf);
return -1;
}
+ if ((size_t)read_size != len) {
+ git_error_set(GIT_ERROR_FILESYSTEM, "could not read (expected %" PRIuZ " bytes, read %" PRIuZ ")", len, (size_t)read_size);
+ git_str_dispose(buf);
+ return -1;
+ }
+
buf->ptr[read_size] = '\0';
buf->size = read_size;
return 0;
}
+int git_futils_readbuffer_fd_full(git_str *buf, git_file fd)
+{
+ static size_t blocksize = 10240;
+ size_t alloc_len = 0, total_size = 0;
+ ssize_t read_size = 0;
+
+ git_str_clear(buf);
+
+ while (true) {
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, blocksize);
+
+ if (git_str_grow(buf, alloc_len) < 0)
+ return -1;
+
+ /* p_read loops internally to read blocksize bytes */
+ read_size = p_read(fd, buf->ptr, blocksize);
+
+ if (read_size < 0) {
+ git_error_set(GIT_ERROR_OS, "failed to read descriptor");
+ git_str_dispose(buf);
+ return -1;
+ }
+
+ total_size += read_size;
+
+ if ((size_t)read_size < blocksize) {
+ break;
+ }
+ }
+
+ buf->ptr[total_size] = '\0';
+ buf->size = total_size;
+
+ return 0;
+}
+
int git_futils_readbuffer_updated(
git_str *out,
const char *path,
@@ -856,7 +898,7 @@ int git_futils_fake_symlink(const char *target, const char *path)
static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done)
{
int error = 0;
- char buffer[FILEIO_BUFSIZE];
+ char buffer[GIT_BUFSIZE_FILEIO];
ssize_t len = 0;
while (!error && (len = p_read(ifd, buffer, sizeof(buffer))) > 0)
diff --git a/src/futils.h b/src/util/futils.h
similarity index 99%
rename from src/futils.h
rename to src/util/futils.h
index a82ec41cc..3f207afb2 100644
--- a/src/futils.h
+++ b/src/util/futils.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_futils_h__
#define INCLUDE_futils_h__
-#include "common.h"
+#include "git2_util.h"
#include "map.h"
#include "posix.h"
@@ -27,6 +27,7 @@ extern int git_futils_readbuffer_updated(
const char *path,
unsigned char checksum[GIT_HASH_SHA1_SIZE],
int *updated);
+extern int git_futils_readbuffer_fd_full(git_str *obj, git_file fd);
extern int git_futils_readbuffer_fd(git_str *obj, git_file fd, size_t len);
/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We
diff --git a/src/common.h b/src/util/git2_util.h
similarity index 71%
rename from src/common.h
rename to src/util/git2_util.h
index 549bddb59..ad3f1c71f 100644
--- a/src/common.h
+++ b/src/util/git2_util.h
@@ -4,8 +4,8 @@
* 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_common_h__
-#define INCLUDE_common_h__
+#ifndef INCLUDE_git2_util_h__
+#define INCLUDE_git2_util_h__
#ifndef LIBGIT2_NO_FEATURES_H
# include "git2/sys/features.h"
@@ -14,13 +14,13 @@
#include "git2/common.h"
#include "cc-compat.h"
+typedef struct git_str git_str;
+
/** Declare a function as always inlined. */
#if defined(_MSC_VER)
# define GIT_INLINE(type) static __inline type
#elif defined(__GNUC__)
# define GIT_INLINE(type) static __inline__ type
-#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define GIT_INLINE(type) static inline type
#else
# define GIT_INLINE(type) static type
#endif
@@ -67,12 +67,12 @@
# include
# include "win32/msvc-compat.h"
# include "win32/mingw-compat.h"
-# include "win32/w32_common.h"
# include "win32/win32-compat.h"
-# include "win32/error.h"
+# include "win32/w32_common.h"
# include "win32/version.h"
+# include "win32/error.h"
# ifdef GIT_THREADS
-# include "win32/thread.h"
+# include "win32/thread.h"
# endif
#else
@@ -99,24 +99,17 @@
#include "git2/types.h"
#include "git2/errors.h"
-#include "errors.h"
#include "thread.h"
#include "integer.h"
#include "assert_safe.h"
-#include "utf8.h"
-
-/*
- * Include the declarations for deprecated functions; this ensures
- * that they're decorated with the proper extern/visibility attributes.
- */
-#include "git2/deprecated.h"
#include "posix.h"
-#define DEFAULT_BUFSIZE 65536
-#define FILEIO_BUFSIZE DEFAULT_BUFSIZE
-#define FILTERIO_BUFSIZE DEFAULT_BUFSIZE
-#define NETIO_BUFSIZE DEFAULT_BUFSIZE
+#define GIT_BUFSIZE_DEFAULT 65536
+#define GIT_BUFSIZE_FILEIO GIT_BUFSIZE_DEFAULT
+#define GIT_BUFSIZE_FILTERIO GIT_BUFSIZE_DEFAULT
+#define GIT_BUFSIZE_NETIO GIT_BUFSIZE_DEFAULT
+
/**
* Check a pointer allocation result, returning -1 if it failed.
@@ -126,7 +119,7 @@
} while(0)
/**
- * Check a string buffer allocation result, returning -1 if it failed.
+ * Check a buffer allocation result, returning -1 if it failed.
*/
#define GIT_ERROR_CHECK_ALLOC_STR(buf) do { \
if ((void *)(buf) == NULL || git_str_oom(buf)) { return -1; } \
@@ -138,40 +131,6 @@
#define GIT_ERROR_CHECK_ERROR(code) \
do { int _err = (code); if (_err) return _err; } while (0)
-/**
- * Check a versioned structure for validity
- */
-GIT_INLINE(int) git_error__check_version(const void *structure, unsigned int expected_max, const char *name)
-{
- unsigned int actual;
-
- if (!structure)
- return 0;
-
- actual = *(const unsigned int*)structure;
- if (actual > 0 && actual <= expected_max)
- return 0;
-
- git_error_set(GIT_ERROR_INVALID, "invalid version %d on %s", actual, name);
- return -1;
-}
-#define GIT_ERROR_CHECK_VERSION(S,V,N) if (git_error__check_version(S,V,N) < 0) return -1
-
-/**
- * Initialize a structure with a version.
- */
-GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
-{
- memset(structure, 0, len);
- *((int*)structure) = version;
-}
-#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
-
-#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \
- TYPE _tmpl = TPL; \
- GIT_ERROR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \
- memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
-
/** Check for additive overflow, setting an error if would occur. */
#define GIT_ADD_SIZET_OVERFLOW(out, one, two) \
@@ -204,11 +163,6 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
#define GIT_ERROR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }
-/* NOTE: other git_error functions are in the public errors.h header file */
-
-/* Forward declare git_str */
-typedef struct git_str git_str;
-
#include "util.h"
#endif
diff --git a/src/hash.c b/src/util/hash.c
similarity index 82%
rename from src/hash.c
rename to src/util/hash.c
index 98ceb05d2..ff900cea7 100644
--- a/src/hash.c
+++ b/src/util/hash.c
@@ -9,7 +9,11 @@
int git_hash_global_init(void)
{
- return git_hash_sha1_global_init();
+ if (git_hash_sha1_global_init() < 0 ||
+ git_hash_sha256_global_init() < 0)
+ return -1;
+
+ return 0;
}
int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm)
@@ -20,6 +24,9 @@ int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm)
case GIT_HASH_ALGORITHM_SHA1:
error = git_hash_sha1_ctx_init(&ctx->ctx.sha1);
break;
+ case GIT_HASH_ALGORITHM_SHA256:
+ error = git_hash_sha256_ctx_init(&ctx->ctx.sha256);
+ break;
default:
git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
error = -1;
@@ -35,6 +42,9 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx)
case GIT_HASH_ALGORITHM_SHA1:
git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1);
return;
+ case GIT_HASH_ALGORITHM_SHA256:
+ git_hash_sha256_ctx_cleanup(&ctx->ctx.sha256);
+ return;
default:
/* unreachable */ ;
}
@@ -45,6 +55,8 @@ int git_hash_init(git_hash_ctx *ctx)
switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_init(&ctx->ctx.sha1);
+ case GIT_HASH_ALGORITHM_SHA256:
+ return git_hash_sha256_init(&ctx->ctx.sha256);
default:
/* unreachable */ ;
}
@@ -58,6 +70,8 @@ int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_update(&ctx->ctx.sha1, data, len);
+ case GIT_HASH_ALGORITHM_SHA256:
+ return git_hash_sha256_update(&ctx->ctx.sha256, data, len);
default:
/* unreachable */ ;
}
@@ -71,6 +85,8 @@ int git_hash_final(unsigned char *out, git_hash_ctx *ctx)
switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_final(out, &ctx->ctx.sha1);
+ case GIT_HASH_ALGORITHM_SHA256:
+ return git_hash_sha256_final(out, &ctx->ctx.sha256);
default:
/* unreachable */ ;
}
diff --git a/src/hash.h b/src/util/hash.h
similarity index 89%
rename from src/hash.h
rename to src/util/hash.h
index 507c1cb25..387c5a66f 100644
--- a/src/hash.h
+++ b/src/util/hash.h
@@ -8,9 +8,9 @@
#ifndef INCLUDE_hash_h__
#define INCLUDE_hash_h__
-#include "common.h"
+#include "git2_util.h"
-#include "hash/sha1.h"
+#include "hash/sha.h"
typedef struct {
void *data;
@@ -19,12 +19,14 @@ typedef struct {
typedef enum {
GIT_HASH_ALGORITHM_NONE = 0,
- GIT_HASH_ALGORITHM_SHA1
+ GIT_HASH_ALGORITHM_SHA1,
+ GIT_HASH_ALGORITHM_SHA256
} git_hash_algorithm_t;
typedef struct git_hash_ctx {
union {
git_hash_sha1_ctx sha1;
+ git_hash_sha256_ctx sha256;
} ctx;
git_hash_algorithm_t algorithm;
} git_hash_ctx;
diff --git a/src/util/hash/builtin.c b/src/util/hash/builtin.c
new file mode 100644
index 000000000..cc4aa58fe
--- /dev/null
+++ b/src/util/hash/builtin.c
@@ -0,0 +1,53 @@
+/*
+ * 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 "builtin.h"
+
+int git_hash_sha256_global_init(void)
+{
+ return 0;
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+ return git_hash_sha256_init(ctx);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+ GIT_UNUSED(ctx);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ if (SHA256Reset(&ctx->c)) {
+ git_error_set(GIT_ERROR_SHA, "SHA256 error");
+ return -1;
+ }
+ return 0;
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+ if (SHA256Input(&ctx->c, data, len)) {
+ git_error_set(GIT_ERROR_SHA, "SHA256 error");
+ return -1;
+ }
+ return 0;
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ if (SHA256Result(&ctx->c, out)) {
+ git_error_set(GIT_ERROR_SHA, "SHA256 error");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/hash/sha1/openssl.h b/src/util/hash/builtin.h
similarity index 58%
rename from src/hash/sha1/openssl.h
rename to src/util/hash/builtin.h
index a223ca03e..769df1ac2 100644
--- a/src/hash/sha1/openssl.h
+++ b/src/util/hash/builtin.h
@@ -5,15 +5,15 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hash_sha1_openssl_h__
-#define INCLUDE_hash_sha1_openssl_h__
+#ifndef INCLUDE_hash_builtin_h__
+#define INCLUDE_hash_builtin_h__
-#include "hash/sha1.h"
+#include "hash/sha.h"
-#include
+#include "rfc6234/sha.h"
-struct git_hash_sha1_ctx {
- SHA_CTX c;
+struct git_hash_sha256_ctx {
+ SHA256Context c;
};
#endif
diff --git a/src/hash/sha1/collisiondetect.c b/src/util/hash/collisiondetect.c
similarity index 92%
rename from src/hash/sha1/collisiondetect.c
rename to src/util/hash/collisiondetect.c
index ec7059c4c..c51a402d7 100644
--- a/src/hash/sha1/collisiondetect.c
+++ b/src/util/hash/collisiondetect.c
@@ -40,7 +40,7 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
{
GIT_ASSERT_ARG(ctx);
if (SHA1DCFinal(out, &ctx->c)) {
- git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected");
+ git_error_set(GIT_ERROR_SHA, "SHA1 collision attack detected");
return -1;
}
diff --git a/src/hash/sha1/collisiondetect.h b/src/util/hash/collisiondetect.h
similarity index 71%
rename from src/hash/sha1/collisiondetect.h
rename to src/util/hash/collisiondetect.h
index eb88e86c1..8de550230 100644
--- a/src/hash/sha1/collisiondetect.h
+++ b/src/util/hash/collisiondetect.h
@@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hash_sha1_collisiondetect_h__
-#define INCLUDE_hash_sha1_collisiondetect_h__
+#ifndef INCLUDE_hash_collisiondetect_h__
+#define INCLUDE_hash_collisiondetect_h__
-#include "hash/sha1.h"
+#include "hash/sha.h"
#include "sha1dc/sha1.h"
diff --git a/src/hash/sha1/common_crypto.c b/src/util/hash/common_crypto.c
similarity index 54%
rename from src/hash/sha1/common_crypto.c
rename to src/util/hash/common_crypto.c
index 9d608f449..b327ba9e3 100644
--- a/src/hash/sha1/common_crypto.c
+++ b/src/util/hash/common_crypto.c
@@ -9,6 +9,8 @@
#define CC_LONG_MAX ((CC_LONG)-1)
+#ifdef GIT_SHA1_COMMON_CRYPTO
+
int git_hash_sha1_global_init(void)
{
return 0;
@@ -55,3 +57,56 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
CC_SHA1_Final(out, &ctx->c);
return 0;
}
+
+#endif
+
+#ifdef GIT_SHA256_COMMON_CRYPTO
+
+int git_hash_sha256_global_init(void)
+{
+ return 0;
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+ return git_hash_sha256_init(ctx);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+ GIT_UNUSED(ctx);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ CC_SHA256_Init(&ctx->c);
+ return 0;
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *_data, size_t len)
+{
+ const unsigned char *data = _data;
+
+ GIT_ASSERT_ARG(ctx);
+
+ while (len > 0) {
+ CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len;
+
+ CC_SHA256_Update(&ctx->c, data, chunk);
+
+ data += chunk;
+ len -= chunk;
+ }
+
+ return 0;
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ CC_SHA256_Final(out, &ctx->c);
+ return 0;
+}
+
+#endif
diff --git a/src/hash/sha1/common_crypto.h b/src/util/hash/common_crypto.h
similarity index 57%
rename from src/hash/sha1/common_crypto.h
rename to src/util/hash/common_crypto.h
index a5fcfb33e..157712b5f 100644
--- a/src/hash/sha1/common_crypto.h
+++ b/src/util/hash/common_crypto.h
@@ -5,15 +5,23 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hash_sha1_common_crypto_h__
-#define INCLUDE_hash_sha1_common_crypto_h__
+#ifndef INCLUDE_hash_common_crypto_h__
+#define INCLUDE_hash_common_crypto_h__
-#include "hash/sha1.h"
+#include "hash/sha.h"
#include
+#ifdef GIT_SHA1_COMMON_CRYPTO
struct git_hash_sha1_ctx {
CC_SHA1_CTX c;
};
+#endif
+
+#ifdef GIT_SHA256_COMMON_CRYPTO
+struct git_hash_sha256_ctx {
+ CC_SHA256_CTX c;
+};
+#endif
#endif
diff --git a/src/hash/sha1/mbedtls.c b/src/util/hash/mbedtls.c
similarity index 53%
rename from src/hash/sha1/mbedtls.c
rename to src/util/hash/mbedtls.c
index 56016bec8..ecdfb7879 100644
--- a/src/hash/sha1/mbedtls.c
+++ b/src/util/hash/mbedtls.c
@@ -7,6 +7,8 @@
#include "mbedtls.h"
+#ifdef GIT_SHA1_MBEDTLS
+
int git_hash_sha1_global_init(void)
{
return 0;
@@ -44,3 +46,47 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
mbedtls_sha1_finish(&ctx->c, out);
return 0;
}
+
+#endif
+
+#ifdef GIT_SHA256_MBEDTLS
+
+int git_hash_sha256_global_init(void)
+{
+ return 0;
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+ return git_hash_sha256_init(ctx);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+ if (ctx)
+ mbedtls_sha256_free(&ctx->c);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha256_init(&ctx->c);
+ mbedtls_sha256_starts(&ctx->c, 0);
+ return 0;
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha256_update(&ctx->c, data, len);
+ return 0;
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ mbedtls_sha256_finish(&ctx->c, out);
+ return 0;
+}
+
+#endif
diff --git a/src/hash/sha1/mbedtls.h b/src/util/hash/mbedtls.h
similarity index 54%
rename from src/hash/sha1/mbedtls.h
rename to src/util/hash/mbedtls.h
index 15f7462a4..05fb38b0e 100644
--- a/src/hash/sha1/mbedtls.h
+++ b/src/util/hash/mbedtls.h
@@ -5,15 +5,25 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#ifndef INCLUDE_hash_sha1_mbedtls_h__
-#define INCLUDE_hash_sha1_mbedtls_h__
+#ifndef INCLUDE_hash_mbedtls_h__
+#define INCLUDE_hash_mbedtls_h__
-#include "hash/sha1.h"
+#include "hash/sha.h"
-#include
+#ifdef GIT_SHA1_MBEDTLS
+# include
struct git_hash_sha1_ctx {
mbedtls_sha1_context c;
};
+#endif
+
+#ifdef GIT_SHA256_MBEDTLS
+# include
+
+struct git_hash_sha256_ctx {
+ mbedtls_sha256_context c;
+};
+#endif
#endif /* INCLUDE_hash_sha1_mbedtls_h__ */
diff --git a/src/util/hash/openssl.c b/src/util/hash/openssl.c
new file mode 100644
index 000000000..649358ca2
--- /dev/null
+++ b/src/util/hash/openssl.c
@@ -0,0 +1,194 @@
+/*
+ * 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 "openssl.h"
+
+#ifdef GIT_OPENSSL_DYNAMIC
+# include
+
+int handle_count;
+void *openssl_handle;
+
+static int git_hash_openssl_global_shutdown(void)
+{
+ if (--handle_count == 0) {
+ dlclose(openssl_handle);
+ openssl_handle = NULL;
+ }
+
+ return 0;
+}
+
+static int git_hash_openssl_global_init(void)
+{
+ if (!handle_count) {
+ if ((openssl_handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.1.1.dylib", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.so.1.0.0", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.1.0.0.dylib", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) {
+ git_error_set(GIT_ERROR_SSL, "could not load ssl libraries");
+ return -1;
+ }
+ }
+
+ if (git_hash_openssl_global_shutdown() < 0)
+ return -1;
+
+ handle_count++;
+ return 0;
+}
+
+#endif
+
+#ifdef GIT_SHA1_OPENSSL
+
+# ifdef GIT_OPENSSL_DYNAMIC
+static int (*SHA1_Init)(SHA_CTX *c);
+static int (*SHA1_Update)(SHA_CTX *c, const void *data, size_t len);
+static int (*SHA1_Final)(unsigned char *md, SHA_CTX *c);
+# endif
+
+int git_hash_sha1_global_init(void)
+{
+#ifdef GIT_OPENSSL_DYNAMIC
+ if (git_hash_openssl_global_init() < 0)
+ return -1;
+
+ if ((SHA1_Init = dlsym(openssl_handle, "SHA1_Init")) == NULL ||
+ (SHA1_Update = dlsym(openssl_handle, "SHA1_Update")) == NULL ||
+ (SHA1_Final = dlsym(openssl_handle, "SHA1_Final")) == NULL) {
+ const char *msg = dlerror();
+ git_error_set(GIT_ERROR_SSL, "could not load hash function: %s", msg ? msg : "unknown error");
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
+{
+ return git_hash_sha1_init(ctx);
+}
+
+void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
+{
+ GIT_UNUSED(ctx);
+}
+
+int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA1_Init(&ctx->c) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to initialize sha1 context");
+ return -1;
+ }
+
+ return 0;
+}
+
+int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA1_Update(&ctx->c, data, len) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to update sha1");
+ return -1;
+ }
+
+ return 0;
+}
+
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA1_Final(out, &ctx->c) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to finalize sha1");
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
+#ifdef GIT_SHA256_OPENSSL
+
+# ifdef GIT_OPENSSL_DYNAMIC
+static int (*SHA256_Init)(SHA256_CTX *c);
+static int (*SHA256_Update)(SHA256_CTX *c, const void *data, size_t len);
+static int (*SHA256_Final)(unsigned char *md, SHA256_CTX *c);
+#endif
+
+int git_hash_sha256_global_init(void)
+{
+#ifdef GIT_OPENSSL_DYNAMIC
+ if (git_hash_openssl_global_init() < 0)
+ return -1;
+
+ if ((SHA256_Init = dlsym(openssl_handle, "SHA256_Init")) == NULL ||
+ (SHA256_Update = dlsym(openssl_handle, "SHA256_Update")) == NULL ||
+ (SHA256_Final = dlsym(openssl_handle, "SHA256_Final")) == NULL) {
+ const char *msg = dlerror();
+ git_error_set(GIT_ERROR_SSL, "could not load hash function: %s", msg ? msg : "unknown error");
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+ return git_hash_sha256_init(ctx);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+ GIT_UNUSED(ctx);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA256_Init(&ctx->c) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to initialize sha256 context");
+ return -1;
+ }
+
+ return 0;
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA256_Update(&ctx->c, data, len) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to update sha256");
+ return -1;
+ }
+
+ return 0;
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+
+ if (SHA256_Final(out, &ctx->c) != 1) {
+ git_error_set(GIT_ERROR_SHA, "failed to finalize sha256");
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/util/hash/openssl.h b/src/util/hash/openssl.h
new file mode 100644
index 000000000..7cb089abc
--- /dev/null
+++ b/src/util/hash/openssl.h
@@ -0,0 +1,45 @@
+/*
+ * 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_hash_openssl_h__
+#define INCLUDE_hash_openssl_h__
+
+#include "hash/sha.h"
+
+#ifndef GIT_OPENSSL_DYNAMIC
+# include
+#else
+
+typedef struct {
+ unsigned int h0, h1, h2, h3, h4;
+ unsigned int Nl, Nh;
+ unsigned int data[16];
+ unsigned int num;
+} SHA_CTX;
+
+typedef struct {
+ unsigned int h[8];
+ unsigned int Nl, Nh;
+ unsigned int data[16];
+ unsigned int num, md_len;
+} SHA256_CTX;
+
+#endif
+
+#ifdef GIT_SHA1_OPENSSL
+struct git_hash_sha1_ctx {
+ SHA_CTX c;
+};
+#endif
+
+#ifdef GIT_SHA256_OPENSSL
+struct git_hash_sha256_ctx {
+ SHA256_CTX c;
+};
+#endif
+
+#endif
diff --git a/src/util/hash/rfc6234/sha.h b/src/util/hash/rfc6234/sha.h
new file mode 100644
index 000000000..e0c400ca1
--- /dev/null
+++ b/src/util/hash/rfc6234/sha.h
@@ -0,0 +1,355 @@
+/**************************** sha.h ****************************/
+/***************** See RFC 6234 for details. *******************/
+/*
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ - Redistributions of source code must retain the above
+ copyright notice, this list of conditions and
+ the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ - Neither the name of Internet Society, IETF or IETF Trust, nor
+ the names of specific contributors, may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _SHA_H_
+#define _SHA_H_
+
+/*
+ * Description:
+ * This file implements the Secure Hash Algorithms
+ * as defined in the U.S. National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-3 published in October 2008
+ * and formerly defined in its predecessors, FIPS PUB 180-1
+ * and FIP PUB 180-2.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-3/fips180-3_final.pdf
+ *
+ * The five hashes are defined in these sizes:
+ * SHA-1 20 byte / 160 bit
+ * SHA-224 28 byte / 224 bit
+ * SHA-256 32 byte / 256 bit
+ * SHA-384 48 byte / 384 bit
+ * SHA-512 64 byte / 512 bit
+ *
+ * Compilation Note:
+ * These files may be compiled with two options:
+ * USE_32BIT_ONLY - use 32-bit arithmetic only, for systems
+ * without 64-bit integers
+ *
+ * USE_MODIFIED_MACROS - use alternate form of the SHA_Ch()
+ * and SHA_Maj() macros that are equivalent
+ * and potentially faster on many systems
+ *
+ */
+
+#include
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+ * must typedef the following:
+ * name meaning
+ * uint64_t unsigned 64-bit integer
+ * uint32_t unsigned 32-bit integer
+ * uint8_t unsigned 8-bit integer (i.e., unsigned char)
+ * int_least16_t integer of >= 16 bits
+ *
+ * See stdint-example.h
+ */
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+/*
+ * All SHA functions return one of these values.
+ */
+enum {
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError, /* called Input after FinalBits or Result */
+ shaBadParam /* passed a bad parameter */
+};
+#endif /* _SHA_enum_ */
+
+/*
+ * These constants hold size information for each of the SHA
+ * hashing operations
+ */
+enum {
+ SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
+ SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
+ SHA512_Message_Block_Size = 128,
+ USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
+ SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
+ SHA384HashSize = 48, SHA512HashSize = 64,
+ USHAMaxHashSize = SHA512HashSize,
+
+ SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
+ SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
+ SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
+};
+
+/*
+ * These constants are used in the USHA (Unified SHA) functions.
+ */
+typedef enum SHAversion {
+ SHA1, SHA224, SHA256, SHA384, SHA512
+} SHAversion;
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation.
+ */
+typedef struct SHA1Context {
+ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ uint32_t Length_High; /* Message length in bits */
+ uint32_t Length_Low; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA1_Message_Block_Size];
+
+ int Computed; /* Is the hash computed? */
+ int Corrupted; /* Cumulative corruption code */
+} SHA1Context;
+
+/*
+ * This structure will hold context information for the SHA-256
+ * hashing operation.
+ */
+typedef struct SHA256Context {
+ uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
+
+ uint32_t Length_High; /* Message length in bits */
+ uint32_t Length_Low; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA256_Message_Block_Size];
+
+ int Computed; /* Is the hash computed? */
+ int Corrupted; /* Cumulative corruption code */
+} SHA256Context;
+
+/*
+ * This structure will hold context information for the SHA-512
+ * hashing operation.
+ */
+typedef struct SHA512Context {
+#ifdef USE_32BIT_ONLY
+ uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */
+ uint32_t Length[4]; /* Message length in bits */
+#else /* !USE_32BIT_ONLY */
+ uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
+ uint64_t Length_High, Length_Low; /* Message length in bits */
+#endif /* USE_32BIT_ONLY */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 1024-bit message blocks */
+ uint8_t Message_Block[SHA512_Message_Block_Size];
+
+ int Computed; /* Is the hash computed?*/
+ int Corrupted; /* Cumulative corruption code */
+} SHA512Context;
+
+/*
+ * This structure will hold context information for the SHA-224
+ * hashing operation. It uses the SHA-256 structure for computation.
+ */
+typedef struct SHA256Context SHA224Context;
+
+/*
+ * This structure will hold context information for the SHA-384
+ * hashing operation. It uses the SHA-512 structure for computation.
+ */
+typedef struct SHA512Context SHA384Context;
+
+/*
+ * This structure holds context information for all SHA
+ * hashing operations.
+ */
+typedef struct USHAContext {
+ int whichSha; /* which SHA is being used */
+ union {
+ SHA1Context sha1Context;
+ SHA224Context sha224Context; SHA256Context sha256Context;
+ SHA384Context sha384Context; SHA512Context sha512Context;
+ } ctx;
+} USHAContext;
+
+/*
+ * This structure will hold context information for the HMAC
+ * keyed-hashing operation.
+ */
+typedef struct HMACContext {
+ int whichSha; /* which SHA is being used */
+ int hashSize; /* hash size of SHA being used */
+ int blockSize; /* block size of SHA being used */
+ USHAContext shaContext; /* SHA context */
+ unsigned char k_opad[USHA_Max_Message_Block_Size];
+ /* outer padding - key XORd with opad */
+ int Computed; /* Is the MAC computed? */
+ int Corrupted; /* Cumulative corruption code */
+
+} HMACContext;
+
+/*
+ * This structure will hold context information for the HKDF
+ * extract-and-expand Key Derivation Functions.
+ */
+typedef struct HKDFContext {
+ int whichSha; /* which SHA is being used */
+ HMACContext hmacContext;
+ int hashSize; /* hash size of SHA being used */
+ unsigned char prk[USHAMaxHashSize];
+ /* pseudo-random key - output of hkdfInput */
+ int Computed; /* Is the key material computed? */
+ int Corrupted; /* Cumulative corruption code */
+} HKDFContext;
+
+/*
+ * Function Prototypes
+ */
+
+/* SHA-1 */
+extern int SHA1Reset(SHA1Context *);
+extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA1FinalBits(SHA1Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA1Result(SHA1Context *,
+ uint8_t Message_Digest[SHA1HashSize]);
+
+/* SHA-224 */
+extern int SHA224Reset(SHA224Context *);
+extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA224FinalBits(SHA224Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA224Result(SHA224Context *,
+ uint8_t Message_Digest[SHA224HashSize]);
+
+/* SHA-256 */
+extern int SHA256Reset(SHA256Context *);
+extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA256FinalBits(SHA256Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA256Result(SHA256Context *,
+ uint8_t Message_Digest[SHA256HashSize]);
+
+/* SHA-384 */
+extern int SHA384Reset(SHA384Context *);
+extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA384FinalBits(SHA384Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA384Result(SHA384Context *,
+ uint8_t Message_Digest[SHA384HashSize]);
+
+/* SHA-512 */
+extern int SHA512Reset(SHA512Context *);
+extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA512FinalBits(SHA512Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA512Result(SHA512Context *,
+ uint8_t Message_Digest[SHA512HashSize]);
+
+/* Unified SHA functions, chosen by whichSha */
+extern int USHAReset(USHAContext *context, SHAversion whichSha);
+extern int USHAInput(USHAContext *context,
+ const uint8_t *bytes, unsigned int bytecount);
+extern int USHAFinalBits(USHAContext *context,
+ uint8_t bits, unsigned int bit_count);
+extern int USHAResult(USHAContext *context,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+extern int USHABlockSize(enum SHAversion whichSha);
+extern int USHAHashSize(enum SHAversion whichSha);
+extern int USHAHashSizeBits(enum SHAversion whichSha);
+extern const char *USHAHashName(enum SHAversion whichSha);
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC 2104,
+ * for all SHAs.
+ * This interface allows a fixed-length text input to be used.
+ */
+extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
+ const unsigned char *text, /* pointer to data stream */
+ int text_len, /* length of data stream */
+ const unsigned char *key, /* pointer to authentication key */
+ int key_len, /* length of authentication key */
+ uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC 2104,
+ * for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+extern int hmacReset(HMACContext *context, enum SHAversion whichSha,
+ const unsigned char *key, int key_len);
+extern int hmacInput(HMACContext *context, const unsigned char *text,
+ int text_len);
+extern int hmacFinalBits(HMACContext *context, uint8_t bits,
+ unsigned int bit_count);
+extern int hmacResult(HMACContext *context,
+ uint8_t digest[USHAMaxHashSize]);
+
+/*
+ * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
+ * RFC 5869, for all SHAs.
+ */
+extern int hkdf(SHAversion whichSha, const unsigned char *salt,
+ int salt_len, const unsigned char *ikm, int ikm_len,
+ const unsigned char *info, int info_len,
+ uint8_t okm[ ], int okm_len);
+extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt,
+ int salt_len, const unsigned char *ikm,
+ int ikm_len, uint8_t prk[USHAMaxHashSize]);
+extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
+ int prk_len, const unsigned char *info,
+ int info_len, uint8_t okm[ ], int okm_len);
+
+/*
+ * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
+ * RFC 5869, for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
+ const unsigned char *salt, int salt_len);
+extern int hkdfInput(HKDFContext *context, const unsigned char *ikm,
+ int ikm_len);
+extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
+ unsigned int ikm_bit_count);
+extern int hkdfResult(HKDFContext *context,
+ uint8_t prk[USHAMaxHashSize],
+ const unsigned char *info, int info_len,
+ uint8_t okm[USHAMaxHashSize], int okm_len);
+#endif /* _SHA_H_ */
diff --git a/src/util/hash/rfc6234/sha224-256.c b/src/util/hash/rfc6234/sha224-256.c
new file mode 100644
index 000000000..c8e0cf854
--- /dev/null
+++ b/src/util/hash/rfc6234/sha224-256.c
@@ -0,0 +1,601 @@
+/************************* sha224-256.c ************************/
+/***************** See RFC 6234 for details. *******************/
+/* Copyright (c) 2011 IETF Trust and the persons identified as */
+/* authors of the code. All rights reserved. */
+/* See sha.h for terms of use and redistribution. */
+
+/*
+ * Description:
+ * This file implements the Secure Hash Algorithms SHA-224 and
+ * SHA-256 as defined in the U.S. National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-3 published in October 2008
+ * and formerly defined in its predecessors, FIPS PUB 180-1
+ * and FIP PUB 180-2.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-3/fips180-3_final.pdf
+ *
+ * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
+ * message digests for a given data stream. It should take about
+ * 2**n steps to find a message with the same digest as a given
+ * message and 2**(n/2) to find any two messages with the same
+ * digest, when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-224 and SHA-256 are defined in terms of 32-bit "words".
+ * This code uses (included via "sha.h") to define 32-
+ * and 8-bit unsigned integer types. If your C compiler does not
+ * support 32-bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-224 and SHA-256 are designed to work with messages less
+ * than 2^64 bits long. This implementation uses SHA224/256Input()
+ * to hash the bits that are a multiple of the size of an 8-bit
+ * octet, and then optionally uses SHA224/256FinalBits()
+ * to hash the final few bits of the input.
+ */
+
+#include "sha.h"
+
+/*
+ * These definitions are defined in FIPS 180-3, section 4.1.
+ * Ch() and Maj() are defined identically in sections 4.1.1,
+ * 4.1.2, and 4.1.3.
+ *
+ * The definitions used in FIPS 180-3 are as follows:
+ */
+#ifndef USE_MODIFIED_MACROS
+#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#else /* USE_MODIFIED_MACROS */
+/*
+ * The following definitions are equivalent and potentially faster.
+ */
+#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
+#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+#endif /* USE_MODIFIED_MACROS */
+
+#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
+
+/* Define the SHA shift, rotate left, and rotate right macros */
+#define SHA256_SHR(bits,word) ((word) >> (bits))
+#define SHA256_ROTL(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+#define SHA256_ROTR(bits,word) \
+ (((word) >> (bits)) | ((word) << (32-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA256_SIGMA0(word) \
+ (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
+#define SHA256_SIGMA1(word) \
+ (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
+#define SHA256_sigma0(word) \
+ (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
+#define SHA256_sigma1(word) \
+ (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
+
+/*
+ * Add "length" to the length.
+ * Set Corrupted when overflow has occurred.
+ */
+static uint32_t addTemp;
+#define SHA224_256AddLength(context, length) \
+ (addTemp = (context)->Length_Low, (context)->Corrupted = \
+ (((context)->Length_Low += (length)) < addTemp) && \
+ (++(context)->Length_High == 0) ? shaInputTooLong : \
+ (context)->Corrupted )
+
+/* Local Function Prototypes */
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
+static void SHA224_256ProcessMessageBlock(SHA256Context *context);
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte);
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte);
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[ ], int HashSize);
+
+/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
+static uint32_t SHA224_H0[SHA256HashSize/4] = {
+ 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
+ 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
+};
+
+/* Initial Hash Values: FIPS 180-3 section 5.3.3 */
+static uint32_t SHA256_H0[SHA256HashSize/4] = {
+ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+/*
+ * SHA224Reset
+ *
+ * Description:
+ * This function will initialize the SHA224Context in preparation
+ * for computing a new SHA224 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Reset(SHA224Context *context)
+{
+ return SHA224_256Reset(context, SHA224_H0);
+}
+
+/*
+ * SHA224Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_array[ ]: [in]
+ * An array of octets representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA224Input(SHA224Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ return SHA256Input(context, message_array, length);
+}
+
+/*
+ * SHA224FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224FinalBits(SHA224Context *context,
+ uint8_t message_bits, unsigned int length)
+{
+ return SHA256FinalBits(context, message_bits, length);
+}
+
+/*
+ * SHA224Result
+ *
+ * Description:
+ * This function will return the 224-bit message digest
+ * into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 27.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Result(SHA224Context *context,
+ uint8_t Message_Digest[SHA224HashSize])
+{
+ return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
+}
+
+/*
+ * SHA256Reset
+ *
+ * Description:
+ * This function will initialize the SHA256Context in preparation
+ * for computing a new SHA256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Reset(SHA256Context *context)
+{
+ return SHA224_256Reset(context, SHA256_H0);
+}
+
+/*
+ * SHA256Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_array[ ]: [in]
+ * An array of octets representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Input(SHA256Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ if (!context) return shaNull;
+ if (!length) return shaSuccess;
+ if (!message_array) return shaNull;
+ if (context->Computed) return context->Corrupted = shaStateError;
+ if (context->Corrupted) return context->Corrupted;
+
+ while (length--) {
+ context->Message_Block[context->Message_Block_Index++] =
+ *message_array;
+
+ if ((SHA224_256AddLength(context, 8) == shaSuccess) &&
+ (context->Message_Block_Index == SHA256_Message_Block_Size))
+ SHA224_256ProcessMessageBlock(context);
+
+ message_array++;
+ }
+
+ return context->Corrupted;
+
+}
+
+/*
+ * SHA256FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256FinalBits(SHA256Context *context,
+ uint8_t message_bits, unsigned int length)
+{
+ static uint8_t masks[8] = {
+ /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+ /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+ /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+ /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+ };
+ static uint8_t markbit[8] = {
+ /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+ /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+ /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+ /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+ };
+
+ if (!context) return shaNull;
+ if (!length) return shaSuccess;
+ if (context->Corrupted) return context->Corrupted;
+ if (context->Computed) return context->Corrupted = shaStateError;
+ if (length >= 8) return context->Corrupted = shaBadParam;
+
+ SHA224_256AddLength(context, length);
+ SHA224_256Finalize(context, (uint8_t)
+ ((message_bits & masks[length]) | markbit[length]));
+
+ return context->Corrupted;
+}
+
+/*
+ * SHA256Result
+ *
+ * Description:
+ * This function will return the 256-bit message digest
+ * into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 31.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Result(SHA256Context *context,
+ uint8_t Message_Digest[SHA256HashSize])
+{
+ return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
+}
+
+/*
+ * SHA224_256Reset
+ *
+ * Description:
+ * This helper function will initialize the SHA256Context in
+ * preparation for computing a new SHA-224 or SHA-256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ * H0[ ]: [in]
+ * The initial hash value array to use.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
+{
+ if (!context) return shaNull;
+
+ context->Length_High = context->Length_Low = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = H0[0];
+ context->Intermediate_Hash[1] = H0[1];
+ context->Intermediate_Hash[2] = H0[2];
+ context->Intermediate_Hash[3] = H0[3];
+ context->Intermediate_Hash[4] = H0[4];
+ context->Intermediate_Hash[5] = H0[5];
+ context->Intermediate_Hash[6] = H0[6];
+ context->Intermediate_Hash[7] = H0[7];
+
+ context->Computed = 0;
+ context->Corrupted = shaSuccess;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA224_256ProcessMessageBlock
+ *
+ * Description:
+ * This helper function will process the next 512 bits of the
+ * message stored in the Message_Block array.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the Secure Hash Standard.
+ */
+static void SHA224_256ProcessMessageBlock(SHA256Context *context)
+{
+ /* Constants defined in FIPS 180-3, section 4.2.2 */
+ static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
+ 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
+ 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
+ 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
+ 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
+ 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
+ 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+ int t, t4; /* Loop counter */
+ uint32_t temp1, temp2; /* Temporary word value */
+ uint32_t W[64]; /* Word sequence */
+ uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = t4 = 0; t < 16; t++, t4 += 4)
+ W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
+ (((uint32_t)context->Message_Block[t4 + 1]) << 16) |
+ (((uint32_t)context->Message_Block[t4 + 2]) << 8) |
+ (((uint32_t)context->Message_Block[t4 + 3]));
+
+ for (t = 16; t < 64; t++)
+ W[t] = SHA256_sigma1(W[t-2]) + W[t-7] +
+ SHA256_sigma0(W[t-15]) + W[t-16];
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+ F = context->Intermediate_Hash[5];
+ G = context->Intermediate_Hash[6];
+ H = context->Intermediate_Hash[7];
+
+ for (t = 0; t < 64; t++) {
+ temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+ temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C);
+ H = G;
+ G = F;
+ F = E;
+ E = D + temp1;
+ D = C;
+ C = B;
+ B = A;
+ A = temp1 + temp2;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+ context->Intermediate_Hash[5] += F;
+ context->Intermediate_Hash[6] += G;
+ context->Intermediate_Hash[7] += H;
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA224_256Finalize
+ *
+ * Description:
+ * This helper function finishes off the digest calculations.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * Pad_Byte: [in]
+ * The last byte to add to the message block before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ int i;
+ SHA224_256PadMessage(context, Pad_Byte);
+ /* message may be sensitive, so clear it out */
+ for (i = 0; i < SHA256_Message_Block_Size; ++i)
+ context->Message_Block[i] = 0;
+ context->Length_High = 0; /* and clear length */
+ context->Length_Low = 0;
+ context->Computed = 1;
+}
+
+/*
+ * SHA224_256PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to the next
+ * even multiple of 512 bits. The first padding bit must be a '1'.
+ * The last 64 bits represent the length of the original message.
+ * All bits in between should be 0. This helper function will pad
+ * the message according to those rules by filling the
+ * Message_Block array accordingly. When it returns, it can be
+ * assumed that the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad.
+ * Pad_Byte: [in]
+ * The last byte to add to the message block before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * Nothing.
+ */
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+ while (context->Message_Block_Index < SHA256_Message_Block_Size)
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ SHA224_256ProcessMessageBlock(context);
+ } else
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+ while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
+ context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
+ context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
+ context->Message_Block[59] = (uint8_t)(context->Length_High);
+ context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
+ context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
+ context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
+ context->Message_Block[63] = (uint8_t)(context->Length_Low);
+
+ SHA224_256ProcessMessageBlock(context);
+}
+
+/*
+ * SHA224_256ResultN
+ *
+ * Description:
+ * This helper function will return the 224-bit or 256-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 27/31.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ * HashSize: [in]
+ * The size of the hash, either 28 or 32.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[ ], int HashSize)
+{
+ int i;
+
+ if (!context) return shaNull;
+ if (!Message_Digest) return shaNull;
+ if (context->Corrupted) return context->Corrupted;
+
+ if (!context->Computed)
+ SHA224_256Finalize(context, 0x80);
+
+ for (i = 0; i < HashSize; ++i)
+ Message_Digest[i] = (uint8_t)
+ (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
+
+ return shaSuccess;
+}
+
diff --git a/src/util/hash/sha.h b/src/util/hash/sha.h
new file mode 100644
index 000000000..4f596234c
--- /dev/null
+++ b/src/util/hash/sha.h
@@ -0,0 +1,70 @@
+/*
+ * 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_hash_sha_h__
+#define INCLUDE_hash_sha_h__
+
+#include "git2_util.h"
+
+typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
+typedef struct git_hash_sha256_ctx git_hash_sha256_ctx;
+
+#if defined(GIT_SHA1_COMMON_CRYPTO) || defined(GIT_SHA256_COMMON_CRYPTO)
+# include "common_crypto.h"
+#endif
+
+#if defined(GIT_SHA1_OPENSSL) || defined(GIT_SHA256_OPENSSL)
+# include "openssl.h"
+#endif
+
+#if defined(GIT_SHA1_WIN32) || defined(GIT_SHA256_WIN32)
+# include "win32.h"
+#endif
+
+#if defined(GIT_SHA1_MBEDTLS) || defined(GIT_SHA256_MBEDTLS)
+# include "mbedtls.h"
+#endif
+
+#if defined(GIT_SHA1_COLLISIONDETECT)
+# include "collisiondetect.h"
+#endif
+
+#if defined(GIT_SHA256_BUILTIN)
+# include "builtin.h"
+#endif
+
+/*
+ * SHA1
+ */
+
+#define GIT_HASH_SHA1_SIZE 20
+
+int git_hash_sha1_global_init(void);
+
+int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx);
+void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx);
+
+int git_hash_sha1_init(git_hash_sha1_ctx *c);
+int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len);
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *c);
+
+/*
+ * SHA256
+ */
+
+#define GIT_HASH_SHA256_SIZE 32
+
+int git_hash_sha256_global_init(void);
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx);
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx);
+
+int git_hash_sha256_init(git_hash_sha256_ctx *c);
+int git_hash_sha256_update(git_hash_sha256_ctx *c, const void *data, size_t len);
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *c);
+
+#endif
diff --git a/src/hash/sha1/sha1dc/sha1.c b/src/util/hash/sha1dc/sha1.c
similarity index 100%
rename from src/hash/sha1/sha1dc/sha1.c
rename to src/util/hash/sha1dc/sha1.c
diff --git a/src/hash/sha1/sha1dc/sha1.h b/src/util/hash/sha1dc/sha1.h
similarity index 100%
rename from src/hash/sha1/sha1dc/sha1.h
rename to src/util/hash/sha1dc/sha1.h
diff --git a/src/hash/sha1/sha1dc/ubc_check.c b/src/util/hash/sha1dc/ubc_check.c
similarity index 100%
rename from src/hash/sha1/sha1dc/ubc_check.c
rename to src/util/hash/sha1dc/ubc_check.c
diff --git a/src/hash/sha1/sha1dc/ubc_check.h b/src/util/hash/sha1dc/ubc_check.h
similarity index 100%
rename from src/hash/sha1/sha1dc/ubc_check.h
rename to src/util/hash/sha1dc/ubc_check.h
diff --git a/src/util/hash/win32.c b/src/util/hash/win32.c
new file mode 100644
index 000000000..f80c0d5ca
--- /dev/null
+++ b/src/util/hash/win32.c
@@ -0,0 +1,549 @@
+/*
+ * 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 "win32.h"
+
+#include "runtime.h"
+
+#include
+#include
+
+#define GIT_HASH_CNG_DLL_NAME "bcrypt.dll"
+
+/* BCRYPT_SHA1_ALGORITHM */
+#define GIT_HASH_CNG_SHA1_TYPE L"SHA1"
+#define GIT_HASH_CNG_SHA256_TYPE L"SHA256"
+
+/* BCRYPT_OBJECT_LENGTH */
+#define GIT_HASH_CNG_HASH_OBJECT_LEN L"ObjectLength"
+
+/* BCRYPT_HASH_REUSEABLE_FLAGS */
+#define GIT_HASH_CNG_HASH_REUSABLE 0x00000020
+
+/* Definitions */
+
+/* CryptoAPI is available for hashing on Windows XP and newer. */
+struct cryptoapi_provider {
+ HCRYPTPROV handle;
+};
+
+/*
+ * CNG (bcrypt.dll) is significantly more performant than CryptoAPI and is
+ * preferred, however it is only available on Windows 2008 and newer and
+ * must therefore be dynamically loaded, and we must inline constants that
+ * would not exist when building in pre-Windows 2008 environments.
+ */
+
+/* Function declarations for CNG */
+typedef NTSTATUS (WINAPI *cng_open_algorithm_provider_fn)(
+ HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm,
+ LPCWSTR pszAlgId,
+ LPCWSTR pszImplementation,
+ DWORD dwFlags);
+
+typedef NTSTATUS (WINAPI *cng_get_property_fn)(
+ HANDLE /* BCRYPT_HANDLE */ hObject,
+ LPCWSTR pszProperty,
+ PUCHAR pbOutput,
+ ULONG cbOutput,
+ ULONG *pcbResult,
+ ULONG dwFlags);
+
+typedef NTSTATUS (WINAPI *cng_create_hash_fn)(
+ HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm,
+ HANDLE /* BCRYPT_HASH_HANDLE */ *phHash,
+ PUCHAR pbHashObject, ULONG cbHashObject,
+ PUCHAR pbSecret,
+ ULONG cbSecret,
+ ULONG dwFlags);
+
+typedef NTSTATUS (WINAPI *cng_finish_hash_fn)(
+ HANDLE /* BCRYPT_HASH_HANDLE */ hHash,
+ PUCHAR pbOutput,
+ ULONG cbOutput,
+ ULONG dwFlags);
+
+typedef NTSTATUS (WINAPI *cng_hash_data_fn)(
+ HANDLE /* BCRYPT_HASH_HANDLE */ hHash,
+ PUCHAR pbInput,
+ ULONG cbInput,
+ ULONG dwFlags);
+
+typedef NTSTATUS (WINAPI *cng_destroy_hash_fn)(
+ HANDLE /* BCRYPT_HASH_HANDLE */ hHash);
+
+typedef NTSTATUS (WINAPI *cng_close_algorithm_provider_fn)(
+ HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm,
+ ULONG dwFlags);
+
+struct cng_provider {
+ /* DLL for CNG */
+ HINSTANCE dll;
+
+ /* Function pointers for CNG */
+ cng_open_algorithm_provider_fn open_algorithm_provider;
+ cng_get_property_fn get_property;
+ cng_create_hash_fn create_hash;
+ cng_finish_hash_fn finish_hash;
+ cng_hash_data_fn hash_data;
+ cng_destroy_hash_fn destroy_hash;
+ cng_close_algorithm_provider_fn close_algorithm_provider;
+
+ HANDLE /* BCRYPT_ALG_HANDLE */ sha1_handle;
+ DWORD sha1_object_size;
+
+ HANDLE /* BCRYPT_ALG_HANDLE */ sha256_handle;
+ DWORD sha256_object_size;
+};
+
+typedef struct {
+ git_hash_win32_provider_t type;
+
+ union {
+ struct cryptoapi_provider cryptoapi;
+ struct cng_provider cng;
+ } provider;
+} hash_win32_provider;
+
+/* Hash provider definition */
+
+static hash_win32_provider hash_provider = {0};
+
+/* Hash initialization */
+
+/* Initialize CNG, if available */
+GIT_INLINE(int) cng_provider_init(void)
+{
+ char dll_path[MAX_PATH];
+ DWORD dll_path_len, size_len;
+
+ /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */
+ if (!git_has_win32_version(6, 0, 1)) {
+ git_error_set(GIT_ERROR_SHA, "CryptoNG is not supported on this platform");
+ return -1;
+ }
+
+ /* Load bcrypt.dll explicitly from the system directory */
+ if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 ||
+ dll_path_len > MAX_PATH ||
+ StringCchCat(dll_path, MAX_PATH, "\\") < 0 ||
+ StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 ||
+ (hash_provider.provider.cng.dll = LoadLibrary(dll_path)) == NULL) {
+ git_error_set(GIT_ERROR_SHA, "CryptoNG library could not be loaded");
+ return -1;
+ }
+
+ /* Load the function addresses */
+ if ((hash_provider.provider.cng.open_algorithm_provider = (cng_open_algorithm_provider_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptOpenAlgorithmProvider"))) == NULL ||
+ (hash_provider.provider.cng.get_property = (cng_get_property_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptGetProperty"))) == NULL ||
+ (hash_provider.provider.cng.create_hash = (cng_create_hash_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptCreateHash"))) == NULL ||
+ (hash_provider.provider.cng.finish_hash = (cng_finish_hash_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptFinishHash"))) == NULL ||
+ (hash_provider.provider.cng.hash_data = (cng_hash_data_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptHashData"))) == NULL ||
+ (hash_provider.provider.cng.destroy_hash = (cng_destroy_hash_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptDestroyHash"))) == NULL ||
+ (hash_provider.provider.cng.close_algorithm_provider = (cng_close_algorithm_provider_fn)((void *)GetProcAddress(hash_provider.provider.cng.dll, "BCryptCloseAlgorithmProvider"))) == NULL) {
+ FreeLibrary(hash_provider.provider.cng.dll);
+
+ git_error_set(GIT_ERROR_OS, "CryptoNG functions could not be loaded");
+ return -1;
+ }
+
+ /* Load the SHA1 algorithm */
+ if (hash_provider.provider.cng.open_algorithm_provider(&hash_provider.provider.cng.sha1_handle, GIT_HASH_CNG_SHA1_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0 ||
+ hash_provider.provider.cng.get_property(hash_provider.provider.cng.sha1_handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_provider.provider.cng.sha1_object_size, sizeof(DWORD), &size_len, 0) < 0) {
+ git_error_set(GIT_ERROR_OS, "algorithm provider could not be initialized");
+ goto on_error;
+ }
+
+ /* Load the SHA256 algorithm */
+ if (hash_provider.provider.cng.open_algorithm_provider(&hash_provider.provider.cng.sha256_handle, GIT_HASH_CNG_SHA256_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0 ||
+ hash_provider.provider.cng.get_property(hash_provider.provider.cng.sha256_handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_provider.provider.cng.sha256_object_size, sizeof(DWORD), &size_len, 0) < 0) {
+ git_error_set(GIT_ERROR_OS, "algorithm provider could not be initialized");
+ goto on_error;
+ }
+
+ hash_provider.type = GIT_HASH_WIN32_CNG;
+ return 0;
+
+on_error:
+ if (hash_provider.provider.cng.sha1_handle)
+ hash_provider.provider.cng.close_algorithm_provider(hash_provider.provider.cng.sha1_handle, 0);
+
+ if (hash_provider.provider.cng.sha256_handle)
+ hash_provider.provider.cng.close_algorithm_provider(hash_provider.provider.cng.sha256_handle, 0);
+
+ if (hash_provider.provider.cng.dll)
+ FreeLibrary(hash_provider.provider.cng.dll);
+
+ return -1;
+}
+
+GIT_INLINE(void) cng_provider_shutdown(void)
+{
+ if (hash_provider.type == GIT_HASH_WIN32_INVALID)
+ return;
+
+ hash_provider.provider.cng.close_algorithm_provider(hash_provider.provider.cng.sha1_handle, 0);
+ hash_provider.provider.cng.close_algorithm_provider(hash_provider.provider.cng.sha256_handle, 0);
+ FreeLibrary(hash_provider.provider.cng.dll);
+
+ hash_provider.type = GIT_HASH_WIN32_INVALID;
+}
+
+/* Initialize CryptoAPI */
+GIT_INLINE(int) cryptoapi_provider_init(void)
+{
+ if (!CryptAcquireContext(&hash_provider.provider.cryptoapi.handle, NULL, 0, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
+ git_error_set(GIT_ERROR_OS, "legacy hash context could not be started");
+ return -1;
+ }
+
+ hash_provider.type = GIT_HASH_WIN32_CRYPTOAPI;
+ return 0;
+}
+
+GIT_INLINE(void) cryptoapi_provider_shutdown(void)
+{
+ if (hash_provider.type == GIT_HASH_WIN32_INVALID)
+ return;
+
+ CryptReleaseContext(hash_provider.provider.cryptoapi.handle, 0);
+
+ hash_provider.type = GIT_HASH_WIN32_INVALID;
+}
+
+static void hash_provider_shutdown(void)
+{
+ if (hash_provider.type == GIT_HASH_WIN32_CNG)
+ cng_provider_shutdown();
+ else if (hash_provider.type == GIT_HASH_WIN32_CRYPTOAPI)
+ cryptoapi_provider_shutdown();
+}
+
+static int hash_provider_init(void)
+{
+ int error = 0;
+
+ if (hash_provider.type != GIT_HASH_WIN32_INVALID)
+ return 0;
+
+ if ((error = cng_provider_init()) < 0)
+ error = cryptoapi_provider_init();
+
+ if (!error)
+ error = git_runtime_shutdown_register(hash_provider_shutdown);
+
+ return error;
+}
+
+git_hash_win32_provider_t git_hash_win32_provider(void)
+{
+ return hash_provider.type;
+}
+
+int git_hash_win32_set_provider(git_hash_win32_provider_t provider)
+{
+ if (provider == hash_provider.type)
+ return 0;
+
+ hash_provider_shutdown();
+
+ if (provider == GIT_HASH_WIN32_CNG)
+ return cng_provider_init();
+ else if (provider == GIT_HASH_WIN32_CRYPTOAPI)
+ return cryptoapi_provider_init();
+
+ git_error_set(GIT_ERROR_SHA, "unsupported win32 provider");
+ return -1;
+}
+
+/* CryptoAPI: available in Windows XP and newer */
+
+GIT_INLINE(int) hash_cryptoapi_init(git_hash_win32_ctx *ctx)
+{
+ if (ctx->ctx.cryptoapi.valid)
+ CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
+
+ if (!CryptCreateHash(hash_provider.provider.cryptoapi.handle, ctx->algorithm, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) {
+ ctx->ctx.cryptoapi.valid = 0;
+ git_error_set(GIT_ERROR_OS, "legacy hash implementation could not be created");
+ return -1;
+ }
+
+ ctx->ctx.cryptoapi.valid = 1;
+ return 0;
+}
+
+GIT_INLINE(int) hash_cryptoapi_update(git_hash_win32_ctx *ctx, const void *_data, size_t len)
+{
+ const BYTE *data = (BYTE *)_data;
+
+ GIT_ASSERT(ctx->ctx.cryptoapi.valid);
+
+ while (len > 0) {
+ DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len;
+
+ if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0)) {
+ git_error_set(GIT_ERROR_OS, "legacy hash data could not be updated");
+ return -1;
+ }
+
+ data += chunk;
+ len -= chunk;
+ }
+
+ return 0;
+}
+
+GIT_INLINE(int) hash_cryptoapi_final(unsigned char *out, git_hash_win32_ctx *ctx)
+{
+ DWORD len = ctx->algorithm == CALG_SHA_256 ? GIT_HASH_SHA256_SIZE : GIT_HASH_SHA1_SIZE;
+ int error = 0;
+
+ GIT_ASSERT(ctx->ctx.cryptoapi.valid);
+
+ if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out, &len, 0)) {
+ git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished");
+ error = -1;
+ }
+
+ CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
+ ctx->ctx.cryptoapi.valid = 0;
+
+ return error;
+}
+
+GIT_INLINE(void) hash_ctx_cryptoapi_cleanup(git_hash_win32_ctx *ctx)
+{
+ if (ctx->ctx.cryptoapi.valid)
+ CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
+}
+
+GIT_INLINE(int) hash_sha1_cryptoapi_ctx_init_init(git_hash_win32_ctx *ctx)
+{
+ ctx->algorithm = CALG_SHA1;
+ return hash_cryptoapi_init(ctx);
+}
+
+GIT_INLINE(int) hash_sha256_cryptoapi_ctx_init(git_hash_win32_ctx *ctx)
+{
+ ctx->algorithm = CALG_SHA_256;
+ return hash_cryptoapi_init(ctx);
+}
+
+/* CNG: Available in Windows Server 2008 and newer */
+
+GIT_INLINE(int) hash_sha1_cng_ctx_init(git_hash_win32_ctx *ctx)
+{
+ if ((ctx->ctx.cng.hash_object = git__malloc(hash_provider.provider.cng.sha1_object_size)) == NULL)
+ return -1;
+
+ if (hash_provider.provider.cng.create_hash(hash_provider.provider.cng.sha1_handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_provider.provider.cng.sha1_object_size, NULL, 0, 0) < 0) {
+ git__free(ctx->ctx.cng.hash_object);
+
+ git_error_set(GIT_ERROR_OS, "sha1 implementation could not be created");
+ return -1;
+ }
+
+ ctx->algorithm = CALG_SHA1;
+ return 0;
+}
+
+GIT_INLINE(int) hash_sha256_cng_ctx_init(git_hash_win32_ctx *ctx)
+{
+ if ((ctx->ctx.cng.hash_object = git__malloc(hash_provider.provider.cng.sha256_object_size)) == NULL)
+ return -1;
+
+ if (hash_provider.provider.cng.create_hash(hash_provider.provider.cng.sha256_handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_provider.provider.cng.sha256_object_size, NULL, 0, 0) < 0) {
+ git__free(ctx->ctx.cng.hash_object);
+
+ git_error_set(GIT_ERROR_OS, "sha256 implementation could not be created");
+ return -1;
+ }
+
+ ctx->algorithm = CALG_SHA_256;
+ return 0;
+}
+
+GIT_INLINE(int) hash_cng_init(git_hash_win32_ctx *ctx)
+{
+ BYTE hash[GIT_HASH_SHA256_SIZE];
+ ULONG size = ctx->algorithm == CALG_SHA_256 ? GIT_HASH_SHA256_SIZE : GIT_HASH_SHA1_SIZE;
+
+ if (!ctx->ctx.cng.updated)
+ return 0;
+
+ /* CNG needs to be finished to restart */
+ if (hash_provider.provider.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, size, 0) < 0) {
+ git_error_set(GIT_ERROR_OS, "hash implementation could not be finished");
+ return -1;
+ }
+
+ ctx->ctx.cng.updated = 0;
+
+ return 0;
+}
+
+GIT_INLINE(int) hash_cng_update(git_hash_win32_ctx *ctx, const void *_data, size_t len)
+{
+ PBYTE data = (PBYTE)_data;
+
+ while (len > 0) {
+ ULONG chunk = (len > ULONG_MAX) ? ULONG_MAX : (ULONG)len;
+
+ if (hash_provider.provider.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0) {
+ git_error_set(GIT_ERROR_OS, "hash could not be updated");
+ return -1;
+ }
+
+ data += chunk;
+ len -= chunk;
+ }
+
+ return 0;
+}
+
+GIT_INLINE(int) hash_cng_final(unsigned char *out, git_hash_win32_ctx *ctx)
+{
+ ULONG size = ctx->algorithm == CALG_SHA_256 ? GIT_HASH_SHA256_SIZE : GIT_HASH_SHA1_SIZE;
+
+ if (hash_provider.provider.cng.finish_hash(ctx->ctx.cng.hash_handle, out, size, 0) < 0) {
+ git_error_set(GIT_ERROR_OS, "hash could not be finished");
+ return -1;
+ }
+
+ ctx->ctx.cng.updated = 0;
+
+ return 0;
+}
+
+GIT_INLINE(void) hash_ctx_cng_cleanup(git_hash_win32_ctx *ctx)
+{
+ hash_provider.provider.cng.destroy_hash(ctx->ctx.cng.hash_handle);
+ git__free(ctx->ctx.cng.hash_object);
+}
+
+/* Indirection between CryptoAPI and CNG */
+
+GIT_INLINE(int) hash_sha1_win32_ctx_init(git_hash_win32_ctx *ctx)
+{
+ GIT_ASSERT_ARG(hash_provider.type);
+
+ memset(ctx, 0x0, sizeof(git_hash_win32_ctx));
+ return (hash_provider.type == GIT_HASH_WIN32_CNG) ? hash_sha1_cng_ctx_init(ctx) : hash_sha1_cryptoapi_ctx_init_init(ctx);
+}
+
+GIT_INLINE(int) hash_sha256_win32_ctx_init(git_hash_win32_ctx *ctx)
+{
+ GIT_ASSERT_ARG(hash_provider.type);
+
+ memset(ctx, 0x0, sizeof(git_hash_win32_ctx));
+ return (hash_provider.type == GIT_HASH_WIN32_CNG) ? hash_sha256_cng_ctx_init(ctx) : hash_sha256_cryptoapi_ctx_init(ctx);
+}
+
+GIT_INLINE(int) hash_win32_init(git_hash_win32_ctx *ctx)
+{
+ return (hash_provider.type == GIT_HASH_WIN32_CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx);
+}
+
+GIT_INLINE(int) hash_win32_update(git_hash_win32_ctx *ctx, const void *data, size_t len)
+{
+ return (hash_provider.type == GIT_HASH_WIN32_CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len);
+}
+
+GIT_INLINE(int) hash_win32_final(unsigned char *out, git_hash_win32_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return (hash_provider.type == GIT_HASH_WIN32_CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx);
+}
+
+GIT_INLINE(void) hash_win32_cleanup(git_hash_win32_ctx *ctx)
+{
+ if (hash_provider.type == GIT_HASH_WIN32_CNG)
+ hash_ctx_cng_cleanup(ctx);
+ else if(hash_provider.type == GIT_HASH_WIN32_CRYPTOAPI)
+ hash_ctx_cryptoapi_cleanup(ctx);
+}
+
+#ifdef GIT_SHA1_WIN32
+
+int git_hash_sha1_global_init(void)
+{
+ return hash_provider_init();
+}
+
+int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_sha1_win32_ctx_init(&ctx->win32);
+}
+
+int git_hash_sha1_init(git_hash_sha1_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_init(&ctx->win32);
+}
+
+int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_update(&ctx->win32, data, len);
+}
+
+int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_final(out, &ctx->win32);
+}
+
+void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx)
+{
+ if (!ctx)
+ return;
+ hash_win32_cleanup(&ctx->win32);
+}
+
+#endif
+
+#ifdef GIT_SHA256_WIN32
+
+int git_hash_sha256_global_init(void)
+{
+ return hash_provider_init();
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_sha256_win32_ctx_init(&ctx->win32);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_init(&ctx->win32);
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_update(&ctx->win32, data, len);
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+ GIT_ASSERT_ARG(ctx);
+ return hash_win32_final(out, &ctx->win32);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+ if (!ctx)
+ return;
+ hash_win32_cleanup(&ctx->win32);
+}
+
+#endif
diff --git a/src/util/hash/win32.h b/src/util/hash/win32.h
new file mode 100644
index 000000000..a9fb87aee
--- /dev/null
+++ b/src/util/hash/win32.h
@@ -0,0 +1,60 @@
+/*
+ * 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_hash_win32_h__
+#define INCLUDE_hash_win32_h__
+
+#include "hash/sha.h"
+
+#include
+
+typedef enum {
+ GIT_HASH_WIN32_INVALID = 0,
+ GIT_HASH_WIN32_CRYPTOAPI,
+ GIT_HASH_WIN32_CNG
+} git_hash_win32_provider_t;
+
+struct git_hash_win32_cryptoapi_ctx {
+ bool valid;
+ HCRYPTHASH hash_handle;
+};
+
+struct git_hash_win32_cng_ctx {
+ bool updated;
+ HANDLE /* BCRYPT_HASH_HANDLE */ hash_handle;
+ PBYTE hash_object;
+};
+
+typedef struct {
+ ALG_ID algorithm;
+
+ union {
+ struct git_hash_win32_cryptoapi_ctx cryptoapi;
+ struct git_hash_win32_cng_ctx cng;
+ } ctx;
+} git_hash_win32_ctx;
+
+/*
+ * Gets/sets the current hash provider (cng or cryptoapi). This is only
+ * for testing purposes.
+ */
+git_hash_win32_provider_t git_hash_win32_provider(void);
+int git_hash_win32_set_provider(git_hash_win32_provider_t provider);
+
+#ifdef GIT_SHA1_WIN32
+struct git_hash_sha1_ctx {
+ git_hash_win32_ctx win32;
+};
+#endif
+
+#ifdef GIT_SHA256_WIN32
+struct git_hash_sha256_ctx {
+ git_hash_win32_ctx win32;
+};
+#endif
+
+#endif
diff --git a/src/integer.h b/src/util/integer.h
similarity index 100%
rename from src/integer.h
rename to src/util/integer.h
diff --git a/src/khash.h b/src/util/khash.h
similarity index 100%
rename from src/khash.h
rename to src/util/khash.h
diff --git a/src/map.h b/src/util/map.h
similarity index 98%
rename from src/map.h
rename to src/util/map.h
index 01931d199..c101e46f6 100644
--- a/src/map.h
+++ b/src/util/map.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_map_h__
#define INCLUDE_map_h__
-#include "common.h"
+#include "git2_util.h"
/* p_mmap() prot values */
diff --git a/src/net.c b/src/util/net.c
similarity index 99%
rename from src/net.c
rename to src/util/net.c
index a76fd1d7c..b2236daf8 100644
--- a/src/net.c
+++ b/src/util/net.c
@@ -6,7 +6,6 @@
*/
#include "net.h"
-#include "netops.h"
#include
diff --git a/src/net.h b/src/util/net.h
similarity index 99%
rename from src/net.h
rename to src/util/net.h
index 499315e6c..88030a952 100644
--- a/src/net.h
+++ b/src/util/net.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_net_h__
#define INCLUDE_net_h__
-#include "common.h"
+#include "git2_util.h"
typedef struct git_net_url {
char *scheme;
diff --git a/src/pool.c b/src/util/pool.c
similarity index 100%
rename from src/pool.c
rename to src/util/pool.c
diff --git a/src/pool.h b/src/util/pool.h
similarity index 99%
rename from src/pool.h
rename to src/util/pool.h
index cecb84665..0238431b0 100644
--- a/src/pool.h
+++ b/src/util/pool.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_pool_h__
#define INCLUDE_pool_h__
-#include "common.h"
+#include "git2_util.h"
#include "vector.h"
diff --git a/src/posix.c b/src/util/posix.c
similarity index 100%
rename from src/posix.c
rename to src/util/posix.c
diff --git a/src/posix.h b/src/util/posix.h
similarity index 99%
rename from src/posix.h
rename to src/util/posix.h
index e6f603078..c8f8cd9d2 100644
--- a/src/posix.h
+++ b/src/util/posix.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_posix_h__
#define INCLUDE_posix_h__
-#include "common.h"
+#include "git2_util.h"
#include
#include
diff --git a/src/pqueue.c b/src/util/pqueue.c
similarity index 100%
rename from src/pqueue.c
rename to src/util/pqueue.c
diff --git a/src/pqueue.h b/src/util/pqueue.h
similarity index 98%
rename from src/pqueue.h
rename to src/util/pqueue.h
index 4db74ea03..97232b4a9 100644
--- a/src/pqueue.h
+++ b/src/util/pqueue.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_pqueue_h__
#define INCLUDE_pqueue_h__
-#include "common.h"
+#include "git2_util.h"
#include "vector.h"
diff --git a/src/rand.c b/src/util/rand.c
similarity index 98%
rename from src/rand.c
rename to src/util/rand.c
index 0a208134e..d28e4aa97 100644
--- a/src/rand.c
+++ b/src/util/rand.c
@@ -6,7 +6,7 @@ worldwide. This software is distributed without any warranty.
See . */
-#include "common.h"
+#include "git2_util.h"
#include "rand.h"
#include "runtime.h"
@@ -106,8 +106,6 @@ GIT_INLINE(int) getseed(uint64_t *seed)
return -1;
}
- getloadavg(loadavg, 3);
-
*seed = 0;
*seed |= ((uint64_t)tv.tv_usec << 40);
*seed |= ((uint64_t)tv.tv_sec);
@@ -119,9 +117,15 @@ GIT_INLINE(int) getseed(uint64_t *seed)
*seed ^= ((uint64_t)getuid() << 8);
*seed ^= ((uint64_t)getgid());
+# if defined(GIT_RAND_GETLOADAVG)
+ getloadavg(loadavg, 3);
+
convert.f = loadavg[0]; *seed ^= (convert.d >> 36);
convert.f = loadavg[1]; *seed ^= (convert.d);
convert.f = loadavg[2]; *seed ^= (convert.d >> 16);
+# else
+ GIT_UNUSED(loadavg[0]);
+# endif
convert.f = git__timer(); *seed ^= (convert.d);
diff --git a/src/rand.h b/src/util/rand.h
similarity index 97%
rename from src/rand.h
rename to src/util/rand.h
index 2e60561e5..fa0619aa2 100644
--- a/src/rand.h
+++ b/src/util/rand.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_rand_h__
#define INCLUDE_rand_h__
-#include "common.h"
+#include "git2_util.h"
/**
* Initialize the random number generation subsystem. This will
diff --git a/src/regexp.c b/src/util/regexp.c
similarity index 100%
rename from src/regexp.c
rename to src/util/regexp.c
diff --git a/src/regexp.h b/src/util/regexp.h
similarity index 99%
rename from src/regexp.h
rename to src/util/regexp.h
index 2592ef383..d0862b107 100644
--- a/src/regexp.h
+++ b/src/util/regexp.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_regexp_h__
#define INCLUDE_regexp_h__
-#include "common.h"
+#include "git2_util.h"
#if defined(GIT_REGEX_BUILTIN) || defined(GIT_REGEX_PCRE)
# include "pcre.h"
diff --git a/src/runtime.c b/src/util/runtime.c
similarity index 99%
rename from src/runtime.c
rename to src/util/runtime.c
index c05dee8b9..a7711ffc4 100644
--- a/src/runtime.c
+++ b/src/util/runtime.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#include "runtime.h"
static git_runtime_shutdown_fn shutdown_callback[32];
diff --git a/src/runtime.h b/src/util/runtime.h
similarity index 98%
rename from src/runtime.h
rename to src/util/runtime.h
index 24ac58ee9..6cbfd6043 100644
--- a/src/runtime.h
+++ b/src/util/runtime.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_runtime_h__
#define INCLUDE_runtime_h__
-#include "common.h"
+#include "git2_util.h"
typedef int (*git_runtime_init_fn)(void);
typedef void (*git_runtime_shutdown_fn)(void);
diff --git a/src/sortedcache.c b/src/util/sortedcache.c
similarity index 100%
rename from src/sortedcache.c
rename to src/util/sortedcache.c
diff --git a/src/sortedcache.h b/src/util/sortedcache.h
similarity index 99%
rename from src/sortedcache.h
rename to src/util/sortedcache.h
index ef260a093..3eee4659f 100644
--- a/src/sortedcache.h
+++ b/src/util/sortedcache.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_sorted_cache_h__
#define INCLUDE_sorted_cache_h__
-#include "common.h"
+#include "git2_util.h"
#include "util.h"
#include "futils.h"
diff --git a/src/str.c b/src/util/str.c
similarity index 100%
rename from src/str.c
rename to src/util/str.c
diff --git a/src/str.h b/src/util/str.h
similarity index 99%
rename from src/str.h
rename to src/util/str.h
index ef769ce2f..588e6fc22 100644
--- a/src/str.h
+++ b/src/util/str.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_str_h__
#define INCLUDE_str_h__
-#include "common.h"
+#include "git2_util.h"
struct git_str {
char *ptr;
diff --git a/src/strmap.c b/src/util/strmap.c
similarity index 100%
rename from src/strmap.c
rename to src/util/strmap.c
diff --git a/src/strmap.h b/src/util/strmap.h
similarity index 99%
rename from src/strmap.h
rename to src/util/strmap.h
index 9f5e4cc8b..b64d3dcb5 100644
--- a/src/strmap.h
+++ b/src/util/strmap.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_strmap_h__
#define INCLUDE_strmap_h__
-#include "common.h"
+#include "git2_util.h"
/** A map with C strings as key. */
typedef struct kh_str_s git_strmap;
diff --git a/src/strnlen.h b/src/util/strnlen.h
similarity index 100%
rename from src/strnlen.h
rename to src/util/strnlen.h
diff --git a/src/thread.c b/src/util/thread.c
similarity index 99%
rename from src/thread.c
rename to src/util/thread.c
index 3171771d7..bc7364f8c 100644
--- a/src/thread.c
+++ b/src/util/thread.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#if !defined(GIT_THREADS)
diff --git a/src/thread.h b/src/util/thread.h
similarity index 100%
rename from src/thread.h
rename to src/util/thread.h
diff --git a/src/tsort.c b/src/util/tsort.c
similarity index 99%
rename from src/tsort.c
rename to src/util/tsort.c
index 045efad23..2ef03d03a 100644
--- a/src/tsort.c
+++ b/src/util/tsort.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
/**
* An array-of-pointers implementation of Python's Timsort
diff --git a/src/unix/map.c b/src/util/unix/map.c
similarity index 98%
rename from src/unix/map.c
rename to src/util/unix/map.c
index 23fcb786e..933077689 100644
--- a/src/unix/map.c
+++ b/src/util/unix/map.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#if !defined(GIT_WIN32) && !defined(NO_MMAP)
diff --git a/src/unix/posix.h b/src/util/unix/posix.h
similarity index 99%
rename from src/unix/posix.h
rename to src/util/unix/posix.h
index 49065e533..778477e8e 100644
--- a/src/unix/posix.h
+++ b/src/util/unix/posix.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_unix_posix_h__
#define INCLUDE_unix_posix_h__
-#include "common.h"
+#include "git2_util.h"
#include
#include
diff --git a/src/unix/pthread.h b/src/util/unix/pthread.h
similarity index 100%
rename from src/unix/pthread.h
rename to src/util/unix/pthread.h
diff --git a/src/unix/realpath.c b/src/util/unix/realpath.c
similarity index 96%
rename from src/unix/realpath.c
rename to src/util/unix/realpath.c
index f1ca669f7..9e31a63b9 100644
--- a/src/unix/realpath.c
+++ b/src/util/unix/realpath.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#ifndef GIT_WIN32
diff --git a/src/utf8.c b/src/util/utf8.c
similarity index 99%
rename from src/utf8.c
rename to src/util/utf8.c
index 77065cb71..c566fdf20 100644
--- a/src/utf8.c
+++ b/src/util/utf8.c
@@ -7,7 +7,7 @@
#include "utf8.h"
-#include "common.h"
+#include "git2_util.h"
/*
* git_utf8_iterate is taken from the utf8proc project,
diff --git a/src/utf8.h b/src/util/utf8.h
similarity index 98%
rename from src/utf8.h
rename to src/util/utf8.h
index dff91b294..753ab07e2 100644
--- a/src/utf8.h
+++ b/src/util/utf8.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_utf8_h__
#define INCLUDE_utf8_h__
-#include "common.h"
+#include "git2_util.h"
/*
* Iterate through an UTF-8 string, yielding one codepoint at a time.
diff --git a/src/util.c b/src/util/util.c
similarity index 99%
rename from src/util.c
rename to src/util/util.c
index e06d4ca09..aee95fddf 100644
--- a/src/util.c
+++ b/src/util/util.c
@@ -7,7 +7,7 @@
#include "util.h"
-#include "common.h"
+#include "git2_util.h"
#ifdef GIT_WIN32
# include "win32/utf-conv.h"
diff --git a/src/util.h b/src/util/util.h
similarity index 99%
rename from src/util.h
rename to src/util/util.h
index 141779ade..8d6d1d6b6 100644
--- a/src/util.h
+++ b/src/util/util.h
@@ -12,7 +12,7 @@
#endif
#include "str.h"
-#include "common.h"
+#include "git2_util.h"
#include "strnlen.h"
#include "thread.h"
diff --git a/src/varint.c b/src/util/varint.c
similarity index 100%
rename from src/varint.c
rename to src/util/varint.c
diff --git a/src/varint.h b/src/util/varint.h
similarity index 94%
rename from src/varint.h
rename to src/util/varint.h
index 652e22486..79b8f5548 100644
--- a/src/varint.h
+++ b/src/util/varint.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_varint_h__
#define INCLUDE_varint_h__
-#include "common.h"
+#include "git2_util.h"
#include
diff --git a/src/vector.c b/src/util/vector.c
similarity index 100%
rename from src/vector.c
rename to src/util/vector.c
diff --git a/src/vector.h b/src/util/vector.h
similarity index 99%
rename from src/vector.h
rename to src/util/vector.h
index ae3c79a4c..e50cdfefc 100644
--- a/src/vector.h
+++ b/src/util/vector.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_vector_h__
#define INCLUDE_vector_h__
-#include "common.h"
+#include "git2_util.h"
typedef int (*git_vector_cmp)(const void *, const void *);
diff --git a/src/wildmatch.c b/src/util/wildmatch.c
similarity index 100%
rename from src/wildmatch.c
rename to src/util/wildmatch.c
diff --git a/src/wildmatch.h b/src/util/wildmatch.h
similarity index 95%
rename from src/wildmatch.h
rename to src/util/wildmatch.h
index 44bb575a6..f20640500 100644
--- a/src/wildmatch.h
+++ b/src/util/wildmatch.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_wildmatch_h__
#define INCLUDE_wildmatch_h__
-#include "common.h"
+#include "git2_util.h"
#define WM_CASEFOLD 1
#define WM_PATHNAME 2
diff --git a/src/win32/dir.c b/src/util/win32/dir.c
similarity index 100%
rename from src/win32/dir.c
rename to src/util/win32/dir.c
diff --git a/src/win32/dir.h b/src/util/win32/dir.h
similarity index 97%
rename from src/win32/dir.h
rename to src/util/win32/dir.h
index acd64729e..810111534 100644
--- a/src/win32/dir.h
+++ b/src/util/win32/dir.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_dir_h__
#define INCLUDE_win32_dir_h__
-#include "common.h"
+#include "git2_util.h"
#include "w32_util.h"
diff --git a/src/win32/error.c b/src/util/win32/error.c
similarity index 100%
rename from src/win32/error.c
rename to src/util/win32/error.c
diff --git a/src/win32/error.h b/src/util/win32/error.h
similarity index 93%
rename from src/win32/error.h
rename to src/util/win32/error.h
index 9e81141ce..fd53b7f99 100644
--- a/src/win32/error.h
+++ b/src/util/win32/error.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_error_h__
#define INCLUDE_win32_error_h__
-#include "common.h"
+#include "git2_util.h"
extern char *git_win32_get_error_message(DWORD error_code);
diff --git a/src/win32/findfile.c b/src/util/win32/findfile.c
similarity index 100%
rename from src/win32/findfile.c
rename to src/util/win32/findfile.c
diff --git a/src/win32/findfile.h b/src/util/win32/findfile.h
similarity index 96%
rename from src/win32/findfile.h
rename to src/util/win32/findfile.h
index 61fb7dbad..7b191d1fe 100644
--- a/src/win32/findfile.h
+++ b/src/util/win32/findfile.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_findfile_h__
#define INCLUDE_win32_findfile_h__
-#include "common.h"
+#include "git2_util.h"
/** Sets the mock registry root for Git for Windows for testing. */
extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir);
diff --git a/src/win32/map.c b/src/util/win32/map.c
similarity index 99%
rename from src/win32/map.c
rename to src/util/win32/map.c
index 2aabc9b15..52e1363ea 100644
--- a/src/win32/map.c
+++ b/src/util/win32/map.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#include "map.h"
#include
diff --git a/src/win32/mingw-compat.h b/src/util/win32/mingw-compat.h
similarity index 100%
rename from src/win32/mingw-compat.h
rename to src/util/win32/mingw-compat.h
diff --git a/src/win32/msvc-compat.h b/src/util/win32/msvc-compat.h
similarity index 100%
rename from src/win32/msvc-compat.h
rename to src/util/win32/msvc-compat.h
diff --git a/src/win32/path_w32.c b/src/util/win32/path_w32.c
similarity index 100%
rename from src/win32/path_w32.c
rename to src/util/win32/path_w32.c
diff --git a/src/win32/path_w32.h b/src/util/win32/path_w32.h
similarity index 99%
rename from src/win32/path_w32.h
rename to src/util/win32/path_w32.h
index 837b11ebd..b241d5c8a 100644
--- a/src/win32/path_w32.h
+++ b/src/util/win32/path_w32.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_path_w32_h__
#define INCLUDE_win32_path_w32_h__
-#include "common.h"
+#include "git2_util.h"
/**
* Create a Win32 path (in UCS-2 format) from a UTF-8 string. If the given
diff --git a/src/win32/posix.h b/src/util/win32/posix.h
similarity index 99%
rename from src/win32/posix.h
rename to src/util/win32/posix.h
index 578347f15..03fa2ac52 100644
--- a/src/win32/posix.h
+++ b/src/util/win32/posix.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_posix_h__
#define INCLUDE_win32_posix_h__
-#include "common.h"
+#include "git2_util.h"
#include "../posix.h"
#include "win32-compat.h"
#include "path_w32.h"
diff --git a/src/win32/posix_w32.c b/src/util/win32/posix_w32.c
similarity index 99%
rename from src/win32/posix_w32.c
rename to src/util/win32/posix_w32.c
index 5f7cd0c26..5862e5c9a 100644
--- a/src/win32/posix_w32.c
+++ b/src/util/win32/posix_w32.c
@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "git2_util.h"
#include "../posix.h"
#include "../futils.h"
diff --git a/tests/precompiled.c b/src/util/win32/precompiled.c
similarity index 100%
rename from tests/precompiled.c
rename to src/util/win32/precompiled.c
diff --git a/src/win32/precompiled.h b/src/util/win32/precompiled.h
similarity index 93%
rename from src/win32/precompiled.h
rename to src/util/win32/precompiled.h
index 806b1698a..1163c3d63 100644
--- a/src/win32/precompiled.h
+++ b/src/util/win32/precompiled.h
@@ -1,4 +1,4 @@
-#include "common.h"
+#include "git2_util.h"
#include
#include
diff --git a/src/win32/reparse.h b/src/util/win32/reparse.h
similarity index 100%
rename from src/win32/reparse.h
rename to src/util/win32/reparse.h
diff --git a/src/win32/thread.c b/src/util/win32/thread.c
similarity index 100%
rename from src/win32/thread.c
rename to src/util/win32/thread.c
diff --git a/src/win32/thread.h b/src/util/win32/thread.h
similarity index 98%
rename from src/win32/thread.h
rename to src/util/win32/thread.h
index 8305036b4..184762e2a 100644
--- a/src/win32/thread.h
+++ b/src/util/win32/thread.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_thread_h__
#define INCLUDE_win32_thread_h__
-#include "common.h"
+#include "git2_util.h"
#if defined (_MSC_VER)
# define GIT_RESTRICT __restrict
diff --git a/src/win32/utf-conv.c b/src/util/win32/utf-conv.c
similarity index 100%
rename from src/win32/utf-conv.c
rename to src/util/win32/utf-conv.c
diff --git a/src/win32/utf-conv.h b/src/util/win32/utf-conv.h
similarity index 98%
rename from src/win32/utf-conv.h
rename to src/util/win32/utf-conv.h
index 6090a4b35..120d647ef 100644
--- a/src/win32/utf-conv.h
+++ b/src/util/win32/utf-conv.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_utf_conv_h__
#define INCLUDE_win32_utf_conv_h__
-#include "common.h"
+#include "git2_util.h"
#include
diff --git a/src/win32/version.h b/src/util/win32/version.h
similarity index 100%
rename from src/win32/version.h
rename to src/util/win32/version.h
diff --git a/src/win32/w32_buffer.c b/src/util/win32/w32_buffer.c
similarity index 100%
rename from src/win32/w32_buffer.c
rename to src/util/win32/w32_buffer.c
diff --git a/src/win32/w32_buffer.h b/src/util/win32/w32_buffer.h
similarity index 95%
rename from src/win32/w32_buffer.h
rename to src/util/win32/w32_buffer.h
index 4227296d8..68ea96035 100644
--- a/src/win32/w32_buffer.h
+++ b/src/util/win32/w32_buffer.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_w32_buffer_h__
#define INCLUDE_win32_w32_buffer_h__
-#include "common.h"
+#include "git2_util.h"
#include "str.h"
/**
diff --git a/src/win32/w32_common.h b/src/util/win32/w32_common.h
similarity index 100%
rename from src/win32/w32_common.h
rename to src/util/win32/w32_common.h
diff --git a/src/win32/w32_leakcheck.c b/src/util/win32/w32_leakcheck.c
similarity index 100%
rename from src/win32/w32_leakcheck.c
rename to src/util/win32/w32_leakcheck.c
diff --git a/src/win32/w32_leakcheck.h b/src/util/win32/w32_leakcheck.h
similarity index 99%
rename from src/win32/w32_leakcheck.h
rename to src/util/win32/w32_leakcheck.h
index cb45e3675..82d863851 100644
--- a/src/win32/w32_leakcheck.h
+++ b/src/util/win32/w32_leakcheck.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_leakcheck_h__
#define INCLUDE_win32_leakcheck_h__
-#include "common.h"
+#include "git2_util.h"
/* Initialize the win32 leak checking system. */
int git_win32_leakcheck_global_init(void);
diff --git a/src/win32/w32_util.c b/src/util/win32/w32_util.c
similarity index 100%
rename from src/win32/w32_util.c
rename to src/util/win32/w32_util.c
diff --git a/src/win32/w32_util.h b/src/util/win32/w32_util.h
similarity index 99%
rename from src/win32/w32_util.h
rename to src/util/win32/w32_util.h
index 1321d30e6..519663720 100644
--- a/src/win32/w32_util.h
+++ b/src/util/win32/w32_util.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_w32_util_h__
#define INCLUDE_win32_w32_util_h__
-#include "common.h"
+#include "git2_util.h"
#include "utf-conv.h"
#include "posix.h"
diff --git a/src/win32/win32-compat.h b/src/util/win32/win32-compat.h
similarity index 100%
rename from src/win32/win32-compat.h
rename to src/util/win32/win32-compat.h
diff --git a/src/zstream.c b/src/util/zstream.c
similarity index 100%
rename from src/zstream.c
rename to src/util/zstream.c
diff --git a/src/zstream.h b/src/util/zstream.h
similarity index 98%
rename from src/zstream.h
rename to src/util/zstream.h
index 3f8b1c72f..d78b11291 100644
--- a/src/zstream.h
+++ b/src/util/zstream.h
@@ -7,7 +7,7 @@
#ifndef INCLUDE_zstream_h__
#define INCLUDE_zstream_h__
-#include "common.h"
+#include "git2_util.h"
#include
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f293c158d..df100e980 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,96 +1,6 @@
-set(Python_ADDITIONAL_VERSIONS 3 2.7)
-find_package(PythonInterp)
+# The main libgit2 tests tree: this CMakeLists.txt includes the
+# subprojects that make up core libgit2 support.
-if(NOT PYTHONINTERP_FOUND)
- message(FATAL_ERROR "Could not find a python interpreter, which is needed to build the tests. "
- "Make sure python is available, or pass -DBUILD_TESTS=OFF to skip building the tests")
-ENDIF()
-
-set(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/resources/")
-set(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
-add_definitions(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
-add_definitions(-DCLAR_TMPDIR=\"libgit2_tests\")
-add_definitions(-DCLAR_WIN32_LONGPATHS)
-add_definitions(-D_FILE_OFFSET_BITS=64)
-
-# Ensure that we do not use deprecated functions internally
-add_definitions(-DGIT_DEPRECATE_HARD)
-
-set(TEST_INCLUDES "${CLAR_PATH}" "${CMAKE_CURRENT_BINARY_DIR}")
-file(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h)
-set(SRC_CLAR "main.c" "clar_libgit2.c" "clar_libgit2_trace.c" "clar_libgit2_timer.c" "clar.c")
-
-if(MSVC_IDE)
- list(APPEND SRC_CLAR "precompiled.c")
-endif()
-
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clar.suite ${CMAKE_CURRENT_BINARY_DIR}/clar_suite.h
- COMMAND ${PYTHON_EXECUTABLE} generate.py -o "${CMAKE_CURRENT_BINARY_DIR}" -f -xonline -xstress -xperf .
- DEPENDS ${SRC_TEST}
- WORKING_DIRECTORY ${CLAR_PATH}
-)
-
-set_source_files_properties(
- ${CLAR_PATH}/clar.c
- PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clar.suite)
-
-add_executable(libgit2_tests ${SRC_CLAR} ${SRC_TEST} ${LIBGIT2_OBJECTS})
-
-set_target_properties(libgit2_tests PROPERTIES C_STANDARD 90)
-set_target_properties(libgit2_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
-
-target_include_directories(libgit2_tests PRIVATE ${TEST_INCLUDES} ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
-target_include_directories(libgit2_tests SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
-target_link_libraries(libgit2_tests ${LIBGIT2_SYSTEM_LIBS})
-
-ide_split_sources(libgit2_tests)
-
-#
-# Old versions of gcc require us to declare our test functions; don't do
-# this on newer compilers to avoid unnecessary recompilation.
-#
-if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
- target_compile_options(libgit2_tests PRIVATE -include "clar_suite.h")
-endif()
-
-if(MSVC_IDE)
- # Precompiled headers
- set_target_properties(libgit2_tests PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
- set_source_files_properties("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
-endif()
-
-function(ADD_CLAR_TEST name)
- if(NOT USE_LEAK_CHECKER STREQUAL "OFF")
- add_test(${name} "${PROJECT_SOURCE_DIR}/script/${USE_LEAK_CHECKER}.sh" "${PROJECT_BINARY_DIR}/libgit2_tests" ${ARGN})
- else()
- add_test(${name} "${PROJECT_BINARY_DIR}/libgit2_tests" ${ARGN})
- endif()
-endfunction(ADD_CLAR_TEST)
-
-add_clar_test(offline -v -xonline)
-add_clar_test(invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
-add_clar_test(online -v -sonline -xonline::customcert)
-add_clar_test(online_customcert -v -sonline::customcert)
-add_clar_test(gitdaemon -v -sonline::push)
-add_clar_test(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh)
-add_clar_test(proxy -v -sonline::clone::proxy)
-add_clar_test(auth_clone -v -sonline::clone::cred)
-add_clar_test(auth_clone_and_push -v -sonline::clone::push -sonline::push)
-
-#
-# Header file validation project: ensure that we do not publish any sloppy
-# definitions in our headers and that a consumer can include
-# even when they have aggressive C90 warnings enabled.
-#
-
-add_executable(headertest headertest.c)
-set_target_properties(headertest PROPERTIES C_STANDARD 90)
-set_target_properties(headertest PROPERTIES C_EXTENSIONS OFF)
-target_include_directories(headertest PRIVATE ${LIBGIT2_INCLUDES})
-
-if (MSVC)
- target_compile_options(headertest PUBLIC /W4 /WX)
-else()
- target_compile_options(headertest PUBLIC -Wall -Wextra -pedantic -Werror)
-endif()
+add_subdirectory(headertest)
+add_subdirectory(libgit2)
+add_subdirectory(util)
diff --git a/tests/README.md b/tests/README.md
index 4369a8f33..460e045e3 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,33 +1,58 @@
-Writing Clar tests for libgit2
-==============================
+# libgit2 tests
-For information on the Clar testing framework and a detailed introduction
-please visit:
+These are the unit and integration tests for the libgit2 projects.
-https://github.com/vmg/clar
+* `benchmarks`
+ These are benchmark tests that excercise the CLI.
+* `clar`
+ This is [clar](https://github.com/clar-test/clar) the common test framework.
+* `headertest`
+ This is a simple project that ensures that our public headers are
+ compatible with extremely strict compilation options.
+* `libgit2`
+ These tests exercise the core git functionality in libgit2 itself.
+* `resources`
+ These are the resources for the tests, including files and git
+ repositories.
+* `util`
+ These are tests of the common utility library.
+## Writing tests for libgit2
-* Write your modules and tests. Use good, meaningful names.
+libgit2 uses the [clar test framework](http://github.com/clar-test/clar), a
+C testing framework.
-* Make sure you actually build the tests by setting:
+The best resources for learning clar are [clar itself](https://github.com/clar-test/clar)
+and the existing tests within libgit2. In general:
- cmake -DBUILD_TESTS=ON build/
+* If you place a `.c` file into a test directory, it is eligible to contain
+test cases.
+* The function name for your test is important; test function names begin
+ with `test_`, followed by the folder path (underscore separated), two
+ underscores as a delimiter, then the test name. For example, a file
+ `merge/analysis.c` may contain a test `uptodate`:
-* Test:
+ ```
+ void test_merge_analysis__uptodate(void)
+ {
+ ...
+ }
+ ```
- ./build/libgit2_tests
+* You can run an individual test by passing `-s` to the test runner. Tests
+ are referred to by their function names; for example, the function
+ `test_merge_analysis__uptodate` is referred to as `merge::analysis::uptodate`.
+ To run only that function you can use the `-s` option on the test runner:
-* Make sure everything is fine.
+ ```
+ libgit2_tests -smerge::analysis::uptodate
+ ```
-* Send your pull request. That's it.
-
-
-Memory leak checks
-------------------
+## Memory leak checking
These are automatically run as part of CI, but if you want to check locally:
-#### Linux
+### Linux
Uses [`valgrind`](http://www.valgrind.org/):
@@ -38,7 +63,7 @@ $ valgrind --leak-check=full --show-reachable=yes --num-callers=50 --suppression
./libgit2_tests
```
-#### macOS
+### macOS
Uses [`leaks`](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/FindingLeaks.html), which requires XCode installed:
@@ -46,3 +71,13 @@ Uses [`leaks`](https://developer.apple.com/library/archive/documentation/Perform
$ MallocStackLogging=1 MallocScribble=1 MallocLogFile=/dev/null CLAR_AT_EXIT="leaks -quiet \$PPID" \
./libgit2_tests
```
+
+### Windows
+
+Build with the `WIN32_LEAKCHECK` option:
+
+```console
+$ cmake -DBUILD_TESTS=ON -DWIN32_LEAKCHECK=ON ..
+$ cmake --build .
+$ ./libgit2_tests
+```
diff --git a/tests/benchmarks/README.md b/tests/benchmarks/README.md
new file mode 100644
index 000000000..f66b27aea
--- /dev/null
+++ b/tests/benchmarks/README.md
@@ -0,0 +1,121 @@
+# libgit2 benchmarks
+
+This folder contains the individual benchmark tests for libgit2,
+meant for understanding the performance characteristics of libgit2,
+comparing your development code to the existing libgit2 code, or
+comparing libgit2 to the git reference implementation.
+
+## Running benchmark tests
+
+Benchmark tests can be run in several different ways: running all
+benchmarks, running one (or more) suite of benchmarks, or running a
+single individual benchmark. You can target either an individual
+version of a CLI, or you can A/B test a baseline CLI against a test
+CLI.
+
+### Specifying the command-line interface to test
+
+By default, the `git` in your path is benchmarked. Use the
+`-c` (or `--cli`) option to specify the command-line interface
+to test.
+
+Example: `libgit2_bench --cli git2_cli` will run the tests against
+`git2_cli`.
+
+### Running tests to compare two different implementations
+
+You can compare a baseline command-line interface against a test
+command-line interface using the `-b (or `--baseline-cli`) option.
+
+Example: `libgit2_bench --baseline-cli git --cli git2_cli` will
+run the tests against both `git` and `git2_cli`.
+
+### Running individual benchmark tests
+
+Similar to how a test suite or individual test is specified in
+[clar](https://github.com/clar-test/clar), the `-s` (or `--suite`)
+option may be used to specify the suite or individual test to run.
+Like clar, the suite and test name are separated by `::`, and like
+clar, this is a prefix match.
+
+Examples:
+* `libgit2_bench -shash_object` will run the tests in the
+ `hash_object` suite.
+* `libgit2_bench -shash_object::random_1kb` will run the
+ `hash_object::random_1kb` test.
+* `libgit2_bench -shash_object::random` will run all the tests that
+ begin with `hash_object::random`.
+
+## Writing benchmark tests
+
+Benchmark tests are meant to be easy to write. Each individual
+benchmark is a shell script that allows it to do set up (eg, creating
+or cloning a repository, creating temporary files, etc), then running
+benchmarks, then teardown.
+
+The `benchmark_helpers.sh` script provides many helpful utility
+functions to allow for cross-platform benchmarking, as well as a
+wrapper for `hyperfine` that is suited to testing libgit2.
+Note that the helper script must be included first, at the beginning
+of the benchmark test.
+
+### Benchmark example
+
+This simplistic example compares the speed of running the `git help`
+command in the baseline CLI to the test CLI.
+
+```bash
+#!/bin/bash -e
+
+# include the benchmark library
+. "$(dirname "$0")/benchmark_helpers.sh"
+
+# run the "help" command; this will benchmark `git2_cli help`
+gitbench help
+```
+
+### Naming
+
+The filename of the benchmark itself is important. A benchmark's
+filename should be the name of the benchmark suite, followed by two
+underscores, followed by the name of the benchmark. For example,
+`hash-object__random_1kb` is the `random_1kb` test in the `hash-object`
+suite.
+
+### Options
+
+The `gitbench` function accepts several options.
+
+* `--sandbox `
+ The name of a test resource (in the `tests/resources` directory).
+ This will be copied as-is to the sandbox location before test
+ execution. This is copied _before_ the `prepare` script is run.
+ This option may be specified multiple times.
+* `--repository `
+ The name of a test resource repository (in the `tests/resources`
+ directory). This repository will be copied into a sandbox location
+ before test execution, and your test will run in this directory.
+ This is copied _before_ the `prepare` script is run.
+* `--prepare