diff --git a/.github/release.yml b/.github/release.yml
index 4d4e31860c2..ac05fc6de70 100644
--- a/.github/release.yml
+++ b/.github/release.yml
@@ -15,6 +15,9 @@ changelog:
- title: Code cleanups
labels:
- cleanup
+ - title: Benchmarks
+ labels:
+ - benchmarks
- title: Build and CI improvements
labels:
- build
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
index 6ee492ac443..3fb912d40d0 100644
--- a/.github/workflows/benchmark.yml
+++ b/.github/workflows/benchmark.yml
@@ -3,6 +3,12 @@ name: Benchmark
on:
workflow_dispatch:
+ inputs:
+ suite:
+ description: Benchmark suite to run
+ debug:
+ type: boolean
+ description: Debugging output
schedule:
- cron: '15 4 * * *'
@@ -23,31 +29,31 @@ jobs:
matrix:
platform:
- name: "Linux (clang, OpenSSL)"
+ id: linux
+ os: ubuntu-latest
+ setup-script: ubuntu
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-12
+ id: macos
+ os: macos-latest
+ setup-script: osx
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
+ id: windows
+ os: windows-2022
+ setup-script: win32
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
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: "Benchmark ${{ matrix.platform.name }}"
env: ${{ matrix.platform.env }}
@@ -62,6 +68,11 @@ jobs:
run: source/ci/setup-${{ matrix.platform.setup-script }}-benchmark.sh
shell: bash
if: matrix.platform.setup-script != ''
+ - name: Clone resource repositories
+ run: |
+ mkdir resources
+ git clone --bare https://github.com/git/git resources/git
+ git clone --bare https://github.com/torvalds/linux resources/linux
- name: Build
run: |
mkdir build && cd build
@@ -69,14 +80,30 @@ jobs:
shell: bash
- name: Benchmark
run: |
+ export BENCHMARK_GIT_REPOSITORY="$(pwd)/resources/git"
+ # avoid linux temporarily; the linux blame benchmarks are simply
+ # too slow to use
+ # export BENCHMARK_LINUX_REPOSITORY="$(pwd)/resources/linux"
+
if [[ "$(uname -s)" == MINGW* ]]; then
GIT2_CLI="$(cygpath -w $(pwd))\\build\\Release\\git2"
else
GIT2_CLI="$(pwd)/build/git2"
fi
+ if [ "${{ github.event.inputs.suite }}" != "" ]; then
+ SUITE_FLAG="--suite ${{ github.event.inputs.suite }}"
+ fi
+
+ if [ "${{ github.event.inputs.debug }}" = "true" ]; then
+ DEBUG_FLAG="--debug"
+ fi
+
mkdir benchmark && cd benchmark
- ../source/tests/benchmarks/benchmark.sh --baseline-cli "git" --cli "${GIT2_CLI}" --name libgit2 --json benchmarks.json --zip benchmarks.zip
+ ../source/tests/benchmarks/benchmark.sh \
+ ${SUITE_FLAG} ${DEBUG_FLAG} \
+ --baseline-cli "git" --cli "${GIT2_CLI}" --name libgit2 \
+ --json benchmarks.json --zip benchmarks.zip
shell: bash
- name: Upload results
uses: actions/upload-artifact@v4
@@ -89,7 +116,7 @@ jobs:
publish:
name: Publish results
needs: [ build ]
- if: ${{ always() && github.repository == 'libgit2/libgit2' }}
+ if: always() && github.repository == 'libgit2/libgit2' && github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- name: Check out benchmark repository
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
new file mode 100644
index 00000000000..d82887d2741
--- /dev/null
+++ b/.github/workflows/documentation.yml
@@ -0,0 +1,76 @@
+# Update the www.libgit2.org reference documentation
+name: Generate Documentation
+
+on:
+ push:
+ branches: [ main ]
+ release:
+ workflow_dispatch:
+ inputs:
+ force:
+ description: 'Force rebuild'
+ type: boolean
+ required: true
+
+concurrency:
+ group: documentation
+
+permissions:
+ contents: read
+
+jobs:
+ documentation:
+ name: "Generate documentation"
+ runs-on: "ubuntu-latest"
+ steps:
+ - name: Check out source repository
+ uses: actions/checkout@v4
+ with:
+ path: source
+ fetch-depth: 0
+ - name: Check out documentation repository
+ uses: actions/checkout@v4
+ with:
+ repository: libgit2/www.libgit2.org
+ path: www
+ fetch-depth: 0
+ ssh-key: ${{ secrets.DOCS_PUBLISH_KEY }}
+ - name: Prepare branches
+ run: |
+ for a in main $(git branch -r --list 'origin/maint/*' | sed -e "s/^ origin\///"); do
+ if [ "$(git rev-parse --abbrev-ref HEAD)" != "${a}" ]; then
+ git branch --track "$a" "origin/$a"
+ fi
+ done
+ working-directory: source
+ - name: Generate documentation
+ run: |
+ args=""
+
+ if [ "${{ inputs.force }}" = "true" ]; then
+ args="--force"
+ fi
+
+ npm install
+ ./generate --verbose $args ../.. ../../../www/docs
+ working-directory: source/script/api-docs
+ - name: Examine changes
+ run: |
+ if [ -n "$(git diff --name-only)" ]; then
+ echo "changes=true" >> $GITHUB_OUTPUT
+ else
+ echo "changes=false" >> $GITHUB_OUTPUT
+ fi
+ id: check
+ working-directory: www
+ - name: Publish documentation
+ run: |
+ DATE=$(date +"%Y-%m-%d")
+
+ git config user.name 'Documentation Site Generator'
+ git config user.email 'libgit2@users.noreply.github.com'
+ git add .
+ git commit -m"Documentation update ${DATE}"
+ git push origin main
+ if: steps.check.outputs.changes == 'true'
+ working-directory: www
diff --git a/.github/workflows/experimental.yml b/.github/workflows/experimental.yml
index 5bfea2c0028..07442bddecb 100644
--- a/.github/workflows/experimental.yml
+++ b/.github/workflows/experimental.yml
@@ -37,7 +37,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DEXPERIMENTAL_SHA256=ON
- name: "macOS (SHA256)"
id: macos-sha256
- os: macos-12
+ os: macos-13
setup-script: osx
env:
CC: clang
@@ -48,13 +48,15 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (SHA256, amd64, Visual Studio)"
id: windows-sha256
- os: windows-2019
+ os: windows-2022
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DEXPERIMENTAL_SHA256=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
+ # TODO: this is a temporary removal
+ SKIP_GITDAEMON_TESTS: true
fail-fast: false
env: ${{ matrix.platform.env }}
runs-on: ${{ matrix.platform.os }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 87e834f10db..3616c743d7e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -42,7 +42,7 @@ jobs:
name: noble
env:
CC: clang
- CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=exec
+ CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=exec -DUSE_HTTP_PARSER=http-parser
CMAKE_GENERATOR: Ninja
- name: "Linux (Xenial, GCC, OpenSSL, OpenSSH)"
id: xenial-gcc-openssl
@@ -64,7 +64,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=libssh2
- name: "macOS"
id: macos
- os: macos-12
+ os: macos-13
setup-script: osx
env:
CC: clang
@@ -75,11 +75,11 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, Visual Studio, Schannel)"
id: windows-amd64-vs
- os: windows-2019
+ os: windows-2022
setup-script: win32
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
BUILD_TEMP: D:\Temp
@@ -87,11 +87,11 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio, WinHTTP)"
id: windows-x86-vs
- os: windows-2019
+ os: windows-2022
setup-script: win32
env:
ARCH: x86
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
BUILD_TEMP: D:\Temp
@@ -99,7 +99,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw, WinHTTP)"
id: windows-amd64-mingw
- os: windows-2019
+ os: windows-2022
setup-script: mingw
env:
ARCH: amd64
@@ -111,7 +111,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw, Schannel)"
id: windows-x86-mingw
- os: windows-2019
+ os: windows-2022
setup-script: mingw
env:
ARCH: x86
@@ -132,7 +132,7 @@ jobs:
env:
CC: clang
CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
- CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
+ CMAKE_OPTIONS: -DCMAKE_C_EXTENSIONS=ON -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
CMAKE_GENERATOR: Ninja
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
@@ -233,6 +233,17 @@ jobs:
name: test-results-${{ matrix.platform.id }}
path: build/results_*.xml
+ documentation:
+ name: Validate documentation
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+ - name: Validate documentation
+ run: |
+ (cd script/api-docs && npm install)
+ script/api-docs/api-generator.js --validate-only --strict --deprecate-hard .
+
test_results:
name: Test results
needs: [ build ]
@@ -240,57 +251,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download test results
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
- name: Generate test summary
uses: test-summary/action@v2
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
- # request or in a forked build. For CI builds in the main repository's
- # main branch, we'll push the gh-pages branch back up so that it is
- # published to our documentation site.
- documentation:
- name: Generate documentation
- if: success() || failure()
- runs-on: ubuntu-latest
- steps:
- - name: Check out repository
- uses: actions/checkout@v4
- with:
- path: source
- fetch-depth: 0
- - name: Set up container
- uses: ./source/.github/actions/download-or-build-container
- with:
- registry: ${{ env.docker-registry }}
- config-path: ${{ env.docker-config-path }}
- container: docurium
- github_token: ${{ secrets.github_token }}
- dockerfile: ${{ matrix.platform.container.dockerfile }}
- - name: Generate documentation
- working-directory: source
- run: |
- git config user.name 'Documentation Generation'
- git config user.email 'libgit2@users.noreply.github.com'
- git branch gh-pages origin/gh-pages
- docker login https://${{ env.docker-registry }} -u ${{ github.actor }} -p ${{ github.token }}
- docker run \
- --rm \
- -v "$(pwd):/home/libgit2" \
- -w /home/libgit2 \
- ${{ env.docker-registry }}/${{ github.repository }}/docurium:latest \
- cm doc api.docurium
- git checkout gh-pages
- zip --exclude .git/\* --exclude .gitignore --exclude .gitattributes -r api-documentation.zip .
- - uses: actions/upload-artifact@v4
- name: Upload artifact
- with:
- name: api-documentation
- path: source/api-documentation.zip
- - name: Push documentation branch
- working-directory: source
- run: git push origin gh-pages
- if: github.event_name == 'push' && github.repository == 'libgit2/libgit2'
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 28a06189d98..b9392f84063 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -43,7 +43,7 @@ jobs:
name: noble
env:
CC: clang
- CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=exec
+ CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=exec -DUSE_HTTP_PARSER=http-parser
CMAKE_GENERATOR: Ninja
- name: "Linux (Xenial, GCC, OpenSSL, OpenSSH)"
id: xenial-gcc-openssl
@@ -65,7 +65,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=libssh2
- name: "macOS"
id: macos
- os: macos-12
+ os: macos-13
setup-script: osx
env:
CC: clang
@@ -74,13 +74,23 @@ jobs:
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
+ - name: "iOS"
+ id: ios
+ os: macos-13
+ setup-script: ios
+ env:
+ CC: clang
+ CMAKE_OPTIONS: -DBUILD_TESTS=OFF -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON -DCMAKE_TOOLCHAIN_FILE=../ios.toolchain.cmake -DCMAKE_SYSTEM_NAME=iOS -DPLATFORM=OS64
+ CMAKE_GENERATOR: Ninja
+ PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
+ SKIP_TESTS: true # Cannot exec iOS app on macOS
- name: "Windows (amd64, Visual Studio, Schannel)"
id: windows-amd64-vs
- os: windows-2019
+ os: windows-2022
setup-script: win32
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
BUILD_TEMP: D:\Temp
@@ -88,11 +98,11 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio, WinHTTP)"
id: windows-x86-vs
- os: windows-2019
+ os: windows-2022
setup-script: win32
env:
ARCH: x86
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
BUILD_TEMP: D:\Temp
@@ -100,7 +110,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw, WinHTTP)"
id: windows-amd64-mingw
- os: windows-2019
+ os: windows-2022
setup-script: mingw
env:
ARCH: amd64
@@ -112,7 +122,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw, Schannel)"
id: windows-x86-mingw
- os: windows-2019
+ os: windows-2022
setup-script: mingw
env:
ARCH: x86
@@ -131,9 +141,9 @@ jobs:
container:
name: noble
env:
- CC: clang-17
+ CC: clang
CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
- CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
+ CMAKE_OPTIONS: -DCMAKE_C_EXTENSIONS=ON -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
CMAKE_GENERATOR: Ninja
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
@@ -146,7 +156,7 @@ jobs:
container:
name: noble
env:
- CC: clang-17
+ CC: clang
CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
CMAKE_GENERATOR: Ninja
@@ -161,7 +171,7 @@ jobs:
container:
name: noble
env:
- CC: clang-17
+ CC: clang
CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
CMAKE_GENERATOR: Ninja
@@ -314,10 +324,10 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (no mmap)"
id: windows-nommap
- os: windows-2019
+ os: windows-2022
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CFLAGS: -DNO_MMAP
CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON
SKIP_SSH_TESTS: true
@@ -346,7 +356,7 @@ jobs:
os: ubuntu-latest
- name: "macOS (SHA256)"
id: macos-sha256
- os: macos-12
+ os: macos-13
setup-script: osx
env:
CC: clang
@@ -356,13 +366,24 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (SHA256, amd64, Visual Studio)"
id: windows-sha256
- os: windows-2019
+ os: windows-2022
env:
ARCH: amd64
- CMAKE_GENERATOR: Visual Studio 16 2019
+ CMAKE_GENERATOR: Visual Studio 17 2022
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DEXPERIMENTAL_SHA256=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
+ # TODO: this is a temporary removal
+ SKIP_GITDAEMON_TESTS: true
+ - name: "Linux (SHA256, Xenial, Clang, OpenSSL-FIPS)"
+ id: linux-sha256-fips
+ container:
+ name: xenial
+ env:
+ CC: clang
+ CMAKE_GENERATOR: Ninja
+ CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DUSE_SHA1=OpenSSL-FIPS -DUSE_SHA256=OpenSSL-FIPS
+ os: ubuntu-latest
fail-fast: false
env: ${{ matrix.platform.env }}
runs-on: ${{ matrix.platform.os }}
@@ -419,7 +440,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download test results
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
- name: Generate test summary
uses: test-summary/action@v2
with:
@@ -471,7 +492,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: 'cpp'
@@ -479,7 +500,7 @@ jobs:
run: |
mkdir build
cd build
- cmake .. -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
+ cmake .. -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON
cmake --build .
- name: Perform CodeQL Analysis
diff --git a/AUTHORS b/AUTHORS
index 784bab3ee7d..f4e852357e5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -75,4 +75,5 @@ Tim Clem
Tim Harder
Torsten Bögershausen
Trent Mick
+Venus Xeon-Blonde
Vicent Marti
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ca8882a00e..31da49a8856 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@
cmake_minimum_required(VERSION 3.5.1)
-project(libgit2 VERSION "1.8.1" LANGUAGES C)
+project(libgit2 VERSION "1.9.0" LANGUAGES C)
# Add find modules to the path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
@@ -30,14 +30,14 @@ option(USE_THREADS "Use threads for parallel processing when possibl
option(USE_NSEC "Support nanosecond precision file mtimes and ctimes" ON)
# Backend selection
-option(USE_SSH "Enable SSH support. Can be set to a specific backend" 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" 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(USE_SSH "" CACHE STRING "Enables SSH support and optionally selects provider. One of ON, OFF, or a specific provider: libssh2 or exec. (Defaults to OFF.)")
+ set(USE_HTTPS "" CACHE STRING "Enable HTTPS support and optionally selects the provider. One of ON, OFF, or a specific provider: OpenSSL, OpenSSL-FIPS, OpenSSL-Dynamic, mbedTLS, SecureTransport, Schannel, or WinHTTP. (Defaults to ON.)")
+ set(USE_SHA1 "" CACHE STRING "Selects SHA1 provider. One of CollisionDetection, HTTPS, or a specific provider. (Defaults to CollisionDetection.)")
+ set(USE_SHA256 "" CACHE STRING "Selects SHA256 provider. One of Builtin, HTTPS, or a specific provider. (Defaults to HTTPS.)")
+option(USE_GSSAPI "Enable SPNEGO authentication using GSSAPI" OFF)
+ set(USE_HTTP_PARSER "" CACHE STRING "Selects HTTP Parser support: http-parser, llhttp, or builtin. (Defaults to builtin.)")
# set(USE_XDIFF "" CACHE STRING "Specifies the xdiff implementation; either system or builtin.")
- set(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
+ set(REGEX_BACKEND "" CACHE STRING "Selects regex provider. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
option(USE_BUNDLED_ZLIB "Use the bundled version of zlib. Can be set to one of Bundled(ON)/Chromium. The Chromium option requires a x86_64 processor with SSE4.2 and CLMUL" OFF)
# Debugging options
@@ -53,11 +53,18 @@ option(SONAME "Set the (SO)VERSION of the target"
option(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF)
# Compilation options
+# Default to c99 on Android Studio for compatibility; c90 everywhere else
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
+ set(CMAKE_C_STANDARD "99" CACHE STRING "The C standard to compile against")
+else()
+ set(CMAKE_C_STANDARD "90" CACHE STRING "The C standard to compile against")
+endif()
+option(CMAKE_C_EXTENSIONS "Whether compiler extensions are supported" OFF)
option(ENABLE_WERROR "Enable compilation with -Werror" OFF)
if(UNIX)
# NTLM client requires crypto libraries from the system HTTPS stack
- if(NOT USE_HTTPS)
+ if(USE_HTTPS STREQUAL "OFF")
option(USE_NTLMCLIENT "Enable NTLM support on Unix." OFF)
else()
option(USE_NTLMCLIENT "Enable NTLM support on Unix." ON)
@@ -90,6 +97,7 @@ endif()
# Modules
+include(FeatureSummary)
include(CheckLibraryExists)
include(CheckFunctionExists)
include(CheckSymbolExists)
@@ -102,7 +110,6 @@ include(FindStatNsec)
include(Findfutimens)
include(GNUInstallDirs)
include(IdeSplitSources)
-include(FeatureSummary)
include(EnableWarnings)
include(DefaultCFlags)
include(ExperimentalFeatures)
@@ -143,3 +150,9 @@ endif()
feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
+
+# warn for not using sha1dc
+
+foreach(WARNING ${WARNINGS})
+ message(WARNING ${WARNING})
+endforeach()
diff --git a/FUNDING.json b/FUNDING.json
new file mode 100644
index 00000000000..eb2f6310368
--- /dev/null
+++ b/FUNDING.json
@@ -0,0 +1,7 @@
+{
+ "drips": {
+ "ethereum": {
+ "ownedBy": "0x939121dD13f796C69d0Ac4185787285518081f8D"
+ }
+ }
+}
diff --git a/README.md b/README.md
index 77efdd4a688..7e0f157184d 100644
--- a/README.md
+++ b/README.md
@@ -1,35 +1,33 @@
libgit2 - the Git linkable library
==================================
+[](https://www.bestpractices.dev/projects/9609)
| Build Status | |
| ------------ | - |
-| **main** branch CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush) |
-| **v1.8 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.8) |
-| **v1.7 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.7) |
-| **Nightly** builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22Nightly+Build%22) [](https://scan.coverity.com/projects/639) |
+| **main** branch builds | [](https://github.com/libgit2/libgit2/actions/workflows/main.yml?query=event%3Apush+branch%3Amain) [](https://github.com/libgit2/libgit2/actions/workflows/experimental.yml?query=event%3Apush+branch%3Amain) |
+| **v1.9 branch** builds | [](https://github.com/libgit2/libgit2/actions/workflows/main.yml?query=event%3Apush+branch%3Amaint%2Fv1.9) [](https://github.com/libgit2/libgit2/actions/workflows/experimental.yml?query=event%3Apush+branch%3Amaint%2Fv1.9) |
+| **v1.8 branch** builds | [](https://github.com/libgit2/libgit2/actions/workflows/main.yml?query=event%3Apush+branch%3Amaint%2Fv1.8) [](https://github.com/libgit2/libgit2/actions/workflows/experimental.yml?query=event%3Apush+branch%3Amaint%2Fv1.8) |
+| **Nightly** builds | [](https://github.com/libgit2/libgit2/actions/workflows/nightly.yml) [](https://scan.coverity.com/projects/639) |
`libgit2` is a portable, pure C implementation of the Git core methods
provided as a linkable library with a solid API, allowing to build Git
-functionality into your application. Language bindings like
-[Rugged](https://github.com/libgit2/rugged) (Ruby),
-[LibGit2Sharp](https://github.com/libgit2/libgit2sharp) (.NET),
-[pygit2](http://www.pygit2.org/) (Python) and
-[NodeGit](http://nodegit.org) (Node) allow you to build Git tooling
-in your favorite language.
-
-`libgit2` is used to power Git GUI clients like
-[GitKraken](https://gitkraken.com/) and [GitButler](https://gitbutler.com/)
-and on Git hosting providers like [GitHub](https://github.com/),
-[GitLab](https://gitlab.com/) and
-[Azure DevOps](https://azure.com/devops).
-We perform the merge every time you click "merge pull request".
-
-`libgit2` is licensed under a **very permissive license** (GPLv2 with a special
-Linking Exception). This means that you can link against the library with any
-kind of software without making that software fall under the GPL.
-Changes to libgit2 would still be covered under its GPL license.
-Additionally, the example code has been released to the public domain (see the
-[separate license](examples/COPYING) for more information).
+functionality into your application.
+
+`libgit2` is used in a variety of places, from GUI clients to hosting
+providers ("forges") and countless utilities and applications in
+between. Because it's written in C, it can be made available to any
+other programming language through "bindings", so you can use it in
+[Ruby](https://github.com/libgit2/rugged),
+[.NET](https://github.com/libgit2/libgit2sharp),
+[Python](http://www.pygit2.org/),
+[Node.js](http://nodegit.org),
+[Rust](https://github.com/rust-lang/git2-rs), and more.
+
+`libgit2` is licensed under a **very permissive license** (GPLv2 with
+a special Linking Exception). This means that you can link against
+the library with any kind of software without making that software
+fall under the GPL. Changes to libgit2 would still be covered under
+its GPL license.
Table of Contents
=================
@@ -47,7 +45,8 @@ Table of Contents
* [Installation](#installation)
* [Advanced Usage](#advanced-usage)
* [Compiler and linker options](#compiler-and-linker-options)
- * [MacOS X](#macos-x)
+ * [macOS](#macos)
+ * [iOS](#ios)
* [Android](#android)
* [MinGW](#mingw)
* [Language Bindings](#language-bindings)
@@ -92,8 +91,8 @@ Quick Start
**Build**
-1. Create a build directory beneath the libgit2 source directory, and change
- into it: `mkdir build && cd build`
+1. Create a build directory beneath the libgit2 source directory,
+ and change into it: `mkdir build && cd build`
2. Create the cmake build environment: `cmake ..`
3. Build libgit2: `cmake --build .`
@@ -107,22 +106,24 @@ Getting Help
- via IRC: join [#libgit2](https://web.libera.chat/#libgit2) on
[libera](https://libera.chat).
-- via Slack: visit [slack.libgit2.org](http://slack.libgit2.org/) to sign up,
- then join us in `#libgit2`
+- via Slack: visit [slack.libgit2.org](http://slack.libgit2.org/)
+ to sign up, then join us in `#libgit2`
**Getting Help**
If you have questions about the library, please be sure to check out the
[API documentation](https://libgit2.org/libgit2/). If you still have
questions, reach out to us on Slack or post a question on
-[StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) (with the `libgit2` tag).
+[StackOverflow](http://stackoverflow.com/questions/tagged/libgit2)
+(with the `libgit2` tag).
**Reporting Bugs**
-Please open a [GitHub Issue](https://github.com/libgit2/libgit2/issues) and
-include as much information as possible. If possible, provide sample code
-that illustrates the problem you're seeing. If you're seeing a bug only
-on a specific repository, please provide a link to it if possible.
+Please open a [GitHub Issue](https://github.com/libgit2/libgit2/issues)
+and include as much information as possible. If possible, provide
+sample code that illustrates the problem you're seeing. If you're
+seeing a bug only on a specific repository, please provide a link to
+it if possible.
We ask that you not open a GitHub Issue for help, only for bug reports.
@@ -137,10 +138,10 @@ libgit2 provides you with the ability to manage Git repositories in the
programming language of your choice. It's used in production to power many
applications including GitHub.com, Plastic SCM and Azure DevOps.
-It does not aim to replace the git tool or its user-facing commands. Some APIs
-resemble the plumbing commands as those align closely with the concepts of the
-Git system, but most commands a user would type are out of scope for this
-library to implement directly.
+It does not aim to replace the git tool or its user-facing commands. Some
+APIs resemble the plumbing commands as those align closely with the
+concepts of the Git system, but most commands a user would type are out
+of scope for this library to implement directly.
The library provides:
@@ -160,23 +161,31 @@ The library provides:
As libgit2 is purely a consumer of the Git system, we have to
adjust to changes made upstream. This has two major consequences:
-* Some changes may require us to change provided interfaces. While we try to
- implement functions in a generic way so that no future changes are required,
- we cannot promise a completely stable API.
-* As we have to keep up with changes in behavior made upstream, we may lag
- behind in some areas. We usually to document these incompatibilities in our
- issue tracker with the label "git change".
+* Some changes may require us to change provided interfaces. While
+ we try to implement functions in a generic way so that no future
+ changes are required, we cannot promise a completely stable API.
+* As we have to keep up with changes in behavior made upstream, we
+ may lag behind in some areas. We usually to document these
+ incompatibilities in our issue tracker with the label "git change".
Optional dependencies
=====================
-While the library provides git functionality without the need for
-dependencies, it can make use of a few libraries to add to it:
-
-- pthreads (non-Windows) to enable threadsafe access as well as multi-threaded pack generation
-- OpenSSL (non-Windows) to talk over HTTPS and provide the SHA-1 functions
-- LibSSH2 to enable the SSH transport
-- iconv (OSX) to handle the HFS+ path encoding peculiarities
+While the library provides git functionality with very few
+dependencies, some recommended dependencies are used for performance
+or complete functionality.
+
+- Hash generation: Git uses SHA1DC (collision detecting SHA1) for
+ its default hash generation. SHA256 support is experimental, and
+ optimized support is provided by system libraries on macOS and
+ Windows, or by the HTTPS library on Unix systems when available.
+- Threading: is provided by the system libraries on Windows, and
+ pthreads on Unix systems.
+- HTTPS: is provided by the system libraries on macOS and Windows,
+ or by OpenSSL or mbedTLS on other Unix systems.
+- SSH: is provided by [libssh2](https://libssh2.org/) or by invoking
+ [OpenSSH](https://www.openssh.com).
+- Unicode: is provided by the system libraries on Windows and macOS.
Initialization
===============
@@ -211,12 +220,9 @@ Building libgit2 - Using CMake
Building
--------
-`libgit2` builds cleanly on most platforms without any external dependencies.
-Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthreads` to be available;
-they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
-for threading.
-
-The `libgit2` library is built using [CMake]() (version 2.8 or newer) on all platforms.
+`libgit2` builds cleanly on most platforms without any external
+dependencies as a requirement. `libgit2` is built using
+[CMake]() (version 2.8 or newer) on all platforms.
On most systems you can build the library using the following commands
@@ -224,10 +230,90 @@ On most systems you can build the library using the following commands
$ cmake ..
$ cmake --build .
+To include the examples in the build, use `cmake -DBUILD_EXAMPLES=ON ..`
+instead of `cmake ..`. The built executable for the examples can then
+be found in `build/examples`, relative to the toplevel directory.
+
Alternatively you can point the CMake GUI tool to the CMakeLists.txt file and generate platform specific build project or IDE workspace.
If you're not familiar with CMake, [a more detailed explanation](https://preshing.com/20170511/how-to-build-a-cmake-based-project/) may be helpful.
+Advanced Options
+----------------
+
+You can specify a number of options to `cmake` that will change the
+way `libgit2` is built. To use this, specify `-Doption=value` during
+the initial `cmake` configuration. For example, to enable SHA256
+compatibility:
+
+ $ mkdir build && cd build
+ $ cmake -DEXPERIMENTAL_SHA256=ON ..
+ $ cmake --build .
+
+libgit2 options:
+
+* `EXPERIMENTAL_SHA256=ON`: turns on SHA256 compatibility; note that
+ this is an API-incompatible change, hence why it is labeled
+ "experimental"
+
+Build options:
+
+* `BUILD_EXAMPLES=ON`: builds the suite of example code
+* `BUILD_FUZZERS=ON`: builds the fuzzing suite
+* `ENABLE_WERROR=ON`: build with `-Werror` or the equivalent, which turns
+ compiler warnings into errors in the libgit2 codebase (but not its
+ dependencies)
+
+Dependency options:
+
+* `USE_SSH=type`: enables SSH support and optionally selects the provider;
+ `type` can be set to `libssh2` or `exec` (which will execute an external
+ OpenSSH command). `ON` implies `libssh2`; defaults to `OFF`.
+* `USE_HTTPS=type`: enables HTTPS support and optionally selects the
+ provider; `type` can be set to `OpenSSL`, `OpenSSL-Dynamic` (to not
+ link against OpenSSL, but load it dynamically), `SecureTransport`,
+ `Schannel` or `WinHTTP`; the default is `SecureTransport` on macOS,
+ `WinHTTP` on Windows, and whichever of `OpenSSL` or `mbedTLS` is
+ detected on other platforms. Defaults to `ON`.
+* `USE_SHA1=type`: selects the SHA1 mechanism to use; `type` can be set
+ to `CollisionDetection`, `HTTPS` to use the system or HTTPS provider,
+ or one of `OpenSSL`, `OpenSSL-Dynamic`, `OpenSSL-FIPS` (to use FIPS
+ compliant routines in OpenSSL), `CommonCrypto`, or `Schannel`.
+ Defaults to `CollisionDetection`. This option is retained for
+ backward compatibility and should not be changed.
+* `USE_SHA256=type`: selects the SHA256 mechanism to use; `type` can be
+ set to `HTTPS` to use the system or HTTPS driver, `builtin`, or one of
+ `OpenSSL`, `OpenSSL-Dynamic`, `OpenSSL-FIPS` (to use FIPS compliant
+ routines in OpenSSL), `CommonCrypto`, or `Schannel`. Defaults to `HTTPS`.
+* `USE_GSSAPI=`: enables GSSAPI for SPNEGO authentication on
+ Unix. Defaults to `OFF`.
+* `USE_HTTP_PARSER=type`: selects the HTTP Parser; either `http-parser`
+ for an external
+ [`http-parser`](https://github.com/nodejs/http-parser) dependency,
+ `llhttp` for an external [`llhttp`](https://github.com/nodejs/llhttp)
+ dependency, or `builtin`. Defaults to `builtin`.
+* `REGEX_BACKEND=type`: selects the regular expression backend to use;
+ one of `regcomp_l`, `pcre2`, `pcre`, `regcomp`, or `builtin`. The
+ default is to use `regcomp_l` where available, PCRE if found, otherwise,
+ to use the builtin.
+* `USE_BUNDLED_ZLIB=type`: selects the bundled zlib; either `ON` or `OFF`.
+ Defaults to using the system zlib if available, falling back to the
+ bundled zlib.
+
+Locating Dependencies
+---------------------
+
+The `libgit2` project uses `cmake` since it helps with cross-platform
+projects, especially those with many dependencies. If your dependencies
+are in non-standard places, you may want to use the `_ROOT_DIR` options
+to specify their location. For example, to specify an OpenSSL location:
+
+ $ cmake -DOPENSSL_ROOT_DIR=/tmp/openssl-3.3.2 ..
+
+Since these options are general to CMake, their
+[documentation](https://cmake.org/documentation/) may be helpful. If
+you have questions about dependencies, please [contact us](#getting-help).
+
Running Tests
-------------
@@ -243,12 +329,13 @@ Invoking the test suite directly is useful because it allows you to execute
individual tests, or groups of tests using the `-s` flag. For example, to
run the index tests:
- $ ./libgit2_tests -sindex
+ $ ./libgit2_tests -sindex
-To run a single test named `index::racy::diff`, which corresponds to the test
-function [`test_index_racy__diff`](https://github.com/libgit2/libgit2/blob/main/tests/index/racy.c#L23):
+To run a single test named `index::racy::diff`, which corresponds to
+the test function
+[`test_index_racy__diff`](https://github.com/libgit2/libgit2/blob/main/tests/index/racy.c#L23):
- $ ./libgit2_tests -sindex::racy::diff
+ $ ./libgit2_tests -sindex::racy::diff
The test suite will print a `.` for every passing test, and an `F` for any
failing test. An `S` indicates that a test was skipped because it is not
@@ -257,7 +344,8 @@ applicable to your platform or is particularly expensive.
**Note:** There should be _no_ failing tests when you build an unmodified
source tree from a [release](https://github.com/libgit2/libgit2/releases),
or from the [main branch](https://github.com/libgit2/libgit2/tree/main).
-Please contact us or [open an issue](https://github.com/libgit2/libgit2/issues)
+Please contact us or
+[open an issue](https://github.com/libgit2/libgit2/issues)
if you see test failures.
Installation
@@ -271,7 +359,8 @@ To install the library you can specify the install prefix by setting:
Advanced Usage
--------------
-For more advanced use or questions about CMake please read .
+For more advanced use or questions about CMake please read the
+[CMake FAQ](https://cmake.org/Wiki/CMake_FAQ).
The following CMake variables are declared:
@@ -286,31 +375,71 @@ To list all build options and their current value, you can do the
following:
# Create and set up a build directory
- $ mkdir build
+ $ mkdir build && cd build
$ cmake ..
+
# List all build options and their values
$ cmake -L
Compiler and linker options
---------------------------
-CMake lets you specify a few variables to control the behavior of the
-compiler and linker. These flags are rarely used but can be useful for
-64-bit to 32-bit cross-compilation.
+There are several options that control the behavior of the compiler and
+linker. These flags may be useful for cross-compilation or specialized
+setups.
- `CMAKE_C_FLAGS`: Set your own compiler flags
+- `CMAKE_C_STANDARD`: the C standard to compile against; defaults to `C90`
+- `CMAKE_C_EXTENSIONS`: whether compiler extensions are supported; defaults to `OFF`
- `CMAKE_FIND_ROOT_PATH`: Override the search path for libraries
- `ZLIB_LIBRARY`, `OPENSSL_SSL_LIBRARY` AND `OPENSSL_CRYPTO_LIBRARY`:
Tell CMake where to find those specific libraries
- `LINK_WITH_STATIC_LIBRARIES`: Link only with static versions of
system libraries
-MacOS X
+macOS
-------
-If you want to build a universal binary for Mac OS X, CMake sets it
-all up for you if you use `-DCMAKE_OSX_ARCHITECTURES="i386;x86_64"`
-when configuring.
+If you'd like to work with Xcode, you can generate an Xcode project with "-G Xcode".
+
+ # Create and set up a build directory
+ $ mkdir build && cd build
+ $ cmake -G Xcode ..
+
+> [!TIP]
+> Universal binary support:
+>
+> If you want to build a universal binary for macOS 11.0+, CMake sets it
+> all up for you if you use `-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"`
+> when configuring.
+>
+> [Deprecated] If you want to build a universal binary for Mac OS X
+> (10.4.4 ~ 10.6), CMake sets it all up for you if you use
+> `-DCMAKE_OSX_ARCHITECTURES="i386;x86_64"` when configuring.
+
+iOS
+-------
+
+1. Get an iOS cmake toolchain File:
+
+You can use a pre-existing toolchain file like [ios-cmake](https://github.com/leetal/ios-cmake) or write your own.
+
+2. Specify the toolchain and system Name:
+
+- The CMAKE_TOOLCHAIN_FILE variable points to the toolchain file for iOS.
+- The CMAKE_SYSTEM_NAME should be set to iOS.
+
+3. Example Command:
+
+Assuming you're using the ios-cmake toolchain, the command might look like this:
+
+```
+cmake -G Xcode -DCMAKE_TOOLCHAIN_FILE=path/to/ios.toolchain.cmake -DCMAKE_SYSTEM_NAME=iOS -DPLATFORM=OS64 ..
+```
+
+4. Build the Project:
+
+After generating the project, open the .xcodeproj file in Xcode, select your iOS device or simulator as the target, and build your project.
Android
-------
@@ -337,16 +466,19 @@ when configuring.
MinGW
-----
-If you want to build the library in MinGW environment with SSH support enabled,
-you may need to pass `-DCMAKE_LIBRARY_PATH="${MINGW_PREFIX}/${MINGW_CHOST}/lib/"` flag
-to CMake when configuring. This is because CMake cannot find the Win32 libraries in
-MinGW folders by default and you might see an error message stating that CMake
-could not resolve `ws2_32` library during configuration.
+If you want to build the library in MinGW environment with SSH support
+enabled, you may need to pass
+`-DCMAKE_LIBRARY_PATH="${MINGW_PREFIX}/${MINGW_CHOST}/lib/"` flag
+to CMake when configuring. This is because CMake cannot find the
+Win32 libraries in MinGW folders by default and you might see an
+error message stating that CMake could not resolve `ws2_32` library
+during configuration.
-Another option would be to install `msys2-w32api-runtime` package before configuring.
-This package installs the Win32 libraries into `/usr/lib` folder which is by default
-recognized as the library path by CMake. Please note though that this package is meant
-for MSYS subsystem which is different from MinGW.
+Another option would be to install `msys2-w32api-runtime` package before
+configuring. This package installs the Win32 libraries into `/usr/lib`
+folder which is by default recognized as the library path by CMake.
+Please note though that this package is meant for MSYS subsystem which
+is different from MinGW.
Language Bindings
==================================
@@ -426,15 +558,16 @@ and
that are good places to jump in and get started. There's much more detailed
information in our list of [outstanding projects](docs/projects.md).
-Please be sure to check the [contribution guidelines](docs/contributing.md) to
-understand our workflow, and the libgit2 [coding conventions](docs/conventions.md).
+Please be sure to check the [contribution guidelines](docs/contributing.md)
+to understand our workflow, and the libgit2
+[coding conventions](docs/conventions.md).
License
==================================
-`libgit2` is under GPL2 **with linking exception**. This means you can link to
-and use the library from any program, proprietary or open source; paid or
-gratis. However, if you modify libgit2 itself, you must distribute the
-source to your modified version of libgit2.
+`libgit2` is under GPL2 **with linking exception**. This means you can
+link to and use the library from any program, proprietary or open source;
+paid or gratis. However, if you modify libgit2 itself, you must distribute
+the source to your modified version of libgit2.
See the [COPYING file](COPYING) for the full license text.
diff --git a/SECURITY.md b/SECURITY.md
index f98eebf505a..914e660b26d 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,7 +4,7 @@
This project will always provide security fixes for the latest two released
versions. E.g. if the latest version is v0.28.x, then we will provide security
-fixes for both v0.28.x and v0.27.y, but no later versions.
+fixes for both v0.28.x and v0.27.y, but no earlier versions.
## Reporting a Vulnerability
diff --git a/ci/docker/noble b/ci/docker/noble
index 05cd2768fe4..e7330277379 100644
--- a/ci/docker/noble
+++ b/ci/docker/noble
@@ -4,20 +4,22 @@ FROM ${BASE} AS apt
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
bzip2 \
- clang \
+ clang \
+ clang-18 \
cmake \
curl \
gcc \
git \
krb5-user \
- libclang-rt-17-dev \
+ libclang-rt-18-dev \
libcurl4-gnutls-dev \
libgcrypt20-dev \
+ libhttp-parser-dev \
libkrb5-dev \
libpcre3-dev \
libssl-dev \
libz-dev \
- llvm-17 \
+ llvm-18 \
make \
ninja-build \
openjdk-8-jre-headless \
@@ -40,10 +42,10 @@ RUN cd /tmp && \
scripts/config.pl set MBEDTLS_MD4_C 1 && \
mkdir build build-msan && \
cd build && \
- CC=clang-17 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
+ CC=clang-18 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
ninja install && \
cd ../build-msan && \
- CC=clang-17 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 .. && \
+ CC=clang-18 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-mbedtls-2.28.6
@@ -54,24 +56,24 @@ RUN cd /tmp && \
cd libssh2-1.11.0 && \
mkdir build build-msan && \
cd build && \
- CC=clang-17 CFLAGS="-fPIC" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
+ CC=clang-18 CFLAGS="-fPIC" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \
ninja install && \
cd ../build-msan && \
- CC=clang-17 CFLAGS="-fPIC -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" LDFLAGS="-fsanitize=memory" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=mbedTLS -DCMAKE_PREFIX_PATH=/usr/local/msan -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \
+ CC=clang-18 CFLAGS="-fPIC -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" LDFLAGS="-fsanitize=memory" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=mbedTLS -DCMAKE_PREFIX_PATH=/usr/local/msan -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \
ninja install && \
cd .. && \
rm -rf libssh2-1.11.0
FROM libssh2 AS valgrind
RUN cd /tmp && \
- curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2 | \
+ curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.23.0.tar.bz2 | \
tar -xj && \
- cd valgrind-3.22.0 && \
- CC=clang-17 ./configure && \
+ cd valgrind-3.23.0 && \
+ CC=clang-18 ./configure && \
make MAKEFLAGS="-j -l$(grep -c ^processor /proc/cpuinfo)" && \
make install && \
cd .. && \
- rm -rf valgrind-3.22.0
+ rm -rf valgrind-3.23.0
FROM valgrind AS adduser
ARG UID=""
diff --git a/ci/docker/xenial b/ci/docker/xenial
index 793df4bda50..c84db419ab9 100644
--- a/ci/docker/xenial
+++ b/ci/docker/xenial
@@ -7,13 +7,13 @@ RUN apt-get update && \
clang \
cmake \
curl \
- gettext \
+ gettext \
gcc \
krb5-user \
libcurl4-gnutls-dev \
- libexpat1-dev \
+ libexpat1-dev \
libgcrypt20-dev \
- libintl-perl \
+ libintl-perl \
libkrb5-dev \
libpcre3-dev \
libssl-dev \
diff --git a/ci/setup-ios-build.sh b/ci/setup-ios-build.sh
new file mode 100755
index 00000000000..623b135cf24
--- /dev/null
+++ b/ci/setup-ios-build.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -ex
+
+brew update
+brew install ninja
+
+sudo mkdir /usr/local/lib || true
+sudo chmod 0755 /usr/local/lib
+sudo ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
+
+curl -s -L https://raw.githubusercontent.com/leetal/ios-cmake/master/ios.toolchain.cmake -o ios.toolchain.cmake
diff --git a/ci/setup-osx-build.sh b/ci/setup-osx-build.sh
index 511d886cb17..5598902546d 100755
--- a/ci/setup-osx-build.sh
+++ b/ci/setup-osx-build.sh
@@ -3,6 +3,8 @@
set -ex
brew update
-brew install pkgconfig libssh2 ninja
+brew install ninja
-ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
+sudo mkdir /usr/local/lib || true
+sudo chmod 0755 /usr/local/lib
+sudo ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
diff --git a/cmake/FindHTTPParser.cmake b/cmake/FindHTTP_Parser.cmake
similarity index 100%
rename from cmake/FindHTTPParser.cmake
rename to cmake/FindHTTP_Parser.cmake
diff --git a/cmake/FindIntlIconv.cmake b/cmake/FindIntlIconv.cmake
index 9e6ded99dc4..07959ca1a19 100644
--- a/cmake/FindIntlIconv.cmake
+++ b/cmake/FindIntlIconv.cmake
@@ -15,6 +15,12 @@ find_path(ICONV_INCLUDE_DIR iconv.h)
check_function_exists(iconv_open libc_has_iconv)
find_library(iconv_lib NAMES iconv libiconv libiconv-2 c)
+# workaround the iOS issue where iconv is provided by libc
+# We set it to false to force it add -liconv to the linker flags
+if(CMAKE_SYSTEM_NAME MATCHES "iOS")
+ set(libc_has_iconv FALSE)
+endif()
+
if(ICONV_INCLUDE_DIR AND libc_has_iconv)
set(ICONV_FOUND TRUE)
set(ICONV_LIBRARIES "")
diff --git a/cmake/SelectGSSAPI.cmake b/cmake/SelectGSSAPI.cmake
index 5bde11697df..829850a4de9 100644
--- a/cmake/SelectGSSAPI.cmake
+++ b/cmake/SelectGSSAPI.cmake
@@ -2,7 +2,7 @@ include(SanitizeBool)
# We try to find any packages our backends might use
find_package(GSSAPI)
-if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin" OR CMAKE_SYSTEM_NAME MATCHES "iOS")
include(FindGSSFramework)
endif()
diff --git a/cmake/SelectHTTPParser.cmake b/cmake/SelectHTTPParser.cmake
index 4fc1f6968e6..e547e2d0166 100644
--- a/cmake/SelectHTTPParser.cmake
+++ b/cmake/SelectHTTPParser.cmake
@@ -1,6 +1,6 @@
# Optional external dependency: http-parser
-if(USE_HTTP_PARSER STREQUAL "http-parser")
- find_package(HTTPParser)
+if(USE_HTTP_PARSER STREQUAL "http-parser" OR USE_HTTP_PARSER STREQUAL "system")
+ find_package(HTTP_Parser)
if(HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
list(APPEND LIBGIT2_SYSTEM_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS})
@@ -23,10 +23,12 @@ elseif(USE_HTTP_PARSER STREQUAL "llhttp")
else()
message(FATAL_ERROR "llhttp support was requested but not found")
endif()
-else()
+elseif(USE_HTTP_PARSER STREQUAL "" OR USE_HTTP_PARSER STREQUAL "builtin")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/llhttp" "${PROJECT_BINARY_DIR}/deps/llhttp")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/llhttp")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$")
set(GIT_HTTPPARSER_BUILTIN 1)
add_feature_info(http-parser ON "using bundled parser")
+else()
+ message(FATAL_ERROR "unknown http-parser: ${USE_HTTP_PARSER}")
endif()
diff --git a/cmake/SelectHTTPSBackend.cmake b/cmake/SelectHTTPSBackend.cmake
index d293001f567..0316b3a1c1a 100644
--- a/cmake/SelectHTTPSBackend.cmake
+++ b/cmake/SelectHTTPSBackend.cmake
@@ -3,14 +3,19 @@ include(SanitizeBool)
# We try to find any packages our backends might use
find_package(OpenSSL)
find_package(mbedTLS)
-if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin" OR CMAKE_SYSTEM_NAME MATCHES "iOS")
find_package(Security)
find_package(CoreFoundation)
endif()
+if(USE_HTTPS STREQUAL "")
+ set(USE_HTTPS ON)
+endif()
+
+sanitizebool(USE_HTTPS)
+
if(USE_HTTPS)
# Auto-select TLS backend
- sanitizebool(USE_HTTPS)
if(USE_HTTPS STREQUAL ON)
if(SECURITY_FOUND)
if(SECURITY_HAS_SSLCREATECONTEXT)
@@ -136,12 +141,12 @@ if(USE_HTTPS)
set(GIT_OPENSSL_DYNAMIC 1)
list(APPEND LIBGIT2_SYSTEM_LIBS dl)
else()
- message(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found")
+ message(FATAL_ERROR "unknown HTTPS backend: ${USE_HTTPS}")
endif()
set(GIT_HTTPS 1)
add_feature_info(HTTPS GIT_HTTPS "using ${USE_HTTPS}")
else()
set(GIT_HTTPS 0)
- add_feature_info(HTTPS NO "")
+ add_feature_info(HTTPS NO "HTTPS support is disabled")
endif()
diff --git a/cmake/SelectHashes.cmake b/cmake/SelectHashes.cmake
index 5c007e58749..35fea3ece0b 100644
--- a/cmake/SelectHashes.cmake
+++ b/cmake/SelectHashes.cmake
@@ -2,13 +2,12 @@
include(SanitizeBool)
-# USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF
sanitizebool(USE_SHA1)
sanitizebool(USE_SHA256)
# sha1
-if(USE_SHA1 STREQUAL ON)
+if(USE_SHA1 STREQUAL "" OR USE_SHA1 STREQUAL ON)
SET(USE_SHA1 "CollisionDetection")
elseif(USE_SHA1 STREQUAL "HTTPS")
if(USE_HTTPS STREQUAL "SecureTransport")
@@ -20,7 +19,7 @@ elseif(USE_SHA1 STREQUAL "HTTPS")
elseif(USE_HTTPS)
set(USE_SHA1 ${USE_HTTPS})
else()
- set(USE_SHA1 "CollisionDetection")
+ message(FATAL_ERROR "asked for HTTPS SHA1 backend but HTTPS is not enabled")
endif()
endif()
@@ -28,6 +27,8 @@ if(USE_SHA1 STREQUAL "CollisionDetection")
set(GIT_SHA1_COLLISIONDETECT 1)
elseif(USE_SHA1 STREQUAL "OpenSSL")
set(GIT_SHA1_OPENSSL 1)
+elseif(USE_SHA1 STREQUAL "OpenSSL-FIPS")
+ set(GIT_SHA1_OPENSSL_FIPS 1)
elseif(USE_SHA1 STREQUAL "OpenSSL-Dynamic")
set(GIT_SHA1_OPENSSL 1)
set(GIT_SHA1_OPENSSL_DYNAMIC 1)
@@ -39,15 +40,21 @@ elseif(USE_SHA1 STREQUAL "mbedTLS")
elseif(USE_SHA1 STREQUAL "Win32")
set(GIT_SHA1_WIN32 1)
else()
- message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
+ 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")
+if(USE_SHA256 STREQUAL "" OR USE_SHA256 STREQUAL ON)
+ if(USE_HTTPS)
+ SET(USE_SHA256 "HTTPS")
+ else()
+ SET(USE_SHA256 "builtin")
+ endif()
+endif()
+
+if(USE_SHA256 STREQUAL "Builtin")
+ set(USE_SHA256 "builtin")
endif()
if(USE_SHA256 STREQUAL "HTTPS")
@@ -62,10 +69,12 @@ if(USE_SHA256 STREQUAL "HTTPS")
endif()
endif()
-if(USE_SHA256 STREQUAL "Builtin")
+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-FIPS")
+ set(GIT_SHA256_OPENSSL_FIPS 1)
elseif(USE_SHA256 STREQUAL "OpenSSL-Dynamic")
set(GIT_SHA256_OPENSSL 1)
set(GIT_SHA256_OPENSSL_DYNAMIC 1)
@@ -77,11 +86,12 @@ elseif(USE_SHA256 STREQUAL "mbedTLS")
elseif(USE_SHA256 STREQUAL "Win32")
set(GIT_SHA256_WIN32 1)
else()
- message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
+ 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(USE_SHA1 STREQUAL "OpenSSL" OR USE_SHA256 STREQUAL "OpenSSL" OR
+ USE_SHA1 STREQUAL "OpenSSL-FIPS" OR USE_SHA256 STREQUAL "OpenSSL-FIPS")
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
list(APPEND LIBGIT2_PC_LIBS "-lssl")
else()
@@ -102,3 +112,10 @@ endif()
add_feature_info(SHA1 ON "using ${USE_SHA1}")
add_feature_info(SHA256 ON "using ${USE_SHA256}")
+
+# warn for users who do not use sha1dc
+
+if(NOT "${USE_SHA1}" STREQUAL "CollisionDetection")
+ list(APPEND WARNINGS "SHA1 support is set to ${USE_SHA1} which is not recommended - git's hash algorithm is sha1dc, it is *not* SHA1. Using SHA1 may leave you and your users susceptible to SHAttered-style attacks.")
+ set(WARNINGS ${WARNINGS} PARENT_SCOPE)
+endif()
diff --git a/cmake/SelectRegex.cmake b/cmake/SelectRegex.cmake
index 2a3a91b8cd3..840ec7f349f 100644
--- a/cmake/SelectRegex.cmake
+++ b/cmake/SelectRegex.cmake
@@ -5,7 +5,12 @@ if(REGEX_BACKEND STREQUAL "")
check_symbol_exists(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L)
if(HAVE_REGCOMP_L)
- set(REGEX_BACKEND "regcomp_l")
+ # 'regcomp_l' has been explicitly marked unavailable on iOS_SDK
+ if(CMAKE_SYSTEM_NAME MATCHES "iOS")
+ set(REGEX_BACKEND "regcomp")
+ else()
+ set(REGEX_BACKEND "regcomp_l")
+ endif()
elseif(PCRE_FOUND)
set(REGEX_BACKEND "pcre")
else()
diff --git a/cmake/SelectSSH.cmake b/cmake/SelectSSH.cmake
index 079857f502b..b0d747114da 100644
--- a/cmake/SelectSSH.cmake
+++ b/cmake/SelectSSH.cmake
@@ -39,6 +39,8 @@ elseif(USE_SSH STREQUAL ON OR USE_SSH STREQUAL "libssh2")
set(GIT_SSH 1)
set(GIT_SSH_LIBSSH2 1)
add_feature_info(SSH ON "using libssh2")
-else()
+elseif(USE_SSH STREQUAL OFF OR USE_SSH STREQUAL "")
add_feature_info(SSH OFF "SSH transport support")
+else()
+ message(FATAL_ERROR "unknown SSH option: ${USE_HTTP_PARSER}")
endif()
diff --git a/cmake/SelectZlib.cmake b/cmake/SelectZlib.cmake
index fb4361abc80..25c7b2f94fa 100644
--- a/cmake/SelectZlib.cmake
+++ b/cmake/SelectZlib.cmake
@@ -4,6 +4,7 @@ include(SanitizeBool)
SanitizeBool(USE_BUNDLED_ZLIB)
if(USE_BUNDLED_ZLIB STREQUAL ON)
set(USE_BUNDLED_ZLIB "Bundled")
+ set(GIT_COMPRESSION_BUILTIN)
endif()
if(USE_BUNDLED_ZLIB STREQUAL "OFF")
@@ -17,6 +18,7 @@ if(USE_BUNDLED_ZLIB STREQUAL "OFF")
list(APPEND LIBGIT2_PC_REQUIRES "zlib")
endif()
add_feature_info(zlib ON "using system zlib")
+ set(GIT_COMPRESSION_ZLIB 1)
else()
message(STATUS "zlib was not found; using bundled 3rd-party sources." )
endif()
@@ -26,9 +28,11 @@ if(USE_BUNDLED_ZLIB STREQUAL "Chromium")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/chromium-zlib")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS $)
add_feature_info(zlib ON "using (Chromium) bundled zlib")
+ set(GIT_COMPRESSION_BUILTIN 1)
elseif(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/zlib" "${PROJECT_BINARY_DIR}/deps/zlib")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/zlib")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS $)
add_feature_info(zlib ON "using bundled zlib")
+ set(GIT_COMPRESSION_BUILTIN 1)
endif()
diff --git a/deps/llhttp/api.c b/deps/llhttp/api.c
index 8c2ce3dc5c4..eddb478315a 100644
--- a/deps/llhttp/api.c
+++ b/deps/llhttp/api.c
@@ -93,7 +93,7 @@ void llhttp_free(llhttp_t* parser) {
free(parser);
}
-#endif // defined(__wasm__)
+#endif /* defined(__wasm__) */
/* Some getters required to get stuff from the parser */
diff --git a/deps/ntlmclient/crypt_openssl.c b/deps/ntlmclient/crypt_openssl.c
index c4be129d39e..3bec2725999 100644
--- a/deps/ntlmclient/crypt_openssl.c
+++ b/deps/ntlmclient/crypt_openssl.c
@@ -26,18 +26,18 @@
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC)
-static inline HMAC_CTX *HMAC_CTX_new(void)
+NTLM_INLINE(HMAC_CTX *) HMAC_CTX_new(void)
{
return calloc(1, sizeof(HMAC_CTX));
}
-static inline int HMAC_CTX_reset(HMAC_CTX *ctx)
+NTLM_INLINE(int) HMAC_CTX_reset(HMAC_CTX *ctx)
{
ntlm_memzero(ctx, sizeof(HMAC_CTX));
return 1;
}
-static inline void HMAC_CTX_free(HMAC_CTX *ctx)
+NTLM_INLINE(void) HMAC_CTX_free(HMAC_CTX *ctx)
{
free(ctx);
}
@@ -48,7 +48,7 @@ static inline void HMAC_CTX_free(HMAC_CTX *ctx)
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x03050000fL) || \
defined(CRYPT_OPENSSL_DYNAMIC)
-static inline void HMAC_CTX_cleanup(HMAC_CTX *ctx)
+NTLM_INLINE(void) HMAC_CTX_cleanup(HMAC_CTX *ctx)
{
NTLM_UNUSED(ctx);
}
diff --git a/deps/ntlmclient/ntlm.c b/deps/ntlmclient/ntlm.c
index 6094a4a3484..28dff670e16 100644
--- a/deps/ntlmclient/ntlm.c
+++ b/deps/ntlmclient/ntlm.c
@@ -43,7 +43,7 @@ static bool supports_unicode(ntlm_client *ntlm)
false : true;
}
-static inline bool increment_size(size_t *out, size_t incr)
+NTLM_INLINE(bool) increment_size(size_t *out, size_t incr)
{
if (SIZE_MAX - *out < incr) {
*out = (size_t)-1;
@@ -272,7 +272,7 @@ int ntlm_client_set_timestamp(ntlm_client *ntlm, uint64_t timestamp)
return 0;
}
-static inline bool write_buf(
+NTLM_INLINE(bool) write_buf(
ntlm_client *ntlm,
ntlm_buf *out,
const unsigned char *buf,
@@ -291,7 +291,7 @@ static inline bool write_buf(
return true;
}
-static inline bool write_byte(
+NTLM_INLINE(bool) write_byte(
ntlm_client *ntlm,
ntlm_buf *out,
uint8_t value)
@@ -305,7 +305,7 @@ static inline bool write_byte(
return true;
}
-static inline bool write_int16(
+NTLM_INLINE(bool) write_int16(
ntlm_client *ntlm,
ntlm_buf *out,
uint16_t value)
@@ -320,7 +320,7 @@ static inline bool write_int16(
return true;
}
-static inline bool write_int32(
+NTLM_INLINE(bool) write_int32(
ntlm_client *ntlm,
ntlm_buf *out,
uint32_t value)
@@ -337,7 +337,7 @@ static inline bool write_int32(
return true;
}
-static inline bool write_version(
+NTLM_INLINE(bool) write_version(
ntlm_client *ntlm,
ntlm_buf *out,
ntlm_version *version)
@@ -348,7 +348,7 @@ static inline bool write_version(
write_int32(ntlm, out, version->reserved);
}
-static inline bool write_bufinfo(
+NTLM_INLINE(bool) write_bufinfo(
ntlm_client *ntlm,
ntlm_buf *out,
size_t len,
@@ -369,7 +369,7 @@ static inline bool write_bufinfo(
write_int32(ntlm, out, (uint32_t)offset);
}
-static inline bool read_buf(
+NTLM_INLINE(bool) read_buf(
unsigned char *out,
ntlm_client *ntlm,
ntlm_buf *message,
@@ -386,7 +386,7 @@ static inline bool read_buf(
return true;
}
-static inline bool read_byte(
+NTLM_INLINE(bool) read_byte(
uint8_t *out,
ntlm_client *ntlm,
ntlm_buf *message)
@@ -400,7 +400,7 @@ static inline bool read_byte(
return true;
}
-static inline bool read_int16(
+NTLM_INLINE(bool) read_int16(
uint16_t *out,
ntlm_client *ntlm,
ntlm_buf *message)
@@ -418,7 +418,7 @@ static inline bool read_int16(
return true;
}
-static inline bool read_int32(
+NTLM_INLINE(bool) read_int32(
uint32_t *out,
ntlm_client *ntlm,
ntlm_buf *message)
@@ -438,7 +438,7 @@ static inline bool read_int32(
return true;
}
-static inline bool read_int64(
+NTLM_INLINE(bool) read_int64(
uint64_t *out,
ntlm_client *ntlm,
ntlm_buf *message)
@@ -462,7 +462,7 @@ static inline bool read_int64(
return true;
}
-static inline bool read_version(
+NTLM_INLINE(bool) read_version(
ntlm_version *out,
ntlm_client *ntlm,
ntlm_buf *message)
@@ -473,7 +473,7 @@ static inline bool read_version(
read_int32(&out->reserved, ntlm, message);
}
-static inline bool read_bufinfo(
+NTLM_INLINE(bool) read_bufinfo(
uint16_t *out_len,
uint32_t *out_offset,
ntlm_client *ntlm,
@@ -486,7 +486,7 @@ static inline bool read_bufinfo(
read_int32(out_offset, ntlm, message);
}
-static inline bool read_string_unicode(
+NTLM_INLINE(bool) read_string_unicode(
char **out,
ntlm_client *ntlm,
ntlm_buf *message,
@@ -504,7 +504,7 @@ static inline bool read_string_unicode(
return ret;
}
-static inline bool read_string_ascii(
+NTLM_INLINE(bool) read_string_ascii(
char **out,
ntlm_client *ntlm,
ntlm_buf *message,
@@ -526,7 +526,7 @@ static inline bool read_string_ascii(
return true;
}
-static inline bool read_string(
+NTLM_INLINE(bool) read_string(
char **out,
ntlm_client *ntlm,
ntlm_buf *message,
@@ -539,7 +539,7 @@ static inline bool read_string(
return read_string_ascii(out, ntlm, message, string_len);
}
-static inline bool read_target_info(
+NTLM_INLINE(bool) read_target_info(
char **server_out,
char **domain_out,
char **server_dns_out,
@@ -965,7 +965,7 @@ static void des_key_from_password(
generate_odd_parity(out);
}
-static inline bool generate_lm_hash(
+NTLM_INLINE(bool) generate_lm_hash(
ntlm_des_block out[2],
ntlm_client *ntlm,
const char *password)
diff --git a/deps/ntlmclient/unicode_builtin.c b/deps/ntlmclient/unicode_builtin.c
index 6d398b7c9f8..cb98f70b3db 100644
--- a/deps/ntlmclient/unicode_builtin.c
+++ b/deps/ntlmclient/unicode_builtin.c
@@ -12,6 +12,7 @@
#include "ntlm.h"
#include "unicode.h"
#include "compat.h"
+#include "util.h"
typedef unsigned int UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
@@ -180,7 +181,7 @@ static ConversionResult ConvertUTF16toUTF8 (
* definition of UTF-8 goes up to 4-byte sequences.
*/
-static inline bool isLegalUTF8(const UTF8 *source, int length) {
+NTLM_INLINE(bool) isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
@@ -288,7 +289,7 @@ typedef enum {
unicode_builtin_utf16_to_8
} unicode_builtin_encoding_direction;
-static inline bool unicode_builtin_encoding_convert(
+NTLM_INLINE(bool) unicode_builtin_encoding_convert(
char **converted,
size_t *converted_len,
ntlm_client *ntlm,
diff --git a/deps/ntlmclient/unicode_iconv.c b/deps/ntlmclient/unicode_iconv.c
index e14da21f545..ac53638bf86 100644
--- a/deps/ntlmclient/unicode_iconv.c
+++ b/deps/ntlmclient/unicode_iconv.c
@@ -14,6 +14,7 @@
#include "ntlmclient.h"
#include "unicode.h"
#include "ntlm.h"
+#include "util.h"
#include "compat.h"
typedef enum {
@@ -40,7 +41,7 @@ bool ntlm_unicode_init(ntlm_client *ntlm)
return true;
}
-static inline bool unicode_iconv_encoding_convert(
+NTLM_INLINE(bool) unicode_iconv_encoding_convert(
char **converted,
size_t *converted_len,
ntlm_client *ntlm,
diff --git a/deps/ntlmclient/utf8.h b/deps/ntlmclient/utf8.h
index a26ae85c37e..495e259db30 100644
--- a/deps/ntlmclient/utf8.h
+++ b/deps/ntlmclient/utf8.h
@@ -1,30 +1,30 @@
-// The latest version of this library is available on GitHub;
-// https://github.com/sheredom/utf8.h
-
-// This is free and unencumbered software released into the public domain.
-//
-// Anyone is free to copy, modify, publish, use, compile, sell, or
-// distribute this software, either in source code form or as a compiled
-// binary, for any purpose, commercial or non-commercial, and by any
-// means.
-//
-// In jurisdictions that recognize copyright laws, the author or authors
-// of this software dedicate any and all copyright interest in the
-// software to the public domain. We make this dedication for the benefit
-// of the public at large and to the detriment of our heirs and
-// successors. We intend this dedication to be an overt act of
-// relinquishment in perpetuity of all present and future rights to this
-// software under copyright law.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-//
-// For more information, please refer to
+/* The latest version of this library is available on GitHub;
+ * https://github.com/sheredom/utf8.h */
+
+/* This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to */
#ifndef SHEREDOM_UTF8_H_INCLUDED
#define SHEREDOM_UTF8_H_INCLUDED
@@ -32,10 +32,25 @@
#if defined(_MSC_VER)
#pragma warning(push)
-// disable 'bytes padding added after construct' warning
+/* disable warning: no function prototype given: converting '()' to '(void)' */
+#pragma warning(disable : 4255)
+
+/* disable warning: '__cplusplus' is not defined as a preprocessor macro,
+ * replacing with '0' for '#if/#elif' */
+#pragma warning(disable : 4668)
+
+/* disable warning: bytes padding added after construct */
#pragma warning(disable : 4820)
#endif
+#if defined(__cplusplus)
+#if defined(_MSC_VER)
+#define utf8_cplusplus _MSVC_LANG
+#else
+#define utf8_cplusplus __cplusplus
+#endif
+#endif
+
#include
#include
@@ -43,7 +58,7 @@
#pragma warning(pop)
#endif
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && (_MSC_VER < 1920)
typedef __int32 utf8_int32_t;
#else
#include
@@ -54,411 +69,516 @@ typedef int32_t utf8_int32_t;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wcast-qual"
+
+#if __has_warning("-Wunsafe-buffer-usage")
+#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
+#endif
#endif
-#ifdef __cplusplus
+#ifdef utf8_cplusplus
extern "C" {
#endif
-#if defined(__clang__) || defined(__GNUC__)
-#define utf8_nonnull __attribute__((nonnull))
-#define utf8_pure __attribute__((pure))
-#define utf8_restrict __restrict__
-#define utf8_weak __attribute__((weak))
-#elif defined(_MSC_VER)
+#if defined(__TINYC__)
+#define UTF8_ATTRIBUTE(a) __attribute((a))
+#else
+#define UTF8_ATTRIBUTE(a) __attribute__((a))
+#endif
+
+#if defined(_MSC_VER)
#define utf8_nonnull
#define utf8_pure
#define utf8_restrict __restrict
#define utf8_weak __inline
+#elif defined(__clang__) || defined(__GNUC__)
+#define utf8_nonnull UTF8_ATTRIBUTE(nonnull)
+#define utf8_pure UTF8_ATTRIBUTE(pure)
+#define utf8_restrict __restrict__
+#define utf8_weak UTF8_ATTRIBUTE(weak)
+#elif defined(__TINYC__)
+#define utf8_nonnull UTF8_ATTRIBUTE(nonnull)
+#define utf8_pure UTF8_ATTRIBUTE(pure)
+#define utf8_restrict
+#define utf8_weak UTF8_ATTRIBUTE(weak)
#else
-#error Non clang, non gcc, non MSVC compiler found!
+#error Non clang, non gcc, non MSVC, non tcc compiler found!
#endif
-#ifdef __cplusplus
+#ifdef utf8_cplusplus
#define utf8_null NULL
#else
#define utf8_null 0
#endif
-// Return less than 0, 0, greater than 0 if src1 < src2, src1 == src2, src1 >
-// src2 respectively, case insensitive.
-utf8_nonnull utf8_pure utf8_weak int utf8casecmp(const void *src1,
- const void *src2);
-
-// Append the utf8 string src onto the utf8 string dst.
-utf8_nonnull utf8_weak void *utf8cat(void *utf8_restrict dst,
- const void *utf8_restrict src);
-
-// Find the first match of the utf8 codepoint chr in the utf8 string src.
-utf8_nonnull utf8_pure utf8_weak void *utf8chr(const void *src,
- utf8_int32_t chr);
-
-// Return less than 0, 0, greater than 0 if src1 < src2,
-// src1 == src2, src1 > src2 respectively.
-utf8_nonnull utf8_pure utf8_weak int utf8cmp(const void *src1,
- const void *src2);
-
-// Copy the utf8 string src onto the memory allocated in dst.
-utf8_nonnull utf8_weak void *utf8cpy(void *utf8_restrict dst,
- const void *utf8_restrict src);
-
-// Number of utf8 codepoints in the utf8 string src that consists entirely
-// of utf8 codepoints not from the utf8 string reject.
-utf8_nonnull utf8_pure utf8_weak size_t utf8cspn(const void *src,
- const void *reject);
-
-// Duplicate the utf8 string src by getting its size, malloc'ing a new buffer
-// copying over the data, and returning that. Or 0 if malloc failed.
-utf8_nonnull utf8_weak void *utf8dup(const void *src);
-
-// Number of utf8 codepoints in the utf8 string str,
-// excluding the null terminating byte.
-utf8_nonnull utf8_pure utf8_weak size_t utf8len(const void *str);
-
-// Return less than 0, 0, greater than 0 if src1 < src2, src1 == src2, src1 >
-// src2 respectively, case insensitive. Checking at most n bytes of each utf8
-// string.
-utf8_nonnull utf8_pure utf8_weak int utf8ncasecmp(const void *src1,
- const void *src2, size_t n);
-
-// Append the utf8 string src onto the utf8 string dst,
-// writing at most n+1 bytes. Can produce an invalid utf8
-// string if n falls partway through a utf8 codepoint.
-utf8_nonnull utf8_weak void *utf8ncat(void *utf8_restrict dst,
- const void *utf8_restrict src, size_t n);
-
-// Return less than 0, 0, greater than 0 if src1 < src2,
-// src1 == src2, src1 > src2 respectively. Checking at most n
-// bytes of each utf8 string.
-utf8_nonnull utf8_pure utf8_weak int utf8ncmp(const void *src1,
- const void *src2, size_t n);
-
-// Copy the utf8 string src onto the memory allocated in dst.
-// Copies at most n bytes. If there is no terminating null byte in
-// the first n bytes of src, the string placed into dst will not be
-// null-terminated. If the size (in bytes) of src is less than n,
-// extra null terminating bytes are appended to dst such that at
-// total of n bytes are written. Can produce an invalid utf8
-// string if n falls partway through a utf8 codepoint.
-utf8_nonnull utf8_weak void *utf8ncpy(void *utf8_restrict dst,
- const void *utf8_restrict src, size_t n);
-
-// Similar to utf8dup, except that at most n bytes of src are copied. If src is
-// longer than n, only n bytes are copied and a null byte is added.
-//
-// Returns a new string if successful, 0 otherwise
-utf8_nonnull utf8_weak void *utf8ndup(const void *src, size_t n);
-
-// Locates the first occurence in the utf8 string str of any byte in the
-// utf8 string accept, or 0 if no match was found.
-utf8_nonnull utf8_pure utf8_weak void *utf8pbrk(const void *str,
- const void *accept);
-
-// Find the last match of the utf8 codepoint chr in the utf8 string src.
-utf8_nonnull utf8_pure utf8_weak void *utf8rchr(const void *src, int chr);
-
-// Number of bytes in the utf8 string str,
-// including the null terminating byte.
-utf8_nonnull utf8_pure utf8_weak size_t utf8size(const void *str);
-
-// Number of utf8 codepoints in the utf8 string src that consists entirely
-// of utf8 codepoints from the utf8 string accept.
-utf8_nonnull utf8_pure utf8_weak size_t utf8spn(const void *src,
- const void *accept);
-
-// The position of the utf8 string needle in the utf8 string haystack.
-utf8_nonnull utf8_pure utf8_weak void *utf8str(const void *haystack,
- const void *needle);
-
-// The position of the utf8 string needle in the utf8 string haystack, case
-// insensitive.
-utf8_nonnull utf8_pure utf8_weak void *utf8casestr(const void *haystack,
- const void *needle);
-
-// Return 0 on success, or the position of the invalid
-// utf8 codepoint on failure.
-utf8_nonnull utf8_pure utf8_weak void *utf8valid(const void *str);
-
-// Sets out_codepoint to the next utf8 codepoint in str, and returns the address
-// of the utf8 codepoint after the current one in str.
-utf8_nonnull utf8_weak void *
-utf8codepoint(const void *utf8_restrict str,
- utf8_int32_t *utf8_restrict out_codepoint);
-
-// Returns the size of the given codepoint in bytes.
-utf8_weak size_t utf8codepointsize(utf8_int32_t chr);
-
-// Write a codepoint to the given string, and return the address to the next
-// place after the written codepoint. Pass how many bytes left in the buffer to
-// n. If there is not enough space for the codepoint, this function returns
-// null.
-utf8_nonnull utf8_weak void *utf8catcodepoint(void *utf8_restrict str,
- utf8_int32_t chr, size_t n);
-
-// Returns 1 if the given character is lowercase, or 0 if it is not.
-utf8_weak int utf8islower(utf8_int32_t chr);
-
-// Returns 1 if the given character is uppercase, or 0 if it is not.
-utf8_weak int utf8isupper(utf8_int32_t chr);
-
-// Transform the given string into all lowercase codepoints.
-utf8_nonnull utf8_weak void utf8lwr(void *utf8_restrict str);
+#if defined(utf8_cplusplus) && utf8_cplusplus >= 201402L && (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1910))
+#define utf8_constexpr14 constexpr
+#define utf8_constexpr14_impl constexpr
+#else
+/* constexpr and weak are incompatible. so only enable one of them */
+#define utf8_constexpr14 utf8_weak
+#define utf8_constexpr14_impl
+#endif
-// Transform the given string into all uppercase codepoints.
-utf8_nonnull utf8_weak void utf8upr(void *utf8_restrict str);
+#if defined(utf8_cplusplus) && utf8_cplusplus >= 202002L
+using utf8_int8_t = char8_t; /* Introduced in C++20 */
+#else
+typedef char utf8_int8_t;
+#endif
-// Make a codepoint lower case if possible.
-utf8_weak utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp);
+/* Return less than 0, 0, greater than 0 if src1 < src2, src1 == src2, src1 >
+ * src2 respectively, case insensitive. */
+utf8_constexpr14 utf8_nonnull utf8_pure int
+utf8casecmp(const utf8_int8_t *src1, const utf8_int8_t *src2);
+
+/* Append the utf8 string src onto the utf8 string dst. */
+utf8_nonnull utf8_weak utf8_int8_t *
+utf8cat(utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src);
+
+/* Find the first match of the utf8 codepoint chr in the utf8 string src. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8chr(const utf8_int8_t *src, utf8_int32_t chr);
+
+/* Return less than 0, 0, greater than 0 if src1 < src2,
+ * src1 == src2, src1 > src2 respectively. */
+utf8_constexpr14 utf8_nonnull utf8_pure int utf8cmp(const utf8_int8_t *src1,
+ const utf8_int8_t *src2);
+
+/* Copy the utf8 string src onto the memory allocated in dst. */
+utf8_nonnull utf8_weak utf8_int8_t *
+utf8cpy(utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src);
+
+/* Number of utf8 codepoints in the utf8 string src that consists entirely
+ * of utf8 codepoints not from the utf8 string reject. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t
+utf8cspn(const utf8_int8_t *src, const utf8_int8_t *reject);
+
+/* Duplicate the utf8 string src by getting its size, malloc'ing a new buffer
+ * copying over the data, and returning that. Or 0 if malloc failed. */
+utf8_weak utf8_int8_t *utf8dup(const utf8_int8_t *src);
+
+/* Number of utf8 codepoints in the utf8 string str,
+ * excluding the null terminating byte. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8len(const utf8_int8_t *str);
+
+/* Similar to utf8len, except that only at most n bytes of src are looked. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nlen(const utf8_int8_t *str,
+ size_t n);
+
+/* Return less than 0, 0, greater than 0 if src1 < src2, src1 == src2, src1 >
+ * src2 respectively, case insensitive. Checking at most n bytes of each utf8
+ * string. */
+utf8_constexpr14 utf8_nonnull utf8_pure int
+utf8ncasecmp(const utf8_int8_t *src1, const utf8_int8_t *src2, size_t n);
+
+/* Append the utf8 string src onto the utf8 string dst,
+ * writing at most n+1 bytes. Can produce an invalid utf8
+ * string if n falls partway through a utf8 codepoint. */
+utf8_nonnull utf8_weak utf8_int8_t *
+utf8ncat(utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src,
+ size_t n);
+
+/* Return less than 0, 0, greater than 0 if src1 < src2,
+ * src1 == src2, src1 > src2 respectively. Checking at most n
+ * bytes of each utf8 string. */
+utf8_constexpr14 utf8_nonnull utf8_pure int
+utf8ncmp(const utf8_int8_t *src1, const utf8_int8_t *src2, size_t n);
+
+/* Copy the utf8 string src onto the memory allocated in dst.
+ * Copies at most n bytes. If n falls partway through a utf8
+ * codepoint, or if dst doesn't have enough room for a null
+ * terminator, the final string will be cut short to preserve
+ * utf8 validity. */
+
+utf8_nonnull utf8_weak utf8_int8_t *
+utf8ncpy(utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src,
+ size_t n);
+
+/* Similar to utf8dup, except that at most n bytes of src are copied. If src is
+ * longer than n, only n bytes are copied and a null byte is added.
+ *
+ * Returns a new string if successful, 0 otherwise */
+utf8_weak utf8_int8_t *utf8ndup(const utf8_int8_t *src, size_t n);
+
+/* Locates the first occurrence in the utf8 string str of any byte in the
+ * utf8 string accept, or 0 if no match was found. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8pbrk(const utf8_int8_t *str, const utf8_int8_t *accept);
+
+/* Find the last match of the utf8 codepoint chr in the utf8 string src. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8rchr(const utf8_int8_t *src, int chr);
+
+/* Number of bytes in the utf8 string str,
+ * including the null terminating byte. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size(const utf8_int8_t *str);
+
+/* Similar to utf8size, except that the null terminating byte is excluded. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t
+utf8size_lazy(const utf8_int8_t *str);
+
+/* Similar to utf8size, except that only at most n bytes of src are looked and
+ * the null terminating byte is excluded. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t
+utf8nsize_lazy(const utf8_int8_t *str, size_t n);
+
+/* Number of utf8 codepoints in the utf8 string src that consists entirely
+ * of utf8 codepoints from the utf8 string accept. */
+utf8_constexpr14 utf8_nonnull utf8_pure size_t
+utf8spn(const utf8_int8_t *src, const utf8_int8_t *accept);
+
+/* The position of the utf8 string needle in the utf8 string haystack. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8str(const utf8_int8_t *haystack, const utf8_int8_t *needle);
+
+/* The position of the utf8 string needle in the utf8 string haystack, case
+ * insensitive. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8casestr(const utf8_int8_t *haystack, const utf8_int8_t *needle);
+
+/* Return 0 on success, or the position of the invalid
+ * utf8 codepoint on failure. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8valid(const utf8_int8_t *str);
+
+/* Similar to utf8valid, except that only at most n bytes of src are looked. */
+utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t *
+utf8nvalid(const utf8_int8_t *str, size_t n);
+
+/* Given a null-terminated string, makes the string valid by replacing invalid
+ * codepoints with a 1-byte replacement. Returns 0 on success. */
+utf8_nonnull utf8_weak int utf8makevalid(utf8_int8_t *str,
+ const utf8_int32_t replacement);
+
+/* Sets out_codepoint to the current utf8 codepoint in str, and returns the
+ * address of the next utf8 codepoint after the current one in str. */
+utf8_constexpr14 utf8_nonnull utf8_int8_t *
+utf8codepoint(const utf8_int8_t *utf8_restrict str,
+ utf8_int32_t *utf8_restrict out_codepoint);
-// Make a codepoint upper case if possible.
-utf8_weak utf8_int32_t utf8uprcodepoint(utf8_int32_t cp);
+/* Calculates the size of the next utf8 codepoint in str. */
+utf8_constexpr14 utf8_nonnull size_t
+utf8codepointcalcsize(const utf8_int8_t *str);
+
+/* Returns the size of the given codepoint in bytes. */
+utf8_constexpr14 size_t utf8codepointsize(utf8_int32_t chr);
+
+/* Write a codepoint to the given string, and return the address to the next
+ * place after the written codepoint. Pass how many bytes left in the buffer to
+ * n. If there is not enough space for the codepoint, this function returns
+ * null. */
+utf8_nonnull utf8_weak utf8_int8_t *
+utf8catcodepoint(utf8_int8_t *str, utf8_int32_t chr, size_t n);
+
+/* Returns 1 if the given character is lowercase, or 0 if it is not. */
+utf8_constexpr14 int utf8islower(utf8_int32_t chr);
+
+/* Returns 1 if the given character is uppercase, or 0 if it is not. */
+utf8_constexpr14 int utf8isupper(utf8_int32_t chr);
+
+/* Transform the given string into all lowercase codepoints. */
+utf8_nonnull utf8_weak void utf8lwr(utf8_int8_t *utf8_restrict str);
+
+/* Transform the given string into all uppercase codepoints. */
+utf8_nonnull utf8_weak void utf8upr(utf8_int8_t *utf8_restrict str);
+
+/* Make a codepoint lower case if possible. */
+utf8_constexpr14 utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp);
+
+/* Make a codepoint upper case if possible. */
+utf8_constexpr14 utf8_int32_t utf8uprcodepoint(utf8_int32_t cp);
+
+/* Sets out_codepoint to the current utf8 codepoint in str, and returns the
+ * address of the previous utf8 codepoint before the current one in str. */
+utf8_constexpr14 utf8_nonnull utf8_int8_t *
+utf8rcodepoint(const utf8_int8_t *utf8_restrict str,
+ utf8_int32_t *utf8_restrict out_codepoint);
+
+/* Duplicate the utf8 string src by getting its size, calling alloc_func_ptr to
+ * copy over data to a new buffer, and returning that. Or 0 if alloc_func_ptr
+ * returned null. */
+utf8_weak utf8_int8_t *utf8dup_ex(const utf8_int8_t *src,
+ utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *,
+ size_t),
+ utf8_int8_t *user_data);
+
+/* Similar to utf8dup, except that at most n bytes of src are copied. If src is
+ * longer than n, only n bytes are copied and a null byte is added.
+ *
+ * Returns a new string if successful, 0 otherwise. */
+utf8_weak utf8_int8_t *utf8ndup_ex(const utf8_int8_t *src, size_t n,
+ utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *,
+ size_t),
+ utf8_int8_t *user_data);
#undef utf8_weak
#undef utf8_pure
#undef utf8_nonnull
-int utf8casecmp(const void *src1, const void *src2) {
- utf8_int32_t src1_cp, src2_cp, src1_orig_cp, src2_orig_cp;
+utf8_constexpr14_impl int utf8casecmp(const utf8_int8_t *src1,
+ const utf8_int8_t *src2) {
+ utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0,
+ src2_upr_cp = 0, src1_orig_cp = 0, src2_orig_cp = 0;
for (;;) {
- src1 = utf8codepoint(src1, &src1_cp);
- src2 = utf8codepoint(src2, &src2_cp);
+ src1 = utf8codepoint(src1, &src1_orig_cp);
+ src2 = utf8codepoint(src2, &src2_orig_cp);
- // Take a copy of src1 & src2
- src1_orig_cp = src1_cp;
- src2_orig_cp = src2_cp;
+ /* lower the srcs if required */
+ src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
+ src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
- // Lower the srcs if required
- src1_cp = utf8lwrcodepoint(src1_cp);
- src2_cp = utf8lwrcodepoint(src2_cp);
+ /* lower the srcs if required */
+ src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
+ src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
- // Check if the lowered codepoints match
+ /* check if the lowered codepoints match */
if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
return 0;
- } else if (src1_cp == src2_cp) {
+ } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
continue;
}
- // If they don't match, then we return which of the original's are less
- if (src1_orig_cp < src2_orig_cp) {
- return -1;
- } else if (src1_orig_cp > src2_orig_cp) {
- return 1;
- }
+ /* if they don't match, then we return the difference between the characters
+ */
+ return src1_lwr_cp - src2_lwr_cp;
}
}
-void *utf8cat(void *utf8_restrict dst, const void *utf8_restrict src) {
- char *d = (char *)dst;
- const char *s = (const char *)src;
-
- // find the null terminating byte in dst
+utf8_int8_t *utf8cat(utf8_int8_t *utf8_restrict dst,
+ const utf8_int8_t *utf8_restrict src) {
+ utf8_int8_t *d = dst;
+ /* find the null terminating byte in dst */
while ('\0' != *d) {
d++;
}
- // overwriting the null terminating byte in dst, append src byte-by-byte
- while ('\0' != *s) {
- *d++ = *s++;
+ /* overwriting the null terminating byte in dst, append src byte-by-byte */
+ while ('\0' != *src) {
+ *d++ = *src++;
}
- // write out a new null terminating byte into dst
+ /* write out a new null terminating byte into dst */
*d = '\0';
return dst;
}
-void *utf8chr(const void *src, utf8_int32_t chr) {
- char c[5] = {'\0', '\0', '\0', '\0', '\0'};
+utf8_constexpr14_impl utf8_int8_t *utf8chr(const utf8_int8_t *src,
+ utf8_int32_t chr) {
+ utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
if (0 == chr) {
- // being asked to return position of null terminating byte, so
- // just run s to the end, and return!
- const char *s = (const char *)src;
- while ('\0' != *s) {
- s++;
+ /* being asked to return position of null terminating byte, so
+ * just run s to the end, and return! */
+ while ('\0' != *src) {
+ src++;
}
- return (void *)s;
+ return (utf8_int8_t *)src;
} else if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
- // 1-byte/7-bit ascii
- // (0b0xxxxxxx)
- c[0] = (char)chr;
+ /* 1-byte/7-bit ascii
+ * (0b0xxxxxxx) */
+ c[0] = (utf8_int8_t)chr;
} else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
- // 2-byte/11-bit utf8 code point
- // (0b110xxxxx 0b10xxxxxx)
- c[0] = 0xc0 | (char)(chr >> 6);
- c[1] = 0x80 | (char)(chr & 0x3f);
+ /* 2-byte/11-bit utf8 code point
+ * (0b110xxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
} else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
- // 3-byte/16-bit utf8 code point
- // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
- c[0] = 0xe0 | (char)(chr >> 12);
- c[1] = 0x80 | (char)((chr >> 6) & 0x3f);
- c[2] = 0x80 | (char)(chr & 0x3f);
- } else { // if (0 == ((int)0xffe00000 & chr)) {
- // 4-byte/21-bit utf8 code point
- // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
- c[0] = 0xf0 | (char)(chr >> 18);
- c[1] = 0x80 | (char)((chr >> 12) & 0x3f);
- c[2] = 0x80 | (char)((chr >> 6) & 0x3f);
- c[3] = 0x80 | (char)(chr & 0x3f);
+ /* 3-byte/16-bit utf8 code point
+ * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
+ } else { /* if (0 == ((int)0xffe00000 & chr)) { */
+ /* 4-byte/21-bit utf8 code point
+ * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
+ c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
}
- // we've made c into a 2 utf8 codepoint string, one for the chr we are
- // seeking, another for the null terminating byte. Now use utf8str to
- // search
+ /* we've made c into a 2 utf8 codepoint string, one for the chr we are
+ * seeking, another for the null terminating byte. Now use utf8str to
+ * search */
return utf8str(src, c);
}
-int utf8cmp(const void *src1, const void *src2) {
- const unsigned char *s1 = (const unsigned char *)src1;
- const unsigned char *s2 = (const unsigned char *)src2;
-
- while (('\0' != *s1) || ('\0' != *s2)) {
- if (*s1 < *s2) {
+utf8_constexpr14_impl int utf8cmp(const utf8_int8_t *src1,
+ const utf8_int8_t *src2) {
+ while (('\0' != *src1) || ('\0' != *src2)) {
+ if (*src1 < *src2) {
return -1;
- } else if (*s1 > *s2) {
+ } else if (*src1 > *src2) {
return 1;
}
- s1++;
- s2++;
+ src1++;
+ src2++;
}
- // both utf8 strings matched
+ /* both utf8 strings matched */
return 0;
}
-int utf8coll(const void *src1, const void *src2);
+utf8_constexpr14_impl int utf8coll(const utf8_int8_t *src1,
+ const utf8_int8_t *src2);
-void *utf8cpy(void *utf8_restrict dst, const void *utf8_restrict src) {
- char *d = (char *)dst;
- const char *s = (const char *)src;
+utf8_int8_t *utf8cpy(utf8_int8_t *utf8_restrict dst,
+ const utf8_int8_t *utf8_restrict src) {
+ utf8_int8_t *d = dst;
- // overwriting anything previously in dst, write byte-by-byte
- // from src
- while ('\0' != *s) {
- *d++ = *s++;
+ /* overwriting anything previously in dst, write byte-by-byte
+ * from src */
+ while ('\0' != *src) {
+ *d++ = *src++;
}
- // append null terminating byte
+ /* append null terminating byte */
*d = '\0';
return dst;
}
-size_t utf8cspn(const void *src, const void *reject) {
- const char *s = (const char *)src;
+utf8_constexpr14_impl size_t utf8cspn(const utf8_int8_t *src,
+ const utf8_int8_t *reject) {
size_t chars = 0;
- while ('\0' != *s) {
- const char *r = (const char *)reject;
+ while ('\0' != *src) {
+ const utf8_int8_t *r = reject;
size_t offset = 0;
while ('\0' != *r) {
- // checking that if *r is the start of a utf8 codepoint
- // (it is not 0b10xxxxxx) and we have successfully matched
- // a previous character (0 < offset) - we found a match
+ /* checking that if *r is the start of a utf8 codepoint
+ * (it is not 0b10xxxxxx) and we have successfully matched
+ * a previous character (0 < offset) - we found a match */
if ((0x80 != (0xc0 & *r)) && (0 < offset)) {
return chars;
} else {
- if (*r == s[offset]) {
- // part of a utf8 codepoint matched, so move our checking
- // onwards to the next byte
+ if (*r == src[offset]) {
+ /* part of a utf8 codepoint matched, so move our checking
+ * onwards to the next byte */
offset++;
r++;
} else {
- // r could be in the middle of an unmatching utf8 code point,
- // so we need to march it on to the next character beginning,
+ /* r could be in the middle of an unmatching utf8 code point,
+ * so we need to march it on to the next character beginning, */
do {
r++;
} while (0x80 == (0xc0 & *r));
- // reset offset too as we found a mismatch
+ /* reset offset too as we found a mismatch */
offset = 0;
}
}
}
- // the current utf8 codepoint in src did not match reject, but src
- // could have been partway through a utf8 codepoint, so we need to
- // march it onto the next utf8 codepoint starting byte
+ /* found a match at the end of *r, so didn't get a chance to test it */
+ if (0 < offset) {
+ return chars;
+ }
+
+ /* the current utf8 codepoint in src did not match reject, but src
+ * could have been partway through a utf8 codepoint, so we need to
+ * march it onto the next utf8 codepoint starting byte */
do {
- s++;
- } while ((0x80 == (0xc0 & *s)));
+ src++;
+ } while ((0x80 == (0xc0 & *src)));
chars++;
}
return chars;
}
-size_t utf8size(const void *str);
+utf8_int8_t *utf8dup(const utf8_int8_t *src) {
+ return utf8dup_ex(src, utf8_null, utf8_null);
+}
-void *utf8dup(const void *src) {
- const char *s = (const char *)src;
- char *n = utf8_null;
+utf8_int8_t *utf8dup_ex(const utf8_int8_t *src,
+ utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t),
+ utf8_int8_t *user_data) {
+ utf8_int8_t *n = utf8_null;
- // figure out how many bytes (including the terminator) we need to copy first
+ /* figure out how many bytes (including the terminator) we need to copy first
+ */
size_t bytes = utf8size(src);
- n = (char *)malloc(bytes);
+ if (alloc_func_ptr) {
+ n = alloc_func_ptr(user_data, bytes);
+ } else {
+#if !defined(UTF8_NO_STD_MALLOC)
+ n = (utf8_int8_t *)malloc(bytes);
+#else
+ return utf8_null;
+#endif
+ }
if (utf8_null == n) {
- // out of memory so we bail
+ /* out of memory so we bail */
return utf8_null;
} else {
bytes = 0;
- // copy src byte-by-byte into our new utf8 string
- while ('\0' != s[bytes]) {
- n[bytes] = s[bytes];
+ /* copy src byte-by-byte into our new utf8 string */
+ while ('\0' != src[bytes]) {
+ n[bytes] = src[bytes];
bytes++;
}
- // append null terminating byte
+ /* append null terminating byte */
n[bytes] = '\0';
return n;
}
}
-void *utf8fry(const void *str);
+utf8_constexpr14_impl utf8_int8_t *utf8fry(const utf8_int8_t *str);
+
+utf8_constexpr14_impl size_t utf8len(const utf8_int8_t *str) {
+ return utf8nlen(str, SIZE_MAX);
+}
-size_t utf8len(const void *str) {
- const unsigned char *s = (const unsigned char *)str;
+utf8_constexpr14_impl size_t utf8nlen(const utf8_int8_t *str, size_t n) {
+ const utf8_int8_t *t = str;
size_t length = 0;
- while ('\0' != *s) {
- if (0xf0 == (0xf8 & *s)) {
- // 4-byte utf8 code point (began with 0b11110xxx)
- s += 4;
- } else if (0xe0 == (0xf0 & *s)) {
- // 3-byte utf8 code point (began with 0b1110xxxx)
- s += 3;
- } else if (0xc0 == (0xe0 & *s)) {
- // 2-byte utf8 code point (began with 0b110xxxxx)
- s += 2;
- } else { // if (0x00 == (0x80 & *s)) {
- // 1-byte ascii (began with 0b0xxxxxxx)
- s += 1;
+ while ((size_t)(str - t) < n && '\0' != *str) {
+ if (0xf0 == (0xf8 & *str)) {
+ /* 4-byte utf8 code point (began with 0b11110xxx) */
+ str += 4;
+ } else if (0xe0 == (0xf0 & *str)) {
+ /* 3-byte utf8 code point (began with 0b1110xxxx) */
+ str += 3;
+ } else if (0xc0 == (0xe0 & *str)) {
+ /* 2-byte utf8 code point (began with 0b110xxxxx) */
+ str += 2;
+ } else { /* if (0x00 == (0x80 & *s)) { */
+ /* 1-byte ascii (began with 0b0xxxxxxx) */
+ str += 1;
}
- // no matter the bytes we marched s forward by, it was
- // only 1 utf8 codepoint
+ /* no matter the bytes we marched s forward by, it was
+ * only 1 utf8 codepoint */
length++;
}
+ if ((size_t)(str - t) > n) {
+ length--;
+ }
return length;
}
-int utf8ncasecmp(const void *src1, const void *src2, size_t n) {
- utf8_int32_t src1_cp, src2_cp, src1_orig_cp, src2_orig_cp;
+utf8_constexpr14_impl int utf8ncasecmp(const utf8_int8_t *src1,
+ const utf8_int8_t *src2, size_t n) {
+ utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0,
+ src2_upr_cp = 0, src1_orig_cp = 0, src2_orig_cp = 0;
do {
- const unsigned char *const s1 = (const unsigned char *)src1;
- const unsigned char *const s2 = (const unsigned char *)src2;
+ const utf8_int8_t *const s1 = src1;
+ const utf8_int8_t *const s2 = src2;
- // first check that we have enough bytes left in n to contain an entire
- // codepoint
+ /* first check that we have enough bytes left in n to contain an entire
+ * codepoint */
if (0 == n) {
return 0;
}
@@ -467,10 +587,8 @@ int utf8ncasecmp(const void *src1, const void *src2, size_t n) {
const utf8_int32_t c1 = (0xe0 & *s1);
const utf8_int32_t c2 = (0xe0 & *s2);
- if (c1 < c2) {
- return -1;
- } else if (c1 > c2) {
- return 1;
+ if (c1 != c2) {
+ return c1 - c2;
} else {
return 0;
}
@@ -480,10 +598,8 @@ int utf8ncasecmp(const void *src1, const void *src2, size_t n) {
const utf8_int32_t c1 = (0xf0 & *s1);
const utf8_int32_t c2 = (0xf0 & *s2);
- if (c1 < c2) {
- return -1;
- } else if (c1 > c2) {
- return 1;
+ if (c1 != c2) {
+ return c1 - c2;
} else {
return 0;
}
@@ -493,307 +609,343 @@ int utf8ncasecmp(const void *src1, const void *src2, size_t n) {
const utf8_int32_t c1 = (0xf8 & *s1);
const utf8_int32_t c2 = (0xf8 & *s2);
- if (c1 < c2) {
- return -1;
- } else if (c1 > c2) {
- return 1;
+ if (c1 != c2) {
+ return c1 - c2;
} else {
return 0;
}
}
- src1 = utf8codepoint(src1, &src1_cp);
- src2 = utf8codepoint(src2, &src2_cp);
- n -= utf8codepointsize(src1_cp);
+ src1 = utf8codepoint(src1, &src1_orig_cp);
+ src2 = utf8codepoint(src2, &src2_orig_cp);
+ n -= utf8codepointsize(src1_orig_cp);
- // Take a copy of src1 & src2
- src1_orig_cp = src1_cp;
- src2_orig_cp = src2_cp;
+ src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
+ src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
- // Lower srcs if required
- src1_cp = utf8lwrcodepoint(src1_cp);
- src2_cp = utf8lwrcodepoint(src2_cp);
+ src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
+ src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
- // Check if the lowered codepoints match
+ /* check if the lowered codepoints match */
if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
return 0;
- } else if (src1_cp == src2_cp) {
+ } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
continue;
}
- // If they don't match, then we return which of the original's are less
- if (src1_orig_cp < src2_orig_cp) {
- return -1;
- } else if (src1_orig_cp > src2_orig_cp) {
- return 1;
- }
+ /* if they don't match, then we return the difference between the characters
+ */
+ return src1_lwr_cp - src2_lwr_cp;
} while (0 < n);
- // both utf8 strings matched
+ /* both utf8 strings matched */
return 0;
}
-void *utf8ncat(void *utf8_restrict dst, const void *utf8_restrict src,
- size_t n) {
- char *d = (char *)dst;
- const char *s = (const char *)src;
+utf8_int8_t *utf8ncat(utf8_int8_t *utf8_restrict dst,
+ const utf8_int8_t *utf8_restrict src, size_t n) {
+ utf8_int8_t *d = dst;
- // find the null terminating byte in dst
+ /* find the null terminating byte in dst */
while ('\0' != *d) {
d++;
}
- // overwriting the null terminating byte in dst, append src byte-by-byte
- // stopping if we run out of space
- do {
- *d++ = *s++;
- } while (('\0' != *s) && (0 != --n));
+ /* overwriting the null terminating byte in dst, append src byte-by-byte
+ * stopping if we run out of space */
+ while (('\0' != *src) && (0 != n--)) {
+ *d++ = *src++;
+ }
- // write out a new null terminating byte into dst
+ /* write out a new null terminating byte into dst */
*d = '\0';
return dst;
}
-int utf8ncmp(const void *src1, const void *src2, size_t n) {
- const unsigned char *s1 = (const unsigned char *)src1;
- const unsigned char *s2 = (const unsigned char *)src2;
-
- while ((('\0' != *s1) || ('\0' != *s2)) && (0 != n--)) {
- if (*s1 < *s2) {
+utf8_constexpr14_impl int utf8ncmp(const utf8_int8_t *src1,
+ const utf8_int8_t *src2, size_t n) {
+ while ((0 != n--) && (('\0' != *src1) || ('\0' != *src2))) {
+ if (*src1 < *src2) {
return -1;
- } else if (*s1 > *s2) {
+ } else if (*src1 > *src2) {
return 1;
}
- s1++;
- s2++;
+ src1++;
+ src2++;
}
- // both utf8 strings matched
+ /* both utf8 strings matched */
return 0;
}
-void *utf8ncpy(void *utf8_restrict dst, const void *utf8_restrict src,
- size_t n) {
- char *d = (char *)dst;
- const char *s = (const char *)src;
+utf8_int8_t *utf8ncpy(utf8_int8_t *utf8_restrict dst,
+ const utf8_int8_t *utf8_restrict src, size_t n) {
+ utf8_int8_t *d = dst;
+ size_t index = 0, check_index = 0;
- // overwriting anything previously in dst, write byte-by-byte
- // from src
- do {
- *d++ = *s++;
- } while (('\0' != *s) && (0 != --n));
+ if (n == 0) {
+ return dst;
+ }
- // append null terminating byte
- while (0 != n) {
- *d++ = '\0';
- n--;
+ /* overwriting anything previously in dst, write byte-by-byte
+ * from src */
+ for (index = 0; index < n; index++) {
+ d[index] = src[index];
+ if ('\0' == src[index]) {
+ break;
+ }
+ }
+
+ for (check_index = index - 1;
+ check_index > 0 && 0x80 == (0xc0 & d[check_index]); check_index--) {
+ /* just moving the index */
+ }
+
+ if (check_index < index &&
+ ((index - check_index) < utf8codepointcalcsize(&d[check_index]) ||
+ (index - check_index) == n)) {
+ index = check_index;
+ }
+
+ /* append null terminating byte */
+ for (; index < n; index++) {
+ d[index] = 0;
}
return dst;
}
-void *utf8ndup(const void *src, size_t n) {
- const char *s = (const char *)src;
- char *c = utf8_null;
+utf8_int8_t *utf8ndup(const utf8_int8_t *src, size_t n) {
+ return utf8ndup_ex(src, n, utf8_null, utf8_null);
+}
+
+utf8_int8_t *utf8ndup_ex(const utf8_int8_t *src, size_t n,
+ utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t),
+ utf8_int8_t *user_data) {
+ utf8_int8_t *c = utf8_null;
size_t bytes = 0;
- // Find the end of the string or stop when n is reached
- while ('\0' != s[bytes] && bytes < n) {
+ /* Find the end of the string or stop when n is reached */
+ while ('\0' != src[bytes] && bytes < n) {
bytes++;
}
- // In case bytes is actually less than n, we need to set it
- // to be used later in the copy byte by byte.
+ /* In case bytes is actually less than n, we need to set it
+ * to be used later in the copy byte by byte. */
n = bytes;
- c = (char *)malloc(bytes + 1);
+ if (alloc_func_ptr) {
+ c = alloc_func_ptr(user_data, bytes + 1);
+ } else {
+#if !defined(UTF8_NO_STD_MALLOC)
+ c = (utf8_int8_t *)malloc(bytes + 1);
+#else
+ c = utf8_null;
+#endif
+ }
+
if (utf8_null == c) {
- // out of memory so we bail
+ /* out of memory so we bail */
return utf8_null;
}
bytes = 0;
- // copy src byte-by-byte into our new utf8 string
- while ('\0' != s[bytes] && bytes < n) {
- c[bytes] = s[bytes];
+ /* copy src byte-by-byte into our new utf8 string */
+ while ('\0' != src[bytes] && bytes < n) {
+ c[bytes] = src[bytes];
bytes++;
}
- // append null terminating byte
+ /* append null terminating byte */
c[bytes] = '\0';
return c;
}
-void *utf8rchr(const void *src, int chr) {
- const char *s = (const char *)src;
- const char *match = utf8_null;
- char c[5] = {'\0', '\0', '\0', '\0', '\0'};
+utf8_constexpr14_impl utf8_int8_t *utf8rchr(const utf8_int8_t *src, int chr) {
+
+ utf8_int8_t *match = utf8_null;
+ utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
if (0 == chr) {
- // being asked to return position of null terminating byte, so
- // just run s to the end, and return!
- while ('\0' != *s) {
- s++;
+ /* being asked to return position of null terminating byte, so
+ * just run s to the end, and return! */
+ while ('\0' != *src) {
+ src++;
}
- return (void *)s;
+ return (utf8_int8_t *)src;
} else if (0 == ((int)0xffffff80 & chr)) {
- // 1-byte/7-bit ascii
- // (0b0xxxxxxx)
- c[0] = (char)chr;
+ /* 1-byte/7-bit ascii
+ * (0b0xxxxxxx) */
+ c[0] = (utf8_int8_t)chr;
} else if (0 == ((int)0xfffff800 & chr)) {
- // 2-byte/11-bit utf8 code point
- // (0b110xxxxx 0b10xxxxxx)
- c[0] = 0xc0 | (char)(chr >> 6);
- c[1] = 0x80 | (char)(chr & 0x3f);
+ /* 2-byte/11-bit utf8 code point
+ * (0b110xxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
} else if (0 == ((int)0xffff0000 & chr)) {
- // 3-byte/16-bit utf8 code point
- // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
- c[0] = 0xe0 | (char)(chr >> 12);
- c[1] = 0x80 | (char)((chr >> 6) & 0x3f);
- c[2] = 0x80 | (char)(chr & 0x3f);
- } else { // if (0 == ((int)0xffe00000 & chr)) {
- // 4-byte/21-bit utf8 code point
- // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
- c[0] = 0xf0 | (char)(chr >> 18);
- c[1] = 0x80 | (char)((chr >> 12) & 0x3f);
- c[2] = 0x80 | (char)((chr >> 6) & 0x3f);
- c[3] = 0x80 | (char)(chr & 0x3f);
+ /* 3-byte/16-bit utf8 code point
+ * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
+ } else { /* if (0 == ((int)0xffe00000 & chr)) { */
+ /* 4-byte/21-bit utf8 code point
+ * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
+ c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
+ c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
+ c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
}
- // we've created a 2 utf8 codepoint string in c that is
- // the utf8 character asked for by chr, and a null
- // terminating byte
+ /* we've created a 2 utf8 codepoint string in c that is
+ * the utf8 character asked for by chr, and a null
+ * terminating byte */
- while ('\0' != *s) {
+ while ('\0' != *src) {
size_t offset = 0;
- while (s[offset] == c[offset]) {
+ while ((src[offset] == c[offset]) && ('\0' != src[offset])) {
offset++;
}
if ('\0' == c[offset]) {
- // we found a matching utf8 code point
- match = s;
- s += offset;
+ /* we found a matching utf8 code point */
+ match = (utf8_int8_t *)src;
+ src += offset;
+
+ if ('\0' == *src) {
+ break;
+ }
} else {
- s += offset;
+ src += offset;
- // need to march s along to next utf8 codepoint start
- // (the next byte that doesn't match 0b10xxxxxx)
- if ('\0' != *s) {
+ /* need to march s along to next utf8 codepoint start
+ * (the next byte that doesn't match 0b10xxxxxx) */
+ if ('\0' != *src) {
do {
- s++;
- } while (0x80 == (0xc0 & *s));
+ src++;
+ } while (0x80 == (0xc0 & *src));
}
}
}
- // return the last match we found (or 0 if no match was found)
- return (void *)match;
+ /* return the last match we found (or 0 if no match was found) */
+ return match;
}
-void *utf8pbrk(const void *str, const void *accept) {
- const char *s = (const char *)str;
-
- while ('\0' != *s) {
- const char *a = (const char *)accept;
+utf8_constexpr14_impl utf8_int8_t *utf8pbrk(const utf8_int8_t *str,
+ const utf8_int8_t *accept) {
+ while ('\0' != *str) {
+ const utf8_int8_t *a = accept;
size_t offset = 0;
while ('\0' != *a) {
- // checking that if *a is the start of a utf8 codepoint
- // (it is not 0b10xxxxxx) and we have successfully matched
- // a previous character (0 < offset) - we found a match
+ /* checking that if *a is the start of a utf8 codepoint
+ * (it is not 0b10xxxxxx) and we have successfully matched
+ * a previous character (0 < offset) - we found a match */
if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
- return (void *)s;
+ return (utf8_int8_t *)str;
} else {
- if (*a == s[offset]) {
- // part of a utf8 codepoint matched, so move our checking
- // onwards to the next byte
+ if (*a == str[offset]) {
+ /* part of a utf8 codepoint matched, so move our checking
+ * onwards to the next byte */
offset++;
a++;
} else {
- // r could be in the middle of an unmatching utf8 code point,
- // so we need to march it on to the next character beginning,
+ /* r could be in the middle of an unmatching utf8 code point,
+ * so we need to march it on to the next character beginning, */
do {
a++;
} while (0x80 == (0xc0 & *a));
- // reset offset too as we found a mismatch
+ /* reset offset too as we found a mismatch */
offset = 0;
}
}
}
- // we found a match on the last utf8 codepoint
+ /* we found a match on the last utf8 codepoint */
if (0 < offset) {
- return (void *)s;
+ return (utf8_int8_t *)str;
}
- // the current utf8 codepoint in src did not match accept, but src
- // could have been partway through a utf8 codepoint, so we need to
- // march it onto the next utf8 codepoint starting byte
+ /* the current utf8 codepoint in src did not match accept, but src
+ * could have been partway through a utf8 codepoint, so we need to
+ * march it onto the next utf8 codepoint starting byte */
do {
- s++;
- } while ((0x80 == (0xc0 & *s)));
+ str++;
+ } while ((0x80 == (0xc0 & *str)));
}
return utf8_null;
}
-size_t utf8size(const void *str) {
- const char *s = (const char *)str;
+utf8_constexpr14_impl size_t utf8size(const utf8_int8_t *str) {
+ return utf8size_lazy(str) + 1;
+}
+
+utf8_constexpr14_impl size_t utf8size_lazy(const utf8_int8_t *str) {
+ return utf8nsize_lazy(str, SIZE_MAX);
+}
+
+utf8_constexpr14_impl size_t utf8nsize_lazy(const utf8_int8_t *str, size_t n) {
size_t size = 0;
- while ('\0' != s[size]) {
+ while (size < n && '\0' != str[size]) {
size++;
}
-
- // we are including the null terminating byte in the size calculation
- size++;
return size;
}
-size_t utf8spn(const void *src, const void *accept) {
- const char *s = (const char *)src;
+utf8_constexpr14_impl size_t utf8spn(const utf8_int8_t *src,
+ const utf8_int8_t *accept) {
size_t chars = 0;
- while ('\0' != *s) {
- const char *a = (const char *)accept;
+ while ('\0' != *src) {
+ const utf8_int8_t *a = accept;
size_t offset = 0;
while ('\0' != *a) {
- // checking that if *r is the start of a utf8 codepoint
- // (it is not 0b10xxxxxx) and we have successfully matched
- // a previous character (0 < offset) - we found a match
+ /* checking that if *r is the start of a utf8 codepoint
+ * (it is not 0b10xxxxxx) and we have successfully matched
+ * a previous character (0 < offset) - we found a match */
if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
- // found a match, so increment the number of utf8 codepoints
- // that have matched and stop checking whether any other utf8
- // codepoints in a match
+ /* found a match, so increment the number of utf8 codepoints
+ * that have matched and stop checking whether any other utf8
+ * codepoints in a match */
chars++;
- s += offset;
+ src += offset;
+ offset = 0;
break;
} else {
- if (*a == s[offset]) {
+ if (*a == src[offset]) {
offset++;
a++;
} else {
- // a could be in the middle of an unmatching utf8 codepoint,
- // so we need to march it on to the next character beginning,
+ /* a could be in the middle of an unmatching utf8 codepoint,
+ * so we need to march it on to the next character beginning, */
do {
a++;
} while (0x80 == (0xc0 & *a));
- // reset offset too as we found a mismatch
+ /* reset offset too as we found a mismatch */
offset = 0;
}
}
}
- // if a got to its terminating null byte, then we didn't find a match.
- // Return the current number of matched utf8 codepoints
+ /* found a match at the end of *a, so didn't get a chance to test it */
+ if (0 < offset) {
+ chars++;
+ src += offset;
+ continue;
+ }
+
+ /* if a got to its terminating null byte, then we didn't find a match.
+ * Return the current number of matched utf8 codepoints */
if ('\0' == *a) {
return chars;
}
@@ -802,302 +954,405 @@ size_t utf8spn(const void *src, const void *accept) {
return chars;
}
-void *utf8str(const void *haystack, const void *needle) {
- const char *h = (const char *)haystack;
+utf8_constexpr14_impl utf8_int8_t *utf8str(const utf8_int8_t *haystack,
+ const utf8_int8_t *needle) {
+ utf8_int32_t throwaway_codepoint = 0;
- // if needle has no utf8 codepoints before the null terminating
- // byte then return haystack
- if ('\0' == *((const char *)needle)) {
- return (void *)haystack;
+ /* if needle has no utf8 codepoints before the null terminating
+ * byte then return haystack */
+ if ('\0' == *needle) {
+ return (utf8_int8_t *)haystack;
}
- while ('\0' != *h) {
- const char *maybeMatch = h;
- const char *n = (const char *)needle;
+ while ('\0' != *haystack) {
+ const utf8_int8_t *maybeMatch = haystack;
+ const utf8_int8_t *n = needle;
- while (*h == *n && (*h != '\0' && *n != '\0')) {
+ while (*haystack == *n && (*haystack != '\0' && *n != '\0')) {
n++;
- h++;
+ haystack++;
}
if ('\0' == *n) {
- // we found the whole utf8 string for needle in haystack at
- // maybeMatch, so return it
- return (void *)maybeMatch;
+ /* we found the whole utf8 string for needle in haystack at
+ * maybeMatch, so return it */
+ return (utf8_int8_t *)maybeMatch;
} else {
- // h could be in the middle of an unmatching utf8 codepoint,
- // so we need to march it on to the next character beginning,
- if ('\0' != *h) {
- do {
- h++;
- } while (0x80 == (0xc0 & *h));
- }
+ /* h could be in the middle of an unmatching utf8 codepoint,
+ * so we need to march it on to the next character beginning
+ * starting from the current character */
+ haystack = utf8codepoint(maybeMatch, &throwaway_codepoint);
}
}
- // no match
+ /* no match */
return utf8_null;
}
-void *utf8casestr(const void *haystack, const void *needle) {
- const void *h = haystack;
-
- // if needle has no utf8 codepoints before the null terminating
- // byte then return haystack
- if ('\0' == *((const char *)needle)) {
- return (void *)haystack;
+utf8_constexpr14_impl utf8_int8_t *utf8casestr(const utf8_int8_t *haystack,
+ const utf8_int8_t *needle) {
+ /* if needle has no utf8 codepoints before the null terminating
+ * byte then return haystack */
+ if ('\0' == *needle) {
+ return (utf8_int8_t *)haystack;
}
for (;;) {
- const void *maybeMatch = h;
- const void *n = needle;
- utf8_int32_t h_cp, n_cp;
+ const utf8_int8_t *maybeMatch = haystack;
+ const utf8_int8_t *n = needle;
+ utf8_int32_t h_cp = 0, n_cp = 0;
- h = utf8codepoint(h, &h_cp);
+ /* Get the next code point and track it */
+ const utf8_int8_t *nextH = haystack = utf8codepoint(haystack, &h_cp);
n = utf8codepoint(n, &n_cp);
while ((0 != h_cp) && (0 != n_cp)) {
h_cp = utf8lwrcodepoint(h_cp);
n_cp = utf8lwrcodepoint(n_cp);
- // if we find a mismatch, bail out!
+ /* if we find a mismatch, bail out! */
if (h_cp != n_cp) {
break;
}
- h = utf8codepoint(h, &h_cp);
+ haystack = utf8codepoint(haystack, &h_cp);
n = utf8codepoint(n, &n_cp);
}
if (0 == n_cp) {
- // we found the whole utf8 string for needle in haystack at
- // maybeMatch, so return it
- return (void *)maybeMatch;
+ /* we found the whole utf8 string for needle in haystack at
+ * maybeMatch, so return it */
+ return (utf8_int8_t *)maybeMatch;
}
if (0 == h_cp) {
- // no match
+ /* no match */
return utf8_null;
}
+
+ /* Roll back to the next code point in the haystack to test */
+ haystack = nextH;
}
}
-void *utf8valid(const void *str) {
- const char *s = (const char *)str;
+utf8_constexpr14_impl utf8_int8_t *utf8valid(const utf8_int8_t *str) {
+ return utf8nvalid(str, SIZE_MAX);
+}
+
+utf8_constexpr14_impl utf8_int8_t *utf8nvalid(const utf8_int8_t *str,
+ size_t n) {
+ const utf8_int8_t *t = str;
+ size_t consumed = 0;
+
+ while ((void)(consumed = (size_t)(str - t)), consumed < n && '\0' != *str) {
+ const size_t remaining = n - consumed;
+
+ if (0xf0 == (0xf8 & *str)) {
+ /* ensure that there's 4 bytes or more remaining */
+ if (remaining < 4) {
+ return (utf8_int8_t *)str;
+ }
+
+ /* ensure each of the 3 following bytes in this 4-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2])) ||
+ (0x80 != (0xc0 & str[3]))) {
+ return (utf8_int8_t *)str;
+ }
+
+ /* ensure that our utf8 codepoint ended after 4 bytes */
+ if ((remaining != 4) && (0x80 == (0xc0 & str[4]))) {
+ return (utf8_int8_t *)str;
+ }
- while ('\0' != *s) {
- if (0xf0 == (0xf8 & *s)) {
- // ensure each of the 3 following bytes in this 4-byte
- // utf8 codepoint began with 0b10xxxxxx
- if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2])) ||
- (0x80 != (0xc0 & s[3]))) {
- return (void *)s;
+ /* ensure that the top 5 bits of this 4-byte utf8
+ * codepoint were not 0, as then we could have used
+ * one of the smaller encodings */
+ if ((0 == (0x07 & str[0])) && (0 == (0x30 & str[1]))) {
+ return (utf8_int8_t *)str;
}
- // ensure that our utf8 codepoint ended after 4 bytes
- if (0x80 == (0xc0 & s[4])) {
- return (void *)s;
+ /* 4-byte utf8 code point (began with 0b11110xxx) */
+ str += 4;
+ } else if (0xe0 == (0xf0 & *str)) {
+ /* ensure that there's 3 bytes or more remaining */
+ if (remaining < 3) {
+ return (utf8_int8_t *)str;
}
- // ensure that the top 5 bits of this 4-byte utf8
- // codepoint were not 0, as then we could have used
- // one of the smaller encodings
- if ((0 == (0x07 & s[0])) && (0 == (0x30 & s[1]))) {
- return (void *)s;
+ /* ensure each of the 2 following bytes in this 3-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2]))) {
+ return (utf8_int8_t *)str;
}
- // 4-byte utf8 code point (began with 0b11110xxx)
- s += 4;
- } else if (0xe0 == (0xf0 & *s)) {
- // ensure each of the 2 following bytes in this 3-byte
- // utf8 codepoint began with 0b10xxxxxx
- if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2]))) {
- return (void *)s;
+ /* ensure that our utf8 codepoint ended after 3 bytes */
+ if ((remaining != 3) && (0x80 == (0xc0 & str[3]))) {
+ return (utf8_int8_t *)str;
}
- // ensure that our utf8 codepoint ended after 3 bytes
- if (0x80 == (0xc0 & s[3])) {
- return (void *)s;
+ /* ensure that the top 5 bits of this 3-byte utf8
+ * codepoint were not 0, as then we could have used
+ * one of the smaller encodings */
+ if ((0 == (0x0f & str[0])) && (0 == (0x20 & str[1]))) {
+ return (utf8_int8_t *)str;
}
- // ensure that the top 5 bits of this 3-byte utf8
- // codepoint were not 0, as then we could have used
- // one of the smaller encodings
- if ((0 == (0x0f & s[0])) && (0 == (0x20 & s[1]))) {
- return (void *)s;
+ /* 3-byte utf8 code point (began with 0b1110xxxx) */
+ str += 3;
+ } else if (0xc0 == (0xe0 & *str)) {
+ /* ensure that there's 2 bytes or more remaining */
+ if (remaining < 2) {
+ return (utf8_int8_t *)str;
}
- // 3-byte utf8 code point (began with 0b1110xxxx)
- s += 3;
- } else if (0xc0 == (0xe0 & *s)) {
- // ensure the 1 following byte in this 2-byte
- // utf8 codepoint began with 0b10xxxxxx
- if (0x80 != (0xc0 & s[1])) {
- return (void *)s;
+ /* ensure the 1 following byte in this 2-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if (0x80 != (0xc0 & str[1])) {
+ return (utf8_int8_t *)str;
}
- // ensure that our utf8 codepoint ended after 2 bytes
- if (0x80 == (0xc0 & s[2])) {
- return (void *)s;
+ /* ensure that our utf8 codepoint ended after 2 bytes */
+ if ((remaining != 2) && (0x80 == (0xc0 & str[2]))) {
+ return (utf8_int8_t *)str;
}
- // ensure that the top 4 bits of this 2-byte utf8
- // codepoint were not 0, as then we could have used
- // one of the smaller encodings
- if (0 == (0x1e & s[0])) {
- return (void *)s;
+ /* ensure that the top 4 bits of this 2-byte utf8
+ * codepoint were not 0, as then we could have used
+ * one of the smaller encodings */
+ if (0 == (0x1e & str[0])) {
+ return (utf8_int8_t *)str;
}
- // 2-byte utf8 code point (began with 0b110xxxxx)
- s += 2;
- } else if (0x00 == (0x80 & *s)) {
- // 1-byte ascii (began with 0b0xxxxxxx)
- s += 1;
+ /* 2-byte utf8 code point (began with 0b110xxxxx) */
+ str += 2;
+ } else if (0x00 == (0x80 & *str)) {
+ /* 1-byte ascii (began with 0b0xxxxxxx) */
+ str += 1;
} else {
- // we have an invalid 0b1xxxxxxx utf8 code point entry
- return (void *)s;
+ /* we have an invalid 0b1xxxxxxx utf8 code point entry */
+ return (utf8_int8_t *)str;
}
}
return utf8_null;
}
-void *utf8codepoint(const void *utf8_restrict str,
- utf8_int32_t *utf8_restrict out_codepoint) {
- const char *s = (const char *)str;
+int utf8makevalid(utf8_int8_t *str, const utf8_int32_t replacement) {
+ utf8_int8_t *read = str;
+ utf8_int8_t *write = read;
+ const utf8_int8_t r = (utf8_int8_t)replacement;
+ utf8_int32_t codepoint = 0;
- if (0xf0 == (0xf8 & s[0])) {
- // 4 byte utf8 codepoint
- *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) |
- ((0x3f & s[2]) << 6) | (0x3f & s[3]);
- s += 4;
- } else if (0xe0 == (0xf0 & s[0])) {
- // 3 byte utf8 codepoint
+ if (replacement > 0x7f) {
+ return -1;
+ }
+
+ while ('\0' != *read) {
+ if (0xf0 == (0xf8 & *read)) {
+ /* ensure each of the 3 following bytes in this 4-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2])) ||
+ (0x80 != (0xc0 & read[3]))) {
+ *write++ = r;
+ read++;
+ continue;
+ }
+
+ /* 4-byte utf8 code point (began with 0b11110xxx) */
+ read = utf8codepoint(read, &codepoint);
+ write = utf8catcodepoint(write, codepoint, 4);
+ } else if (0xe0 == (0xf0 & *read)) {
+ /* ensure each of the 2 following bytes in this 3-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2]))) {
+ *write++ = r;
+ read++;
+ continue;
+ }
+
+ /* 3-byte utf8 code point (began with 0b1110xxxx) */
+ read = utf8codepoint(read, &codepoint);
+ write = utf8catcodepoint(write, codepoint, 3);
+ } else if (0xc0 == (0xe0 & *read)) {
+ /* ensure the 1 following byte in this 2-byte
+ * utf8 codepoint began with 0b10xxxxxx */
+ if (0x80 != (0xc0 & read[1])) {
+ *write++ = r;
+ read++;
+ continue;
+ }
+
+ /* 2-byte utf8 code point (began with 0b110xxxxx) */
+ read = utf8codepoint(read, &codepoint);
+ write = utf8catcodepoint(write, codepoint, 2);
+ } else if (0x00 == (0x80 & *read)) {
+ /* 1-byte ascii (began with 0b0xxxxxxx) */
+ read = utf8codepoint(read, &codepoint);
+ write = utf8catcodepoint(write, codepoint, 1);
+ } else {
+ /* if we got here then we've got a dangling continuation (0b10xxxxxx) */
+ *write++ = r;
+ read++;
+ continue;
+ }
+ }
+
+ *write = '\0';
+
+ return 0;
+}
+
+utf8_constexpr14_impl utf8_int8_t *
+utf8codepoint(const utf8_int8_t *utf8_restrict str,
+ utf8_int32_t *utf8_restrict out_codepoint) {
+ if (0xf0 == (0xf8 & str[0])) {
+ /* 4 byte utf8 codepoint */
+ *out_codepoint = ((0x07 & str[0]) << 18) | ((0x3f & str[1]) << 12) |
+ ((0x3f & str[2]) << 6) | (0x3f & str[3]);
+ str += 4;
+ } else if (0xe0 == (0xf0 & str[0])) {
+ /* 3 byte utf8 codepoint */
*out_codepoint =
- ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
- s += 3;
- } else if (0xc0 == (0xe0 & s[0])) {
- // 2 byte utf8 codepoint
- *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
- s += 2;
+ ((0x0f & str[0]) << 12) | ((0x3f & str[1]) << 6) | (0x3f & str[2]);
+ str += 3;
+ } else if (0xc0 == (0xe0 & str[0])) {
+ /* 2 byte utf8 codepoint */
+ *out_codepoint = ((0x1f & str[0]) << 6) | (0x3f & str[1]);
+ str += 2;
} else {
- // 1 byte utf8 codepoint otherwise
- *out_codepoint = s[0];
- s += 1;
+ /* 1 byte utf8 codepoint otherwise */
+ *out_codepoint = str[0];
+ str += 1;
}
- return (void *)s;
+ return (utf8_int8_t *)str;
}
-size_t utf8codepointsize(utf8_int32_t chr) {
+utf8_constexpr14_impl size_t utf8codepointcalcsize(const utf8_int8_t *str) {
+ if (0xf0 == (0xf8 & str[0])) {
+ /* 4 byte utf8 codepoint */
+ return 4;
+ } else if (0xe0 == (0xf0 & str[0])) {
+ /* 3 byte utf8 codepoint */
+ return 3;
+ } else if (0xc0 == (0xe0 & str[0])) {
+ /* 2 byte utf8 codepoint */
+ return 2;
+ }
+
+ /* 1 byte utf8 codepoint otherwise */
+ return 1;
+}
+
+utf8_constexpr14_impl size_t utf8codepointsize(utf8_int32_t chr) {
if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
return 1;
} else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
return 2;
} else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
return 3;
- } else { // if (0 == ((int)0xffe00000 & chr)) {
+ } else { /* if (0 == ((int)0xffe00000 & chr)) { */
return 4;
}
}
-void *utf8catcodepoint(void *utf8_restrict str, utf8_int32_t chr, size_t n) {
- char *s = (char *)str;
-
+utf8_int8_t *utf8catcodepoint(utf8_int8_t *str, utf8_int32_t chr, size_t n) {
if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
- // 1-byte/7-bit ascii
- // (0b0xxxxxxx)
+ /* 1-byte/7-bit ascii
+ * (0b0xxxxxxx) */
if (n < 1) {
return utf8_null;
}
- s[0] = (char)chr;
- s += 1;
+ str[0] = (utf8_int8_t)chr;
+ str += 1;
} else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
- // 2-byte/11-bit utf8 code point
- // (0b110xxxxx 0b10xxxxxx)
+ /* 2-byte/11-bit utf8 code point
+ * (0b110xxxxx 0b10xxxxxx) */
if (n < 2) {
return utf8_null;
}
- s[0] = 0xc0 | (char)(chr >> 6);
- s[1] = 0x80 | (char)(chr & 0x3f);
- s += 2;
+ str[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)((chr >> 6) & 0x1f));
+ str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
+ str += 2;
} else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
- // 3-byte/16-bit utf8 code point
- // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
+ /* 3-byte/16-bit utf8 code point
+ * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
if (n < 3) {
return utf8_null;
}
- s[0] = 0xe0 | (char)(chr >> 12);
- s[1] = 0x80 | (char)((chr >> 6) & 0x3f);
- s[2] = 0x80 | (char)(chr & 0x3f);
- s += 3;
- } else { // if (0 == ((int)0xffe00000 & chr)) {
- // 4-byte/21-bit utf8 code point
- // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
+ str[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)((chr >> 12) & 0x0f));
+ str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
+ str += 3;
+ } else { /* if (0 == ((int)0xffe00000 & chr)) { */
+ /* 4-byte/21-bit utf8 code point
+ * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
if (n < 4) {
return utf8_null;
}
- s[0] = 0xf0 | (char)(chr >> 18);
- s[1] = 0x80 | (char)((chr >> 12) & 0x3f);
- s[2] = 0x80 | (char)((chr >> 6) & 0x3f);
- s[3] = 0x80 | (char)(chr & 0x3f);
- s += 4;
+ str[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)((chr >> 18) & 0x07));
+ str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
+ str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
+ str[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
+ str += 4;
}
- return s;
+ return str;
}
-int utf8islower(utf8_int32_t chr) { return chr != utf8uprcodepoint(chr); }
-
-int utf8isupper(utf8_int32_t chr) { return chr != utf8lwrcodepoint(chr); }
+utf8_constexpr14_impl int utf8islower(utf8_int32_t chr) {
+ return chr != utf8uprcodepoint(chr);
+}
-void utf8lwr(void *utf8_restrict str) {
- void *p, *pn;
- utf8_int32_t cp;
+utf8_constexpr14_impl int utf8isupper(utf8_int32_t chr) {
+ return chr != utf8lwrcodepoint(chr);
+}
- p = (char *)str;
- pn = utf8codepoint(p, &cp);
+void utf8lwr(utf8_int8_t *utf8_restrict str) {
+ utf8_int32_t cp = 0;
+ utf8_int8_t *pn = utf8codepoint(str, &cp);
while (cp != 0) {
const utf8_int32_t lwr_cp = utf8lwrcodepoint(cp);
const size_t size = utf8codepointsize(lwr_cp);
if (lwr_cp != cp) {
- utf8catcodepoint(p, lwr_cp, size);
+ utf8catcodepoint(str, lwr_cp, size);
}
- p = pn;
- pn = utf8codepoint(p, &cp);
+ str = pn;
+ pn = utf8codepoint(str, &cp);
}
}
-void utf8upr(void *utf8_restrict str) {
- void *p, *pn;
- utf8_int32_t cp;
-
- p = (char *)str;
- pn = utf8codepoint(p, &cp);
+void utf8upr(utf8_int8_t *utf8_restrict str) {
+ utf8_int32_t cp = 0;
+ utf8_int8_t *pn = utf8codepoint(str, &cp);
while (cp != 0) {
const utf8_int32_t lwr_cp = utf8uprcodepoint(cp);
const size_t size = utf8codepointsize(lwr_cp);
if (lwr_cp != cp) {
- utf8catcodepoint(p, lwr_cp, size);
+ utf8catcodepoint(str, lwr_cp, size);
}
- p = pn;
- pn = utf8codepoint(p, &cp);
+ str = pn;
+ pn = utf8codepoint(str, &cp);
}
}
-utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp) {
+utf8_constexpr14_impl utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp) {
if (((0x0041 <= cp) && (0x005a >= cp)) ||
((0x00c0 <= cp) && (0x00d6 >= cp)) ||
((0x00d8 <= cp) && (0x00de >= cp)) ||
((0x0391 <= cp) && (0x03a1 >= cp)) ||
- ((0x03a3 <= cp) && (0x03ab >= cp))) {
+ ((0x03a3 <= cp) && (0x03ab >= cp)) ||
+ ((0x0410 <= cp) && (0x042f >= cp))) {
cp += 32;
+ } else if ((0x0400 <= cp) && (0x040f >= cp)) {
+ cp += 80;
} else if (((0x0100 <= cp) && (0x012f >= cp)) ||
((0x0132 <= cp) && (0x0137 >= cp)) ||
((0x014a <= cp) && (0x0177 >= cp)) ||
@@ -1107,7 +1362,9 @@ utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp) {
((0x01f8 <= cp) && (0x021f >= cp)) ||
((0x0222 <= cp) && (0x0233 >= cp)) ||
((0x0246 <= cp) && (0x024f >= cp)) ||
- ((0x03d8 <= cp) && (0x03ef >= cp))) {
+ ((0x03d8 <= cp) && (0x03ef >= cp)) ||
+ ((0x0460 <= cp) && (0x0481 >= cp)) ||
+ ((0x048a <= cp) && (0x04ff >= cp))) {
cp |= 0x1;
} else if (((0x0139 <= cp) && (0x0148 >= cp)) ||
((0x0179 <= cp) && (0x017e >= cp)) ||
@@ -1118,62 +1375,147 @@ utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp) {
cp &= ~0x1;
} else {
switch (cp) {
- default: break;
- case 0x0178: cp = 0x00ff; break;
- case 0x0243: cp = 0x0180; break;
- case 0x018e: cp = 0x01dd; break;
- case 0x023d: cp = 0x019a; break;
- case 0x0220: cp = 0x019e; break;
- case 0x01b7: cp = 0x0292; break;
- case 0x01c4: cp = 0x01c6; break;
- case 0x01c7: cp = 0x01c9; break;
- case 0x01ca: cp = 0x01cc; break;
- case 0x01f1: cp = 0x01f3; break;
- case 0x01f7: cp = 0x01bf; break;
- case 0x0187: cp = 0x0188; break;
- case 0x018b: cp = 0x018c; break;
- case 0x0191: cp = 0x0192; break;
- case 0x0198: cp = 0x0199; break;
- case 0x01a7: cp = 0x01a8; break;
- case 0x01ac: cp = 0x01ad; break;
- case 0x01af: cp = 0x01b0; break;
- case 0x01b8: cp = 0x01b9; break;
- case 0x01bc: cp = 0x01bd; break;
- case 0x01f4: cp = 0x01f5; break;
- case 0x023b: cp = 0x023c; break;
- case 0x0241: cp = 0x0242; break;
- case 0x03fd: cp = 0x037b; break;
- case 0x03fe: cp = 0x037c; break;
- case 0x03ff: cp = 0x037d; break;
- case 0x037f: cp = 0x03f3; break;
- case 0x0386: cp = 0x03ac; break;
- case 0x0388: cp = 0x03ad; break;
- case 0x0389: cp = 0x03ae; break;
- case 0x038a: cp = 0x03af; break;
- case 0x038c: cp = 0x03cc; break;
- case 0x038e: cp = 0x03cd; break;
- case 0x038f: cp = 0x03ce; break;
- case 0x0370: cp = 0x0371; break;
- case 0x0372: cp = 0x0373; break;
- case 0x0376: cp = 0x0377; break;
- case 0x03f4: cp = 0x03d1; break;
- case 0x03cf: cp = 0x03d7; break;
- case 0x03f9: cp = 0x03f2; break;
- case 0x03f7: cp = 0x03f8; break;
- case 0x03fa: cp = 0x03fb; break;
- };
+ default:
+ break;
+ case 0x0178:
+ cp = 0x00ff;
+ break;
+ case 0x0243:
+ cp = 0x0180;
+ break;
+ case 0x018e:
+ cp = 0x01dd;
+ break;
+ case 0x023d:
+ cp = 0x019a;
+ break;
+ case 0x0220:
+ cp = 0x019e;
+ break;
+ case 0x01b7:
+ cp = 0x0292;
+ break;
+ case 0x01c4:
+ cp = 0x01c6;
+ break;
+ case 0x01c7:
+ cp = 0x01c9;
+ break;
+ case 0x01ca:
+ cp = 0x01cc;
+ break;
+ case 0x01f1:
+ cp = 0x01f3;
+ break;
+ case 0x01f7:
+ cp = 0x01bf;
+ break;
+ case 0x0187:
+ cp = 0x0188;
+ break;
+ case 0x018b:
+ cp = 0x018c;
+ break;
+ case 0x0191:
+ cp = 0x0192;
+ break;
+ case 0x0198:
+ cp = 0x0199;
+ break;
+ case 0x01a7:
+ cp = 0x01a8;
+ break;
+ case 0x01ac:
+ cp = 0x01ad;
+ break;
+ case 0x01b8:
+ cp = 0x01b9;
+ break;
+ case 0x01bc:
+ cp = 0x01bd;
+ break;
+ case 0x01f4:
+ cp = 0x01f5;
+ break;
+ case 0x023b:
+ cp = 0x023c;
+ break;
+ case 0x0241:
+ cp = 0x0242;
+ break;
+ case 0x03fd:
+ cp = 0x037b;
+ break;
+ case 0x03fe:
+ cp = 0x037c;
+ break;
+ case 0x03ff:
+ cp = 0x037d;
+ break;
+ case 0x037f:
+ cp = 0x03f3;
+ break;
+ case 0x0386:
+ cp = 0x03ac;
+ break;
+ case 0x0388:
+ cp = 0x03ad;
+ break;
+ case 0x0389:
+ cp = 0x03ae;
+ break;
+ case 0x038a:
+ cp = 0x03af;
+ break;
+ case 0x038c:
+ cp = 0x03cc;
+ break;
+ case 0x038e:
+ cp = 0x03cd;
+ break;
+ case 0x038f:
+ cp = 0x03ce;
+ break;
+ case 0x0370:
+ cp = 0x0371;
+ break;
+ case 0x0372:
+ cp = 0x0373;
+ break;
+ case 0x0376:
+ cp = 0x0377;
+ break;
+ case 0x03f4:
+ cp = 0x03b8;
+ break;
+ case 0x03cf:
+ cp = 0x03d7;
+ break;
+ case 0x03f9:
+ cp = 0x03f2;
+ break;
+ case 0x03f7:
+ cp = 0x03f8;
+ break;
+ case 0x03fa:
+ cp = 0x03fb;
+ break;
+ }
}
return cp;
}
-utf8_int32_t utf8uprcodepoint(utf8_int32_t cp) {
+utf8_constexpr14_impl utf8_int32_t utf8uprcodepoint(utf8_int32_t cp) {
if (((0x0061 <= cp) && (0x007a >= cp)) ||
((0x00e0 <= cp) && (0x00f6 >= cp)) ||
((0x00f8 <= cp) && (0x00fe >= cp)) ||
((0x03b1 <= cp) && (0x03c1 >= cp)) ||
- ((0x03c3 <= cp) && (0x03cb >= cp))) {
+ ((0x03c3 <= cp) && (0x03cb >= cp)) ||
+ ((0x0430 <= cp) && (0x044f >= cp))) {
cp -= 32;
+ } else if ((0x0450 <= cp) && (0x045f >= cp)) {
+ cp -= 80;
} else if (((0x0100 <= cp) && (0x012f >= cp)) ||
((0x0132 <= cp) && (0x0137 >= cp)) ||
((0x014a <= cp) && (0x0177 >= cp)) ||
@@ -1183,7 +1525,9 @@ utf8_int32_t utf8uprcodepoint(utf8_int32_t cp) {
((0x01f8 <= cp) && (0x021f >= cp)) ||
((0x0222 <= cp) && (0x0233 >= cp)) ||
((0x0246 <= cp) && (0x024f >= cp)) ||
- ((0x03d8 <= cp) && (0x03ef >= cp))) {
+ ((0x03d8 <= cp) && (0x03ef >= cp)) ||
+ ((0x0460 <= cp) && (0x0481 >= cp)) ||
+ ((0x048a <= cp) && (0x04ff >= cp))) {
cp &= ~0x1;
} else if (((0x0139 <= cp) && (0x0148 >= cp)) ||
((0x0179 <= cp) && (0x017e >= cp)) ||
@@ -1194,64 +1538,175 @@ utf8_int32_t utf8uprcodepoint(utf8_int32_t cp) {
cp |= 0x1;
} else {
switch (cp) {
- default: break;
- case 0x00ff: cp = 0x0178; break;
- case 0x0180: cp = 0x0243; break;
- case 0x01dd: cp = 0x018e; break;
- case 0x019a: cp = 0x023d; break;
- case 0x019e: cp = 0x0220; break;
- case 0x0292: cp = 0x01b7; break;
- case 0x01c6: cp = 0x01c4; break;
- case 0x01c9: cp = 0x01c7; break;
- case 0x01cc: cp = 0x01ca; break;
- case 0x01f3: cp = 0x01f1; break;
- case 0x01bf: cp = 0x01f7; break;
- case 0x0188: cp = 0x0187; break;
- case 0x018c: cp = 0x018b; break;
- case 0x0192: cp = 0x0191; break;
- case 0x0199: cp = 0x0198; break;
- case 0x01a8: cp = 0x01a7; break;
- case 0x01ad: cp = 0x01ac; break;
- case 0x01b0: cp = 0x01af; break;
- case 0x01b9: cp = 0x01b8; break;
- case 0x01bd: cp = 0x01bc; break;
- case 0x01f5: cp = 0x01f4; break;
- case 0x023c: cp = 0x023b; break;
- case 0x0242: cp = 0x0241; break;
- case 0x037b: cp = 0x03fd; break;
- case 0x037c: cp = 0x03fe; break;
- case 0x037d: cp = 0x03ff; break;
- case 0x03f3: cp = 0x037f; break;
- case 0x03ac: cp = 0x0386; break;
- case 0x03ad: cp = 0x0388; break;
- case 0x03ae: cp = 0x0389; break;
- case 0x03af: cp = 0x038a; break;
- case 0x03cc: cp = 0x038c; break;
- case 0x03cd: cp = 0x038e; break;
- case 0x03ce: cp = 0x038f; break;
- case 0x0371: cp = 0x0370; break;
- case 0x0373: cp = 0x0372; break;
- case 0x0377: cp = 0x0376; break;
- case 0x03d1: cp = 0x03f4; break;
- case 0x03d7: cp = 0x03cf; break;
- case 0x03f2: cp = 0x03f9; break;
- case 0x03f8: cp = 0x03f7; break;
- case 0x03fb: cp = 0x03fa; break;
- };
+ default:
+ break;
+ case 0x00ff:
+ cp = 0x0178;
+ break;
+ case 0x0180:
+ cp = 0x0243;
+ break;
+ case 0x01dd:
+ cp = 0x018e;
+ break;
+ case 0x019a:
+ cp = 0x023d;
+ break;
+ case 0x019e:
+ cp = 0x0220;
+ break;
+ case 0x0292:
+ cp = 0x01b7;
+ break;
+ case 0x01c6:
+ cp = 0x01c4;
+ break;
+ case 0x01c9:
+ cp = 0x01c7;
+ break;
+ case 0x01cc:
+ cp = 0x01ca;
+ break;
+ case 0x01f3:
+ cp = 0x01f1;
+ break;
+ case 0x01bf:
+ cp = 0x01f7;
+ break;
+ case 0x0188:
+ cp = 0x0187;
+ break;
+ case 0x018c:
+ cp = 0x018b;
+ break;
+ case 0x0192:
+ cp = 0x0191;
+ break;
+ case 0x0199:
+ cp = 0x0198;
+ break;
+ case 0x01a8:
+ cp = 0x01a7;
+ break;
+ case 0x01ad:
+ cp = 0x01ac;
+ break;
+ case 0x01b9:
+ cp = 0x01b8;
+ break;
+ case 0x01bd:
+ cp = 0x01bc;
+ break;
+ case 0x01f5:
+ cp = 0x01f4;
+ break;
+ case 0x023c:
+ cp = 0x023b;
+ break;
+ case 0x0242:
+ cp = 0x0241;
+ break;
+ case 0x037b:
+ cp = 0x03fd;
+ break;
+ case 0x037c:
+ cp = 0x03fe;
+ break;
+ case 0x037d:
+ cp = 0x03ff;
+ break;
+ case 0x03f3:
+ cp = 0x037f;
+ break;
+ case 0x03ac:
+ cp = 0x0386;
+ break;
+ case 0x03ad:
+ cp = 0x0388;
+ break;
+ case 0x03ae:
+ cp = 0x0389;
+ break;
+ case 0x03af:
+ cp = 0x038a;
+ break;
+ case 0x03cc:
+ cp = 0x038c;
+ break;
+ case 0x03cd:
+ cp = 0x038e;
+ break;
+ case 0x03ce:
+ cp = 0x038f;
+ break;
+ case 0x0371:
+ cp = 0x0370;
+ break;
+ case 0x0373:
+ cp = 0x0372;
+ break;
+ case 0x0377:
+ cp = 0x0376;
+ break;
+ case 0x03d1:
+ cp = 0x0398;
+ break;
+ case 0x03d7:
+ cp = 0x03cf;
+ break;
+ case 0x03f2:
+ cp = 0x03f9;
+ break;
+ case 0x03f8:
+ cp = 0x03f7;
+ break;
+ case 0x03fb:
+ cp = 0x03fa;
+ break;
+ }
}
return cp;
}
+utf8_constexpr14_impl utf8_int8_t *
+utf8rcodepoint(const utf8_int8_t *utf8_restrict str,
+ utf8_int32_t *utf8_restrict out_codepoint) {
+ const utf8_int8_t *s = (const utf8_int8_t *)str;
+
+ if (0xf0 == (0xf8 & s[0])) {
+ /* 4 byte utf8 codepoint */
+ *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) |
+ ((0x3f & s[2]) << 6) | (0x3f & s[3]);
+ } else if (0xe0 == (0xf0 & s[0])) {
+ /* 3 byte utf8 codepoint */
+ *out_codepoint =
+ ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
+ } else if (0xc0 == (0xe0 & s[0])) {
+ /* 2 byte utf8 codepoint */
+ *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
+ } else {
+ /* 1 byte utf8 codepoint otherwise */
+ *out_codepoint = s[0];
+ }
+
+ do {
+ s--;
+ } while ((0 != (0x80 & s[0])) && (0x80 == (0xc0 & s[0])));
+
+ return (utf8_int8_t *)s;
+}
+
#undef utf8_restrict
+#undef utf8_constexpr14
#undef utf8_null
-#ifdef __cplusplus
-} // extern "C"
+#ifdef utf8_cplusplus
+} /* extern "C" */
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
-#endif // SHEREDOM_UTF8_H_INCLUDED
+#endif /* SHEREDOM_UTF8_H_INCLUDED */
diff --git a/deps/ntlmclient/util.h b/deps/ntlmclient/util.h
index d4bb472ccc4..48e0169932f 100644
--- a/deps/ntlmclient/util.h
+++ b/deps/ntlmclient/util.h
@@ -9,6 +9,17 @@
#ifndef PRIVATE_UTIL_H__
#define PRIVATE_UTIL_H__
+#include
+#include
+
+#if defined(_MSC_VER)
+# define NTLM_INLINE(type) static __inline type
+#elif defined(__GNUC__)
+# define NTLM_INLINE(type) static __inline__ type
+#else
+# define NTLM_INLINE(type) static type
+#endif
+
extern void ntlm_memzero(void *data, size_t size);
extern uint64_t ntlm_htonll(uint64_t value);
diff --git a/deps/pcre/CMakeLists.txt b/deps/pcre/CMakeLists.txt
index 431dda01a02..53b5cee86d5 100644
--- a/deps/pcre/CMakeLists.txt
+++ b/deps/pcre/CMakeLists.txt
@@ -22,6 +22,7 @@ check_type_size("unsigned long long" UNSIGNED_LONG_LONG)
disable_warnings(unused-function)
disable_warnings(implicit-fallthrough)
+disable_warnings(unused-but-set-variable)
# User-configurable options
diff --git a/deps/zlib/deflate.c b/deps/zlib/deflate.c
index bd011751920..012ea8148e8 100644
--- a/deps/zlib/deflate.c
+++ b/deps/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
+ " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -493,7 +493,7 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
* symbols from which it is being constructed.
*/
- s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
@@ -503,8 +503,14 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
deflateEnd (strm);
return Z_MEM_ERROR;
}
+#ifdef LIT_MEM
+ s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
+ s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
+ s->sym_end = s->lit_bufsize - 1;
+#else
s->sym_buf = s->pending_buf + s->lit_bufsize;
s->sym_end = (s->lit_bufsize - 1) * 3;
+#endif
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
* on 16 bit machines and because stored blocks are restricted to
* 64K-1 bytes.
@@ -720,9 +726,15 @@ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;
+#ifdef LIT_MEM
+ if (bits < 0 || bits > 16 ||
+ (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+#else
if (bits < 0 || bits > 16 ||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
+#endif
do {
put = Buf_size - s->bi_valid;
if (put > bits)
@@ -1294,7 +1306,7 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
@@ -1305,10 +1317,15 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
- zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+ zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+#ifdef LIT_MEM
+ ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
+ ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
+#else
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
+#endif
ds->l_desc.dyn_tree = ds->dyn_ltree;
ds->d_desc.dyn_tree = ds->dyn_dtree;
@@ -1539,13 +1556,21 @@ local uInt longest_match(deflate_state *s, IPos cur_match) {
*/
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
/* check that the match is indeed a match */
- if (zmemcmp(s->window + match,
- s->window + start, length) != EQUAL) {
- fprintf(stderr, " start %u, match %u, length %d\n",
- start, match, length);
+ Bytef *back = s->window + (int)match, *here = s->window + start;
+ IPos len = length;
+ if (match == (IPos)-1) {
+ /* match starts one byte before the current window -- just compare the
+ subsequent length-1 bytes */
+ back++;
+ here++;
+ len--;
+ }
+ if (zmemcmp(back, here, len) != EQUAL) {
+ fprintf(stderr, " start %u, match %d, length %d\n",
+ start, (int)match, length);
do {
- fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
- } while (--length != 0);
+ fprintf(stderr, "(%02x %02x)", *back++, *here++);
+ } while (--len != 0);
z_error("invalid match");
}
if (z_verbose > 1) {
diff --git a/deps/zlib/deflate.h b/deps/zlib/deflate.h
index 8696791429f..300c6ada62b 100644
--- a/deps/zlib/deflate.h
+++ b/deps/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2018 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -23,6 +23,10 @@
# define GZIP
#endif
+/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
+ the cost of a larger memory footprint */
+/* #define LIT_MEM */
+
/* ===========================================================================
* Internal compression state.
*/
@@ -217,7 +221,14 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
+#ifdef LIT_MEM
+# define LIT_BUFS 5
+ ushf *d_buf; /* buffer for distances */
+ uchf *l_buf; /* buffer for literals/lengths */
+#else
+# define LIT_BUFS 4
uchf *sym_buf; /* buffer for distances and literals/lengths */
+#endif
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
@@ -239,7 +250,7 @@ typedef struct internal_state {
* - I can't count above 4
*/
- uInt sym_next; /* running index in sym_buf */
+ uInt sym_next; /* running index in symbol buffer */
uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
@@ -318,6 +329,25 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
extern const uch ZLIB_INTERNAL _dist_code[];
#endif
+#ifdef LIT_MEM
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->sym_next] = 0; \
+ s->l_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->d_buf[s->sym_next] = dist; \
+ s->l_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#else
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->sym_buf[s->sym_next++] = 0; \
@@ -337,6 +367,7 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
+#endif
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
diff --git a/deps/zlib/gzguts.h b/deps/zlib/gzguts.h
index f9375047e8c..eba72085bb7 100644
--- a/deps/zlib/gzguts.h
+++ b/deps/zlib/gzguts.h
@@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004-2019 Mark Adler
+ * Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -210,9 +210,5 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
-#ifdef INT_MAX
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
-#else
unsigned ZLIB_INTERNAL gz_intmax(void);
-# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
-#endif
+#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
diff --git a/deps/zlib/inflate.c b/deps/zlib/inflate.c
index b0757a9b249..94ecff015a9 100644
--- a/deps/zlib/inflate.c
+++ b/deps/zlib/inflate.c
@@ -1387,7 +1387,7 @@ int ZEXPORT inflateSync(z_streamp strm) {
/* if first time, start search in bit buffer */
if (state->mode != SYNC) {
state->mode = SYNC;
- state->hold <<= state->bits & 7;
+ state->hold >>= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while (state->bits >= 8) {
diff --git a/deps/zlib/inftrees.c b/deps/zlib/inftrees.c
index 8a208c2daa8..98cfe164458 100644
--- a/deps/zlib/inftrees.c
+++ b/deps/zlib/inftrees.c
@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2023 Mark Adler
+ * Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.3 Copyright 1995-2023 Mark Adler ";
+ " inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -57,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/deps/zlib/inftrees.h b/deps/zlib/inftrees.h
index a10712d8cb5..396f74b5da7 100644
--- a/deps/zlib/inftrees.h
+++ b/deps/zlib/inftrees.h
@@ -41,8 +41,8 @@ typedef struct {
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
- returns returns 852, and "enough 30 6 15" for distance codes returns 592.
- The initial root table size (9 or 6) is found in the fifth argument of the
+ returns 852, and "enough 30 6 15" for distance codes returns 592. The
+ initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
diff --git a/deps/zlib/trees.c b/deps/zlib/trees.c
index 8dbdc40bacc..6a523ef34e3 100644
--- a/deps/zlib/trees.c
+++ b/deps/zlib/trees.c
@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2021 Jean-loup Gailly
+ * Copyright (C) 1995-2024 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -899,14 +899,19 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
const ct_data *dtree) {
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
- unsigned sx = 0; /* running index in sym_buf */
+ unsigned sx = 0; /* running index in symbol buffers */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
if (s->sym_next != 0) do {
+#ifdef LIT_MEM
+ dist = s->d_buf[sx];
+ lc = s->l_buf[sx++];
+#else
dist = s->sym_buf[sx++] & 0xff;
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
lc = s->sym_buf[sx++];
+#endif
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
@@ -931,8 +936,12 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
}
} /* literal or match pair ? */
- /* Check that the overlay between pending_buf and sym_buf is ok: */
+ /* Check for no overlay of pending_buf on needed symbols */
+#ifdef LIT_MEM
+ Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
+#else
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
+#endif
} while (sx < s->sym_next);
@@ -1082,9 +1091,14 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
* the current block must be flushed.
*/
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
+#ifdef LIT_MEM
+ s->d_buf[s->sym_next] = (ush)dist;
+ s->l_buf[s->sym_next++] = (uch)lc;
+#else
s->sym_buf[s->sym_next++] = (uch)dist;
s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
s->sym_buf[s->sym_next++] = (uch)lc;
+#endif
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;
diff --git a/deps/zlib/zconf.h b/deps/zlib/zconf.h
index fb76ffe312a..62adc8d8431 100644
--- a/deps/zlib/zconf.h
+++ b/deps/zlib/zconf.h
@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -300,14 +300,6 @@
# endif
#endif
-#ifndef Z_ARG /* function prototypes for stdarg */
-# if defined(STDC) || defined(Z_HAVE_STDARG_H)
-# define Z_ARG(args) args
-# else
-# define Z_ARG(args) ()
-# endif
-#endif
-
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
diff --git a/deps/zlib/zlib.h b/deps/zlib/zlib.h
index 6b7244f9943..8d4b932eaf6 100644
--- a/deps/zlib/zlib.h
+++ b/deps/zlib/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.3, August 18th, 2023
+ version 1.3.1, January 22nd, 2024
- Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.3"
-#define ZLIB_VERNUM 0x1300
+#define ZLIB_VERSION "1.3.1"
+#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 3
-#define ZLIB_VER_REVISION 0
+#define ZLIB_VER_REVISION 1
#define ZLIB_VER_SUBREVISION 0
/*
@@ -936,10 +936,10 @@ ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
- In the success case, the application may save the current current value of
- total_in which indicates where valid compressed data was found. In the
- error case, the application may repeatedly call inflateSync, providing more
- input each time, until success or end of the input data.
+ In the success case, the application may save the current value of total_in
+ which indicates where valid compressed data was found. In the error case,
+ the application may repeatedly call inflateSync, providing more input each
+ time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
@@ -1758,14 +1758,14 @@ ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
- len2.
+ len2. len2 must be non-negative.
*/
/*
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
Return the operator corresponding to length len2, to be used with
- crc32_combine_op().
+ crc32_combine_op(). len2 must be non-negative.
*/
ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
diff --git a/deps/zlib/zutil.h b/deps/zlib/zutil.h
index 902a304cc2d..48dd7febae6 100644
--- a/deps/zlib/zutil.h
+++ b/deps/zlib/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -56,7 +56,7 @@ typedef unsigned long ulg;
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))
@@ -137,17 +137,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif
#endif
-#if defined(MACOS) || defined(TARGET_OS_MAC)
+#if defined(MACOS)
# define OS_CODE 7
-# ifndef Z_SOLO
-# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-# include /* for fdopen */
-# else
-# ifndef fdopen
-# define fdopen(fd,mode) NULL /* No fdopen() */
-# endif
-# endif
-# endif
#endif
#ifdef __acorn
@@ -170,18 +161,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define OS_CODE 19
#endif
-#if defined(_BEOS_) || defined(RISCOS)
-# define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
-#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
-# if defined(_WIN32_WCE)
-# define fdopen(fd,mode) NULL /* No fdopen() */
-# else
-# define fdopen(fd,type) _fdopen(fd,type)
-# endif
-#endif
-
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008
diff --git a/docs/changelog.md b/docs/changelog.md
index a35a389a4c6..9824d994bc7 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,3 +1,404 @@
+v1.9.0
+------
+
+This is release v1.9.0, "Schwibbogen". As usual, it contains numerous
+bug fixes, compatibility improvements, and new features.
+
+This is expected to be the final release in the libgit2 v1.x lineage.
+libgit2 v2.0 is expected to be the next version, with support for
+SHA256 moving to "supported" status (out of "experimental" status).
+This means that v2.0 will have API and ABI changes to support SHA256.
+
+## Major changes
+
+* **Documentation improvements**
+ We've launched a new website for our API reference docs at
+ https://libgit2.org/docs/reference/main/. To support this,
+ we've updated the documentation to ensure that all APIs are
+ well-documented, and added docurium-style specifiers to indicate
+ more depth about the API surface.
+
+ We now also publish a JSON blob with the API structure and the
+ documentation that may be helpful for binding authors.
+
+* **TLS cipher updates**
+ libgit2 has updated our TLS cipher selection to match the
+ "compatibility" cipher suite settings as [documented by
+ Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS).
+
+* **Blame improvements**
+ The blame API now contains committer information and commit summaries
+ for blame hunks, and the ability to get information about the line of
+ text that was modified. In addition, a CLI blame command has been added
+ so that the blame functionality can be benchmarked by our benchmark
+ suite.
+
+* **More CLI commands**
+ libgit2 has added `blame` and `init` commands, which have allowed for
+ [further benchmarking](https://benchmarks.libgit2.org/) and several API
+ improvements and git compatibility updates.
+
+* **Warning when configuring without SHA1DC**
+ Users are encouraged to use SHA1DC, which is _git's hash_; users
+ should not use SHA1 in the general case. Users will now be warned
+ if they try to configure cmake with a SHA1 backend (`-DUSE_SHA1=...`).
+
+## Breaking changes
+
+There are several ABI-breaking changes that integrators, particularly
+maintainers of bindings or FFI users, may want to be aware of.
+
+* **Blame hunk structure updates** (ABI breaking change)
+ There are numerous additions to the `git_blame_hunk` structure to
+ accommodate more information about the blame process.
+
+* **Checkout strategy updates** (ABI breaking change)
+ The values for `GIT_CHECKOUT_SAFE` and `GIT_CHECKOUT_NONE` have been
+ updated. `GIT_CHECKOUT_SAFE` is now `0`; this was implicitly the
+ default value (with the options constructors setting that as the
+ checkout strategy). It is now the default if the checkout strategy
+ is set to `0`. This allows for an overall code simplification in the
+ library.
+
+* **Configuration entry member removal** (ABI breaking change)
+ The `git_config_entry` structure no longer contains a `free` member;
+ this was an oversight as end-users should not try to free that
+ structure.
+
+* **Configuration backend function changes** (ABI breaking change)
+ `git_config_backend`s should now return `git_config_backend_entry`
+ objects instead of `git_config_entry` objects. This allows backends
+ to provide a mechanism to nicely free the configuration entries that
+ they provide.
+
+## What's Changed
+
+### New features
+
+* The `git_signature_default_from_env` API will now produce a pair
+ of `git_signature`s representing the author, and the committer,
+ taking the `GIT_AUTHOR_NAME` and `GIT_COMMITTER_NAME` environment
+ variables into account. Added by @u-quark in
+ https://github.com/libgit2/libgit2/pull/6706
+
+* packbuilder can now be interrupted from a callback. Added @roberth
+ in https://github.com/libgit2/libgit2/pull/6874
+
+* libgit2 now claims to honor the `preciousObject` repository extension.
+ This extension indicates that the client will never delete objects
+ (in other words, will not garbage collect). libgit2 has no functionality
+ to remove objects, so it implicitly obeys this in all cases. Added
+ by @ethomson in https://github.com/libgit2/libgit2/pull/6886
+
+* Push status will be reported even when a push fails. This is useful
+ to give information from the server about possible updates, even when
+ the overall status failed. Added by @yerseg in
+ https://github.com/libgit2/libgit2/pull/6876
+
+* You can now generate a thin pack from a mempack instance using
+ `git_mempack_write_thin_pack`. Added by @roberth in
+ https://github.com/libgit2/libgit2/pull/6875
+
+* The new `LIBGIT2_VERSION_CHECK` macro will indicate whether the version
+ of libgit2 being compiled against is at least the version specified.
+ For example: `#if LIBGIT2_VERSION_CHECK(1, 6, 3)` is true for libgit2
+ version 1.6.3 or newer. In addition, the new `LIBGIT2_VERSION_NUMBER`
+ macro will return an integer version representing the libgit2 version
+ number. For example, for version 1.6.3, `LIBGIT2_VERSION_NUMBER` will
+ evaluate to `010603`. Added by @HamedMasafi in
+ https://github.com/libgit2/libgit2/pull/6882
+
+* Custom X509 certificates can be added to OpenSSL's certificate store
+ using the `GIT_OPT_ADD_SSL_X509_CERT` option. Added by @yerseg in
+ https://github.com/libgit2/libgit2/pull/6877
+
+* The libgit2 compatibility CLI now has a `git blame` command. Added by
+ @ethomson in https://github.com/libgit2/libgit2/pull/6907
+
+* Remote callbacks now provide an `update_refs` callback so that users
+ can now get the `refspec` of the updated reference during push. This
+ gives more complete information about the remote reference that was
+ updated. Added by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6559
+
+* An optional FIPS-compliant mode for hashing is now available; you
+ can set `-DUSE_SHA256=OpenSSL-FIPS` to enable it. Added by @marcind-dot
+ in https://github.com/libgit2/libgit2/pull/6906
+
+* The git-compatible CLI now supports the `git init` command, which has
+ been useful in identifying API improvements and incompatibilities with
+ git. Added by @ethomson in https://github.com/libgit2/libgit2/pull/6984
+
+* Consumers can now query more information about how libgit2 was
+ compiled, and query the "backends" that libgit2 uses. Added by
+ @ethomson in https://github.com/libgit2/libgit2/pull/6971
+
+### Bug fixes
+
+* Fix constness issue introduced in #6716 by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6829
+* odb: conditional `git_hash_ctx_cleanup` in `git_odb_stream` by
+ @gensmusic in https://github.com/libgit2/libgit2/pull/6836
+* Fix shallow root maintenance during fetch by @kcsaul in
+ https://github.com/libgit2/libgit2/pull/6846
+* Headers cleanup by @anatol in
+ https://github.com/libgit2/libgit2/pull/6842
+* http: Initialize `on_status` when using the http-parser backend by
+ @civodul in https://github.com/libgit2/libgit2/pull/6870
+* Leak in `truncate_racily_clean` in index.c by @lstoppa in
+ https://github.com/libgit2/libgit2/pull/6884
+* ssh: Omit port option from ssh command unless specified in remote url
+ by @jayong93 in https://github.com/libgit2/libgit2/pull/6845
+* diff: print the file header on `GIT_DIFF_FORMAT_PATCH_HEADER` by
+ @carlosmn in https://github.com/libgit2/libgit2/pull/6888
+* Add more robust reporting to SecureTransport errors on macos by
+ @vcfxb in https://github.com/libgit2/libgit2/pull/6848
+* transport: do not filter tags based on ref dir in local by @rindeal
+ in https://github.com/libgit2/libgit2/pull/6881
+* push: handle tags to blobs by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6898
+* Fixes for OpenSSL dynamic by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6901
+* realpath: unbreak build on OpenBSD by @ajacoutot in
+ https://github.com/libgit2/libgit2/pull/6932
+* util/win32: Continue if access is denied when deleting a folder by
+ @lrm29 in https://github.com/libgit2/libgit2/pull/6929
+* object: `git_object_short_id` fails with core.abbrev string values by
+ @lrm29 in https://github.com/libgit2/libgit2/pull/6944
+* Clear data after negotiation by @lrm29 in
+ https://github.com/libgit2/libgit2/pull/6947
+* smart: ignore shallow/unshallow packets during ACK processing by
+ @kempniu in https://github.com/libgit2/libgit2/pull/6973
+
+### Security fixes
+
+* ssh: Include rsa-sha2-256 and rsa-sha2-512 in the list of hostkey types
+ by @lrm29 in https://github.com/libgit2/libgit2/pull/6938
+* TLS: v1.2 and updated cipher list by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6960
+
+### Code cleanups
+
+* checkout: make safe checkout the default by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6037
+* url: track whether url explicitly specified a port by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6851
+* config: remove `free` ptr from `git_config_entry` by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6804
+* Add SecCopyErrorMessageString for iOS and update README for iOS by
+ @Kyle-Ye in https://github.com/libgit2/libgit2/pull/6862
+* vector: free is now dispose by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6896
+* hashmap: a libgit2-idiomatic khash by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6897
+* hashmap: asserts by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6902
+* hashmap: further asserts by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6904
+* Make `GIT_WIN32` an internal declaration by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6940
+* pathspec: additional pathspec wildcard tests by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6959
+* repo: don't require option when `template_path` is specified by @ethomson
+ in https://github.com/libgit2/libgit2/pull/6983
+* options: update X509 cert constant by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6974
+* remote: Handle fetching negative refspecs by @ryan-ph in
+ https://github.com/libgit2/libgit2/pull/6962
+* Restore tls v1.0 support temporarily by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6964
+* SHA256 improvements by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6965
+
+### Benchmarks
+
+* Add benchmarks for blame by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6920
+
+### Build and CI improvements
+
+* README: add experimental builds to ci table by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6816
+* Update stransport.c by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6891
+* stransport: initialize for iOS by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6893
+* CI updates by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6895
+* Configurable C standard by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6911
+* cmake: update python locator by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6915
+* ci: don't run Windows SHA256 gitdaemon tests by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6916
+* cmake-standard c standards by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6914
+* ci: don't run Windows SHA256 gitdaemon tests by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6919
+* Improve dependency selection in CMake by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6924
+* ci: port latest fixes to nightlies by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6926
+* cmake: warn for not using sha1dc by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6986
+
+### Documentation improvements
+
+* Fix docs for `git_odb_stream_read` return value. by @ehuss in
+ https://github.com/libgit2/libgit2/pull/6837
+* docs: Add instructions to build examples by @thymusvulgaris in
+ https://github.com/libgit2/libgit2/pull/6839
+* Fix contradictory phrase in SECURITY.md by @Kyle-Ye in
+ https://github.com/libgit2/libgit2/pull/6859
+* Update README.md by @Kyle-Ye in
+ https://github.com/libgit2/libgit2/pull/6860
+* README updates by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6908
+* typo: s/size on bytes/size in bytes/ by @John-Colvin in
+ https://github.com/libgit2/libgit2/pull/6909
+* readme: add OpenSSF best practices badge by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6925
+* Update documentation of `merge_base_many` by @Caleb-T-Owens in
+ https://github.com/libgit2/libgit2/pull/6927
+* Include documentation generator by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6945
+* Update documentation generation workflow by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6948
+* Improve documentation and validate during CI by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6949
+* Add search functionality to our docs generator by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6953
+* Documentation: don't resort versions by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6954
+* Documentation: update `refdb_backend` docs by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6955
+* Documentation: clean up old documentation by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6957
+* docs: remind people about `git_libgit2_init` by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6958
+* Update changelog with v1.8.4 content by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6961
+
+### Git compatibility fixes
+
+* Limit `.gitattributes` and `.gitignore` files to 100 MiB by @csware in
+ https://github.com/libgit2/libgit2/pull/6834
+* refs: Handle normalizing negative refspecs by @ryan-ph in
+ https://github.com/libgit2/libgit2/pull/6951
+* repo: put a newline on the .git link file by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6981
+
+### Dependency updates
+
+* zlib: update bundled zlib to v1.3.1 by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6905
+* Update ntlmclient dependency by @ethomson in
+ https://github.com/libgit2/libgit2/pull/6912
+
+### Other changes
+
+* Create FUNDING.json by @BenJam in
+ https://github.com/libgit2/libgit2/pull/6853
+
+## New Contributors
+
+* @gensmusic made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6836
+* @u-quark made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6706
+* @thymusvulgaris made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6839
+* @anatol made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6842
+* @BenJam made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6853
+* @Kyle-Ye made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6859
+* @civodul made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6870
+* @lstoppa made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6884
+* @jayong93 made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6845
+* @roberth made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6874
+* @vcfxb made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6848
+* @yerseg made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6876
+* @rindeal made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6881
+* @HamedMasafi made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6882
+* @John-Colvin made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6909
+* @marcind-dot made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6906
+* @ajacoutot made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6932
+* @Caleb-T-Owens made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6927
+* @ryan-ph made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6951
+* @bmarques1995 made their first contribution in
+ https://github.com/libgit2/libgit2/pull/6840
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.8.4...v1.9.0
+
+v1.8.4
+------
+
+We erroneously shipped v1.8.3 without actually including the change
+in v1.8.2. This release re-re-introduces the pre-v1.8.0 `commit`
+constness behavior.
+
+## What's Changed
+
+### Bug fixes
+
+* Fix constness issue introduced in #6716 by @ethomson in https://github.com/libgit2/libgit2/pull/6829
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.8.3...v1.8.4
+
+v1.8.3
+------
+
+This release fixes a bug introduced in v1.8.1 for users of the legacy
+[Node.js http-parser](https://github.com/nodejs/http-parser)
+dependency.
+
+## What's Changed
+
+### Bug fixes
+
+* http: Backport on_status initialize fix for http-parser by @ethomson in https://github.com/libgit2/libgit2/pull/6931
+
+v1.8.2
+------
+
+This release reverts a const-correctness change introduced in
+v1.8.0 for the `git_commit_create` functions. We now retain the
+const-behavior for the `commits` arguments from prior to v1.8.0.
+
+This change was meant to resolve compatibility issues with bindings
+and downstream users.
+
+## What's Changed
+
+### New features
+
+* Introduce a stricter debugging allocator for testing by @ethomson in https://github.com/libgit2/libgit2/pull/6811
+
+### Bug fixes
+
+* Fix constness issue introduced in #6716 by @ethomson in https://github.com/libgit2/libgit2/pull/6829
+
+### Build and CI improvements
+
+* README: add experimental builds to ci table by @ethomson in https://github.com/libgit2/libgit2/pull/6816
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.8.1...v1.8.2
+
v1.8.1
------
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 8e38c7d4e66..986daae59df 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -3,7 +3,6 @@
file(GLOB SRC_EXAMPLES *.c *.h)
add_executable(lg2 ${SRC_EXAMPLES})
-set_target_properties(lg2 PROPERTIES C_STANDARD 90)
# Ensure that we do not use deprecated functions internally
add_definitions(-DGIT_DEPRECATE_HARD)
diff --git a/examples/blame.c b/examples/blame.c
index 0996e7a1fdb..1e2869a6395 100644
--- a/examples/blame.c
+++ b/examples/blame.c
@@ -97,7 +97,7 @@ int lg2_blame(git_repository *repo, int argc, char *argv[])
while (i < rawsize) {
const char *eol = memchr(rawdata + i, '\n', (size_t)(rawsize - i));
char oid[10] = {0};
- const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line);
+ const git_blame_hunk *hunk = git_blame_hunk_byline(blame, line);
if (break_on_null_hunk && !hunk)
break;
diff --git a/examples/commit.c b/examples/commit.c
index aedc1af7e1c..c6e0a8dc447 100644
--- a/examples/commit.c
+++ b/examples/commit.c
@@ -39,7 +39,7 @@ int lg2_commit(git_repository *repo, int argc, char **argv)
git_index *index;
git_object *parent = NULL;
git_reference *ref = NULL;
- git_signature *signature;
+ git_signature *author_signature, *committer_signature;
/* Validate args */
if (argc < 3 || strcmp(opt, "-m") != 0) {
@@ -63,21 +63,23 @@ int lg2_commit(git_repository *repo, int argc, char **argv)
check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL);
- check_lg2(git_signature_default(&signature, repo), "Error creating signature", NULL);
+ check_lg2(git_signature_default_from_env(&author_signature, &committer_signature, repo),
+ "Error creating signature", NULL);
check_lg2(git_commit_create_v(
&commit_oid,
repo,
"HEAD",
- signature,
- signature,
+ author_signature,
+ committer_signature,
NULL,
comment,
tree,
parent ? 1 : 0, parent), "Error creating commit", NULL);
git_index_free(index);
- git_signature_free(signature);
+ git_signature_free(author_signature);
+ git_signature_free(committer_signature);
git_tree_free(tree);
git_object_free(parent);
git_reference_free(ref);
diff --git a/examples/fetch.c b/examples/fetch.c
index bbd882cfb59..a8b3527a8cb 100644
--- a/examples/fetch.c
+++ b/examples/fetch.c
@@ -13,20 +13,24 @@ static int progress_cb(const char *str, int len, void *data)
* updated. The message we output depends on whether it's a new one or
* an update.
*/
-static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data)
+static int update_cb(const char *refname, const git_oid *a, const git_oid *b, git_refspec *spec, void *data)
{
char a_str[GIT_OID_SHA1_HEXSIZE+1], b_str[GIT_OID_SHA1_HEXSIZE+1];
+ git_buf remote_name;
(void)data;
+ if (git_refspec_rtransform(&remote_name, spec, refname) < 0)
+ return -1;
+
git_oid_fmt(b_str, b);
b_str[GIT_OID_SHA1_HEXSIZE] = '\0';
if (git_oid_is_zero(a)) {
- printf("[new] %.20s %s\n", b_str, refname);
+ printf("[new] %.20s %s -> %s\n", b_str, remote_name.ptr, refname);
} else {
git_oid_fmt(a_str, a);
a_str[GIT_OID_SHA1_HEXSIZE] = '\0';
- printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname);
+ printf("[updated] %.10s..%.10s %s -> %s\n", a_str, b_str, remote_name.ptr, refname);
}
return 0;
@@ -72,7 +76,7 @@ int lg2_fetch(git_repository *repo, int argc, char **argv)
goto on_error;
/* Set up the callbacks (only update_tips for now) */
- fetch_opts.callbacks.update_tips = &update_cb;
+ fetch_opts.callbacks.update_refs = &update_cb;
fetch_opts.callbacks.sideband_progress = &progress_cb;
fetch_opts.callbacks.transfer_progress = transfer_progress_cb;
fetch_opts.callbacks.credentials = cred_acquire_cb;
diff --git a/examples/index-pack.c b/examples/index-pack.c
index 0f8234c7591..e9f32b8b291 100644
--- a/examples/index-pack.c
+++ b/examples/index-pack.c
@@ -29,7 +29,7 @@ int lg2_index_pack(git_repository *repo, int argc, char **argv)
}
#ifdef GIT_EXPERIMENTAL_SHA256
- error = git_indexer_new(&idx, ".", git_repository_oid_type(repo), NULL);
+ error = git_indexer_new(&idx, ".", NULL);
#else
error = git_indexer_new(&idx, ".", 0, NULL, NULL);
#endif
diff --git a/examples/init.c b/examples/init.c
index 2f681c5ae6e..036c156ab08 100644
--- a/examples/init.c
+++ b/examples/init.c
@@ -123,14 +123,14 @@ int lg2_init(git_repository *repo, int argc, char *argv[])
*/
static void create_initial_commit(git_repository *repo)
{
- git_signature *sig;
+ git_signature *author_sig = NULL, *committer_sig = NULL;
git_index *index;
git_oid tree_id, commit_id;
git_tree *tree;
/** First use the config to initialize a commit signature for the user. */
- if (git_signature_default(&sig, repo) < 0)
+ if ((git_signature_default_from_env(&author_sig, &committer_sig, repo) < 0))
fatal("Unable to create a commit signature.",
"Perhaps 'user.name' and 'user.email' are not set");
@@ -162,14 +162,15 @@ static void create_initial_commit(git_repository *repo)
*/
if (git_commit_create_v(
- &commit_id, repo, "HEAD", sig, sig,
+ &commit_id, repo, "HEAD", author_sig, committer_sig,
NULL, "Initial commit", tree, 0) < 0)
fatal("Could not create the initial commit", NULL);
/** Clean up so we don't leak memory. */
git_tree_free(tree);
- git_signature_free(sig);
+ git_signature_free(author_sig);
+ git_signature_free(committer_sig);
}
static void usage(const char *error, const char *arg)
diff --git a/examples/merge.c b/examples/merge.c
index 718c767d038..7a76912cd24 100644
--- a/examples/merge.c
+++ b/examples/merge.c
@@ -263,7 +263,7 @@ static int create_merge_commit(git_repository *repo, git_index *index, struct me
sign, sign,
NULL, msg,
tree,
- opts->annotated_count + 1, parents);
+ opts->annotated_count + 1, (const git_commit **)parents);
check_lg2(err, "failed to create commit", NULL);
/* We're done merging, cleanup the repository state */
diff --git a/examples/show-index.c b/examples/show-index.c
index 0a5e7d1a2e4..ac0040874ec 100644
--- a/examples/show-index.c
+++ b/examples/show-index.c
@@ -31,7 +31,7 @@ int lg2_show_index(git_repository *repo, int argc, char **argv)
dirlen = strlen(dir);
if (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) {
#ifdef GIT_EXPERIMENTAL_SHA256
- check_lg2(git_index_open(&index, dir, GIT_OID_SHA1), "could not open index", dir);
+ check_lg2(git_index_open(&index, dir, NULL), "could not open index", dir);
#else
check_lg2(git_index_open(&index, dir), "could not open index", dir);
#endif
diff --git a/examples/stash.c b/examples/stash.c
index 8142439c702..197724364f6 100644
--- a/examples/stash.c
+++ b/examples/stash.c
@@ -108,7 +108,7 @@ static int cmd_push(git_repository *repo, struct opts *opts)
if (opts->argc)
usage("push does not accept any parameters");
- check_lg2(git_signature_default(&signature, repo),
+ check_lg2(git_signature_default_from_env(&signature, NULL, repo),
"Unable to get signature", NULL);
check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT),
"Unable to save stash", NULL);
diff --git a/examples/tag.c b/examples/tag.c
index e4f71ae625f..ebe1a9d7bf0 100644
--- a/examples/tag.c
+++ b/examples/tag.c
@@ -226,7 +226,7 @@ static void action_create_tag(tag_state *state)
check_lg2(git_revparse_single(&target, repo, opts->target),
"Unable to resolve spec", opts->target);
- check_lg2(git_signature_default(&tagger, repo),
+ check_lg2(git_signature_default_from_env(&tagger, NULL, repo),
"Unable to create signature", NULL);
check_lg2(git_tag_create(&oid, repo, opts->tag_name,
diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt
index 01f0f51997f..4063def331a 100644
--- a/fuzzers/CMakeLists.txt
+++ b/fuzzers/CMakeLists.txt
@@ -20,8 +20,6 @@ foreach(fuzz_target_src ${SRC_FUZZERS})
endif()
add_executable(${fuzz_target_name} ${${fuzz_target_name}_SOURCES})
- set_target_properties(${fuzz_target_name} PROPERTIES C_STANDARD 90)
-
target_include_directories(${fuzz_target_name} PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
target_include_directories(${fuzz_target_name} SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
diff --git a/fuzzers/packfile_fuzzer.c b/fuzzers/packfile_fuzzer.c
index aeba9575c3e..bcbdd8bc40b 100644
--- a/fuzzers/packfile_fuzzer.c
+++ b/fuzzers/packfile_fuzzer.c
@@ -84,7 +84,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
}
#ifdef GIT_EXPERIMENTAL_SHA256
- error = git_indexer_new(&indexer, ".", GIT_OID_SHA1, NULL);
+ error = git_indexer_new(&indexer, ".", NULL);
#else
error = git_indexer_new(&indexer, ".", 0, odb, NULL);
#endif
diff --git a/fuzzers/standalone_driver.c b/fuzzers/standalone_driver.c
index cd4f71751ae..17b54de952e 100644
--- a/fuzzers/standalone_driver.c
+++ b/fuzzers/standalone_driver.c
@@ -67,7 +67,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Done %d runs\n", i);
exit:
- git_vector_free_deep(&corpus_files);
+ git_vector_dispose_deep(&corpus_files);
git_libgit2_shutdown();
return error;
}
diff --git a/include/git2/annotated_commit.h b/include/git2/annotated_commit.h
index 3b7103f2001..04f3b1c381f 100644
--- a/include/git2/annotated_commit.h
+++ b/include/git2/annotated_commit.h
@@ -13,9 +13,16 @@
/**
* @file git2/annotated_commit.h
- * @brief Git annotated commit routines
+ * @brief A commit and information about how it was looked up by the user.
* @defgroup git_annotated_commit Git annotated commit routines
* @ingroup Git
+ *
+ * An "annotated commit" is a commit that contains information about
+ * how the commit was resolved, which can be used for maintaining the
+ * user's "intent" through commands like merge and rebase. For example,
+ * if a user wants to "merge HEAD" then an annotated commit is used to
+ * both contain the HEAD commit _and_ the fact that it was resolved as
+ * the HEAD ref.
* @{
*/
GIT_BEGIN_DECL
@@ -25,7 +32,7 @@ GIT_BEGIN_DECL
* The resulting git_annotated_commit must be freed with
* `git_annotated_commit_free`.
*
- * @param out pointer to store the git_annotated_commit result in
+ * @param[out] out pointer to store the git_annotated_commit result in
* @param repo repository that contains the given reference
* @param ref reference to use to lookup the git_annotated_commit
* @return 0 on success or error code
@@ -40,7 +47,7 @@ GIT_EXTERN(int) git_annotated_commit_from_ref(
* The resulting git_annotated_commit must be freed with
* `git_annotated_commit_free`.
*
- * @param out pointer to store the git_annotated_commit result in
+ * @param[out] out pointer to store the git_annotated_commit result in
* @param repo repository that contains the given commit
* @param branch_name name of the (remote) branch
* @param remote_url url of the remote
@@ -67,7 +74,7 @@ GIT_EXTERN(int) git_annotated_commit_from_fetchhead(
* most specific function (eg `git_annotated_commit_from_ref`)
* instead of this one when that data is known.
*
- * @param out pointer to store the git_annotated_commit result in
+ * @param[out] out pointer to store the git_annotated_commit result in
* @param repo repository that contains the given commit
* @param id the commit object id to lookup
* @return 0 on success or error code
@@ -84,7 +91,7 @@ GIT_EXTERN(int) git_annotated_commit_lookup(
* http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for
* information on the syntax accepted.
*
- * @param out pointer to store the git_annotated_commit result in
+ * @param[out] out pointer to store the git_annotated_commit result in
* @param repo repository that contains the given commit
* @param revspec the extended sha syntax string to use to lookup the commit
* @return 0 on success or error code
diff --git a/include/git2/apply.h b/include/git2/apply.h
index db652bde0b3..7ab939d1f2d 100644
--- a/include/git2/apply.h
+++ b/include/git2/apply.h
@@ -14,9 +14,12 @@
/**
* @file git2/apply.h
- * @brief Git patch application routines
+ * @brief Apply patches to the working directory or index
* @defgroup git_apply Git patch application routines
* @ingroup Git
+ *
+ * Mechanisms to apply a patch to the index, the working directory,
+ * or both.
* @{
*/
GIT_BEGIN_DECL
@@ -57,7 +60,15 @@ typedef int GIT_CALLBACK(git_apply_hunk_cb)(
const git_diff_hunk *hunk,
void *payload);
-/** Flags controlling the behavior of git_apply */
+/**
+ * Flags controlling the behavior of `git_apply`.
+ *
+ * When the callback:
+ * - returns < 0, the apply process will be aborted.
+ * - returns > 0, the hunk will not be applied, but the apply process
+ * continues
+ * - returns 0, the hunk is applied, and the apply process continues.
+ */
typedef enum {
/**
* Don't actually make changes, just test that the patch applies.
@@ -67,12 +78,19 @@ typedef enum {
} git_apply_flags_t;
/**
- * Apply options structure
+ * Apply options structure.
+ *
+ * When the callback:
+ * - returns < 0, the apply process will be aborted.
+ * - returns > 0, the hunk will not be applied, but the apply process
+ * continues
+ * - returns 0, the hunk is applied, and the apply process continues.
*
* Initialize with `GIT_APPLY_OPTIONS_INIT`. Alternatively, you can
* use `git_apply_options_init`.
*
- * @see git_apply_to_tree, git_apply
+ * @see git_apply_to_tree
+ * @see git_apply
*/
typedef struct {
unsigned int version; /**< The version */
@@ -83,14 +101,17 @@ typedef struct {
/** When applying a patch, callback that will be made per hunk. */
git_apply_hunk_cb hunk_cb;
- /** Payload passed to both delta_cb & hunk_cb. */
+ /** Payload passed to both `delta_cb` & `hunk_cb`. */
void *payload;
- /** Bitmask of git_apply_flags_t */
+ /** Bitmask of `git_apply_flags_t` */
unsigned int flags;
} git_apply_options;
+/** Current version for the `git_apply_options` structure */
#define GIT_APPLY_OPTIONS_VERSION 1
+
+/** Static constructor for `git_apply_options` */
#define GIT_APPLY_OPTIONS_INIT {GIT_APPLY_OPTIONS_VERSION}
/**
diff --git a/include/git2/attr.h b/include/git2/attr.h
index 69929b3dfc6..e5216fef99e 100644
--- a/include/git2/attr.h
+++ b/include/git2/attr.h
@@ -12,9 +12,13 @@
/**
* @file git2/attr.h
- * @brief Git attribute management routines
+ * @brief Attribute management routines
* @defgroup git_attr Git attribute management routines
* @ingroup Git
+ *
+ * Attributes specify additional information about how git should
+ * handle particular paths - for example, they may indicate whether
+ * a particular filter is applied, like LFS or line ending conversions.
* @{
*/
GIT_BEGIN_DECL
@@ -114,8 +118,12 @@ GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr);
* use index only for creating archives or for a bare repo (if an
* index has been specified for the bare repo).
*/
+
+/** Examine attribute in working directory, then index */
#define GIT_ATTR_CHECK_FILE_THEN_INDEX 0
+/** Examine attribute in index, then working directory */
#define GIT_ATTR_CHECK_INDEX_THEN_FILE 1
+/** Examine attributes only in the index */
#define GIT_ATTR_CHECK_INDEX_ONLY 2
/**
@@ -132,8 +140,12 @@ GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr);
* Passing the `GIT_ATTR_CHECK_INCLUDE_COMMIT` flag will use attributes
* from a `.gitattributes` file in a specific commit.
*/
+
+/** Ignore system attributes */
#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2)
+/** Honor `.gitattributes` in the HEAD revision */
#define GIT_ATTR_CHECK_INCLUDE_HEAD (1 << 3)
+/** Honor `.gitattributes` in a specific commit */
#define GIT_ATTR_CHECK_INCLUDE_COMMIT (1 << 4)
/**
@@ -158,7 +170,10 @@ typedef struct {
git_oid attr_commit_id;
} git_attr_options;
+/** Current version for the `git_attr_options` structure */
#define GIT_ATTR_OPTIONS_VERSION 1
+
+/** Static constructor for `git_attr_options` */
#define GIT_ATTR_OPTIONS_INIT {GIT_ATTR_OPTIONS_VERSION}
/**
diff --git a/include/git2/blame.h b/include/git2/blame.h
index cb961a56209..f3e66924c89 100644
--- a/include/git2/blame.h
+++ b/include/git2/blame.h
@@ -13,9 +13,14 @@
/**
* @file git2/blame.h
- * @brief Git blame routines
+ * @brief Specify a file's most recent changes per-line
* @defgroup git_blame Git blame routines
* @ingroup Git
+ *
+ * Producing a "blame" (or "annotated history") decorates individual
+ * lines in a file with the commit that introduced that particular line
+ * of changes. This can be useful to indicate when and why a particular
+ * change was made.
* @{
*/
GIT_BEGIN_DECL
@@ -87,7 +92,7 @@ typedef struct git_blame_options {
unsigned int version;
/** A combination of `git_blame_flag_t` */
- uint32_t flags;
+ unsigned int flags;
/**
* The lower bound on the number of alphanumeric characters that
@@ -122,7 +127,10 @@ typedef struct git_blame_options {
size_t max_line;
} git_blame_options;
+/** Current version for the `git_blame_options` structure */
#define GIT_BLAME_OPTIONS_VERSION 1
+
+/** Static constructor for `git_blame_options` */
#define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION}
/**
@@ -165,6 +173,13 @@ typedef struct git_blame_hunk {
*/
git_signature *final_signature;
+ /**
+ * The committer of `final_commit_id`. If `GIT_BLAME_USE_MAILMAP` has
+ * been specified, it will contain the canonical real name and email
+ * address.
+ */
+ git_signature *final_committer;
+
/**
* The OID of the commit where this hunk was found.
* This will usually be the same as `final_commit_id`, except when
@@ -190,6 +205,18 @@ typedef struct git_blame_hunk {
*/
git_signature *orig_signature;
+ /**
+ * The committer of `orig_commit_id`. If `GIT_BLAME_USE_MAILMAP` has
+ * been specified, it will contain the canonical real name and email
+ * address.
+ */
+ git_signature *orig_committer;
+
+ /*
+ * The summary of the commit.
+ */
+ const char *summary;
+
/**
* The 1 iff the hunk has been tracked to a boundary commit (the root,
* or the commit specified in git_blame_options.oldest_commit)
@@ -197,16 +224,75 @@ typedef struct git_blame_hunk {
char boundary;
} git_blame_hunk;
+/**
+ * Structure that represents a line in a blamed file.
+ */
+typedef struct git_blame_line {
+ const char *ptr;
+ size_t len;
+} git_blame_line;
/** Opaque structure to hold blame results */
typedef struct git_blame git_blame;
+/**
+ * Gets the number of lines that exist in the blame structure.
+ *
+ * @param blame The blame structure to query.
+ * @return The number of line.
+ */
+GIT_EXTERN(size_t) git_blame_linecount(git_blame *blame);
+
/**
* Gets the number of hunks that exist in the blame structure.
*
* @param blame The blame structure to query.
* @return The number of hunks.
*/
+GIT_EXTERN(size_t) git_blame_hunkcount(git_blame *blame);
+
+/**
+ * Gets the blame hunk at the given index.
+ *
+ * @param blame the blame structure to query
+ * @param index index of the hunk to retrieve
+ * @return the hunk at the given index, or NULL on error
+ */
+GIT_EXTERN(const git_blame_hunk *) git_blame_hunk_byindex(
+ git_blame *blame,
+ size_t index);
+
+/**
+ * Gets the hunk that relates to the given line number in the newest
+ * commit.
+ *
+ * @param blame the blame structure to query
+ * @param lineno the (1-based) line number to find a hunk for
+ * @return the hunk that contains the given line, or NULL on error
+ */
+GIT_EXTERN(const git_blame_hunk *) git_blame_hunk_byline(
+ git_blame *blame,
+ size_t lineno);
+
+/**
+ * Gets the information about the line in the blame.
+ *
+ * @param blame the blame structure to query
+ * @param idx the (1-based) line number
+ * @return the blamed line, or NULL on error
+ */
+GIT_EXTERN(const git_blame_line *) git_blame_line_byindex(
+ git_blame *blame,
+ size_t idx);
+
+#ifndef GIT_DEPRECATE_HARD
+/**
+ * Gets the number of hunks that exist in the blame structure.
+ *
+ * @param blame The blame structure to query.
+ * @return The number of hunks.
+ */
+
GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame);
/**
@@ -216,9 +302,9 @@ GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame);
* @param index index of the hunk to retrieve
* @return the hunk at the given index, or NULL on error
*/
-GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byindex(
- git_blame *blame,
- uint32_t index);
+GIT_EXTERN(const git_blame_hunk *) git_blame_get_hunk_byindex(
+ git_blame *blame,
+ uint32_t index);
/**
* Gets the hunk that relates to the given line number in the newest commit.
@@ -227,39 +313,58 @@ GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byindex(
* @param lineno the (1-based) line number to find a hunk for
* @return the hunk that contains the given line, or NULL on error
*/
-GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byline(
- git_blame *blame,
- size_t lineno);
+GIT_EXTERN(const git_blame_hunk *) git_blame_get_hunk_byline(
+ git_blame *blame,
+ size_t lineno);
+#endif
/**
- * Get the blame for a single file.
+ * Get the blame for a single file in the repository.
*
* @param out pointer that will receive the blame object
* @param repo repository whose history is to be walked
* @param path path to file to consider
- * @param options options for the blame operation. If NULL, this is treated as
- * though GIT_BLAME_OPTIONS_INIT were passed.
- * @return 0 on success, or an error code. (use git_error_last for information
- * about the error.)
+ * @param options options for the blame operation or NULL
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_blame_file(
- git_blame **out,
- git_repository *repo,
- const char *path,
- git_blame_options *options);
+ git_blame **out,
+ git_repository *repo,
+ const char *path,
+ git_blame_options *options);
+/**
+ * Get the blame for a single file in the repository, using the specified
+ * buffer contents as the uncommitted changes of the file (the working
+ * directory contents).
+ *
+ * @param out pointer that will receive the blame object
+ * @param repo repository whose history is to be walked
+ * @param path path to file to consider
+ * @param contents the uncommitted changes
+ * @param contents_len the length of the changes buffer
+ * @param options options for the blame operation or NULL
+ * @return 0 on success, or an error code
+ */
+GIT_EXTERN(int) git_blame_file_from_buffer(
+ git_blame **out,
+ git_repository *repo,
+ const char *path,
+ const char *contents,
+ size_t contents_len,
+ git_blame_options *options);
/**
- * Get blame data for a file that has been modified in memory. The `reference`
- * parameter is a pre-calculated blame for the in-odb history of the file. This
- * means that once a file blame is completed (which can be expensive), updating
- * the buffer blame is very fast.
+ * Get blame data for a file that has been modified in memory. The `blame`
+ * parameter is a pre-calculated blame for the in-odb history of the file.
+ * This means that once a file blame is completed (which can be expensive),
+ * updating the buffer blame is very fast.
*
- * Lines that differ between the buffer and the committed version are marked as
- * having a zero OID for their final_commit_id.
+ * Lines that differ between the buffer and the committed version are
+ * marked as having a zero OID for their final_commit_id.
*
* @param out pointer that will receive the resulting blame data
- * @param reference cached blame from the history of the file (usually the output
+ * @param base cached blame from the history of the file (usually the output
* from git_blame_file)
* @param buffer the (possibly) modified contents of the file
* @param buffer_len number of valid bytes in the buffer
@@ -267,10 +372,10 @@ GIT_EXTERN(int) git_blame_file(
* about the error)
*/
GIT_EXTERN(int) git_blame_buffer(
- git_blame **out,
- git_blame *reference,
- const char *buffer,
- size_t buffer_len);
+ git_blame **out,
+ git_blame *base,
+ const char *buffer,
+ size_t buffer_len);
/**
* Free memory allocated by git_blame_file or git_blame_buffer.
diff --git a/include/git2/blob.h b/include/git2/blob.h
index 6db85f38d1b..0ed168555ec 100644
--- a/include/git2/blob.h
+++ b/include/git2/blob.h
@@ -15,9 +15,13 @@
/**
* @file git2/blob.h
- * @brief Git blob load and write routines
+ * @brief A blob represents a file in a git repository.
* @defgroup git_blob Git blob load and write routines
* @ingroup Git
+ *
+ * A blob represents a file in a git repository. This is the raw data
+ * as it is stored in the repository itself. Blobs may be "filtered"
+ * to produce the on-disk content.
* @{
*/
GIT_BEGIN_DECL
@@ -25,12 +29,15 @@ GIT_BEGIN_DECL
/**
* Lookup a blob object from a repository.
*
- * @param blob pointer to the looked up blob
+ * @param[out] blob pointer to the looked up blob
* @param repo the repo to use when locating the blob.
* @param id identity of the blob to locate.
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git_oid *id);
+GIT_EXTERN(int) git_blob_lookup(
+ git_blob **blob,
+ git_repository *repo,
+ const git_oid *id);
/**
* Lookup a blob object from a repository,
@@ -38,7 +45,7 @@ GIT_EXTERN(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git
*
* @see git_object_lookup_prefix
*
- * @param blob pointer to the looked up blob
+ * @param[out] blob pointer to the looked up blob
* @param repo the repo to use when locating the blob.
* @param id identity of the blob to locate.
* @param len the length of the short identifier
@@ -84,7 +91,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob);
* time.
*
* @param blob pointer to the blob
- * @return the pointer, or NULL on error
+ * @return @type `unsigned char *` the pointer, or NULL on error
*/
GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
@@ -92,12 +99,14 @@ GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
* Get the size in bytes of the contents of a blob
*
* @param blob pointer to the blob
- * @return size on bytes
+ * @return size in bytes
*/
GIT_EXTERN(git_object_size_t) git_blob_rawsize(const git_blob *blob);
/**
* Flags to control the functionality of `git_blob_filter`.
+ *
+ * @flags
*/
typedef enum {
/** When set, filters will not be applied to binary files. */
@@ -128,16 +137,34 @@ typedef enum {
* Initialize with `GIT_BLOB_FILTER_OPTIONS_INIT`. Alternatively, you can
* use `git_blob_filter_options_init`.
*
+ * @options[version] GIT_BLOB_FILTER_OPTIONS_VERSION
+ * @options[init_macro] GIT_BLOB_FILTER_OPTIONS_INIT
+ * @options[init_function] git_blob_filter_options_init
*/
typedef struct {
+ /** Version number of the options structure. */
int version;
- /** Flags to control the filtering process, see `git_blob_filter_flag_t` above */
+ /**
+ * Flags to control the filtering process, see `git_blob_filter_flag_t` above.
+ *
+ * @type[flags] git_blob_filter_flag_t
+ */
uint32_t flags;
#ifdef GIT_DEPRECATE_HARD
+ /**
+ * Unused and reserved for ABI compatibility.
+ *
+ * @deprecated this value should not be set
+ */
void *reserved;
#else
+ /**
+ * This value is unused and reserved for API compatibility.
+ *
+ * @deprecated this value should not be set
+ */
git_oid *commit_id;
#endif
@@ -148,8 +175,18 @@ typedef struct {
git_oid attr_commit_id;
} git_blob_filter_options;
+/**
+ * The current version number for the `git_blob_filter_options` structure ABI.
+ */
#define GIT_BLOB_FILTER_OPTIONS_VERSION 1
-#define GIT_BLOB_FILTER_OPTIONS_INIT {GIT_BLOB_FILTER_OPTIONS_VERSION, GIT_BLOB_FILTER_CHECK_FOR_BINARY}
+
+/**
+ * The default values for `git_blob_filter_options`.
+ */
+#define GIT_BLOB_FILTER_OPTIONS_INIT { \
+ GIT_BLOB_FILTER_OPTIONS_VERSION, \
+ GIT_BLOB_FILTER_CHECK_FOR_BINARY \
+ }
/**
* Initialize git_blob_filter_options structure
@@ -158,10 +195,12 @@ typedef struct {
* to creating an instance with `GIT_BLOB_FILTER_OPTIONS_INIT`.
*
* @param opts The `git_blob_filter_options` struct to initialize.
- * @param version The struct version; pass `GIT_BLOB_FILTER_OPTIONS_VERSION`.
+ * @param version The struct version; pass GIT_BLOB_FILTER_OPTIONS_VERSION
* @return Zero on success; -1 on failure.
*/
-GIT_EXTERN(int) git_blob_filter_options_init(git_blob_filter_options *opts, unsigned int version);
+GIT_EXTERN(int) git_blob_filter_options_init(
+ git_blob_filter_options *opts,
+ unsigned int version);
/**
* Get a buffer with the filtered content of a blob.
@@ -171,7 +210,7 @@ GIT_EXTERN(int) git_blob_filter_options_init(git_blob_filter_options *opts, unsi
* CRLF filtering or other types of changes depending on the file
* attributes set for the blob and the content detected in it.
*
- * The output is written into a `git_buf` which the caller must free
+ * The output is written into a `git_buf` which the caller must dispose
* when done (via `git_buf_dispose`).
*
* If no filters need to be applied, then the `out` buffer will just
@@ -183,7 +222,7 @@ GIT_EXTERN(int) git_blob_filter_options_init(git_blob_filter_options *opts, unsi
* @param blob Pointer to the blob
* @param as_path Path used for file attribute lookups, etc.
* @param opts Options to use for filtering the blob
- * @return 0 on success or an error code
+ * @return @type[enum] git_error_code 0 on success or an error code
*/
GIT_EXTERN(int) git_blob_filter(
git_buf *out,
@@ -192,10 +231,10 @@ GIT_EXTERN(int) git_blob_filter(
git_blob_filter_options *opts);
/**
- * Read a file from the working folder of a repository
- * and write it to the Object Database as a loose blob
+ * Read a file from the working folder of a repository and write it
+ * to the object database.
*
- * @param id return the id of the written blob
+ * @param[out] id return the id of the written blob
* @param repo repository where the blob will be written.
* this repository cannot be bare
* @param relative_path file from which the blob will be created,
@@ -205,19 +244,23 @@ GIT_EXTERN(int) git_blob_filter(
GIT_EXTERN(int) git_blob_create_from_workdir(git_oid *id, git_repository *repo, const char *relative_path);
/**
- * Read a file from the filesystem and write its content
- * to the Object Database as a loose blob
+ * Read a file from the filesystem (not necessarily inside the
+ * working folder of the repository) and write it to the object
+ * database.
*
- * @param id return the id of the written blob
+ * @param[out] id return the id of the written blob
* @param repo repository where the blob will be written.
* this repository can be bare or not
* @param path file from which the blob will be created
* @return 0 or an error code
*/
-GIT_EXTERN(int) git_blob_create_from_disk(git_oid *id, git_repository *repo, const char *path);
+GIT_EXTERN(int) git_blob_create_from_disk(
+ git_oid *id,
+ git_repository *repo,
+ const char *path);
/**
- * Create a stream to write a new blob into the object db
+ * Create a stream to write a new blob into the object database.
*
* This function may need to buffer the data on disk and will in
* general not be the right choice if you know the size of the data
@@ -234,7 +277,7 @@ GIT_EXTERN(int) git_blob_create_from_disk(git_oid *id, git_repository *repo, con
* what git filters should be applied to the object before it is written
* to the object database.
*
- * @param out the stream into which to write
+ * @param[out] out the stream into which to write
* @param repo Repository where the blob will be written.
* This repository can be bare or not.
* @param hintpath If not NULL, will be used to select data filters
@@ -247,11 +290,11 @@ GIT_EXTERN(int) git_blob_create_from_stream(
const char *hintpath);
/**
- * Close the stream and write the blob to the object db
+ * Close the stream and finalize writing the blob to the object database.
*
* The stream will be closed and freed.
*
- * @param out the id of the new blob
+ * @param[out] out the id of the new blob
* @param stream the stream to close
* @return 0 or an error code
*/
@@ -260,9 +303,9 @@ GIT_EXTERN(int) git_blob_create_from_stream_commit(
git_writestream *stream);
/**
- * Write an in-memory buffer to the ODB as a blob
+ * Write an in-memory buffer to the object database as a blob.
*
- * @param id return the id of the written blob
+ * @param[out] id return the id of the written blob
* @param repo repository where the blob will be written
* @param buffer data to be written into the blob
* @param len length of the data
@@ -272,14 +315,14 @@ GIT_EXTERN(int) git_blob_create_from_buffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len);
/**
- * Determine if the blob content is most certainly binary or not.
+ * Determine if the blob content is most likely binary or not.
*
* The heuristic used to guess if a file is binary is taken from core git:
* Searching for NUL bytes and looking for a reasonable ratio of printable
* to non-printable characters among the first 8000 bytes.
*
* @param blob The blob which content should be analyzed
- * @return 1 if the content of the blob is detected
+ * @return @type bool 1 if the content of the blob is detected
* as binary; 0 otherwise.
*/
GIT_EXTERN(int) git_blob_is_binary(const git_blob *blob);
@@ -300,7 +343,7 @@ GIT_EXTERN(int) git_blob_data_is_binary(const char *data, size_t len);
* Create an in-memory copy of a blob. The copy must be explicitly
* free'd or it will leak.
*
- * @param out Pointer to store the copy of the object
+ * @param[out] out Pointer to store the copy of the object
* @param source Original object to copy
* @return 0.
*/
diff --git a/include/git2/branch.h b/include/git2/branch.h
index 27c6fa15727..56d737d0fb0 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -13,9 +13,15 @@
/**
* @file git2/branch.h
- * @brief Git branch parsing routines
+ * @brief Branch creation and handling
* @defgroup git_branch Git branch management
* @ingroup Git
+ *
+ * A branch is a specific type of reference, at any particular time,
+ * a git working directory typically is said to have a branch "checked out",
+ * meaning that commits that are created will be made "on" a branch.
+ * This occurs by updating the branch reference to point to the new
+ * commit. The checked out branch is indicated by the `HEAD` meta-ref.
* @{
*/
GIT_BEGIN_DECL
@@ -33,18 +39,13 @@ GIT_BEGIN_DECL
* See `git_tag_create()` for rules about valid names.
*
* @param out Pointer where to store the underlying reference.
- *
* @param repo the repository to create the branch in.
- *
* @param branch_name Name for the branch; this name is
- * validated for consistency. It should also not conflict with
- * an already existing branch name.
- *
+ * validated for consistency. It should also not conflict with
+ * an already existing branch name.
* @param target Commit to which this branch should point. This object
- * must belong to the given `repo`.
- *
+ * must belong to the given `repo`.
* @param force Overwrite existing branch.
- *
* @return 0, GIT_EINVALIDSPEC or an error code.
* A proper reference is written in the refs/heads namespace
* pointing to the provided target commit.
@@ -63,15 +64,21 @@ GIT_EXTERN(int) git_branch_create(
* commit, which lets you specify which extended sha syntax string was
* specified by a user, allowing for more exact reflog messages.
*
- * See the documentation for `git_branch_create()`.
- *
- * @see git_branch_create
+ * @param ref_out Pointer where to store the underlying reference.
+ * @param repo the repository to create the branch in.
+ * @param branch_name Name for the branch; this name is
+ * validated for consistency. It should also not conflict with
+ * an already existing branch name.
+ * @param target Annotated commit to which this branch should point. This
+ * object must belong to the given `repo`.
+ * @param force Overwrite existing branch.
+ * @return 0, GIT_EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_branch_create_from_annotated(
git_reference **ref_out,
- git_repository *repository,
+ git_repository *repo,
const char *branch_name,
- const git_annotated_commit *commit,
+ const git_annotated_commit *target,
int force);
/**
@@ -222,7 +229,7 @@ GIT_EXTERN(int) git_branch_upstream(
* @param branch the branch to configure
* @param branch_name remote-tracking or local branch to set as upstream.
*
- * @return 0 on success; GIT_ENOTFOUND if there's no branch named `branch_name`
+ * @return @type git_error_t 0 on success; GIT_ENOTFOUND if there's no branch named `branch_name`
* or an error code
*/
GIT_EXTERN(int) git_branch_set_upstream(
diff --git a/include/git2/buffer.h b/include/git2/buffer.h
index 9fa97203457..3fe4f854857 100644
--- a/include/git2/buffer.h
+++ b/include/git2/buffer.h
@@ -11,9 +11,12 @@
/**
* @file git2/buffer.h
- * @brief Buffer export structure
- *
+ * @brief A data structure to return data to callers
* @ingroup Git
+ *
+ * The `git_buf` buffer is used to return arbitrary data - typically
+ * strings - to callers. Callers are responsible for freeing the memory
+ * in a buffer with the `git_buf_dispose` function.
* @{
*/
GIT_BEGIN_DECL
@@ -67,8 +70,7 @@ typedef struct {
*/
GIT_EXTERN(void) git_buf_dispose(git_buf *buffer);
-GIT_END_DECL
-
/** @} */
+GIT_END_DECL
#endif
diff --git a/include/git2/cert.h b/include/git2/cert.h
index 05213a57192..7b91b638d4f 100644
--- a/include/git2/cert.h
+++ b/include/git2/cert.h
@@ -12,7 +12,7 @@
/**
* @file git2/cert.h
- * @brief Git certificate objects
+ * @brief TLS and SSH certificate handling
* @defgroup git_cert Certificate objects
* @ingroup Git
* @{
@@ -169,4 +169,5 @@ typedef struct {
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index 9f834111a67..bdea928459a 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -13,9 +13,13 @@
/**
* @file git2/checkout.h
- * @brief Git checkout routines
+ * @brief Update the contents of the working directory
* @defgroup git_checkout Git checkout routines
* @ingroup Git
+ *
+ * Update the contents of the working directory, or a subset of the
+ * files in the working directory, to point to the data in the index
+ * or a specific commit.
* @{
*/
GIT_BEGIN_DECL
@@ -31,17 +35,11 @@ GIT_BEGIN_DECL
* check out, the "baseline" tree of what was checked out previously, the
* working directory for actual files, and the index for staged changes.
*
- * You give checkout one of three strategies for update:
- *
- * - `GIT_CHECKOUT_NONE` is a dry-run strategy that checks for conflicts,
- * etc., but doesn't make any actual changes.
- *
- * - `GIT_CHECKOUT_FORCE` is at the opposite extreme, taking any action to
- * make the working directory match the target (including potentially
- * discarding modified files).
+ * You give checkout one of two strategies for update:
*
- * - `GIT_CHECKOUT_SAFE` is between these two options, it will only make
- * modifications that will not lose changes.
+ * - `GIT_CHECKOUT_SAFE` is the default, and similar to git's default,
+ * which will make modifications that will not lose changes in the
+ * working directory.
*
* | target == baseline | target != baseline |
* ---------------------|-----------------------|----------------------|
@@ -55,6 +53,10 @@ GIT_BEGIN_DECL
* baseline present | | |
* ---------------------|-----------------------|----------------------|
*
+ * - `GIT_CHECKOUT_FORCE` will take any action to make the working
+ * directory match the target (including potentially discarding
+ * modified files).
+ *
* To emulate `git checkout`, use `GIT_CHECKOUT_SAFE` with a checkout
* notification callback (see below) that displays information about dirty
* files. The default behavior will cancel checkout on conflicts.
@@ -69,6 +71,9 @@ GIT_BEGIN_DECL
*
* There are some additional flags to modify the behavior of checkout:
*
+ * - `GIT_CHECKOUT_DRY_RUN` is a dry-run strategy that checks for conflicts,
+ * etc., but doesn't make any actual changes.
+ *
* - GIT_CHECKOUT_ALLOW_CONFLICTS makes SAFE mode apply safe file updates
* even if there are conflicts (instead of cancelling the checkout).
*
@@ -102,29 +107,24 @@ GIT_BEGIN_DECL
* files or folders that fold to the same name on case insensitive
* filesystems. This can cause files to retain their existing names
* and write through existing symbolic links.
+ *
+ * @flags
*/
typedef enum {
- GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */
-
/**
* Allow safe updates that cannot overwrite uncommitted data.
- * If the uncommitted changes don't conflict with the checked out files,
- * the checkout will still proceed, leaving the changes intact.
- *
- * Mutually exclusive with GIT_CHECKOUT_FORCE.
- * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE.
+ * If the uncommitted changes don't conflict with the checked
+ * out files, the checkout will still proceed, leaving the
+ * changes intact.
*/
- GIT_CHECKOUT_SAFE = (1u << 0),
+ GIT_CHECKOUT_SAFE = 0,
/**
- * Allow all updates to force working directory to look like index.
- *
- * Mutually exclusive with GIT_CHECKOUT_SAFE.
- * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE.
+ * Allow all updates to force working directory to look like
+ * the index, potentially losing data in the process.
*/
GIT_CHECKOUT_FORCE = (1u << 1),
-
/** Allow checkout to recreate missing files */
GIT_CHECKOUT_RECREATE_MISSING = (1u << 2),
@@ -178,8 +178,9 @@ typedef enum {
GIT_CHECKOUT_DONT_WRITE_INDEX = (1u << 23),
/**
- * Show what would be done by a checkout. Stop after sending
- * notifications; don't update the working directory or index.
+ * Perform a "dry run", reporting what _would_ be done but
+ * without actually making changes in the working directory
+ * or the index.
*/
GIT_CHECKOUT_DRY_RUN = (1u << 24),
@@ -187,6 +188,14 @@ typedef enum {
GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3 = (1u << 25),
/**
+ * Do not do a checkout and do not fire callbacks; this is primarily
+ * useful only for internal functions that will perform the
+ * checkout themselves but need to pass checkout options into
+ * another function, for example, `git_clone`.
+ */
+ GIT_CHECKOUT_NONE = (1u << 30),
+
+ /*
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
@@ -194,7 +203,6 @@ typedef enum {
GIT_CHECKOUT_UPDATE_SUBMODULES = (1u << 16),
/** Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED) */
GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED = (1u << 17)
-
} git_checkout_strategy_t;
/**
@@ -210,6 +218,8 @@ typedef enum {
* Notification callbacks are made prior to modifying any files on disk,
* so canceling on any notification will still happen prior to any files
* being modified.
+ *
+ * @flags
*/
typedef enum {
GIT_CHECKOUT_NOTIFY_NONE = 0,
@@ -251,7 +261,17 @@ typedef struct {
size_t chmod_calls;
} git_checkout_perfdata;
-/** Checkout notification callback function */
+/**
+ * Checkout notification callback function.
+ *
+ * @param why the notification reason
+ * @param path the path to the file being checked out
+ * @param baseline the baseline's diff file information
+ * @param target the checkout target diff file information
+ * @param workdir the working directory diff file information
+ * @param payload the user-supplied callback payload
+ * @return 0 on success, or an error code
+ */
typedef int GIT_CALLBACK(git_checkout_notify_cb)(
git_checkout_notify_t why,
const char *path,
@@ -260,14 +280,26 @@ typedef int GIT_CALLBACK(git_checkout_notify_cb)(
const git_diff_file *workdir,
void *payload);
-/** Checkout progress notification function */
+/**
+ * Checkout progress notification function.
+ *
+ * @param path the path to the file being checked out
+ * @param completed_steps number of checkout steps completed
+ * @param total_steps number of total steps in the checkout process
+ * @param payload the user-supplied callback payload
+ */
typedef void GIT_CALLBACK(git_checkout_progress_cb)(
const char *path,
size_t completed_steps,
size_t total_steps,
void *payload);
-/** Checkout perfdata notification function */
+/**
+ * Checkout performance data reporting function.
+ *
+ * @param perfdata the performance data for the checkout
+ * @param payload the user-supplied callback payload
+ */
typedef void GIT_CALLBACK(git_checkout_perfdata_cb)(
const git_checkout_perfdata *perfdata,
void *payload);
@@ -278,10 +310,18 @@ typedef void GIT_CALLBACK(git_checkout_perfdata_cb)(
* Initialize with `GIT_CHECKOUT_OPTIONS_INIT`. Alternatively, you can
* use `git_checkout_options_init`.
*
+ * @options[version] GIT_CHECKOUT_OPTIONS_VERSION
+ * @options[init_macro] GIT_CHECKOUT_OPTIONS_INIT
+ * @options[init_function] git_checkout_options_init
*/
typedef struct git_checkout_options {
unsigned int version; /**< The version */
+ /**
+ * Checkout strategy. Default is a safe checkout.
+ *
+ * @type[flags] git_checkout_strategy_t
+ */
unsigned int checkout_strategy; /**< default will be a safe checkout */
int disable_filters; /**< don't apply filters like CRLF conversion */
@@ -289,7 +329,13 @@ typedef struct git_checkout_options {
unsigned int file_mode; /**< default is 0644 or 0755 as dictated by blob */
int file_open_flags; /**< default is O_CREAT | O_TRUNC | O_WRONLY */
- unsigned int notify_flags; /**< see `git_checkout_notify_t` above */
+ /**
+ * Checkout notification flags specify what operations the notify
+ * callback is invoked for.
+ *
+ * @type[flags] git_checkout_notify_t
+ */
+ unsigned int notify_flags;
/**
* Optional callback to get notifications on specific file states.
@@ -344,8 +390,12 @@ typedef struct git_checkout_options {
void *perfdata_payload;
} git_checkout_options;
+
+/** Current version for the `git_checkout_options` structure */
#define GIT_CHECKOUT_OPTIONS_VERSION 1
-#define GIT_CHECKOUT_OPTIONS_INIT {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE}
+
+/** Static constructor for `git_checkout_options` */
+#define GIT_CHECKOUT_OPTIONS_INIT { GIT_CHECKOUT_OPTIONS_VERSION }
/**
* Initialize git_checkout_options structure
@@ -414,4 +464,5 @@ GIT_EXTERN(int) git_checkout_tree(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/cherrypick.h b/include/git2/cherrypick.h
index 0e6a252e6f1..e6cf99ea51d 100644
--- a/include/git2/cherrypick.h
+++ b/include/git2/cherrypick.h
@@ -13,9 +13,12 @@
/**
* @file git2/cherrypick.h
- * @brief Git cherry-pick routines
+ * @brief Cherry-pick the contents of an individual commit
* @defgroup git_cherrypick Git cherry-pick routines
* @ingroup Git
+ *
+ * "Cherry-pick" will attempts to re-apply the changes in an
+ * individual commit to the current index and working directory.
* @{
*/
GIT_BEGIN_DECL
@@ -33,8 +36,13 @@ typedef struct {
git_checkout_options checkout_opts; /**< Options for the checkout */
} git_cherrypick_options;
+/** Current version for the `git_cherrypick_options` structure */
#define GIT_CHERRYPICK_OPTIONS_VERSION 1
-#define GIT_CHERRYPICK_OPTIONS_INIT {GIT_CHERRYPICK_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
+
+/** Static constructor for `git_cherrypick_options` */
+#define GIT_CHERRYPICK_OPTIONS_INIT { \
+ GIT_CHERRYPICK_OPTIONS_VERSION, 0, \
+ GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT }
/**
* Initialize git_cherrypick_options structure
@@ -89,4 +97,3 @@ GIT_EXTERN(int) git_cherrypick(
GIT_END_DECL
#endif
-
diff --git a/include/git2/clone.h b/include/git2/clone.h
index 3481f254c9d..b7a47ab484b 100644
--- a/include/git2/clone.h
+++ b/include/git2/clone.h
@@ -17,9 +17,13 @@
/**
* @file git2/clone.h
- * @brief Git cloning routines
+ * @brief Clone a remote repository to the local disk
* @defgroup git_clone Git cloning routines
* @ingroup Git
+ *
+ * Clone will take a remote repository - located on a remote server
+ * accessible by HTTPS or SSH, or a repository located elsewhere on
+ * the local disk - and place a copy in the given local path.
* @{
*/
GIT_BEGIN_DECL
@@ -59,7 +63,7 @@ typedef enum {
* Callers of git_clone may provide a function matching this signature to override
* the remote creation and customization process during a clone operation.
*
- * @param out the resulting remote
+ * @param[out] out the resulting remote
* @param repo the repository in which to create the remote
* @param name the remote's name
* @param url the remote's url
@@ -81,7 +85,7 @@ typedef int GIT_CALLBACK(git_remote_create_cb)(
* to override the repository creation and customization process
* during a clone operation.
*
- * @param out the resulting repository
+ * @param[out] out the resulting repository
* @param path path in which to create the repository
* @param bare whether the repository is bare. This is the value from the clone options
* @param payload payload specified by the options
@@ -99,14 +103,17 @@ typedef int GIT_CALLBACK(git_repository_create_cb)(
* Initialize with `GIT_CLONE_OPTIONS_INIT`. Alternatively, you can
* use `git_clone_options_init`.
*
+ * @options[version] GIT_CLONE_OPTIONS_VERSION
+ * @options[init_macro] GIT_CLONE_OPTIONS_INIT
+ * @options[init_function] git_clone_options_init
*/
typedef struct git_clone_options {
unsigned int version;
/**
* These options are passed to the checkout step. To disable
- * checkout, set the `checkout_strategy` to
- * `GIT_CHECKOUT_NONE`.
+ * checkout, set the `checkout_strategy` to `GIT_CHECKOUT_NONE`
+ * or `GIT_CHECKOUT_DRY_RUN`.
*/
git_checkout_options checkout_opts;
@@ -163,10 +170,14 @@ typedef struct git_clone_options {
void *remote_cb_payload;
} git_clone_options;
+/** Current version for the `git_clone_options` structure */
#define GIT_CLONE_OPTIONS_VERSION 1
-#define GIT_CLONE_OPTIONS_INIT { GIT_CLONE_OPTIONS_VERSION, \
- { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \
- GIT_FETCH_OPTIONS_INIT }
+
+/** Static constructor for `git_clone_options` */
+#define GIT_CLONE_OPTIONS_INIT \
+ { GIT_CLONE_OPTIONS_VERSION, \
+ GIT_CHECKOUT_OPTIONS_INIT, \
+ GIT_FETCH_OPTIONS_INIT }
/**
* Initialize git_clone_options structure
@@ -189,7 +200,11 @@ GIT_EXTERN(int) git_clone_options_init(
* git's defaults. You can use the options in the callback to
* customize how these are created.
*
- * @param out pointer that will receive the resulting repository object
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
+ * @param[out] out pointer that will receive the resulting repository object
* @param url the remote repository to clone
* @param local_path local directory to clone to
* @param options configuration options for the clone. If NULL, the
@@ -206,4 +221,5 @@ GIT_EXTERN(int) git_clone(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/commit.h b/include/git2/commit.h
index ef38c66e6cc..b998e188974 100644
--- a/include/git2/commit.h
+++ b/include/git2/commit.h
@@ -14,9 +14,13 @@
/**
* @file git2/commit.h
- * @brief Git commit parsing, formatting routines
+ * @brief A representation of a set of changes in the repository
* @defgroup git_commit Git commit parsing, formatting routines
* @ingroup Git
+ *
+ * A commit represents a set of changes made to the files within a
+ * repository, and metadata about who made the changes, and when the
+ * changes were made.
* @{
*/
GIT_BEGIN_DECL
@@ -366,7 +370,7 @@ GIT_EXTERN(int) git_commit_create(
const char *message,
const git_tree *tree,
size_t parent_count,
- git_commit * const parents[]);
+ const git_commit *parents[]);
/**
* Create new commit in the repository using a variable argument list.
@@ -380,7 +384,38 @@ GIT_EXTERN(int) git_commit_create(
*
* All other parameters remain the same as `git_commit_create()`.
*
- * @see git_commit_create
+ * @param id Pointer in which to store the OID of the newly created commit
+ *
+ * @param repo Repository where to store the commit
+ *
+ * @param update_ref If not NULL, name of the reference that
+ * will be updated to point to this commit. If the reference
+ * is not direct, it will be resolved to a direct reference.
+ * Use "HEAD" to update the HEAD of the current branch and
+ * make it point to this commit. If the reference doesn't
+ * exist yet, it will be created. If it does exist, the first
+ * parent must be the tip of this branch.
+ *
+ * @param author Signature with author and author time of commit
+ *
+ * @param committer Signature with committer and * commit time of commit
+ *
+ * @param message_encoding The encoding for the message in the
+ * commit, represented with a standard encoding name.
+ * E.g. "UTF-8". If NULL, no encoding header is written and
+ * UTF-8 is assumed.
+ *
+ * @param message Full message for this commit
+ *
+ * @param tree An instance of a `git_tree` object that will
+ * be used as the tree for the commit. This tree object must
+ * also be owned by the given `repo`.
+ *
+ * @param parent_count Number of parents for this commit
+ *
+ * @return 0 or an error code
+ * The created commit will be written to the Object Database and
+ * the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_create_v(
git_oid *id,
@@ -416,7 +451,10 @@ typedef struct {
const char *message_encoding;
} git_commit_create_options;
+/** Current version for the `git_commit_create_options` structure */
#define GIT_COMMIT_CREATE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_commit_create_options` */
#define GIT_COMMIT_CREATE_OPTIONS_INIT { GIT_COMMIT_CREATE_OPTIONS_VERSION }
/**
@@ -456,7 +494,36 @@ GIT_EXTERN(int) git_commit_create_from_stage(
*
* All parameters have the same meanings as in `git_commit_create()`.
*
- * @see git_commit_create
+ * @param id Pointer in which to store the OID of the newly created commit
+ *
+ * @param commit_to_amend The commit to amend
+ *
+ * @param update_ref If not NULL, name of the reference that
+ * will be updated to point to this commit. If the reference
+ * is not direct, it will be resolved to a direct reference.
+ * Use "HEAD" to update the HEAD of the current branch and
+ * make it point to this commit. If the reference doesn't
+ * exist yet, it will be created. If it does exist, the first
+ * parent must be the tip of this branch.
+ *
+ * @param author Signature with author and author time of commit
+ *
+ * @param committer Signature with committer and * commit time of commit
+ *
+ * @param message_encoding The encoding for the message in the
+ * commit, represented with a standard encoding name.
+ * E.g. "UTF-8". If NULL, no encoding header is written and
+ * UTF-8 is assumed.
+ *
+ * @param message Full message for this commit
+ *
+ * @param tree An instance of a `git_tree` object that will
+ * be used as the tree for the commit. This tree object must
+ * also be owned by the given `repo`.
+ *
+ * @return 0 or an error code
+ * The created commit will be written to the Object Database and
+ * the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_amend(
git_oid *id,
@@ -512,7 +579,7 @@ GIT_EXTERN(int) git_commit_create_buffer(
const char *message,
const git_tree *tree,
size_t parent_count,
- git_commit * const parents[]);
+ const git_commit *parents[]);
/**
* Create a commit object from the given buffer and signature
@@ -581,7 +648,7 @@ typedef int (*git_commit_create_cb)(
const char *message,
const git_tree *tree,
size_t parent_count,
- git_commit * const parents[],
+ const git_commit *parents[],
void *payload);
/** An array of commits returned from the library */
@@ -604,4 +671,5 @@ GIT_EXTERN(void) git_commitarray_dispose(git_commitarray *array);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/common.h b/include/git2/common.h
index b7cf20b31c9..40a3903ce72 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -11,7 +11,9 @@
#include
#ifdef __cplusplus
+ /** Start declarations in C mode for C++ compatibility */
# define GIT_BEGIN_DECL extern "C" {
+ /** End declarations in C mode */
# define GIT_END_DECL }
#else
/** Start declarations in C mode */
@@ -71,19 +73,19 @@ typedef size_t size_t;
# define GIT_FORMAT_PRINTF(a,b) /* empty */
#endif
-#if (defined(_WIN32)) && !defined(__CYGWIN__)
-#define GIT_WIN32 1
-#endif
-
#ifdef __amigaos4__
#include
#endif
/**
* @file git2/common.h
- * @brief Git common platform definitions
+ * @brief Base platform functionality
* @defgroup git_common Git common platform definitions
* @ingroup Git
+ *
+ * Common platform functionality including introspecting libgit2
+ * itself - information like how it was built, and the current
+ * running version.
* @{
*/
@@ -94,10 +96,10 @@ GIT_BEGIN_DECL
* environment variable). A semi-colon ";" is used on Windows and
* AmigaOS, and a colon ":" for all other systems.
*/
-#if defined(GIT_WIN32) || defined(AMIGA)
-#define GIT_PATH_LIST_SEPARATOR ';'
+#if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(AMIGA)
+# define GIT_PATH_LIST_SEPARATOR ';'
#else
-#define GIT_PATH_LIST_SEPARATOR ':'
+# define GIT_PATH_LIST_SEPARATOR ':'
#endif
/**
@@ -128,56 +130,80 @@ GIT_EXTERN(int) git_libgit2_version(int *major, int *minor, int *rev);
GIT_EXTERN(const char *) git_libgit2_prerelease(void);
/**
- * Combinations of these values describe the features with which libgit2
- * was compiled
+ * Configurable features of libgit2; either optional settings (like
+ * threading), or features that can be enabled by one of a number of
+ * different backend "providers" (like HTTPS, which can be provided by
+ * OpenSSL, mbedTLS, or system libraries).
*/
typedef enum {
- /**
- * If set, libgit2 was built thread-aware and can be safely used from multiple
- * threads.
- */
- GIT_FEATURE_THREADS = (1 << 0),
- /**
- * If set, libgit2 was built with and linked against a TLS implementation.
- * Custom TLS streams may still be added by the user to support HTTPS
- * regardless of this.
- */
- GIT_FEATURE_HTTPS = (1 << 1),
- /**
- * If set, libgit2 was built with and linked against libssh2. A custom
- * transport may still be added by the user to support libssh2 regardless of
- * this.
- */
- GIT_FEATURE_SSH = (1 << 2),
- /**
- * If set, libgit2 was built with support for sub-second resolution in file
- * modification times.
- */
- GIT_FEATURE_NSEC = (1 << 3)
+ /**
+ * libgit2 is thread-aware and can be used from multiple threads
+ * (as described in the documentation).
+ */
+ GIT_FEATURE_THREADS = (1 << 0),
+
+ /** HTTPS remotes */
+ GIT_FEATURE_HTTPS = (1 << 1),
+
+ /** SSH remotes */
+ GIT_FEATURE_SSH = (1 << 2),
+
+ /** Sub-second resolution in index timestamps */
+ GIT_FEATURE_NSEC = (1 << 3),
+
+ /** HTTP parsing; always available */
+ GIT_FEATURE_HTTP_PARSER = (1 << 4),
+
+ /** Regular expression support; always available */
+ GIT_FEATURE_REGEX = (1 << 5),
+
+ /** Internationalization support for filename translation */
+ GIT_FEATURE_I18N = (1 << 6),
+
+ /** NTLM support over HTTPS */
+ GIT_FEATURE_AUTH_NTLM = (1 << 7),
+
+ /** Kerberos (SPNEGO) authentication support over HTTPS */
+ GIT_FEATURE_AUTH_NEGOTIATE = (1 << 8),
+
+ /** zlib support; always available */
+ GIT_FEATURE_COMPRESSION = (1 << 9),
+
+ /** SHA1 object support; always available */
+ GIT_FEATURE_SHA1 = (1 << 10),
+
+ /** SHA256 object support */
+ GIT_FEATURE_SHA256 = (1 << 11)
} git_feature_t;
/**
* Query compile time options for libgit2.
*
* @return A combination of GIT_FEATURE_* values.
+ */
+GIT_EXTERN(int) git_libgit2_features(void);
+
+/**
+ * Query the backend details for the compile-time feature in libgit2.
*
- * - GIT_FEATURE_THREADS
- * Libgit2 was compiled with thread support. Note that thread support is
- * still to be seen as a 'work in progress' - basic object lookups are
- * believed to be threadsafe, but other operations may not be.
+ * This will return the "backend" for the feature, which is useful for
+ * things like HTTPS or SSH support, that can have multiple backends
+ * that could be compiled in.
*
- * - GIT_FEATURE_HTTPS
- * Libgit2 supports the https:// protocol. This requires the openssl
- * library to be found when compiling libgit2.
+ * For example, when libgit2 is compiled with dynamic OpenSSL support,
+ * the feature backend will be `openssl-dynamic`. The feature backend
+ * names reflect the compilation options specified to the build system
+ * (though in all lower case). The backend _may_ be "builtin" for
+ * features that are provided by libgit2 itself.
*
- * - GIT_FEATURE_SSH
- * Libgit2 supports the SSH protocol for network operations. This requires
- * the libssh2 library to be found when compiling libgit2
+ * If the feature is not supported by the library, this API returns
+ * `NULL`.
*
- * - GIT_FEATURE_NSEC
- * Libgit2 supports the sub-second resolution in file modification times.
+ * @param feature the feature to query details for
+ * @return the provider details, or NULL if the feature is not supported
*/
-GIT_EXTERN(int) git_libgit2_features(void);
+GIT_EXTERN(const char *) git_libgit2_feature_backend(
+ git_feature_t feature);
/**
* Global library options
@@ -230,7 +256,8 @@ typedef enum {
GIT_OPT_SET_SERVER_TIMEOUT,
GIT_OPT_GET_SERVER_TIMEOUT,
GIT_OPT_SET_USER_AGENT_PRODUCT,
- GIT_OPT_GET_USER_AGENT_PRODUCT
+ GIT_OPT_GET_USER_AGENT_PRODUCT,
+ GIT_OPT_ADD_SSL_X509_CERT
} git_libgit2_opt_t;
/**
@@ -335,8 +362,21 @@ typedef enum {
* > - `path` is the location of a directory holding several
* > certificates, one per file.
* >
+ * > Calling `GIT_OPT_ADD_SSL_X509_CERT` may override the
+ * > data in `path`.
+ * >
* > Either parameter may be `NULL`, but not both.
*
+ * * opts(GIT_OPT_ADD_SSL_X509_CERT, const X509 *cert)
+ *
+ * > Add a raw X509 certificate into the SSL certs store.
+ * > This certificate is only used by libgit2 invocations
+ * > during the application lifetime and is not persisted
+ * > to disk. This certificate cannot be removed from the
+ * > application once is has been added.
+ * >
+ * > - `cert` is the raw X509 cert will be added to cert store.
+ *
* * opts(GIT_OPT_SET_USER_AGENT, const char *user_agent)
*
* > Set the value of the comment section of the User-Agent header.
@@ -524,7 +564,6 @@ typedef enum {
* > to a remote server. Set to 0 to use the system default.
*
* @param option Option key
- * @param ... value to set the option
* @return 0 on success, <0 on failure
*/
GIT_EXTERN(int) git_libgit2_opts(int option, ...);
diff --git a/include/git2/config.h b/include/git2/config.h
index 32361431326..f9c26675403 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -13,9 +13,13 @@
/**
* @file git2/config.h
- * @brief Git config management routines
+ * @brief Per-repository, per-user or per-system configuration
* @defgroup git_config Git config management routines
* @ingroup Git
+ *
+ * Git configuration affects the operation of the version control
+ * system, and can be specified on a per-repository basis, in user
+ * settings, or at the system level.
* @{
*/
GIT_BEGIN_DECL
@@ -38,37 +42,57 @@ GIT_BEGIN_DECL
*
* git_config_open_default() and git_repository_config() honor those
* priority levels as well.
+ *
+ * @see git_config_open_default
+ * @see git_repository_config
*/
typedef enum {
- /** System-wide on Windows, for compatibility with portable git */
+ /**
+ * System-wide on Windows, for compatibility with "Portable Git".
+ */
GIT_CONFIG_LEVEL_PROGRAMDATA = 1,
- /** System-wide configuration file; /etc/gitconfig on Linux systems */
+ /**
+ * System-wide configuration file; `/etc/gitconfig` on Linux.
+ */
GIT_CONFIG_LEVEL_SYSTEM = 2,
- /** XDG compatible configuration file; typically ~/.config/git/config */
+ /**
+ * XDG compatible configuration file; typically
+ * `~/.config/git/config`.
+ */
GIT_CONFIG_LEVEL_XDG = 3,
- /** User-specific configuration file (also called Global configuration
- * file); typically ~/.gitconfig
+ /**
+ * Global configuration file is the user-specific configuration;
+ * typically `~/.gitconfig`.
*/
GIT_CONFIG_LEVEL_GLOBAL = 4,
- /** Repository specific configuration file; $WORK_DIR/.git/config on
- * non-bare repos
+ /**
+ * Local configuration, the repository-specific configuration file;
+ * typically `$GIT_DIR/config`.
*/
GIT_CONFIG_LEVEL_LOCAL = 5,
- /** Worktree specific configuration file; $GIT_DIR/config.worktree
+ /**
+ * Worktree-specific configuration; typically
+ * `$GIT_DIR/config.worktree`.
*/
GIT_CONFIG_LEVEL_WORKTREE = 6,
- /** Application specific configuration file; freely defined by applications
+ /**
+ * Application-specific configuration file. Callers into libgit2
+ * can add their own configuration beginning at this level.
*/
GIT_CONFIG_LEVEL_APP = 7,
- /** Represents the highest level available config file (i.e. the most
- * specific config file available that actually is loaded)
+ /**
+ * Not a configuration level; callers can use this value when
+ * querying configuration levels to specify that they want to
+ * have data from the highest-level currently configuration.
+ * This can be used to indicate that callers want the most
+ * specific config file available that actually is loaded.
*/
GIT_CONFIG_HIGHEST_LEVEL = -1
} git_config_level_t;
@@ -77,13 +101,13 @@ typedef enum {
* An entry in a configuration file
*/
typedef struct git_config_entry {
- /** Name of the configuration entry (normalized) */
+ /** Name of the configuration entry (normalized). */
const char *name;
- /** Literal (string) value of the entry */
+ /** Literal (string) value of the entry. */
const char *value;
- /** The type of backend that this entry exists in (eg, "file") */
+ /** The type of backend that this entry exists in (eg, "file"). */
const char *backend_type;
/**
@@ -92,28 +116,22 @@ typedef struct git_config_entry {
*/
const char *origin_path;
- /** Depth of includes where this variable was found */
+ /** Depth of includes where this variable was found. */
unsigned int include_depth;
- /** Configuration level for the file this was found in */
+ /** Configuration level for the file this was found in. */
git_config_level_t level;
-
- /**
- * Free function for this entry; for internal purposes. Callers
- * should call `git_config_entry_free` to free data.
- */
- void GIT_CALLBACK(free)(struct git_config_entry *entry);
} git_config_entry;
/**
- * Free a config entry
+ * Free a config entry.
*
* @param entry The entry to free.
*/
GIT_EXTERN(void) git_config_entry_free(git_config_entry *entry);
/**
- * A config enumeration callback
+ * A config enumeration callback.
*
* @param entry the entry currently being enumerated
* @param payload a user-specified pointer
@@ -122,7 +140,7 @@ GIT_EXTERN(void) git_config_entry_free(git_config_entry *entry);
typedef int GIT_CALLBACK(git_config_foreach_cb)(const git_config_entry *entry, void *payload);
/**
- * An opaque structure for a configuration iterator
+ * An opaque structure for a configuration iterator.
*/
typedef struct git_config_iterator git_config_iterator;
@@ -247,9 +265,9 @@ GIT_EXTERN(int) git_config_new(git_config **out);
* @param cfg the configuration to add the file to
* @param path path to the configuration file to add
* @param level the priority level of the backend
- * @param force replace config file at the given priority level
* @param repo optional repository to allow parsing of
* conditional includes
+ * @param force replace config file at the given priority level
* @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0),
* GIT_ENOTFOUND when the file doesn't exist or error code
@@ -311,6 +329,17 @@ GIT_EXTERN(int) git_config_open_level(
*/
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
+/**
+ * Set the write order for configuration backends. By default, the
+ * write ordering does not match the read ordering; for example, the
+ * worktree configuration is a high-priority for reading, but is not
+ * written to unless explicitly chosen.
+ *
+ * @param cfg the configuration to change write order of
+ * @param levels the ordering of levels for writing
+ * @param len the length of the levels array
+ * @return 0 or an error code
+ */
GIT_EXTERN(int) git_config_set_writeorder(
git_config *cfg,
git_config_level_t *levels,
@@ -819,4 +848,5 @@ GIT_EXTERN(int) git_config_lock(git_transaction **tx, git_config *cfg);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/credential.h b/include/git2/credential.h
index 7a04bc06479..33755ca916d 100644
--- a/include/git2/credential.h
+++ b/include/git2/credential.h
@@ -11,9 +11,12 @@
/**
* @file git2/credential.h
- * @brief Git authentication & credential management
+ * @brief Authentication and credential management
* @defgroup git_credential Authentication & credential management
* @ingroup Git
+ *
+ * Credentials specify how to authenticate to a remote system
+ * over HTTPS or SSH.
* @{
*/
GIT_BEGIN_DECL
@@ -119,7 +122,7 @@ typedef struct git_credential_ssh_custom git_credential_ssh_custom;
* an error. As such, it's easy to get in a loop if you fail to stop providing
* the same incorrect credentials.
*
- * @param out The newly created credential object.
+ * @param[out] out The newly created credential object.
* @param url The resource for which we are demanding a credential.
* @param username_from_url The username that was embedded in a "user\@host"
* remote url, or NULL if not included.
@@ -241,6 +244,18 @@ typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT;
typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE;
#endif
+/**
+ * Callback for interactive SSH credentials.
+ *
+ * @param name the name
+ * @param name_len the length of the name
+ * @param instruction the authentication instruction
+ * @param instruction_len the length of the instruction
+ * @param num_prompts the number of prompts
+ * @param prompts the prompts
+ * @param responses the responses
+ * @param abstract the abstract
+ */
typedef void GIT_CALLBACK(git_credential_ssh_interactive_cb)(
const char *name,
int name_len,
@@ -278,6 +293,18 @@ GIT_EXTERN(int) git_credential_ssh_key_from_agent(
git_credential **out,
const char *username);
+/**
+ * Callback for credential signing.
+ *
+ * @param session the libssh2 session
+ * @param sig the signature
+ * @param sig_len the length of the signature
+ * @param data the data
+ * @param data_len the length of the data
+ * @param abstract the abstract
+ * @return 0 for success, < 0 to indicate an error, > 0 to indicate
+ * no credential was acquired
+ */
typedef int GIT_CALLBACK(git_credential_sign_cb)(
LIBSSH2_SESSION *session,
unsigned char **sig, size_t *sig_len,
@@ -312,4 +339,5 @@ GIT_EXTERN(int) git_credential_ssh_custom_new(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/credential_helpers.h b/include/git2/credential_helpers.h
index f0fb07041d9..706558d5bd0 100644
--- a/include/git2/credential_helpers.h
+++ b/include/git2/credential_helpers.h
@@ -50,4 +50,5 @@ GIT_EXTERN(int) git_credential_userpass(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/deprecated.h b/include/git2/deprecated.h
index 52864ebe166..b8b0238da66 100644
--- a/include/git2/deprecated.h
+++ b/include/git2/deprecated.h
@@ -52,7 +52,7 @@
/**
* @file git2/deprecated.h
- * @brief libgit2 deprecated functions and values
+ * @brief Deprecated functions and values
* @ingroup Git
* @{
*/
@@ -69,15 +69,23 @@ GIT_BEGIN_DECL
*/
/**@{*/
+/** @deprecated use GIT_ATTR_VALUE_UNSPECIFIED */
#define GIT_ATTR_UNSPECIFIED_T GIT_ATTR_VALUE_UNSPECIFIED
+/** @deprecated use GIT_ATTR_VALUE_TRUE */
#define GIT_ATTR_TRUE_T GIT_ATTR_VALUE_TRUE
+/** @deprecated use GIT_ATTR_VALUE_FALSE */
#define GIT_ATTR_FALSE_T GIT_ATTR_VALUE_FALSE
+/** @deprecated use GIT_ATTR_VALUE_STRING */
#define GIT_ATTR_VALUE_T GIT_ATTR_VALUE_STRING
+/** @deprecated use GIT_ATTR_IS_TRUE */
#define GIT_ATTR_TRUE(attr) GIT_ATTR_IS_TRUE(attr)
+/** @deprecated use GIT_ATTR_IS_FALSE */
#define GIT_ATTR_FALSE(attr) GIT_ATTR_IS_FALSE(attr)
+/** @deprecated use GIT_ATTR_IS_UNSPECIFIED */
#define GIT_ATTR_UNSPECIFIED(attr) GIT_ATTR_IS_UNSPECIFIED(attr)
+/** @deprecated use git_attr_value_t */
typedef git_attr_value_t git_attr_t;
/**@}*/
@@ -93,6 +101,7 @@ typedef git_attr_value_t git_attr_t;
*/
/**@{*/
+/** @deprecated use GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD */
#define GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD
GIT_EXTERN(int) git_blob_create_fromworkdir(git_oid *id, git_repository *repo, const char *relative_path);
@@ -285,11 +294,16 @@ typedef int (*git_commit_signing_cb)(
*/
/**@{*/
+/** @deprecated use GIT_CONFIGMAP_FALSE */
#define GIT_CVAR_FALSE GIT_CONFIGMAP_FALSE
+/** @deprecated use GIT_CONFIGMAP_TRUE */
#define GIT_CVAR_TRUE GIT_CONFIGMAP_TRUE
+/** @deprecated use GIT_CONFIGMAP_INT32 */
#define GIT_CVAR_INT32 GIT_CONFIGMAP_INT32
+/** @deprecated use GIT_CONFIGMAP_STRING */
#define GIT_CVAR_STRING GIT_CONFIGMAP_STRING
+/** @deprecated use git_cvar_map */
typedef git_configmap git_cvar_map;
/**@}*/
@@ -314,11 +328,12 @@ typedef enum {
/** Don't insert "[PATCH]" in the subject header*/
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0)
-
} git_diff_format_email_flags_t;
/**
* Options for controlling the formatting of the generated e-mail.
+ *
+ * @deprecated use `git_email_create_options`
*/
typedef struct {
unsigned int version;
@@ -345,7 +360,9 @@ typedef struct {
const git_signature *author;
} git_diff_format_email_options;
+/** @deprecated use `git_email_create_options` */
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
+/** @deprecated use `git_email_create_options` */
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL}
/**
@@ -401,41 +418,75 @@ GIT_EXTERN(int) git_diff_format_email_options_init(
*/
/**@{*/
+/** @deprecated use `GIT_ERROR_NONE` */
#define GITERR_NONE GIT_ERROR_NONE
+/** @deprecated use `GIT_ERROR_NOMEMORY` */
#define GITERR_NOMEMORY GIT_ERROR_NOMEMORY
+/** @deprecated use `GIT_ERROR_OS` */
#define GITERR_OS GIT_ERROR_OS
+/** @deprecated use `GIT_ERROR_INVALID` */
#define GITERR_INVALID GIT_ERROR_INVALID
+/** @deprecated use `GIT_ERROR_REFERENCE` */
#define GITERR_REFERENCE GIT_ERROR_REFERENCE
+/** @deprecated use `GIT_ERROR_ZLIB` */
#define GITERR_ZLIB GIT_ERROR_ZLIB
+/** @deprecated use `GIT_ERROR_REPOSITORY` */
#define GITERR_REPOSITORY GIT_ERROR_REPOSITORY
+/** @deprecated use `GIT_ERROR_CONFIG` */
#define GITERR_CONFIG GIT_ERROR_CONFIG
+/** @deprecated use `GIT_ERROR_REGEX` */
#define GITERR_REGEX GIT_ERROR_REGEX
+/** @deprecated use `GIT_ERROR_ODB` */
#define GITERR_ODB GIT_ERROR_ODB
+/** @deprecated use `GIT_ERROR_INDEX` */
#define GITERR_INDEX GIT_ERROR_INDEX
+/** @deprecated use `GIT_ERROR_OBJECT` */
#define GITERR_OBJECT GIT_ERROR_OBJECT
+/** @deprecated use `GIT_ERROR_NET` */
#define GITERR_NET GIT_ERROR_NET
+/** @deprecated use `GIT_ERROR_TAG` */
#define GITERR_TAG GIT_ERROR_TAG
+/** @deprecated use `GIT_ERROR_TREE` */
#define GITERR_TREE GIT_ERROR_TREE
+/** @deprecated use `GIT_ERROR_INDEXER` */
#define GITERR_INDEXER GIT_ERROR_INDEXER
+/** @deprecated use `GIT_ERROR_SSL` */
#define GITERR_SSL GIT_ERROR_SSL
+/** @deprecated use `GIT_ERROR_SUBMODULE` */
#define GITERR_SUBMODULE GIT_ERROR_SUBMODULE
+/** @deprecated use `GIT_ERROR_THREAD` */
#define GITERR_THREAD GIT_ERROR_THREAD
+/** @deprecated use `GIT_ERROR_STASH` */
#define GITERR_STASH GIT_ERROR_STASH
+/** @deprecated use `GIT_ERROR_CHECKOUT` */
#define GITERR_CHECKOUT GIT_ERROR_CHECKOUT
+/** @deprecated use `GIT_ERROR_FETCHHEAD` */
#define GITERR_FETCHHEAD GIT_ERROR_FETCHHEAD
+/** @deprecated use `GIT_ERROR_MERGE` */
#define GITERR_MERGE GIT_ERROR_MERGE
+/** @deprecated use `GIT_ERROR_SSH` */
#define GITERR_SSH GIT_ERROR_SSH
+/** @deprecated use `GIT_ERROR_FILTER` */
#define GITERR_FILTER GIT_ERROR_FILTER
+/** @deprecated use `GIT_ERROR_REVERT` */
#define GITERR_REVERT GIT_ERROR_REVERT
+/** @deprecated use `GIT_ERROR_CALLBACK` */
#define GITERR_CALLBACK GIT_ERROR_CALLBACK
+/** @deprecated use `GIT_ERROR_CHERRYPICK` */
#define GITERR_CHERRYPICK GIT_ERROR_CHERRYPICK
+/** @deprecated use `GIT_ERROR_DESCRIBE` */
#define GITERR_DESCRIBE GIT_ERROR_DESCRIBE
+/** @deprecated use `GIT_ERROR_REBASE` */
#define GITERR_REBASE GIT_ERROR_REBASE
+/** @deprecated use `GIT_ERROR_FILESYSTEM` */
#define GITERR_FILESYSTEM GIT_ERROR_FILESYSTEM
+/** @deprecated use `GIT_ERROR_PATCH` */
#define GITERR_PATCH GIT_ERROR_PATCH
+/** @deprecated use `GIT_ERROR_WORKTREE` */
#define GITERR_WORKTREE GIT_ERROR_WORKTREE
+/** @deprecated use `GIT_ERROR_SHA1` */
#define GITERR_SHA1 GIT_ERROR_SHA1
-
+/** @deprecated use `GIT_ERROR_SHA` */
#define GIT_ERROR_SHA1 GIT_ERROR_SHA
/**
@@ -500,37 +551,63 @@ GIT_EXTERN(void) giterr_set_oom(void);
*/
/**@{*/
+/* The git_idxentry_extended_flag_t enum */
+/** @deprecated use `GIT_INDEX_ENTRY_NAMEMASK` */
#define GIT_IDXENTRY_NAMEMASK GIT_INDEX_ENTRY_NAMEMASK
+/** @deprecated use `GIT_INDEX_ENTRY_STAGEMASK` */
#define GIT_IDXENTRY_STAGEMASK GIT_INDEX_ENTRY_STAGEMASK
+/** @deprecated use `GIT_INDEX_ENTRY_STAGESHIFT` */
#define GIT_IDXENTRY_STAGESHIFT GIT_INDEX_ENTRY_STAGESHIFT
/* The git_indxentry_flag_t enum */
+/** @deprecated use `GIT_INDEX_ENTRY_EXTENDED` */
#define GIT_IDXENTRY_EXTENDED GIT_INDEX_ENTRY_EXTENDED
+/** @deprecated use `GIT_INDEX_ENTRY_VALID` */
#define GIT_IDXENTRY_VALID GIT_INDEX_ENTRY_VALID
+/** @deprecated use `GIT_INDEX_ENTRY_STAGE` */
#define GIT_IDXENTRY_STAGE(E) GIT_INDEX_ENTRY_STAGE(E)
+/** @deprecated use `GIT_INDEX_ENTRY_STAGE_SET` */
#define GIT_IDXENTRY_STAGE_SET(E,S) GIT_INDEX_ENTRY_STAGE_SET(E,S)
/* The git_idxentry_extended_flag_t enum */
+/** @deprecated use `GIT_INDEX_ENTRY_INTENT_TO_ADD` */
#define GIT_IDXENTRY_INTENT_TO_ADD GIT_INDEX_ENTRY_INTENT_TO_ADD
+/** @deprecated use `GIT_INDEX_ENTRY_SKIP_WORKTREE` */
#define GIT_IDXENTRY_SKIP_WORKTREE GIT_INDEX_ENTRY_SKIP_WORKTREE
+/** @deprecated use `GIT_INDEX_ENTRY_INTENT_TO_ADD | GIT_INDEX_ENTRY_SKIP_WORKTREE` */
#define GIT_IDXENTRY_EXTENDED_FLAGS (GIT_INDEX_ENTRY_INTENT_TO_ADD | GIT_INDEX_ENTRY_SKIP_WORKTREE)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_EXTENDED2 (1 << 15)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_UPDATE (1 << 0)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_REMOVE (1 << 1)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_UPTODATE (1 << 2)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_ADDED (1 << 3)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_HASHED (1 << 4)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_UNHASHED (1 << 5)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_WT_REMOVE (1 << 6)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_CONFLICTED (1 << 7)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_UNPACKED (1 << 8)
+/** @deprecated this value is not public */
#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 9)
/* The git_index_capability_t enum */
+/** @deprecated use `GIT_INDEX_CAPABILITY_IGNORE_CASE` */
#define GIT_INDEXCAP_IGNORE_CASE GIT_INDEX_CAPABILITY_IGNORE_CASE
+/** @deprecated use `GIT_INDEX_CAPABILITY_NO_FILEMODE` */
#define GIT_INDEXCAP_NO_FILEMODE GIT_INDEX_CAPABILITY_NO_FILEMODE
+/** @deprecated use `GIT_INDEX_CAPABILITY_NO_SYMLINKS` */
#define GIT_INDEXCAP_NO_SYMLINKS GIT_INDEX_CAPABILITY_NO_SYMLINKS
+/** @deprecated use `GIT_INDEX_CAPABILITY_FROM_OWNER` */
#define GIT_INDEXCAP_FROM_OWNER GIT_INDEX_CAPABILITY_FROM_OWNER
GIT_EXTERN(int) git_index_add_frombuffer(
@@ -550,17 +627,28 @@ GIT_EXTERN(int) git_index_add_frombuffer(
*/
/**@{*/
+/** @deprecate use `git_object_t` */
#define git_otype git_object_t
+/** @deprecate use `GIT_OBJECT_ANY` */
#define GIT_OBJ_ANY GIT_OBJECT_ANY
+/** @deprecate use `GIT_OBJECT_INVALID` */
#define GIT_OBJ_BAD GIT_OBJECT_INVALID
+/** @deprecated this value is not public */
#define GIT_OBJ__EXT1 0
+/** @deprecate use `GIT_OBJECT_COMMIT` */
#define GIT_OBJ_COMMIT GIT_OBJECT_COMMIT
+/** @deprecate use `GIT_OBJECT_TREE` */
#define GIT_OBJ_TREE GIT_OBJECT_TREE
+/** @deprecate use `GIT_OBJECT_BLOB` */
#define GIT_OBJ_BLOB GIT_OBJECT_BLOB
+/** @deprecate use `GIT_OBJECT_TAG` */
#define GIT_OBJ_TAG GIT_OBJECT_TAG
+/** @deprecated this value is not public */
#define GIT_OBJ__EXT2 5
+/** @deprecate use `GIT_OBJECT_OFS_DELTA` */
#define GIT_OBJ_OFS_DELTA GIT_OBJECT_OFS_DELTA
+/** @deprecate use `GIT_OBJECT_REF_DELTA` */
#define GIT_OBJ_REF_DELTA GIT_OBJECT_REF_DELTA
/**
@@ -612,17 +700,27 @@ GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
/**@{*/
/** Basic type of any Git reference. */
+/** @deprecate use `git_reference_t` */
#define git_ref_t git_reference_t
+/** @deprecate use `git_reference_format_t` */
#define git_reference_normalize_t git_reference_format_t
+/** @deprecate use `GIT_REFERENCE_INVALID` */
#define GIT_REF_INVALID GIT_REFERENCE_INVALID
+/** @deprecate use `GIT_REFERENCE_DIRECT` */
#define GIT_REF_OID GIT_REFERENCE_DIRECT
+/** @deprecate use `GIT_REFERENCE_SYMBOLIC` */
#define GIT_REF_SYMBOLIC GIT_REFERENCE_SYMBOLIC
+/** @deprecate use `GIT_REFERENCE_ALL` */
#define GIT_REF_LISTALL GIT_REFERENCE_ALL
+/** @deprecate use `GIT_REFERENCE_FORMAT_NORMAL` */
#define GIT_REF_FORMAT_NORMAL GIT_REFERENCE_FORMAT_NORMAL
+/** @deprecate use `GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL` */
#define GIT_REF_FORMAT_ALLOW_ONELEVEL GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL
+/** @deprecate use `GIT_REFERENCE_FORMAT_REFSPEC_PATTERN` */
#define GIT_REF_FORMAT_REFSPEC_PATTERN GIT_REFERENCE_FORMAT_REFSPEC_PATTERN
+/** @deprecate use `GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND` */
#define GIT_REF_FORMAT_REFSPEC_SHORTHAND GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND
/**
@@ -663,8 +761,11 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
typedef git_revspec_t git_revparse_mode_t;
+/** @deprecated use `GIT_REVSPEC_SINGLE` */
#define GIT_REVPARSE_SINGLE GIT_REVSPEC_SINGLE
+/** @deprecated use `GIT_REVSPEC_RANGE` */
#define GIT_REVPARSE_RANGE GIT_REVSPEC_RANGE
+/** @deprecated use `GIT_REVSPEC_MERGE_BASE` */
#define GIT_REVPARSE_MERGE_BASE GIT_REVSPEC_MERGE_BASE
/**@}*/
@@ -693,14 +794,22 @@ typedef git_credential_sign_cb git_cred_sign_cb;
typedef git_credential_ssh_interactive_cb git_cred_ssh_interactive_callback;
typedef git_credential_ssh_interactive_cb git_cred_ssh_interactive_cb;
+/** @deprecated use `git_credential_t` */
#define git_credtype_t git_credential_t
+/** @deprecated use `GIT_CREDENTIAL_USERPASS_PLAINTEXT` */
#define GIT_CREDTYPE_USERPASS_PLAINTEXT GIT_CREDENTIAL_USERPASS_PLAINTEXT
+/** @deprecated use `GIT_CREDENTIAL_SSH_KEY` */
#define GIT_CREDTYPE_SSH_KEY GIT_CREDENTIAL_SSH_KEY
+/** @deprecated use `GIT_CREDENTIAL_SSH_CUSTOM` */
#define GIT_CREDTYPE_SSH_CUSTOM GIT_CREDENTIAL_SSH_CUSTOM
+/** @deprecated use `GIT_CREDENTIAL_DEFAULT` */
#define GIT_CREDTYPE_DEFAULT GIT_CREDENTIAL_DEFAULT
+/** @deprecated use `GIT_CREDENTIAL_SSH_INTERACTIVE` */
#define GIT_CREDTYPE_SSH_INTERACTIVE GIT_CREDENTIAL_SSH_INTERACTIVE
+/** @deprecated use `GIT_CREDENTIAL_USERNAME` */
#define GIT_CREDTYPE_USERNAME GIT_CREDENTIAL_USERNAME
+/** @deprecated use `GIT_CREDENTIAL_SSH_MEMORY` */
#define GIT_CREDTYPE_SSH_MEMORY GIT_CREDENTIAL_SSH_MEMORY
GIT_EXTERN(void) git_cred_free(git_credential *cred);
@@ -778,8 +887,11 @@ typedef git_trace_cb git_trace_callback;
/**@{*/
#ifndef GIT_EXPERIMENTAL_SHA256
+/** Deprecated OID "raw size" definition */
# define GIT_OID_RAWSZ GIT_OID_SHA1_SIZE
+/** Deprecated OID "hex size" definition */
# define GIT_OID_HEXSZ GIT_OID_SHA1_HEXSIZE
+/** Deprecated OID "hex zero" definition */
# define GIT_OID_HEX_ZERO GIT_OID_SHA1_HEXZERO
#endif
@@ -892,6 +1004,24 @@ GIT_EXTERN(void) git_strarray_free(git_strarray *array);
/**@}*/
+/** @name Deprecated Version Constants
+ *
+ * These constants are retained for backward compatibility. The newer
+ * versions of these constants should be preferred in all new code.
+ *
+ * There is no plan to remove these backward compatibility constants at
+ * this time.
+ */
+/**@{*/
+
+#define LIBGIT2_VER_MAJOR LIBGIT2_VERSION_MAJOR
+#define LIBGIT2_VER_MINOR LIBGIT2_VERSION_MINOR
+#define LIBGIT2_VER_REVISION LIBGIT2_VERSION_REVISION
+#define LIBGIT2_VER_PATCH LIBGIT2_VERSION_PATCH
+#define LIBGIT2_VER_PRERELEASE LIBGIT2_VERSION_PRERELEASE
+
+/**@}*/
+
/** @name Deprecated Options Initialization Functions
*
* These functions are retained for backward compatibility. The newer
diff --git a/include/git2/describe.h b/include/git2/describe.h
index 7a796f1309c..938c470d272 100644
--- a/include/git2/describe.h
+++ b/include/git2/describe.h
@@ -13,10 +13,14 @@
/**
* @file git2/describe.h
- * @brief Git describing routines
+ * @brief Describe a commit in reference to tags
* @defgroup git_describe Git describing routines
* @ingroup Git
* @{
+ *
+ * Describe a commit, showing information about how the current commit
+ * relates to the tags. This can be useful for showing how the current
+ * commit has changed from a particular tagged version of the repository.
*/
GIT_BEGIN_DECL
@@ -60,10 +64,15 @@ typedef struct git_describe_options {
int show_commit_oid_as_fallback;
} git_describe_options;
+/** Default maximum candidate tags */
#define GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS 10
+/** Default abbreviated size */
#define GIT_DESCRIBE_DEFAULT_ABBREVIATED_SIZE 7
+/** Current version for the `git_describe_options` structure */
#define GIT_DESCRIBE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_describe_options` */
#define GIT_DESCRIBE_OPTIONS_INIT { \
GIT_DESCRIBE_OPTIONS_VERSION, \
GIT_DESCRIBE_DEFAULT_MAX_CANDIDATES_TAGS, \
@@ -110,7 +119,10 @@ typedef struct {
const char *dirty_suffix;
} git_describe_format_options;
+/** Current version for the `git_describe_format_options` structure */
#define GIT_DESCRIBE_FORMAT_OPTIONS_VERSION 1
+
+/** Static constructor for `git_describe_format_options` */
#define GIT_DESCRIBE_FORMAT_OPTIONS_INIT { \
GIT_DESCRIBE_FORMAT_OPTIONS_VERSION, \
GIT_DESCRIBE_DEFAULT_ABBREVIATED_SIZE, \
diff --git a/include/git2/diff.h b/include/git2/diff.h
index 384b6e74570..b12e8ab2754 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -15,7 +15,7 @@
/**
* @file git2/diff.h
- * @brief Git tree and file differencing routines.
+ * @brief Indicate the differences between two versions of the repository
* @ingroup Git
* @{
*/
@@ -342,6 +342,12 @@ typedef struct {
* diff process continues.
* - returns 0, the delta is inserted into the diff, and the diff process
* continues.
+ *
+ * @param diff_so_far the diff structure as it currently exists
+ * @param delta_to_add the delta that is to be added
+ * @param matched_pathspec the pathspec
+ * @param payload the user-specified callback payload
+ * @return 0 on success, 1 to skip this delta, or an error code
*/
typedef int GIT_CALLBACK(git_diff_notify_cb)(
const git_diff *diff_so_far,
@@ -357,7 +363,8 @@ typedef int GIT_CALLBACK(git_diff_notify_cb)(
* @param diff_so_far The diff being generated.
* @param old_path The path to the old file or NULL.
* @param new_path The path to the new file or NULL.
- * @return Non-zero to abort the diff.
+ * @param payload the user-specified callback payload
+ * @return 0 or an error code
*/
typedef int GIT_CALLBACK(git_diff_progress_cb)(
const git_diff *diff_so_far,
@@ -463,10 +470,10 @@ typedef struct {
const char *new_prefix;
} git_diff_options;
-/* The current version of the diff options structure */
+/** The current version of the diff options structure */
#define GIT_DIFF_OPTIONS_VERSION 1
-/* Stack initializer for diff options. Alternatively use
+/** Stack initializer for diff options. Alternatively use
* `git_diff_options_init` programmatic initialization.
*/
#define GIT_DIFF_OPTIONS_INIT \
@@ -492,12 +499,14 @@ GIT_EXTERN(int) git_diff_options_init(
* @param delta A pointer to the delta data for the file
* @param progress Goes from 0 to 1 over the diff
* @param payload User-specified pointer from foreach function
+ * @return 0 or an error code
*/
typedef int GIT_CALLBACK(git_diff_file_cb)(
const git_diff_delta *delta,
float progress,
void *payload);
+/** Maximum size of the hunk header */
#define GIT_DIFF_HUNK_HEADER_SIZE 128
/**
@@ -558,6 +567,11 @@ typedef struct {
/**
* When iterating over a diff, callback that will be made for
* binary content within the diff.
+ *
+ * @param delta the delta
+ * @param binary the binary content
+ * @param payload the user-specified callback payload
+ * @return 0 or an error code
*/
typedef int GIT_CALLBACK(git_diff_binary_cb)(
const git_diff_delta *delta,
@@ -584,6 +598,11 @@ typedef struct {
/**
* When iterating over a diff, callback that will be made per hunk.
+ *
+ * @param delta the delta
+ * @param hunk the hunk
+ * @param payload the user-specified callback payload
+ * @return 0 or an error code
*/
typedef int GIT_CALLBACK(git_diff_hunk_cb)(
const git_diff_delta *delta,
@@ -645,6 +664,12 @@ typedef struct {
* When printing a diff, callback that will be made to output each line
* of text. This uses some extra GIT_DIFF_LINE_... constants for output
* of lines of file and hunk headers.
+ *
+ * @param delta the delta that contains the line
+ * @param hunk the hunk that contains the line
+ * @param line the line in the diff
+ * @param payload the user-specified callback payload
+ * @return 0 or an error code
*/
typedef int GIT_CALLBACK(git_diff_line_cb)(
const git_diff_delta *delta, /**< delta that contains this data */
@@ -802,7 +827,10 @@ typedef struct {
git_diff_similarity_metric *metric;
} git_diff_find_options;
+/** Current version for the `git_diff_find_options` structure */
#define GIT_DIFF_FIND_OPTIONS_VERSION 1
+
+/** Static constructor for `git_diff_find_options` */
#define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION}
/**
@@ -1296,10 +1324,10 @@ typedef struct {
git_oid_t oid_type;
} git_diff_parse_options;
-/* The current version of the diff parse options structure */
+/** The current version of the diff parse options structure */
#define GIT_DIFF_PARSE_OPTIONS_VERSION 1
-/* Stack initializer for diff parse options. Alternatively use
+/** Stack initializer for diff parse options. Alternatively use
* `git_diff_parse_options_init` programmatic initialization.
*/
#define GIT_DIFF_PARSE_OPTIONS_INIT \
@@ -1432,7 +1460,10 @@ typedef struct git_diff_patchid_options {
unsigned int version;
} git_diff_patchid_options;
+/** Current version for the `git_diff_patchid_options` structure */
#define GIT_DIFF_PATCHID_OPTIONS_VERSION 1
+
+/** Static constructor for `git_diff_patchid_options` */
#define GIT_DIFF_PATCHID_OPTIONS_INIT { GIT_DIFF_PATCHID_OPTIONS_VERSION }
/**
@@ -1470,8 +1501,7 @@ GIT_EXTERN(int) git_diff_patchid_options_init(
*/
GIT_EXTERN(int) git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts);
-GIT_END_DECL
-
/** @} */
+GIT_END_DECL
#endif
diff --git a/include/git2/email.h b/include/git2/email.h
index 3389353e796..ad37e424985 100644
--- a/include/git2/email.h
+++ b/include/git2/email.h
@@ -12,7 +12,7 @@
/**
* @file git2/email.h
- * @brief Git email formatting and application routines.
+ * @brief Produce email-ready patches
* @ingroup Git
* @{
*/
@@ -71,11 +71,14 @@ typedef struct {
size_t reroll_number;
} git_email_create_options;
-/*
+/** Current version for the `git_email_create_options` structure */
+#define GIT_EMAIL_CREATE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_email_create_options`
+ *
* By default, our options include rename detection and binary
* diffs to match `git format-patch`.
*/
-#define GIT_EMAIL_CREATE_OPTIONS_VERSION 1
#define GIT_EMAIL_CREATE_OPTIONS_INIT \
{ \
GIT_EMAIL_CREATE_OPTIONS_VERSION, \
@@ -84,30 +87,6 @@ typedef struct {
GIT_DIFF_FIND_OPTIONS_INIT \
}
-/**
- * Create a diff for a commit in mbox format for sending via email.
- *
- * @param out buffer to store the e-mail patch in
- * @param diff the changes to include in the email
- * @param patch_idx the patch index
- * @param patch_count the total number of patches that will be included
- * @param commit_id the commit id for this change
- * @param summary the commit message for this change
- * @param body optional text to include above the diffstat
- * @param author the person who authored this commit
- * @param opts email creation options
- */
-GIT_EXTERN(int) git_email_create_from_diff(
- git_buf *out,
- git_diff *diff,
- size_t patch_idx,
- size_t patch_count,
- const git_oid *commit_id,
- const char *summary,
- const char *body,
- const git_signature *author,
- const git_email_create_options *opts);
-
/**
* Create a diff for a commit in mbox format for sending via email.
* The commit must not be a merge commit.
@@ -115,14 +94,14 @@ GIT_EXTERN(int) git_email_create_from_diff(
* @param out buffer to store the e-mail patch in
* @param commit commit to create a patch for
* @param opts email creation options
+ * @return 0 or an error code
*/
GIT_EXTERN(int) git_email_create_from_commit(
git_buf *out,
git_commit *commit,
const git_email_create_options *opts);
-GIT_END_DECL
-
/** @} */
+GIT_END_DECL
#endif
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 52fa5f0720d..11413907e7c 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -11,7 +11,7 @@
/**
* @file git2/errors.h
- * @brief Git error handling routines and variables
+ * @brief Error handling routines and variables
* @ingroup Git
* @{
*/
@@ -19,13 +19,20 @@ GIT_BEGIN_DECL
/** Generic return codes */
typedef enum {
- GIT_OK = 0, /**< No error */
+ /**
+ * No error occurred; the call was successful.
+ */
+ GIT_OK = 0,
+
+ /**
+ * An error occurred; call `git_error_last` for more information.
+ */
+ GIT_ERROR = -1,
- GIT_ERROR = -1, /**< Generic error */
- GIT_ENOTFOUND = -3, /**< Requested object could not be found */
- GIT_EEXISTS = -4, /**< Object exists preventing operation */
- GIT_EAMBIGUOUS = -5, /**< More than one object matches */
- GIT_EBUFS = -6, /**< Output buffer too short to hold data */
+ GIT_ENOTFOUND = -3, /**< Requested object could not be found. */
+ GIT_EEXISTS = -4, /**< Object exists preventing operation. */
+ GIT_EAMBIGUOUS = -5, /**< More than one object matches. */
+ GIT_EBUFS = -6, /**< Output buffer too short to hold data. */
/**
* GIT_EUSER is a special error that is never generated by libgit2
@@ -34,10 +41,10 @@ typedef enum {
*/
GIT_EUSER = -7,
- GIT_EBAREREPO = -8, /**< Operation not allowed on bare repository */
- GIT_EUNBORNBRANCH = -9, /**< HEAD refers to branch with no commits */
- GIT_EUNMERGED = -10, /**< Merge in progress prevented operation */
- GIT_ENONFASTFORWARD = -11, /**< Reference was not fast-forwardable */
+ GIT_EBAREREPO = -8, /**< Operation not allowed on bare repository. */
+ GIT_EUNBORNBRANCH = -9, /**< HEAD refers to branch with no commits. */
+ GIT_EUNMERGED = -10, /**< Merge in progress prevented operation */
+ GIT_ENONFASTFORWARD = -11, /**< Reference was not fast-forwardable */
GIT_EINVALIDSPEC = -12, /**< Name/ref spec was not in a valid format */
GIT_ECONFLICT = -13, /**< Checkout conflicts prevented operation */
GIT_ELOCKED = -14, /**< Lock file prevented operation */
@@ -66,17 +73,9 @@ typedef enum {
} git_error_code;
/**
- * Structure to store extra details of the last error that occurred.
- *
- * This is kept on a per-thread basis if GIT_THREADS was defined when the
- * library was build, otherwise one is kept globally for the library
+ * Error classes are the category of error. They reflect the area of the
+ * code where an error occurred.
*/
-typedef struct {
- char *message;
- int klass;
-} git_error;
-
-/** Error classes */
typedef enum {
GIT_ERROR_NONE = 0,
GIT_ERROR_NOMEMORY,
@@ -117,6 +116,17 @@ typedef enum {
GIT_ERROR_GRAFTS
} git_error_t;
+/**
+ * Structure to store extra details of the last error that occurred.
+ *
+ * This is kept on a per-thread basis if GIT_THREADS was defined when the
+ * library was build, otherwise one is kept globally for the library
+ */
+typedef struct {
+ char *message; /**< The error message for the last error. */
+ int klass; /**< The category of the last error. @type git_error_t */
+} git_error;
+
/**
* Return the last `git_error` object that was generated for the
* current thread.
@@ -134,10 +144,11 @@ typedef enum {
* The memory for this object is managed by libgit2. It should not
* be freed.
*
- * @return A git_error object.
+ * @return A pointer to a `git_error` object that describes the error.
*/
GIT_EXTERN(const git_error *) git_error_last(void);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/filter.h b/include/git2/filter.h
index 79bf14ce5b7..cf6c5f59d97 100644
--- a/include/git2/filter.h
+++ b/include/git2/filter.h
@@ -14,9 +14,15 @@
/**
* @file git2/filter.h
- * @brief Git filter APIs
- *
+ * @brief Filters modify files during checkout or commit
* @ingroup Git
+ *
+ * During checkout, filters update a file from a "canonical" state to
+ * a format appropriate for the local filesystem; during commit, filters
+ * produce the canonical state. For example, on Windows, the line ending
+ * filters _may_ take a canonical state (with Unix-style newlines) in
+ * the repository, and place the contents on-disk with Windows-style
+ * `\r\n` line endings.
* @{
*/
GIT_BEGIN_DECL
@@ -79,8 +85,11 @@ typedef struct {
git_oid attr_commit_id;
} git_filter_options;
- #define GIT_FILTER_OPTIONS_VERSION 1
- #define GIT_FILTER_OPTIONS_INIT {GIT_FILTER_OPTIONS_VERSION}
+/** Current version for the `git_filter_options` structure */
+#define GIT_FILTER_OPTIONS_VERSION 1
+
+/** Static constructor for `git_filter_options` */
+#define GIT_FILTER_OPTIONS_INIT {GIT_FILTER_OPTIONS_VERSION}
/**
* A filter that can transform file data
@@ -268,9 +277,7 @@ GIT_EXTERN(int) git_filter_list_stream_blob(
*/
GIT_EXTERN(void) git_filter_list_free(git_filter_list *filters);
-
-GIT_END_DECL
-
/** @} */
+GIT_END_DECL
#endif
diff --git a/include/git2/global.h b/include/git2/global.h
index 2a87e10c6c8..f15eb2d2880 100644
--- a/include/git2/global.h
+++ b/include/git2/global.h
@@ -9,6 +9,12 @@
#include "common.h"
+/**
+ * @file git2/global.h
+ * @brief libgit2 library initializer and shutdown functionality
+ * @ingroup Git
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -32,7 +38,7 @@ GIT_EXTERN(int) git_libgit2_init(void);
* many times as `git_libgit2_init()` was called - it will return the
* number of remainining initializations that have not been shutdown
* (after this one).
- *
+ *
* @return the number of remaining initializations of the library, or an
* error code.
*/
@@ -40,5 +46,6 @@ GIT_EXTERN(int) git_libgit2_shutdown(void);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/graph.h b/include/git2/graph.h
index 56edb2f87f9..1792020a4be 100644
--- a/include/git2/graph.h
+++ b/include/git2/graph.h
@@ -13,7 +13,7 @@
/**
* @file git2/graph.h
- * @brief Git graph traversal routines
+ * @brief Graph traversal routines
* @defgroup git_revwalk Git graph traversal routines
* @ingroup Git
* @{
@@ -61,8 +61,8 @@ GIT_EXTERN(int) git_graph_descendant_of(
*
* @param repo the repository where the commits exist
* @param commit a previously loaded commit
- * @param length the number of commits in the provided `descendant_array`
* @param descendant_array oids of the commits
+ * @param length the number of commits in the provided `descendant_array`
* @return 1 if the given commit is an ancestor of any of the given potential
* descendants, 0 if not, error code otherwise.
*/
@@ -74,4 +74,5 @@ GIT_EXTERN(int) git_graph_reachable_from_any(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/ignore.h b/include/git2/ignore.h
index 4c441c63384..730f2214ba5 100644
--- a/include/git2/ignore.h
+++ b/include/git2/ignore.h
@@ -10,6 +10,15 @@
#include "common.h"
#include "types.h"
+/**
+ * @file git2/ignore.h
+ * @brief Ignore particular untracked files
+ * @ingroup Git
+ * @{
+ *
+ * When examining the repository status, git can optionally ignore
+ * specified untracked files.
+ */
GIT_BEGIN_DECL
/**
@@ -73,6 +82,7 @@ GIT_EXTERN(int) git_ignore_path_is_ignored(
git_repository *repo,
const char *path);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/index.h b/include/git2/index.h
index 6e806371bf4..0adff1abd95 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -15,9 +15,14 @@
/**
* @file git2/index.h
- * @brief Git index parsing and manipulation routines
+ * @brief Index (aka "cache" aka "staging area")
* @defgroup git_index Git index parsing and manipulation routines
* @ingroup Git
+ *
+ * The index (or "cache", or "staging area") is the contents of the
+ * next commit. In addition, the index stores other data, such as
+ * conflicts that occurred during the last merge operation, and
+ * the "treecache" to speed up various on-disk operations.
* @{
*/
GIT_BEGIN_DECL
@@ -77,8 +82,11 @@ typedef struct git_index_entry {
* data in the `flags`.
*/
+/** Mask for name length */
#define GIT_INDEX_ENTRY_NAMEMASK (0x0fff)
+/** Mask for index entry stage */
#define GIT_INDEX_ENTRY_STAGEMASK (0x3000)
+/** Shift bits for index entry */
#define GIT_INDEX_ENTRY_STAGESHIFT 12
/**
@@ -89,9 +97,17 @@ typedef enum {
GIT_INDEX_ENTRY_VALID = (0x8000)
} git_index_entry_flag_t;
+/**
+ * Macro to get the stage value (0 for the "main index", or a conflict
+ * value) from an index entry.
+ */
#define GIT_INDEX_ENTRY_STAGE(E) \
(((E)->flags & GIT_INDEX_ENTRY_STAGEMASK) >> GIT_INDEX_ENTRY_STAGESHIFT)
+/**
+ * Macro to set the stage value (0 for the "main index", or a conflict
+ * value) for an index entry.
+ */
#define GIT_INDEX_ENTRY_STAGE_SET(E,S) do { \
(E)->flags = ((E)->flags & ~GIT_INDEX_ENTRY_STAGEMASK) | \
(((S) & 0x03) << GIT_INDEX_ENTRY_STAGESHIFT); } while (0)
@@ -131,7 +147,14 @@ typedef enum {
} git_index_capability_t;
-/** Callback for APIs that add/remove/update files matching pathspec */
+/**
+ * Callback for APIs that add/remove/update files matching pathspec
+ *
+ * @param path the path
+ * @param matched_pathspec the given pathspec
+ * @param payload the user-specified payload
+ * @return 0 to continue with the index operation, positive number to skip this file for the index operation, negative number on failure
+ */
typedef int GIT_CALLBACK(git_index_matched_path_cb)(
const char *path, const char *matched_pathspec, void *payload);
@@ -166,6 +189,74 @@ typedef enum {
GIT_INDEX_STAGE_THEIRS = 3
} git_index_stage_t;
+#ifdef GIT_EXPERIMENTAL_SHA256
+
+/**
+ * The options for opening or creating an index.
+ *
+ * Initialize with `GIT_INDEX_OPTIONS_INIT`. Alternatively, you can
+ * use `git_index_options_init`.
+ *
+ * @options[version] GIT_INDEX_OPTIONS_VERSION
+ * @options[init_macro] GIT_INDEX_OPTIONS_INIT
+ * @options[init_function] git_index_options_init
+ */
+typedef struct git_index_options {
+ unsigned int version; /**< The version */
+
+ /**
+ * The object ID type for the object IDs that exist in the index.
+ *
+ * If this is not specified, this defaults to `GIT_OID_SHA1`.
+ */
+ git_oid_t oid_type;
+} git_index_options;
+
+/** Current version for the `git_index_options` structure */
+#define GIT_INDEX_OPTIONS_VERSION 1
+
+/** Static constructor for `git_index_options` */
+#define GIT_INDEX_OPTIONS_INIT { GIT_INDEX_OPTIONS_VERSION }
+
+/**
+ * Initialize git_index_options structure
+ *
+ * Initializes a `git_index_options` with default values. Equivalent to creating
+ * an instance with GIT_INDEX_OPTIONS_INIT.
+ *
+ * @param opts The `git_index_options` struct to initialize.
+ * @param version The struct version; pass `GIT_INDEX_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_index_options_init(
+ git_index_options *opts,
+ unsigned int version);
+
+/**
+ * Creates a new bare Git index object, without a repository to back
+ * it. This index object is capable of storing SHA256 objects.
+ *
+ * @param index_out the pointer for the new index
+ * @param index_path the path to the index file in disk
+ * @param opts the options for opening the index, or NULL
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_index_open(
+ git_index **index_out,
+ const char *index_path,
+ const git_index_options *opts);
+
+/**
+ * Create an in-memory index object.
+ *
+ * @param index_out the pointer for the new index
+ * @param opts the options for opening the index, or NULL
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_index_new(git_index **index_out, const git_index_options *opts);
+
+#else
+
/**
* Create a new bare Git index object as a memory representation
* of the Git index file in 'index_path', without a repository
@@ -180,16 +271,11 @@ typedef enum {
*
* The index must be freed once it's no longer in use.
*
- * @param out the pointer for the new index
+ * @param index_out the pointer for the new index
* @param index_path the path to the index file in disk
* @return 0 or an error code
*/
-
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_index_open(git_index **out, const char *index_path, git_oid_t oid_type);
-#else
-GIT_EXTERN(int) git_index_open(git_index **out, const char *index_path);
-#endif
+GIT_EXTERN(int) git_index_open(git_index **index_out, const char *index_path);
/**
* Create an in-memory index object.
@@ -199,13 +285,11 @@ GIT_EXTERN(int) git_index_open(git_index **out, const char *index_path);
*
* The index must be freed once it's no longer in use.
*
- * @param out the pointer for the new index
+ * @param index_out the pointer for the new index
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_index_new(git_index **out, git_oid_t oid_type);
-#else
-GIT_EXTERN(int) git_index_new(git_index **out);
+GIT_EXTERN(int) git_index_new(git_index **index_out);
+
#endif
/**
@@ -845,4 +929,5 @@ GIT_EXTERN(void) git_index_conflict_iterator_free(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/indexer.h b/include/git2/indexer.h
index 630eef93456..9aaedc3c43f 100644
--- a/include/git2/indexer.h
+++ b/include/git2/indexer.h
@@ -4,13 +4,23 @@
* 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_git_indexer_h__
-#define _INCLUDE_git_indexer_h__
+#ifndef INCLUDE_git_indexer_h__
+#define INCLUDE_git_indexer_h__
#include "common.h"
#include "types.h"
#include "oid.h"
+/**
+ * @file git2/indexer.h
+ * @brief Packfile indexing
+ * @ingroup Git
+ * @{
+ *
+ * Indexing is the operation of taking a packfile - which is simply a
+ * collection of unordered commits - and producing an "index" so that
+ * one can lookup a commit in the packfile by object ID.
+ */
GIT_BEGIN_DECL
/** A git indexer object */
@@ -53,6 +63,7 @@ typedef struct git_indexer_progress {
*
* @param stats Structure containing information about the state of the transfer
* @param payload Payload provided by caller
+ * @return 0 on success or an error code
*/
typedef int GIT_CALLBACK(git_indexer_progress_cb)(const git_indexer_progress *stats, void *payload);
@@ -66,6 +77,9 @@ typedef struct git_indexer_options {
/** permissions to use creating packfile or 0 for defaults */
unsigned int mode;
+ /** the type of object ids in the packfile or 0 for SHA1 */
+ git_oid_t oid_type;
+
/**
* object database from which to read base objects when
* fixing thin packs. This can be NULL if there are no thin
@@ -85,7 +99,10 @@ typedef struct git_indexer_options {
unsigned char verify;
} git_indexer_options;
+/** Current version for the `git_indexer_options` structure */
#define GIT_INDEXER_OPTIONS_VERSION 1
+
+/** Static constructor for `git_indexer_options` */
#define GIT_INDEXER_OPTIONS_INIT { GIT_INDEXER_OPTIONS_VERSION }
/**
@@ -106,13 +123,12 @@ GIT_EXTERN(int) git_indexer_options_init(
*
* @param out where to store the indexer instance
* @param path to the directory where the packfile should be stored
- * @param oid_type the oid type to use for objects
+ * @param opts the options to create the indexer with
* @return 0 or an error code.
*/
GIT_EXTERN(int) git_indexer_new(
git_indexer **out,
const char *path,
- git_oid_t oid_type,
git_indexer_options *opts);
#else
/**
@@ -190,6 +206,7 @@ GIT_EXTERN(const char *) git_indexer_name(const git_indexer *idx);
*/
GIT_EXTERN(void) git_indexer_free(git_indexer *idx);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h
index 7c3f60fcc82..fd6ae7170c2 100644
--- a/include/git2/mailmap.h
+++ b/include/git2/mailmap.h
@@ -13,10 +13,15 @@
/**
* @file git2/mailmap.h
- * @brief Mailmap parsing routines
+ * @brief Mailmaps provide alternate email addresses for users
* @defgroup git_mailmap Git mailmap routines
* @ingroup Git
* @{
+ *
+ * A mailmap can be used to specify alternate email addresses for
+ * repository committers or authors. This allows systems to map
+ * commits made using different email addresses to the same logical
+ * person.
*/
GIT_BEGIN_DECL
@@ -112,4 +117,5 @@ GIT_EXTERN(int) git_mailmap_resolve_signature(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/merge.h b/include/git2/merge.h
index fcce5594d47..be3b065b8a2 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -17,9 +17,12 @@
/**
* @file git2/merge.h
- * @brief Git merge routines
+ * @brief Merge re-joins diverging branches of history
* @defgroup git_merge Git merge routines
* @ingroup Git
+ *
+ * Merge will take two commits and attempt to produce a commit that
+ * includes the changes that were made in both branches.
* @{
*/
GIT_BEGIN_DECL
@@ -45,7 +48,10 @@ typedef struct {
unsigned int mode;
} git_merge_file_input;
+/** Current version for the `git_merge_file_input_options` structure */
#define GIT_MERGE_FILE_INPUT_VERSION 1
+
+/** Static constructor for `git_merge_file_input_options` */
#define GIT_MERGE_FILE_INPUT_INIT {GIT_MERGE_FILE_INPUT_VERSION}
/**
@@ -180,6 +186,7 @@ typedef enum {
GIT_MERGE_FILE_ACCEPT_CONFLICTS = (1 << 9)
} git_merge_file_flag_t;
+/** Default size for conflict markers */
#define GIT_MERGE_CONFLICT_MARKER_SIZE 7
/**
@@ -217,7 +224,10 @@ typedef struct {
unsigned short marker_size;
} git_merge_file_options;
+/** Current version for the `git_merge_file_options` structure */
#define GIT_MERGE_FILE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_merge_file_options` */
#define GIT_MERGE_FILE_OPTIONS_INIT {GIT_MERGE_FILE_OPTIONS_VERSION}
/**
@@ -312,7 +322,10 @@ typedef struct {
uint32_t file_flags;
} git_merge_options;
+/** Current version for the `git_merge_options` structure */
#define GIT_MERGE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_merge_options` */
#define GIT_MERGE_OPTIONS_INIT { \
GIT_MERGE_OPTIONS_VERSION, GIT_MERGE_FIND_RENAMES }
@@ -471,6 +484,37 @@ GIT_EXTERN(int) git_merge_base_many(
/**
* Find all merge bases given a list of commits
*
+ * This behaves similar to [`git merge-base`](https://git-scm.com/docs/git-merge-base#_discussion).
+ *
+ * Given three commits `a`, `b`, and `c`, `merge_base_many`
+ * will compute a hypothetical commit `m`, which is a merge between `b`
+ * and `c`.
+
+ * For example, with the following topology:
+ * ```text
+ * o---o---o---o---C
+ * /
+ * / o---o---o---B
+ * / /
+ * ---2---1---o---o---o---A
+ * ```
+ *
+ * the result of `merge_base_many` given `a`, `b`, and `c` is 1. This is
+ * because the equivalent topology with the imaginary merge commit `m`
+ * between `b` and `c` is:
+ * ```text
+ * o---o---o---o---o
+ * / \
+ * / o---o---o---o---M
+ * / /
+ * ---2---1---o---o---o---A
+ * ```
+ *
+ * and the result of `merge_base_many` given `a` and `m` is 1.
+ *
+ * If you're looking to recieve the common ancestor between all the
+ * given commits, use `merge_base_octopus`.
+ *
* @param out array in which to store the resulting ids
* @param repo the repository where the commits exist
* @param length The number of commits in the provided `input_array`
@@ -623,4 +667,5 @@ GIT_EXTERN(int) git_merge(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/message.h b/include/git2/message.h
index cd3ddf730e0..874d027f23f 100644
--- a/include/git2/message.h
+++ b/include/git2/message.h
@@ -12,7 +12,7 @@
/**
* @file git2/message.h
- * @brief Git message management routines
+ * @brief Commit messages
* @ingroup Git
* @{
*/
@@ -83,4 +83,4 @@ GIT_EXTERN(void) git_message_trailer_array_free(git_message_trailer_array *arr);
/** @} */
GIT_END_DECL
-#endif /* INCLUDE_git_message_h__ */
+#endif
diff --git a/include/git2/net.h b/include/git2/net.h
index 8103eafbfda..93bdac4995f 100644
--- a/include/git2/net.h
+++ b/include/git2/net.h
@@ -13,12 +13,13 @@
/**
* @file git2/net.h
- * @brief Git networking declarations
+ * @brief Low-level networking functionality
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/** Default git protocol port number */
#define GIT_DEFAULT_PORT "9418"
/**
@@ -51,4 +52,5 @@ struct git_remote_head {
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/notes.h b/include/git2/notes.h
index c135881a7c8..3784d5f5222 100644
--- a/include/git2/notes.h
+++ b/include/git2/notes.h
@@ -11,7 +11,7 @@
/**
* @file git2/notes.h
- * @brief Git notes management routines
+ * @brief Notes are metadata attached to an object
* @defgroup git_note Git notes management routines
* @ingroup Git
* @{
@@ -21,13 +21,15 @@ GIT_BEGIN_DECL
/**
* Callback for git_note_foreach.
*
- * Receives:
- * - blob_id: Oid of the blob containing the message
- * - annotated_object_id: Oid of the git object being annotated
- * - payload: Payload data passed to `git_note_foreach`
+ * @param blob_id object id of the blob containing the message
+ * @param annotated_object_id the id of the object being annotated
+ * @param payload user-specified data to the foreach function
+ * @return 0 on success, or a negative number on failure
*/
typedef int GIT_CALLBACK(git_note_foreach_cb)(
- const git_oid *blob_id, const git_oid *annotated_object_id, void *payload);
+ const git_oid *blob_id,
+ const git_oid *annotated_object_id,
+ void *payload);
/**
* note iterator
@@ -303,4 +305,5 @@ GIT_EXTERN(int) git_note_foreach(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/object.h b/include/git2/object.h
index 6384aaa6e94..8a50239fe8d 100644
--- a/include/git2/object.h
+++ b/include/git2/object.h
@@ -14,13 +14,14 @@
/**
* @file git2/object.h
- * @brief Git revision object management routines
+ * @brief Objects are blobs (files), trees (directories), commits, and annotated tags
* @defgroup git_object Git revision object management routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/** Maximum size of a git object */
#define GIT_OBJECT_SIZE_MAX UINT64_MAX
/**
@@ -53,18 +54,18 @@ GIT_EXTERN(int) git_object_lookup(
*
* The object obtained will be so that its identifier
* matches the first 'len' hexadecimal characters
- * (packets of 4 bits) of the given 'id'.
- * 'len' must be at least GIT_OID_MINPREFIXLEN, and
- * long enough to identify a unique object matching
- * the prefix; otherwise the method will fail.
+ * (packets of 4 bits) of the given `id`. `len` must be
+ * at least `GIT_OID_MINPREFIXLEN`, and long enough to
+ * identify a unique object matching the prefix; otherwise
+ * the method will fail.
*
* The generated reference is owned by the repository and
* should be closed with the `git_object_free` method
* instead of free'd manually.
*
- * The 'type' parameter must match the type of the object
+ * The `type` parameter must match the type of the object
* in the odb; the method will fail otherwise.
- * The special value 'GIT_OBJECT_ANY' may be passed to let
+ * The special value `GIT_OBJECT_ANY` may be passed to let
* the method guess the object's type.
*
* @param object_out pointer where to store the looked-up object
@@ -260,7 +261,7 @@ GIT_EXTERN(int) git_object_rawcontent_is_valid(
* @warning This function is experimental and its signature may change in
* the future.
*
- * @param valid Output pointer to set with validity of the object content
+ * @param[out] valid Output pointer to set with validity of the object content
* @param buf The contents to validate
* @param len The length of the buffer
* @param object_type The type of the object in the buffer
diff --git a/include/git2/odb.h b/include/git2/odb.h
index c7d6a894cd2..e809c36d70e 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -15,7 +15,7 @@
/**
* @file git2/odb.h
- * @brief Git object database routines
+ * @brief An object database manages the storage of git objects
* @defgroup git_odb Git object database routines
* @ingroup Git
* @{
@@ -35,6 +35,10 @@ typedef enum {
/**
* Function type for callbacks from git_odb_foreach.
+ *
+ * @param id an id of an object in the object database
+ * @param payload the payload from the initial call to git_odb_foreach
+ * @return 0 on success, or an error code
*/
typedef int GIT_CALLBACK(git_odb_foreach_cb)(const git_oid *id, void *payload);
@@ -49,30 +53,53 @@ typedef struct {
git_oid_t oid_type;
} git_odb_options;
-/* The current version of the diff options structure */
+/** The current version of the diff options structure */
#define GIT_ODB_OPTIONS_VERSION 1
-/* Stack initializer for odb options. Alternatively use
+/**
+ * Stack initializer for odb options. Alternatively use
* `git_odb_options_init` programmatic initialization.
*/
#define GIT_ODB_OPTIONS_INIT { GIT_ODB_OPTIONS_VERSION }
+#ifdef GIT_EXPERIMENTAL_SHA256
+
/**
* Create a new object database with no backends.
*
- * Before the ODB can be used for read/writing, a custom database
- * backend must be manually added using `git_odb_add_backend()`
+ * @param[out] odb location to store the database pointer, if opened.
+ * @param opts the options for this object database or NULL for defaults
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_new(git_odb **odb, const git_odb_options *opts);
+
+/**
+ * Create a new object database and automatically add loose and packed
+ * backends.
*
- * @param out location to store the database pointer, if opened.
+ * @param[out] odb_out location to store the database pointer, if opened.
* Set to NULL if the open failed.
+ * @param objects_dir path of the backends' "objects" directory.
* @param opts the options for this object database or NULL for defaults
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_odb_new(git_odb **out, const git_odb_options *opts);
+GIT_EXTERN(int) git_odb_open(
+ git_odb **odb_out,
+ const char *objects_dir,
+ const git_odb_options *opts);
+
#else
-GIT_EXTERN(int) git_odb_new(git_odb **out);
-#endif
+
+/**
+ * Create a new object database with no backends.
+ *
+ * Before the ODB can be used for read/writing, a custom database
+ * backend must be manually added using `git_odb_add_backend()`
+ *
+ * @param[out] odb location to store the database pointer, if opened.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_new(git_odb **odb);
/**
* Create a new object database and automatically add
@@ -85,19 +112,12 @@ GIT_EXTERN(int) git_odb_new(git_odb **out);
* assuming `objects_dir` as the Objects folder which
* contains a 'pack/' folder with the corresponding data
*
- * @param out location to store the database pointer, if opened.
+ * @param[out] odb_out location to store the database pointer, if opened.
* Set to NULL if the open failed.
* @param objects_dir path of the backends' "objects" directory.
- * @param opts the options for this object database or NULL for defaults
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_odb_open(
- git_odb **out,
- const char *objects_dir,
- const git_odb_options *opts);
-#else
-GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
+GIT_EXTERN(int) git_odb_open(git_odb **odb_out, const char *objects_dir);
#endif
/**
@@ -134,13 +154,13 @@ GIT_EXTERN(void) git_odb_free(git_odb *db);
* internally cached, so it should be closed
* by the user once it's no longer in use.
*
- * @param out pointer where to store the read object
+ * @param[out] obj pointer where to store the read object
* @param db database to search for the object in.
* @param id identity of the object to read.
* @return 0 if the object was read, GIT_ENOTFOUND if the object is
* not in the database.
*/
-GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id);
+GIT_EXTERN(int) git_odb_read(git_odb_object **obj, git_odb *db, const git_oid *id);
/**
* Read an object from the database, given a prefix
@@ -160,7 +180,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i
* internally cached, so it should be closed
* by the user once it's no longer in use.
*
- * @param out pointer where to store the read object
+ * @param[out] obj pointer where to store the read object
* @param db database to search for the object in.
* @param short_id a prefix of the id of the object to read.
* @param len the length of the prefix
@@ -168,7 +188,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i
* database. GIT_EAMBIGUOUS if the prefix is ambiguous
* (several objects match the prefix)
*/
-GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len);
+GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **obj, git_odb *db, const git_oid *short_id, size_t len);
/**
* Read the header of an object from the database, without
@@ -180,8 +200,8 @@ GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git
* of an object, so the whole object will be read and then the
* header will be returned.
*
- * @param len_out pointer where to store the length
- * @param type_out pointer where to store the type
+ * @param[out] len_out pointer where to store the length
+ * @param[out] type_out pointer where to store the type
* @param db database to search for the object in.
* @param id identity of the object to read.
* @return 0 if the object was read, GIT_ENOTFOUND if the object is not
@@ -286,7 +306,7 @@ GIT_EXTERN(int) git_odb_expand_ids(
* @param db database to refresh
* @return 0 on success, error code otherwise
*/
-GIT_EXTERN(int) git_odb_refresh(struct git_odb *db);
+GIT_EXTERN(int) git_odb_refresh(git_odb *db);
/**
* List all objects available in the database
@@ -301,7 +321,10 @@ GIT_EXTERN(int) git_odb_refresh(struct git_odb *db);
* @param payload data to pass to the callback
* @return 0 on success, non-zero callback return value, or error code
*/
-GIT_EXTERN(int) git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload);
+GIT_EXTERN(int) git_odb_foreach(
+ git_odb *db,
+ git_odb_foreach_cb cb,
+ void *payload);
/**
* Write an object directly into the ODB
@@ -316,7 +339,7 @@ GIT_EXTERN(int) git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payloa
*
* @param out pointer to store the OID result of the write
* @param odb object database where to store the object
- * @param data buffer with the data to store
+ * @param data @type `const unsigned char *` buffer with the data to store
* @param len size of the buffer
* @param type type of the data to store
* @return 0 or an error code
@@ -382,7 +405,7 @@ GIT_EXTERN(int) git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stre
* @param stream the stream
* @param buffer a user-allocated buffer to store the data in.
* @param len the buffer's length
- * @return 0 if the read succeeded, error code otherwise
+ * @return the number of bytes read if succeeded, error code otherwise
*/
GIT_EXTERN(int) git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len);
@@ -466,29 +489,54 @@ GIT_EXTERN(int) git_odb_write_pack(
GIT_EXTERN(int) git_odb_write_multi_pack_index(
git_odb *db);
+#ifdef GIT_EXPERIMENTAL_SHA256
+
/**
- * Determine the object-ID (sha1 or sha256 hash) of a data buffer
+ * Generate the object ID (in SHA1 or SHA256 format) for a given data buffer.
*
- * The resulting OID will be the identifier for the data buffer as if
- * the data buffer it were to written to the ODB.
- *
- * @param out the resulting object-ID.
+ * @param[out] oid the resulting object ID.
* @param data data to hash
* @param len size of the data
* @param object_type of the data to hash
* @param oid_type the oid type to hash to
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_odb_hash(
- git_oid *out,
+ git_oid *oid,
const void *data,
size_t len,
git_object_t object_type,
git_oid_t oid_type);
+
+/**
+ * Determine the object ID of a file on disk.
+ *
+ * @param[out] oid oid structure the result is written into.
+ * @param path file to read and determine object id for
+ * @param object_type of the data to hash
+ * @param oid_type the oid type to hash to
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_hashfile(
+ git_oid *oid,
+ const char *path,
+ git_object_t object_type,
+ git_oid_t oid_type);
#else
-GIT_EXTERN(int) git_odb_hash(git_oid *out, const void *data, size_t len, git_object_t type);
-#endif
+
+/**
+ * Determine the object-ID (sha1 or sha256 hash) of a data buffer
+ *
+ * The resulting OID will be the identifier for the data buffer as if
+ * the data buffer it were to written to the ODB.
+ *
+ * @param[out] oid the resulting object-ID.
+ * @param data data to hash
+ * @param len size of the data
+ * @param object_type of the data to hash
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_hash(git_oid *oid, const void *data, size_t len, git_object_t object_type);
/**
* Read a file from disk and fill a git_oid with the object id
@@ -498,20 +546,13 @@ GIT_EXTERN(int) git_odb_hash(git_oid *out, const void *data, size_t len, git_obj
* the `-w` flag, however, with the --no-filters flag.
* If you need filters, see git_repository_hashfile.
*
- * @param out oid structure the result is written into.
+ * @param[out] oid oid structure the result is written into.
* @param path file to read and determine object id for
* @param object_type of the data to hash
- * @param oid_type the oid type to hash to
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_odb_hashfile(
- git_oid *out,
- const char *path,
- git_object_t object_type,
- git_oid_t oid_type);
-#else
-GIT_EXTERN(int) git_odb_hashfile(git_oid *out, const char *path, git_object_t type);
+GIT_EXTERN(int) git_odb_hashfile(git_oid *oid, const char *path, git_object_t object_type);
+
#endif
/**
@@ -557,7 +598,7 @@ GIT_EXTERN(const git_oid *) git_odb_object_id(git_odb_object *object);
* This pointer is owned by the object and shall not be free'd.
*
* @param object the object
- * @return a pointer to the data
+ * @return @type `const unsigned char *` a pointer to the data
*/
GIT_EXTERN(const void *) git_odb_object_data(git_odb_object *object);
@@ -651,4 +692,5 @@ GIT_EXTERN(int) git_odb_set_commit_graph(git_odb *odb, git_commit_graph *cgraph)
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index 12dd0fd38a3..88ca29fb9f8 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -13,17 +13,13 @@
/**
* @file git2/backend.h
- * @brief Git custom backend functions
+ * @brief Object database backends manage the storage of git objects
* @defgroup git_odb Git object database routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
-/*
- * Constructors for in-box ODB backends.
- */
-
/** Options for configuring a packfile object backend. */
typedef struct {
unsigned int version; /**< version for the struct */
@@ -35,56 +31,16 @@ typedef struct {
git_oid_t oid_type;
} git_odb_backend_pack_options;
-/* The current version of the diff options structure */
+/** The current version of the diff options structure */
#define GIT_ODB_BACKEND_PACK_OPTIONS_VERSION 1
-/* Stack initializer for odb pack backend options. Alternatively use
+/**
+ * Stack initializer for odb pack backend options. Alternatively use
* `git_odb_backend_pack_options_init` programmatic initialization.
*/
#define GIT_ODB_BACKEND_PACK_OPTIONS_INIT \
{ GIT_ODB_BACKEND_PACK_OPTIONS_VERSION }
-/**
- * Create a backend for the packfiles.
- *
- * @param out location to store the odb backend pointer
- * @param objects_dir the Git repository's objects directory
- *
- * @return 0 or an error code
- */
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_odb_backend_pack(
- git_odb_backend **out,
- const char *objects_dir,
- const git_odb_backend_pack_options *opts);
-#else
-GIT_EXTERN(int) git_odb_backend_pack(
- git_odb_backend **out,
- const char *objects_dir);
-#endif
-
-/**
- * Create a backend out of a single packfile
- *
- * This can be useful for inspecting the contents of a single
- * packfile.
- *
- * @param out location to store the odb backend pointer
- * @param index_file path to the packfile's .idx file
- *
- * @return 0 or an error code
- */
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_odb_backend_one_pack(
- git_odb_backend **out,
- const char *index_file,
- const git_odb_backend_pack_options *opts);
-#else
-GIT_EXTERN(int) git_odb_backend_one_pack(
- git_odb_backend **out,
- const char *index_file);
-#endif
-
typedef enum {
GIT_ODB_BACKEND_LOOSE_FSYNC = (1 << 0)
} git_odb_backend_loose_flag_t;
@@ -118,30 +74,100 @@ typedef struct {
git_oid_t oid_type;
} git_odb_backend_loose_options;
-/* The current version of the diff options structure */
+/** The current version of the diff options structure */
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION 1
-/* Stack initializer for odb loose backend options. Alternatively use
+/**
+ * Stack initializer for odb loose backend options. Alternatively use
* `git_odb_backend_loose_options_init` programmatic initialization.
*/
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT \
{ GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION, 0, -1 }
+/*
+ * Constructors for in-box ODB backends.
+ */
+
+#ifdef GIT_EXPERIMENTAL_SHA256
+
+/**
+ * Create a backend for a directory containing packfiles.
+ *
+ * @param[out] out location to store the odb backend pointer
+ * @param objects_dir the Git repository's objects directory
+ * @param opts the options to use when creating the pack backend
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_backend_pack(
+ git_odb_backend **out,
+ const char *objects_dir,
+ const git_odb_backend_pack_options *opts);
+
+/**
+ * Create a backend for a single packfile.
+ *
+ * @param[out] out location to store the odb backend pointer
+ * @param index_file path to the packfile's .idx file
+ * @param opts the options to use when creating the pack backend
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_backend_one_pack(
+ git_odb_backend **out,
+ const char *index_file,
+ const git_odb_backend_pack_options *opts);
+
/**
* Create a backend for loose objects
*
- * @param out location to store the odb backend pointer
+ * @param[out] out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory
* @param opts options for the loose object backend or NULL
*
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_odb_backend_loose(
git_odb_backend **out,
const char *objects_dir,
git_odb_backend_loose_options *opts);
+
#else
+
+/**
+ * Create a backend for a directory containing packfiles.
+ *
+ * @param[out] out location to store the odb backend pointer
+ * @param objects_dir the Git repository's objects directory
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_backend_pack(
+ git_odb_backend **out,
+ const char *objects_dir);
+
+/**
+ * Create a backend out of a single packfile
+ *
+ * This can be useful for inspecting the contents of a single
+ * packfile.
+ *
+ * @param[out] out location to store the odb backend pointer
+ * @param index_file path to the packfile's .idx file
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_odb_backend_one_pack(
+ git_odb_backend **out,
+ const char *index_file);
+
+/**
+ * Create a backend for loose objects
+ *
+ * @param[out] out location to store the odb backend pointer
+ * @param objects_dir the Git repository's objects directory
+ * @param compression_level zlib compression level (0-9), or -1 for the default
+ * @param do_fsync if non-zero, perform an fsync on write
+ * @param dir_mode permission to use when creating directories, or 0 for default
+ * @param file_mode permission to use when creating directories, or 0 for default
+ * @return 0 or an error code
+ */
GIT_EXTERN(int) git_odb_backend_loose(
git_odb_backend **out,
const char *objects_dir,
@@ -149,6 +175,7 @@ GIT_EXTERN(int) git_odb_backend_loose(
int do_fsync,
unsigned int dir_mode,
unsigned int file_mode);
+
#endif
/** Streaming mode */
@@ -218,6 +245,7 @@ struct git_odb_writepack {
void GIT_CALLBACK(free)(git_odb_writepack *writepack);
};
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/oid.h b/include/git2/oid.h
index 35b43ef183a..0af9737a04d 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -13,7 +13,7 @@
/**
* @file git2/oid.h
- * @brief Git object id routines
+ * @brief Object IDs
* @defgroup git_oid Git object id routines
* @ingroup Git
* @{
@@ -82,13 +82,18 @@ typedef enum {
#endif
-/* Maximum possible object ID size in raw / hex string format. */
-#ifndef GIT_EXPERIMENTAL_SHA256
-# define GIT_OID_MAX_SIZE GIT_OID_SHA1_SIZE
-# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA1_HEXSIZE
-#else
+/** Maximum possible object ID size in raw format */
+#ifdef GIT_EXPERIMENTAL_SHA256
# define GIT_OID_MAX_SIZE GIT_OID_SHA256_SIZE
+#else
+# define GIT_OID_MAX_SIZE GIT_OID_SHA1_SIZE
+#endif
+
+/** Maximum possible object ID size in hex format */
+#ifdef GIT_EXPERIMENTAL_SHA256
# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA256_HEXSIZE
+#else
+# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA1_HEXSIZE
#endif
/** Minimum length (in number of hex characters,
@@ -107,6 +112,15 @@ typedef struct git_oid {
unsigned char id[GIT_OID_MAX_SIZE];
} git_oid;
+#ifdef GIT_EXPERIMENTAL_SHA256
+
+GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str, git_oid_t type);
+GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str, git_oid_t type);
+GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length, git_oid_t type);
+GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw, git_oid_t type);
+
+#else
+
/**
* Parse a hex formatted object id into a git_oid.
*
@@ -119,28 +133,18 @@ typedef struct git_oid {
* the hex sequence and have at least the number of bytes
* needed for an oid encoded in hex (40 bytes for sha1,
* 256 bytes for sha256).
- * @param type the type of object id
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str, git_oid_t type);
-#else
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str);
-#endif
/**
* Parse a hex formatted NUL-terminated string into a git_oid.
*
* @param out oid structure the result is written into.
* @param str input hex string; must be null-terminated.
- * @param type the type of object id
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str, git_oid_t type);
-#else
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
-#endif
/**
* Parse N characters of a hex formatted object id into a git_oid.
@@ -151,14 +155,9 @@ GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
* @param out oid structure the result is written into.
* @param str input hex string of at least size `length`
* @param length length of the input string
- * @param type the type of object id
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length, git_oid_t type);
-#else
GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
-#endif
/**
* Copy an already raw oid into a git_oid structure.
@@ -167,10 +166,8 @@ GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
* @param raw the raw input bytes to be copied.
* @return 0 on success or error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw, git_oid_t type);
-#else
GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw);
+
#endif
/**
@@ -310,6 +307,7 @@ GIT_EXTERN(int) git_oid_strcmp(const git_oid *id, const char *str);
/**
* Check is an oid is all zeros.
*
+ * @param id the object ID to check
* @return 1 if all zeros, 0 otherwise.
*/
GIT_EXTERN(int) git_oid_is_zero(const git_oid *id);
@@ -370,4 +368,5 @@ GIT_EXTERN(void) git_oid_shorten_free(git_oid_shorten *os);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/oidarray.h b/include/git2/oidarray.h
index 94fc58daba4..e79a55953df 100644
--- a/include/git2/oidarray.h
+++ b/include/git2/oidarray.h
@@ -10,6 +10,13 @@
#include "common.h"
#include "oid.h"
+/**
+ * @file git2/oidarray.h
+ * @brief An array of object IDs
+ * @defgroup git_oidarray Arrays of object IDs
+ * @ingroup Git
+ * @{
+ */
GIT_BEGIN_DECL
/** Array of object ids */
@@ -34,4 +41,3 @@ GIT_EXTERN(void) git_oidarray_dispose(git_oidarray *array);
GIT_END_DECL
#endif
-
diff --git a/include/git2/pack.h b/include/git2/pack.h
index 0f6bd2ab928..3837e04468d 100644
--- a/include/git2/pack.h
+++ b/include/git2/pack.h
@@ -233,7 +233,15 @@ GIT_EXTERN(size_t) git_packbuilder_object_count(git_packbuilder *pb);
*/
GIT_EXTERN(size_t) git_packbuilder_written(git_packbuilder *pb);
-/** Packbuilder progress notification function */
+/**
+ * Packbuilder progress notification function.
+ *
+ * @param stage the stage of the packbuilder
+ * @param current the current object
+ * @param total the total number of objects
+ * @param payload the callback payload
+ * @return 0 on success or an error code
+ */
typedef int GIT_CALLBACK(git_packbuilder_progress)(
int stage,
uint32_t current,
@@ -247,6 +255,9 @@ typedef int GIT_CALLBACK(git_packbuilder_progress)(
* @param progress_cb Function to call with progress information during
* pack building. Be aware that this is called inline with pack building
* operations, so performance may be affected.
+ * When progress_cb returns an error, the pack building process will be
+ * aborted and the error will be returned from the invoked function.
+ * `pb` must then be freed.
* @param progress_cb_payload Payload for progress callback.
* @return 0 or an error code
*/
@@ -264,4 +275,5 @@ GIT_EXTERN(void) git_packbuilder_free(git_packbuilder *pb);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/patch.h b/include/git2/patch.h
index 9cf758a3edb..782482158be 100644
--- a/include/git2/patch.h
+++ b/include/git2/patch.h
@@ -14,7 +14,7 @@
/**
* @file git2/patch.h
- * @brief Patch handling routines.
+ * @brief Patches store the textual diffs in a delta
* @ingroup Git
* @{
*/
@@ -283,8 +283,7 @@ GIT_EXTERN(int) git_patch_to_buf(
git_buf *out,
git_patch *patch);
-GIT_END_DECL
-
/**@}*/
+GIT_END_DECL
#endif
diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h
index acbd5cd1d6f..6f6918cdb9d 100644
--- a/include/git2/pathspec.h
+++ b/include/git2/pathspec.h
@@ -12,6 +12,13 @@
#include "strarray.h"
#include "diff.h"
+/**
+ * @file git2/pathspec.h
+ * @brief Specifiers for path matching
+ * @defgroup git_pathspec Specifiers for path matching
+ * @ingroup Git
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -276,5 +283,7 @@ GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount(
GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry(
const git_pathspec_match_list *m, size_t pos);
+/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/proxy.h b/include/git2/proxy.h
index cfc0c645f8b..195ab75e099 100644
--- a/include/git2/proxy.h
+++ b/include/git2/proxy.h
@@ -12,6 +12,12 @@
#include "cert.h"
#include "credential.h"
+/**
+ * @file git2/proxy.h
+ * @brief TLS proxies
+ * @ingroup Git
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -78,7 +84,10 @@ typedef struct {
void *payload;
} git_proxy_options;
+/** Current version for the `git_proxy_options` structure */
#define GIT_PROXY_OPTIONS_VERSION 1
+
+/** Static constructor for `git_proxy_options` */
#define GIT_PROXY_OPTIONS_INIT {GIT_PROXY_OPTIONS_VERSION}
/**
@@ -93,6 +102,7 @@ typedef struct {
*/
GIT_EXTERN(int) git_proxy_options_init(git_proxy_options *opts, unsigned int version);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/rebase.h b/include/git2/rebase.h
index b1ac71f94ee..3fb3e5733a2 100644
--- a/include/git2/rebase.h
+++ b/include/git2/rebase.h
@@ -17,8 +17,8 @@
/**
* @file git2/rebase.h
- * @brief Git rebase routines
- * @defgroup git_rebase Git merge routines
+ * @brief Rebase manipulates commits, placing them on a new parent
+ * @defgroup git_rebase Rebase manipulates commits, placing them on a new parent
* @ingroup Git
* @{
*/
@@ -67,10 +67,9 @@ typedef struct {
/**
* Options to control how files are written during `git_rebase_init`,
- * `git_rebase_next` and `git_rebase_abort`. Note that a minimum
- * strategy of `GIT_CHECKOUT_SAFE` is defaulted in `init` and `next`,
- * and a minimum strategy of `GIT_CHECKOUT_FORCE` is defaulted in
- * `abort` to match git semantics.
+ * `git_rebase_next` and `git_rebase_abort`. Note that during
+ * `abort`, these options will add an implied `GIT_CHECKOUT_FORCE`
+ * to match git semantics.
*/
git_checkout_options checkout_options;
@@ -155,7 +154,10 @@ typedef enum {
GIT_REBASE_OPERATION_EXEC
} git_rebase_operation_t;
+/** Current version for the `git_rebase_options` structure */
#define GIT_REBASE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_rebase_options` */
#define GIT_REBASE_OPTIONS_INIT \
{ GIT_REBASE_OPTIONS_VERSION, 0, 0, NULL, GIT_MERGE_OPTIONS_INIT, \
GIT_CHECKOUT_OPTIONS_INIT, NULL, NULL }
@@ -396,4 +398,5 @@ GIT_EXTERN(void) git_rebase_free(git_rebase *rebase);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/refdb.h b/include/git2/refdb.h
index c4849abdc4e..536ef10da29 100644
--- a/include/git2/refdb.h
+++ b/include/git2/refdb.h
@@ -14,8 +14,8 @@
/**
* @file git2/refdb.h
- * @brief Git custom refs backend functions
- * @defgroup git_refdb Git custom refs backend API
+ * @brief A database for references (branches and tags)
+ * @defgroup git_refdb A database for references (branches and tags)
* @ingroup Git
* @{
*/
diff --git a/include/git2/reflog.h b/include/git2/reflog.h
index ec365c1fab2..a0956c63a6a 100644
--- a/include/git2/reflog.h
+++ b/include/git2/reflog.h
@@ -13,8 +13,8 @@
/**
* @file git2/reflog.h
- * @brief Git reflog management routines
- * @defgroup git_reflog Git reflog management routines
+ * @brief Reference logs store how references change
+ * @defgroup git_reflog Reference logs store how references change
* @ingroup Git
* @{
*/
@@ -167,4 +167,5 @@ GIT_EXTERN(void) git_reflog_free(git_reflog *reflog);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 06f8bb97c48..d820f2a1867 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -14,8 +14,8 @@
/**
* @file git2/refs.h
- * @brief Git reference management routines
- * @defgroup git_reference Git reference management routines
+ * @brief References point to a commit; generally these are branches and tags
+ * @defgroup git_reference References point to a commit; generally these are branches and tags
* @ingroup Git
* @{
*/
@@ -29,7 +29,7 @@ GIT_BEGIN_DECL
* The name will be checked for validity.
* See `git_reference_symbolic_create()` for rules about valid names.
*
- * @param out pointer to the looked-up reference
+ * @param[out] out pointer to the looked-up reference
* @param repo the repository to look up the reference
* @param name the long name for the reference (e.g. HEAD, refs/heads/master, refs/tags/v0.1.0, ...)
* @return 0 on success, GIT_ENOTFOUND, GIT_EINVALIDSPEC or an error code.
@@ -371,6 +371,7 @@ GIT_EXTERN(int) git_reference_set_target(
* reflog is enabled for the repository. We only rename
* the reflog if it exists.
*
+ * @param[out] new_ref The new reference
* @param ref The reference to rename
* @param new_name The new name for the reference
* @param force Overwrite an existing reference
@@ -406,6 +407,7 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
* This method removes the named reference from the repository without
* looking at its old value.
*
+ * @param repo The repository to remove the reference from
* @param name The reference to remove
* @return 0 or an error code
*/
@@ -518,7 +520,7 @@ GIT_EXTERN(int) git_reference_cmp(
/**
* Create an iterator for the repo's references
*
- * @param out pointer in which to store the iterator
+ * @param[out] out pointer in which to store the iterator
* @param repo the repository
* @return 0 or an error code
*/
@@ -543,7 +545,7 @@ GIT_EXTERN(int) git_reference_iterator_glob_new(
/**
* Get the next reference
*
- * @param out pointer in which to store the reference
+ * @param[out] out pointer in which to store the reference
* @param iter the iterator
* @return 0, GIT_ITEROVER if there are no more; or an error code
*/
@@ -724,7 +726,7 @@ GIT_EXTERN(int) git_reference_normalize_name(
* If you pass `GIT_OBJECT_ANY` as the target type, then the object
* will be peeled until a non-tag object is met.
*
- * @param out Pointer to the peeled git_object
+ * @param[out] out Pointer to the peeled git_object
* @param ref The reference to be processed
* @param type The type of the requested object (GIT_OBJECT_COMMIT,
* GIT_OBJECT_TAG, GIT_OBJECT_TREE, GIT_OBJECT_BLOB or GIT_OBJECT_ANY).
@@ -768,4 +770,5 @@ GIT_EXTERN(const char *) git_reference_shorthand(const git_reference *ref);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/refspec.h b/include/git2/refspec.h
index e7087132b04..49d5f89f7e6 100644
--- a/include/git2/refspec.h
+++ b/include/git2/refspec.h
@@ -14,8 +14,8 @@
/**
* @file git2/refspec.h
- * @brief Git refspec attributes
- * @defgroup git_refspec Git refspec attributes
+ * @brief Refspecs map local references to remote references
+ * @defgroup git_refspec Refspecs map local references to remote references
* @ingroup Git
* @{
*/
@@ -79,7 +79,16 @@ GIT_EXTERN(int) git_refspec_force(const git_refspec *refspec);
GIT_EXTERN(git_direction) git_refspec_direction(const git_refspec *spec);
/**
- * Check if a refspec's source descriptor matches a reference
+ * Check if a refspec's source descriptor matches a negative reference
+ *
+ * @param refspec the refspec
+ * @param refname the name of the reference to check
+ * @return 1 if the refspec matches, 0 otherwise
+ */
+GIT_EXTERN(int) git_refspec_src_matches_negative(const git_refspec *refspec, const char *refname);
+
+/**
+ * Check if a refspec's source descriptor matches a reference
*
* @param refspec the refspec
* @param refname the name of the reference to check
@@ -116,6 +125,7 @@ GIT_EXTERN(int) git_refspec_transform(git_buf *out, const git_refspec *spec, con
*/
GIT_EXTERN(int) git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 5505f6c358d..ecb7b537eb7 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -19,8 +19,8 @@
/**
* @file git2/remote.h
- * @brief Git remote management functions
- * @defgroup git_remote remote management functions
+ * @brief Remotes are where local repositories fetch from and push to
+ * @defgroup git_remote Remotes are where local repositories fetch from and push to
* @ingroup Git
* @{
*/
@@ -83,7 +83,7 @@ typedef enum {
/* Write the fetch results to FETCH_HEAD. */
GIT_REMOTE_UPDATE_FETCHHEAD = (1 << 0),
- /* Report unchanged tips in the update_tips callback. */
+ /* Report unchanged tips in the update_refs callback. */
GIT_REMOTE_UPDATE_REPORT_UNCHANGED = (1 << 1)
} git_remote_update_flags;
@@ -116,7 +116,10 @@ typedef struct git_remote_create_options {
unsigned int flags;
} git_remote_create_options;
+/** Current version for the `git_remote_create_options` structure */
#define GIT_REMOTE_CREATE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_remote_create_options` */
#define GIT_REMOTE_CREATE_OPTIONS_INIT {GIT_REMOTE_CREATE_OPTIONS_VERSION}
/**
@@ -466,7 +469,15 @@ typedef enum git_remote_completion_t {
GIT_REMOTE_COMPLETION_ERROR
} git_remote_completion_t;
-/** Push network progress notification function */
+/**
+ * Push network progress notification callback.
+ *
+ * @param current The number of objects pushed so far
+ * @param total The total number of objects to push
+ * @param bytes The number of bytes pushed
+ * @param payload The user-specified payload callback
+ * @return 0 or an error code to stop the transfer
+ */
typedef int GIT_CALLBACK(git_push_transfer_progress_cb)(
unsigned int current,
unsigned int total,
@@ -502,8 +513,12 @@ typedef struct {
* as commands to the destination.
* @param len number of elements in `updates`
* @param payload Payload provided by the caller
+ * @return 0 or an error code to stop the push
*/
-typedef int GIT_CALLBACK(git_push_negotiation)(const git_push_update **updates, size_t len, void *payload);
+typedef int GIT_CALLBACK(git_push_negotiation)(
+ const git_push_update **updates,
+ size_t len,
+ void *payload);
/**
* Callback used to inform of the update status from the remote.
@@ -568,7 +583,8 @@ struct git_remote_callbacks {
* Completion is called when different parts of the download
* process are done (currently unused).
*/
- int GIT_CALLBACK(completion)(git_remote_completion_t type, void *data);
+ int GIT_CALLBACK(completion)(git_remote_completion_t type,
+ void *data);
/**
* This will be called if the remote host requires
@@ -594,11 +610,22 @@ struct git_remote_callbacks {
*/
git_indexer_progress_cb transfer_progress;
+#ifdef GIT_DEPRECATE_HARD
+ void *reserved_update_tips;
+#else
/**
- * Each time a reference is updated locally, this function
- * will be called with information about it.
+ * Deprecated callback for reference updates, callers should
+ * set `update_refs` instead. This is retained for backward
+ * compatibility; if you specify both `update_refs` and
+ * `update_tips`, then only the `update_refs` function will
+ * be called.
+ *
+ * @deprecated the `update_refs` callback in this structure
+ * should be preferred
*/
- int GIT_CALLBACK(update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
+ int GIT_CALLBACK(update_tips)(const char *refname,
+ const git_oid *a, const git_oid *b, void *data);
+#endif
/**
* Function to call with progress information during pack
@@ -655,9 +682,25 @@ struct git_remote_callbacks {
*/
git_url_resolve_cb resolve_url;
#endif
+
+ /**
+ * Each time a reference is updated locally, this function
+ * will be called with information about it. This should be
+ * preferred over the `update_tips` callback in this
+ * structure.
+ */
+ int GIT_CALLBACK(update_refs)(
+ const char *refname,
+ const git_oid *a,
+ const git_oid *b,
+ git_refspec *spec,
+ void *data);
};
+/** Current version for the `git_remote_callbacks_options` structure */
#define GIT_REMOTE_CALLBACKS_VERSION 1
+
+/** Static constructor for `git_remote_callbacks_options` */
#define GIT_REMOTE_CALLBACKS_INIT {GIT_REMOTE_CALLBACKS_VERSION}
/**
@@ -784,7 +827,10 @@ typedef struct {
git_strarray custom_headers;
} git_fetch_options;
+/** Current version for the `git_fetch_options` structure */
#define GIT_FETCH_OPTIONS_VERSION 1
+
+/** Static constructor for `git_fetch_options` */
#define GIT_FETCH_OPTIONS_INIT { \
GIT_FETCH_OPTIONS_VERSION, \
GIT_REMOTE_CALLBACKS_INIT, \
@@ -852,7 +898,10 @@ typedef struct {
git_strarray remote_push_options;
} git_push_options;
+/** Current version for the `git_push_options` structure */
#define GIT_PUSH_OPTIONS_VERSION 1
+
+/** Static constructor for `git_push_options` */
#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION, 1, GIT_REMOTE_CALLBACKS_INIT, GIT_PROXY_OPTIONS_INIT }
/**
@@ -896,7 +945,10 @@ typedef struct {
git_strarray custom_headers;
} git_remote_connect_options;
+/** Current version for the `git_remote_connect_options` structure */
#define GIT_REMOTE_CONNECT_OPTIONS_VERSION 1
+
+/** Static constructor for `git_remote_connect_options` */
#define GIT_REMOTE_CONNECT_OPTIONS_INIT { \
GIT_REMOTE_CONNECT_OPTIONS_VERSION, \
GIT_REMOTE_CALLBACKS_INIT, \
@@ -1016,14 +1068,14 @@ GIT_EXTERN(int) git_remote_upload(
* `git_remote_connect` will be used (if it was called).
*
* @param remote the remote to update
- * @param reflog_message The message to insert into the reflogs. If
- * NULL and fetching, the default is "fetch ", where is
- * the name of the remote (or its url, for in-memory remotes). This
- * parameter is ignored when pushing.
* @param callbacks pointer to the callback structure to use or NULL
* @param update_flags the git_remote_update_flags for these tips.
* @param download_tags what the behaviour for downloading tags is for this fetch. This is
* ignored for push. This must be the same value passed to `git_remote_download()`.
+ * @param reflog_message The message to insert into the reflogs. If
+ * NULL and fetching, the default is "fetch ", where is
+ * the name of the remote (or its url, for in-memory remotes). This
+ * parameter is ignored when pushing.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_update_tips(
@@ -1091,6 +1143,9 @@ GIT_EXTERN(int) git_remote_push(
/**
* Get the statistics structure that is filled in by the fetch operation.
+ *
+ * @param remote the remote to get statistics for
+ * @return the git_indexer_progress for the remote
*/
GIT_EXTERN(const git_indexer_progress *) git_remote_stats(git_remote *remote);
@@ -1190,4 +1245,5 @@ GIT_EXTERN(int) git_remote_default_branch(git_buf *out, git_remote *remote);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 0afda72d402..b203576affc 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -10,13 +10,14 @@
#include "common.h"
#include "types.h"
#include "oid.h"
+#include "odb.h"
#include "buffer.h"
#include "commit.h"
/**
* @file git2/repository.h
- * @brief Git repository management routines
- * @defgroup git_repository Git repository management routines
+ * @brief The repository stores revisions for a source tree
+ * @defgroup git_repository The repository stores revisions for a source tree
* @ingroup Git
* @{
*/
@@ -31,7 +32,11 @@ GIT_BEGIN_DECL
* The method will automatically detect if 'path' is a normal
* or bare repository or fail is 'path' is neither.
*
- * @param out pointer to the repo which will be opened
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
+ * @param[out] out pointer to the repo which will be opened
* @param path the path to the repository
* @return 0 or an error code
*/
@@ -57,19 +62,11 @@ GIT_EXTERN(int) git_repository_open_from_worktree(git_repository **out, git_work
*
* @param out pointer to the repo
* @param odb the object database to wrap
- * @param oid_type the oid type of the object database
* @return 0 or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_repository_wrap_odb(
- git_repository **out,
- git_odb *odb,
- git_oid_t oid_type);
-#else
GIT_EXTERN(int) git_repository_wrap_odb(
git_repository **out,
git_odb *odb);
-#endif
/**
* Look for a git repository and copy its path in the given buffer.
@@ -81,6 +78,10 @@ GIT_EXTERN(int) git_repository_wrap_odb(
* The method will automatically detect if the repository is bare
* (if there is a repository).
*
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
* @param out A pointer to a user-allocated git_buf which will contain
* the found path.
*
@@ -158,7 +159,11 @@ typedef enum {
/**
* Find and open a repository with extended controls.
*
- * @param out Pointer to the repo which will be opened. This can
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
+ * @param[out] out Pointer to the repo which will be opened. This can
* actually be NULL if you only want to use the error code to
* see if a repo at this path could be opened.
* @param path Path to open as git repository. If the flags
@@ -186,7 +191,11 @@ GIT_EXTERN(int) git_repository_open_ext(
* if you're e.g. hosting git repositories and need to access them
* efficiently
*
- * @param out Pointer to the repo which will be opened.
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
+ * @param[out] out Pointer to the repo which will be opened.
* @param bare_path Direct path to the bare repository
* @return 0 on success, or an error code
*/
@@ -211,7 +220,11 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
* TODO:
* - Reinit the repository
*
- * @param out pointer to the repo which will be created or reinitialized
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
+ * @param[out] out pointer to the repo which will be created or reinitialized
* @param path the path to the repository
* @param is_bare if true, a Git repository without a working directory is
* created at the pointed path. If false, provided path will be
@@ -373,7 +386,10 @@ typedef struct {
#endif
} git_repository_init_options;
+/** Current version for the `git_repository_init_options` structure */
#define GIT_REPOSITORY_INIT_OPTIONS_VERSION 1
+
+/** Static constructor for `git_repository_init_options` */
#define GIT_REPOSITORY_INIT_OPTIONS_INIT {GIT_REPOSITORY_INIT_OPTIONS_VERSION}
/**
@@ -398,6 +414,10 @@ GIT_EXTERN(int) git_repository_init_options_init(
* auto-detect the case sensitivity of the file system and if the
* file system supports file mode bits correctly.
*
+ * Note that the libgit2 library _must_ be initialized using
+ * `git_libgit2_init` before any APIs can be called, including
+ * this one.
+ *
* @param out Pointer to the repo which will be created or reinitialized.
* @param repo_path The path to the repository.
* @param opts Pointer to git_repository_init_options struct.
@@ -415,7 +435,7 @@ GIT_EXTERN(int) git_repository_init_ext(
* `git_reference_free()` must be called when done with it to release the
* allocated memory and prevent a leak.
*
- * @param out pointer to the reference which will be retrieved
+ * @param[out] out pointer to the reference which will be retrieved
* @param repo a repository object
*
* @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing
@@ -636,7 +656,7 @@ GIT_EXTERN(int) git_repository_config_snapshot(git_config **out, git_repository
* The ODB must be freed once it's no longer being used by
* the user.
*
- * @param out Pointer to store the loaded ODB
+ * @param[out] out Pointer to store the loaded ODB
* @param repo A repository object
* @return 0, or an error code
*/
@@ -652,7 +672,7 @@ GIT_EXTERN(int) git_repository_odb(git_odb **out, git_repository *repo);
* The refdb must be freed once it's no longer being used by
* the user.
*
- * @param out Pointer to store the loaded refdb
+ * @param[out] out Pointer to store the loaded refdb
* @param repo A repository object
* @return 0, or an error code
*/
@@ -668,7 +688,7 @@ GIT_EXTERN(int) git_repository_refdb(git_refdb **out, git_repository *repo);
* The index must be freed once it's no longer being used by
* the user.
*
- * @param out Pointer to store the loaded index
+ * @param[out] out Pointer to store the loaded index
* @param repo A repository object
* @return 0, or an error code
*/
@@ -858,7 +878,9 @@ GIT_EXTERN(int) git_repository_set_head_detached(
*
* See the documentation for `git_repository_set_head_detached()`.
*
- * @see git_repository_set_head_detached
+ * @param repo Repository pointer
+ * @param committish annotated commit to point HEAD to
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head_detached_from_annotated(
git_repository *repo,
@@ -951,8 +973,8 @@ GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo);
* The memory is owned by the repository and must not be freed by the
* user.
*
- * @param name where to store the pointer to the name
- * @param email where to store the pointer to the email
+ * @param[out] name where to store the pointer to the name
+ * @param[out] email where to store the pointer to the email
* @param repo the repository
* @return 0 or an error code
*/
@@ -993,4 +1015,5 @@ GIT_EXTERN(int) git_repository_commit_parents(git_commitarray *commits, git_repo
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/reset.h b/include/git2/reset.h
index b2ee2ba7bfb..0123f7c7600 100644
--- a/include/git2/reset.h
+++ b/include/git2/reset.h
@@ -14,7 +14,7 @@
/**
* @file git2/reset.h
- * @brief Git reset management routines
+ * @brief Reset will update the local repository to a prior state
* @ingroup Git
* @{
*/
@@ -75,11 +75,23 @@ GIT_EXTERN(int) git_reset(
*
* See the documentation for `git_reset()`.
*
- * @see git_reset
+ * @param repo Repository where to perform the reset operation.
+ *
+ * @param target Annotated commit to which the Head should be moved to.
+ * This object must belong to the given `repo`, it will be dereferenced
+ * to a git_commit which oid will be used as the target of the branch.
+ *
+ * @param reset_type Kind of reset operation to perform.
+ *
+ * @param checkout_opts Optional checkout options to be used for a HARD reset.
+ * The checkout_strategy field will be overridden (based on reset_type).
+ * This parameter can be used to propagate notify and progress callbacks.
+ *
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_reset_from_annotated(
git_repository *repo,
- const git_annotated_commit *commit,
+ const git_annotated_commit *target,
git_reset_t reset_type,
const git_checkout_options *checkout_opts);
@@ -108,4 +120,5 @@ GIT_EXTERN(int) git_reset_default(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/revert.h b/include/git2/revert.h
index 331e90dffcf..ec51eca2dd8 100644
--- a/include/git2/revert.h
+++ b/include/git2/revert.h
@@ -13,8 +13,8 @@
/**
* @file git2/revert.h
- * @brief Git revert routines
- * @defgroup git_revert Git revert routines
+ * @brief Cherry-pick the inverse of a change to "undo" its effects
+ * @defgroup git_revert Cherry-pick the inverse of a change to "undo" its effects
* @ingroup Git
* @{
*/
@@ -33,8 +33,13 @@ typedef struct {
git_checkout_options checkout_opts; /**< Options for the checkout */
} git_revert_options;
+/** Current version for the `git_revert_options` structure */
#define GIT_REVERT_OPTIONS_VERSION 1
-#define GIT_REVERT_OPTIONS_INIT {GIT_REVERT_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
+
+/** Static constructor for `git_revert_options` */
+#define GIT_REVERT_OPTIONS_INIT { \
+ GIT_REVERT_OPTIONS_VERSION, 0, \
+ GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT }
/**
* Initialize git_revert_options structure
@@ -87,5 +92,5 @@ GIT_EXTERN(int) git_revert(
/** @} */
GIT_END_DECL
-#endif
+#endif
diff --git a/include/git2/revparse.h b/include/git2/revparse.h
index 51ea2dc13f5..c14fe3dc874 100644
--- a/include/git2/revparse.h
+++ b/include/git2/revparse.h
@@ -12,8 +12,8 @@
/**
* @file git2/revparse.h
- * @brief Git revision parsing routines
- * @defgroup git_revparse Git revision parsing routines
+ * @brief Parse the textual revision information
+ * @defgroup git_revparse Parse the textual revision information
* @ingroup Git
* @{
*/
@@ -107,7 +107,7 @@ GIT_EXTERN(int) git_revparse(
git_repository *repo,
const char *spec);
-
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/revwalk.h b/include/git2/revwalk.h
index 4aa9f5b1e0e..7c4ac5465d9 100644
--- a/include/git2/revwalk.h
+++ b/include/git2/revwalk.h
@@ -13,8 +13,8 @@
/**
* @file git2/revwalk.h
- * @brief Git revision traversal routines
- * @defgroup git_revwalk Git revision traversal routines
+ * @brief Traverse (walk) the commit graph (revision history)
+ * @defgroup git_revwalk Traverse (walk) the commit graph (revision history)
* @ingroup Git
* @{
*/
@@ -299,4 +299,5 @@ GIT_EXTERN(int) git_revwalk_add_hide_cb(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/signature.h b/include/git2/signature.h
index 849998e66f7..20ec24b340a 100644
--- a/include/git2/signature.h
+++ b/include/git2/signature.h
@@ -12,9 +12,13 @@
/**
* @file git2/signature.h
- * @brief Git signature creation
+ * @brief Signatures are the actor in a repository and when they acted
* @defgroup git_signature Git signature creation
* @ingroup Git
+ *
+ * Signatures contain the information about the actor (committer or
+ * author) in a repository, and the time that they performed the
+ * commit, or authoring.
* @{
*/
GIT_BEGIN_DECL
@@ -48,6 +52,42 @@ GIT_EXTERN(int) git_signature_new(git_signature **out, const char *name, const c
*/
GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const char *email);
+/**
+ * Create a new author and/or committer signatures with default
+ * information based on the configuration and environment variables.
+ *
+ * If `author_out` is set, it will be populated with the author
+ * information. The `GIT_AUTHOR_NAME` and `GIT_AUTHOR_EMAIL`
+ * environment variables will be honored, and `user.name` and
+ * `user.email` configuration options will be honored if the
+ * environment variables are unset. For timestamps, `GIT_AUTHOR_DATE`
+ * will be used, otherwise the current time will be used.
+ *
+ * If `committer_out` is set, it will be populated with the
+ * committer information. The `GIT_COMMITTER_NAME` and
+ * `GIT_COMMITTER_EMAIL` environment variables will be honored,
+ * and `user.name` and `user.email` configuration options will
+ * be honored if the environment variables are unset. For timestamps,
+ * `GIT_COMMITTER_DATE` will be used, otherwise the current time will
+ * be used.
+ *
+ * If neither `GIT_AUTHOR_DATE` nor `GIT_COMMITTER_DATE` are set,
+ * both timestamps will be set to the same time.
+ *
+ * It will return `GIT_ENOTFOUND` if either the `user.name` or
+ * `user.email` are not set and there is no fallback from an environment
+ * variable. One of `author_out` or `committer_out` must be set.
+ *
+ * @param author_out pointer to set the author signature, or NULL
+ * @param committer_out pointer to set the committer signature, or NULL
+ * @param repo repository pointer
+ * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code
+ */
+GIT_EXTERN(int) git_signature_default_from_env(
+ git_signature **author_out,
+ git_signature **committer_out,
+ git_repository *repo);
+
/**
* Create a new action signature with default user and now timestamp.
*
@@ -56,6 +96,10 @@ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const c
* based on that information. It will return GIT_ENOTFOUND if either the
* user.name or user.email are not set.
*
+ * Note that these do not examine environment variables, only the
+ * configuration files. Use `git_signature_default_from_env` to
+ * consider the environment variables.
+ *
* @param out new signature
* @param repo repository pointer
* @return 0 on success, GIT_ENOTFOUND if config is missing, or error code
@@ -100,4 +144,5 @@ GIT_EXTERN(void) git_signature_free(git_signature *sig);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/stash.h b/include/git2/stash.h
index dcfc013dc4e..ad28c32639a 100644
--- a/include/git2/stash.h
+++ b/include/git2/stash.h
@@ -13,8 +13,13 @@
/**
* @file git2/stash.h
- * @brief Git stash management routines
+ * @brief Stashes stores some uncommitted state in the repository
* @ingroup Git
+ *
+ * Stashes stores some uncommitted state in the repository; generally
+ * this allows a user to stash some changes so that they can restore
+ * the working directory to an unmodified state. This can allow a
+ * developer to work on two different changes in parallel.
* @{
*/
GIT_BEGIN_DECL
@@ -94,7 +99,10 @@ typedef struct git_stash_save_options {
git_strarray paths;
} git_stash_save_options;
+/** Current version for the `git_stash_save_options` structure */
#define GIT_STASH_SAVE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_stash_save_options` */
#define GIT_STASH_SAVE_OPTIONS_INIT { GIT_STASH_SAVE_OPTIONS_VERSION }
/**
@@ -165,6 +173,10 @@ typedef enum {
* Stash application progress notification function.
* Return 0 to continue processing, or a negative value to
* abort the stash application.
+ *
+ * @param progress the progress information
+ * @param payload the user-specified payload to the apply function
+ * @return 0 on success, -1 on error
*/
typedef int GIT_CALLBACK(git_stash_apply_progress_cb)(
git_stash_apply_progress_t progress,
@@ -191,7 +203,10 @@ typedef struct git_stash_apply_options {
void *progress_payload;
} git_stash_apply_options;
+/** Current version for the `git_stash_apply_options` structure */
#define GIT_STASH_APPLY_OPTIONS_VERSION 1
+
+/** Static constructor for `git_stash_apply_options` */
#define GIT_STASH_APPLY_OPTIONS_INIT { \
GIT_STASH_APPLY_OPTIONS_VERSION, \
GIT_STASH_APPLY_DEFAULT, \
@@ -225,8 +240,6 @@ GIT_EXTERN(int) git_stash_apply_options_init(
* GIT_EMERGECONFLICT and both the working directory and index will be left
* unmodified.
*
- * Note that a minimum checkout strategy of `GIT_CHECKOUT_SAFE` is implied.
- *
* @param repo The owning repository.
* @param index The position within the stash list. 0 points to the
* most recent stashed state.
@@ -311,4 +324,5 @@ GIT_EXTERN(int) git_stash_pop(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/status.h b/include/git2/status.h
index bb28e875b00..e13783b6746 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -14,7 +14,7 @@
/**
* @file git2/status.h
- * @brief Git file status routines
+ * @brief Status indicates how a user has changed the working directory and index
* @defgroup git_status Git file status routines
* @ingroup Git
* @{
@@ -54,11 +54,10 @@ typedef enum {
/**
* Function pointer to receive status on individual files
*
- * `path` is the relative path to the file from the root of the repository.
- *
- * `status_flags` is a combination of `git_status_t` values that apply.
- *
- * `payload` is the value you passed to the foreach function as payload.
+ * @param path is the path to the file
+ * @param status_flags the `git_status_t` values for file's status
+ * @param payload the user-specified payload to the foreach function
+ * @return 0 on success, or a negative number on failure
*/
typedef int GIT_CALLBACK(git_status_cb)(
const char *path, unsigned int status_flags, void *payload);
@@ -207,6 +206,7 @@ typedef enum {
GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 15)
} git_status_opt_t;
+/** Default `git_status_opt_t` values */
#define GIT_STATUS_OPT_DEFAULTS \
(GIT_STATUS_OPT_INCLUDE_IGNORED | \
GIT_STATUS_OPT_INCLUDE_UNTRACKED | \
@@ -261,7 +261,10 @@ typedef struct {
uint16_t rename_threshold;
} git_status_options;
+/** Current version for the `git_status_options` structure */
#define GIT_STATUS_OPTIONS_VERSION 1
+
+/** Static constructor for `git_status_options` */
#define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION}
/**
@@ -449,4 +452,5 @@ GIT_EXTERN(int) git_status_should_ignore(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/stdint.h b/include/git2/stdint.h
index 6950427d2d0..4b235c73f87 100644
--- a/include/git2/stdint.h
+++ b/include/git2/stdint.h
@@ -1,37 +1,37 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2008 Alexander Chemeris
-//
-// 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 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 of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef _MSC_VER // [
-
-#ifndef _MSC_STDINT_H_ // [
+/* ISO C9x compliant stdint.h for Microsoft Visual Studio
+ * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+ *
+ * Copyright (c) 2006-2008 Alexander Chemeris
+ *
+ * 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 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 of the author may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ *******************************************************************************/
+
+#ifdef _MSC_VER /* [ */
+
+#ifndef _MSC_STDINT_H_ /* [ */
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
@@ -40,10 +40,11 @@
#include
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+ * compiling for ARM we should wrap include with 'extern "C++" {}'
+ * or compiler give many errors like this:
+ * error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+*/
#ifdef __cplusplus
extern "C" {
#endif
@@ -52,7 +53,7 @@ extern "C" {
}
#endif
-// Define _W64 macros to mark types changing their size, like intptr_t.
+/* Define _W64 macros to mark types changing their size, like intptr_t. */
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
@@ -62,13 +63,14 @@ extern "C" {
#endif
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
+/* 7.18.1 Integer types
+ *
+ * 7.18.1.1 Exact-width integer types
+ *
+ * Visual Studio 6 and Embedded Visual C++ 4 doesn't
+ * realize that, e.g. char has the same size as __int8
+ * so we give up on __intX for them.
+ */
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
@@ -88,7 +90,7 @@ typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
-// 7.18.1.2 Minimum-width integer types
+/* 7.18.1.2 Minimum-width integer types */
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
@@ -98,7 +100,7 @@ typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
-// 7.18.1.3 Fastest minimum-width integer types
+/* 7.18.1.3 Fastest minimum-width integer types */
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
@@ -108,25 +110,25 @@ typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
+/* 7.18.1.4 Integer types capable of holding object pointers */
+#ifdef _WIN64 /* [ */
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
+#else /* _WIN64 ][ */
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
+#endif /* _WIN64 ] */
-// 7.18.1.5 Greatest-width integer types
+/* 7.18.1.5 Greatest-width integer types */
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
-// 7.18.2 Limits of specified-width integer types
+/* 7.18.2 Limits of specified-width integer types */
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* [ See footnote 220 at page 257 and footnote 221 at page 259 */
-// 7.18.2.1 Limits of exact-width integer types
+/* 7.18.2.1 Limits of exact-width integer types */
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
@@ -140,7 +142,7 @@ typedef uint64_t uintmax_t;
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
-// 7.18.2.2 Limits of minimum-width integer types
+/* 7.18.2.2 Limits of minimum-width integer types */
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
@@ -154,7 +156,7 @@ typedef uint64_t uintmax_t;
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
-// 7.18.2.3 Limits of fastest minimum-width integer types
+/* 7.18.2.3 Limits of fastest minimum-width integer types */
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
@@ -168,62 +170,62 @@ typedef uint64_t uintmax_t;
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
+/* 7.18.2.4 Limits of integer types capable of holding object pointers */
+#ifdef _WIN64 /* [ */
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
+#else /* _WIN64 ][ */
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
+#endif /* _WIN64 ] */
-// 7.18.2.5 Limits of greatest-width integer types
+/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
-// 7.18.3 Limits of other integer types
+/* 7.18.3 Limits of other integer types */
-#ifdef _WIN64 // [
+#ifdef _WIN64 /* [ */
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
+#else /* _WIN64 ][ */
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
+#endif /* _WIN64 ] */
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
+#ifndef SIZE_MAX /* [ */
+# ifdef _WIN64 /* [ */
# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
+# else /* _WIN64 ][ */
# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
+# endif /* _WIN64 ] */
+#endif /* SIZE_MAX ] */
-// WCHAR_MIN and WCHAR_MAX are also defined in
-#ifndef WCHAR_MIN // [
+/* WCHAR_MIN and WCHAR_MAX are also defined in */
+#ifndef WCHAR_MIN /* [ */
# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
+#endif /* WCHAR_MIN ] */
+#ifndef WCHAR_MAX /* [ */
# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
+#endif /* WCHAR_MAX ] */
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
-#endif // __STDC_LIMIT_MACROS ]
+#endif /* __STDC_LIMIT_MACROS ] */
-// 7.18.4 Limits of other integer types
+/* 7.18.4 Limits of other integer types
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* [ See footnote 224 at page 260 */
-// 7.18.4.1 Macros for minimum-width integer constants
+/* 7.18.4.1 Macros for minimum-width integer constants */
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
@@ -235,13 +237,13 @@ typedef uint64_t uintmax_t;
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
-// 7.18.4.2 Macros for greatest-width integer constants
+/* 7.18.4.2 Macros for greatest-width integer constants */
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
-#endif // __STDC_CONSTANT_MACROS ]
+#endif /* __STDC_CONSTANT_MACROS ] */
-#endif // _MSC_STDINT_H_ ]
+#endif /* _MSC_STDINT_H_ ] */
-#endif // _MSC_VER ]
\ No newline at end of file
+#endif /* _MSC_VER ] */
diff --git a/include/git2/strarray.h b/include/git2/strarray.h
index 03d93f8fbbc..dcb628a1846 100644
--- a/include/git2/strarray.h
+++ b/include/git2/strarray.h
@@ -11,8 +11,8 @@
/**
* @file git2/strarray.h
- * @brief Git string array routines
- * @defgroup git_strarray Git string array routines
+ * @brief An array of strings for the user to free
+ * @defgroup git_strarray An array of strings for the user to free
* @ingroup Git
* @{
*/
@@ -40,4 +40,3 @@ GIT_EXTERN(void) git_strarray_dispose(git_strarray *array);
GIT_END_DECL
#endif
-
diff --git a/include/git2/submodule.h b/include/git2/submodule.h
index 2082966f6bb..911b3cee39c 100644
--- a/include/git2/submodule.h
+++ b/include/git2/submodule.h
@@ -15,7 +15,7 @@
/**
* @file git2/submodule.h
- * @brief Git submodule management utilities
+ * @brief Submodules place another repository's contents within this one
*
* Submodule support in libgit2 builds a list of known submodules and keeps
* it in the repository. The list is built from the .gitmodules file, the
@@ -88,20 +88,27 @@ typedef enum {
GIT_SUBMODULE_STATUS_WD_UNTRACKED = (1u << 13)
} git_submodule_status_t;
+/** Submodule source bits */
#define GIT_SUBMODULE_STATUS__IN_FLAGS 0x000Fu
+/** Submodule index status */
#define GIT_SUBMODULE_STATUS__INDEX_FLAGS 0x0070u
+/** Submodule working directory status */
#define GIT_SUBMODULE_STATUS__WD_FLAGS 0x3F80u
+/** Whether the submodule is modified */
#define GIT_SUBMODULE_STATUS_IS_UNMODIFIED(S) \
(((S) & ~GIT_SUBMODULE_STATUS__IN_FLAGS) == 0)
+/** Whether the submodule is modified (in the index) */
#define GIT_SUBMODULE_STATUS_IS_INDEX_UNMODIFIED(S) \
(((S) & GIT_SUBMODULE_STATUS__INDEX_FLAGS) == 0)
+/** Whether the submodule is modified (in the working directory) */
#define GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(S) \
(((S) & (GIT_SUBMODULE_STATUS__WD_FLAGS & \
~GIT_SUBMODULE_STATUS_WD_UNINITIALIZED)) == 0)
+/** Whether the submodule working directory is dirty */
#define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \
(((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \
GIT_SUBMODULE_STATUS_WD_WD_MODIFIED | \
@@ -130,10 +137,8 @@ typedef struct git_submodule_update_options {
/**
* These options are passed to the checkout step. To disable
- * checkout, set the `checkout_strategy` to
- * `GIT_CHECKOUT_NONE`. Generally you will want the use
- * GIT_CHECKOUT_SAFE to update files in the working
- * directory.
+ * checkout, set the `checkout_strategy` to `GIT_CHECKOUT_NONE`
+ * or `GIT_CHECKOUT_DRY_RUN`.
*/
git_checkout_options checkout_opts;
@@ -152,11 +157,15 @@ typedef struct git_submodule_update_options {
int allow_fetch;
} git_submodule_update_options;
+/** Current version for the `git_submodule_update_options` structure */
#define GIT_SUBMODULE_UPDATE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_submodule_update_options` */
#define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \
{ GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \
- { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \
- GIT_FETCH_OPTIONS_INIT, 1 }
+ GIT_CHECKOUT_OPTIONS_INIT, \
+ GIT_FETCH_OPTIONS_INIT, \
+ 1 }
/**
* Initialize git_submodule_update_options structure
@@ -531,7 +540,8 @@ GIT_EXTERN(int) git_submodule_set_update(
* Note that at this time, libgit2 does not honor this setting and the
* fetch functionality current ignores submodules.
*
- * @return 0 if fetchRecurseSubmodules is false, 1 if true
+ * @param submodule the submodule to examine
+ * @return the submodule recursion configuration
*/
GIT_EXTERN(git_submodule_recurse_t) git_submodule_fetch_recurse_submodules(
git_submodule *submodule);
@@ -543,7 +553,7 @@ GIT_EXTERN(git_submodule_recurse_t) git_submodule_fetch_recurse_submodules(
*
* @param repo the repository to affect
* @param name the submodule to configure
- * @param fetch_recurse_submodules Boolean value
+ * @param fetch_recurse_submodules the submodule recursion configuration
* @return old value for fetchRecurseSubmodules
*/
GIT_EXTERN(int) git_submodule_set_fetch_recurse_submodules(
@@ -665,4 +675,5 @@ GIT_EXTERN(int) git_submodule_location(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/alloc.h b/include/git2/sys/alloc.h
index e7f85b890c8..67506f2b17e 100644
--- a/include/git2/sys/alloc.h
+++ b/include/git2/sys/alloc.h
@@ -10,6 +10,17 @@
#include "git2/common.h"
+/**
+ * @file git2/sys/alloc.h
+ * @brief Custom memory allocators
+ * @defgroup git_merge Git merge routines
+ * @ingroup Git
+ *
+ * Users can configure custom allocators; this is particularly
+ * interesting when running in constrained environments, when calling
+ * from another language, or during testing.
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -62,6 +73,7 @@ int git_stdalloc_init_allocator(git_allocator *allocator);
*/
int git_win32_crtdbg_init_allocator(git_allocator *allocator);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/commit.h b/include/git2/sys/commit.h
index ba671061f76..a8253c06743 100644
--- a/include/git2/sys/commit.h
+++ b/include/git2/sys/commit.h
@@ -14,7 +14,7 @@
/**
* @file git2/sys/commit.h
* @brief Low-level Git commit creation
- * @defgroup git_backend Git custom backend APIs
+ * @defgroup git_commit Low-level Git commit creation
* @ingroup Git
* @{
*/
@@ -29,7 +29,43 @@ GIT_BEGIN_DECL
* the `tree`, neither the `parents` list of `git_oid`s are checked for
* validity.
*
- * @see git_commit_create
+ * @param id Pointer in which to store the OID of the newly created commit
+ *
+ * @param repo Repository where to store the commit
+ *
+ * @param update_ref If not NULL, name of the reference that
+ * will be updated to point to this commit. If the reference
+ * is not direct, it will be resolved to a direct reference.
+ * Use "HEAD" to update the HEAD of the current branch and
+ * make it point to this commit. If the reference doesn't
+ * exist yet, it will be created. If it does exist, the first
+ * parent must be the tip of this branch.
+ *
+ * @param author Signature with author and author time of commit
+ *
+ * @param committer Signature with committer and * commit time of commit
+ *
+ * @param message_encoding The encoding for the message in the
+ * commit, represented with a standard encoding name.
+ * E.g. "UTF-8". If NULL, no encoding header is written and
+ * UTF-8 is assumed.
+ *
+ * @param message Full message for this commit
+ *
+ * @param tree An instance of a `git_tree` object that will
+ * be used as the tree for the commit. This tree object must
+ * also be owned by the given `repo`.
+ *
+ * @param parent_count Number of parents for this commit
+ *
+ * @param parents Array of `parent_count` pointers to `git_commit`
+ * objects that will be used as the parents for this commit. This
+ * array may be NULL if `parent_count` is 0 (root commit). All the
+ * given commits must be owned by the `repo`.
+ *
+ * @return 0 or an error code
+ * The created commit will be written to the Object Database and
+ * the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_create_from_ids(
git_oid *id,
@@ -49,6 +85,10 @@ GIT_EXTERN(int) git_commit_create_from_ids(
* This is invoked with the count of the number of parents processed so far
* along with the user supplied payload. This should return a git_oid of
* the next parent or NULL if all parents have been provided.
+ *
+ * @param idx the index of the parent
+ * @param payload the user-specified payload
+ * @return the object id of the parent, or NULL if there are no further parents
*/
typedef const git_oid * GIT_CALLBACK(git_commit_parent_callback)(size_t idx, void *payload);
@@ -61,7 +101,40 @@ typedef const git_oid * GIT_CALLBACK(git_commit_parent_callback)(size_t idx, voi
* with `parent_payload` and should return `git_oid` values or NULL to
* indicate that all parents are accounted for.
*
- * @see git_commit_create
+ * @param id Pointer in which to store the OID of the newly created commit
+ *
+ * @param repo Repository where to store the commit
+ *
+ * @param update_ref If not NULL, name of the reference that
+ * will be updated to point to this commit. If the reference
+ * is not direct, it will be resolved to a direct reference.
+ * Use "HEAD" to update the HEAD of the current branch and
+ * make it point to this commit. If the reference doesn't
+ * exist yet, it will be created. If it does exist, the first
+ * parent must be the tip of this branch.
+ *
+ * @param author Signature with author and author time of commit
+ *
+ * @param committer Signature with committer and * commit time of commit
+ *
+ * @param message_encoding The encoding for the message in the
+ * commit, represented with a standard encoding name.
+ * E.g. "UTF-8". If NULL, no encoding header is written and
+ * UTF-8 is assumed.
+ *
+ * @param message Full message for this commit
+ *
+ * @param tree An instance of a `git_tree` object that will
+ * be used as the tree for the commit. This tree object must
+ * also be owned by the given `repo`.
+ *
+ * @param parent_cb Callback to invoke to obtain parent information
+ *
+ * @param parent_payload User-specified payload to provide to the callback
+ *
+ * @return 0 or an error code
+ * The created commit will be written to the Object Database and
+ * the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_create_from_callback(
git_oid *id,
@@ -77,4 +150,5 @@ GIT_EXTERN(int) git_commit_create_from_callback(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/commit_graph.h b/include/git2/sys/commit_graph.h
index 06e045fcd2b..ff547ef0c1f 100644
--- a/include/git2/sys/commit_graph.h
+++ b/include/git2/sys/commit_graph.h
@@ -12,13 +12,52 @@
/**
* @file git2/sys/commit_graph.h
- * @brief Git commit-graph
- * @defgroup git_commit_graph Git commit-graph APIs
+ * @brief Commit graphs store information about commit relationships
+ * @defgroup git_commit_graph Commit graphs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/**
+ * Options structure for `git_commit_graph_open_new`.
+ *
+ * Initialize with `GIT_COMMIT_GRAPH_OPEN_OPTIONS_INIT`. Alternatively,
+ * you can use `git_commit_graph_open_options_init`.
+ */
+typedef struct {
+ unsigned int version;
+
+#ifdef GIT_EXPERIMENTAL_SHA256
+ /** The object ID type that this commit graph contains. */
+ git_oid_t oid_type;
+#endif
+} git_commit_graph_open_options;
+
+/** Current version for the `git_commit_graph_open_options` structure */
+#define GIT_COMMIT_GRAPH_OPEN_OPTIONS_VERSION 1
+
+/** Static constructor for `git_commit_graph_open_options` */
+#define GIT_COMMIT_GRAPH_OPEN_OPTIONS_INIT { \
+ GIT_COMMIT_GRAPH_OPEN_OPTIONS_VERSION \
+ }
+
+/**
+ * Initialize git_commit_graph_open_options structure
+ *
+ * Initializes a `git_commit_graph_open_options` with default values.
+ * Equivalent to creating an instance with
+ * `GIT_COMMIT_GRAPH_OPEN_OPTIONS_INIT`.
+ *
+ * @param opts The `git_commit_graph_open_options` struct to initialize.
+ * @param version The struct version; pass `GIT_COMMIT_GRAPH_OPEN_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_commit_graph_open_options_init(
+ git_commit_graph_open_options *opts,
+ unsigned int version);
+
+
/**
* Opens a `git_commit_graph` from a path to an objects directory.
*
@@ -32,7 +71,7 @@ GIT_EXTERN(int) git_commit_graph_open(
git_commit_graph **cgraph_out,
const char *objects_dir
#ifdef GIT_EXPERIMENTAL_SHA256
- , git_oid_t oid_type
+ , const git_commit_graph_open_options *options
#endif
);
@@ -46,54 +85,6 @@ GIT_EXTERN(int) git_commit_graph_open(
*/
GIT_EXTERN(void) git_commit_graph_free(git_commit_graph *cgraph);
-/**
- * Create a new writer for `commit-graph` files.
- *
- * @param out Location to store the writer pointer.
- * @param objects_info_dir The `objects/info` directory.
- * The `commit-graph` file will be written in this directory.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_commit_graph_writer_new(
- git_commit_graph_writer **out,
- const char *objects_info_dir
-#ifdef GIT_EXPERIMENTAL_SHA256
- , git_oid_t oid_type
-#endif
- );
-
-/**
- * Free the commit-graph writer and its resources.
- *
- * @param w The writer to free. If NULL no action is taken.
- */
-GIT_EXTERN(void) git_commit_graph_writer_free(git_commit_graph_writer *w);
-
-/**
- * Add an `.idx` file (associated to a packfile) to the writer.
- *
- * @param w The writer.
- * @param repo The repository that owns the `.idx` file.
- * @param idx_path The path of an `.idx` file.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_commit_graph_writer_add_index_file(
- git_commit_graph_writer *w,
- git_repository *repo,
- const char *idx_path);
-
-/**
- * Add a revwalk to the writer. This will add all the commits from the revwalk
- * to the commit-graph.
- *
- * @param w The writer.
- * @param walk The git_revwalk.
- * @return 0 or an error code
- */
-GIT_EXTERN(int) git_commit_graph_writer_add_revwalk(
- git_commit_graph_writer *w,
- git_revwalk *walk);
-
/**
* The strategy to use when adding a new set of commits to a pre-existing
@@ -108,15 +99,19 @@ typedef enum {
} git_commit_graph_split_strategy_t;
/**
- * Options structure for
- * `git_commit_graph_writer_commit`/`git_commit_graph_writer_dump`.
+ * Options structure for `git_commit_graph_writer_new`.
*
- * Initialize with `GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT`. Alternatively, you
- * can use `git_commit_graph_writer_options_init`.
+ * Initialize with `GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT`. Alternatively,
+ * you can use `git_commit_graph_writer_options_init`.
*/
typedef struct {
unsigned int version;
+#ifdef GIT_EXPERIMENTAL_SHA256
+ /** The object ID type that this commit graph contains. */
+ git_oid_t oid_type;
+#endif
+
/**
* The strategy to use when adding new commits to a pre-existing commit-graph
* chain.
@@ -136,7 +131,10 @@ typedef struct {
size_t max_commits;
} git_commit_graph_writer_options;
+/** Current version for the `git_commit_graph_writer_options` structure */
#define GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION 1
+
+/** Static constructor for `git_commit_graph_writer_options` */
#define GIT_COMMIT_GRAPH_WRITER_OPTIONS_INIT { \
GIT_COMMIT_GRAPH_WRITER_OPTIONS_VERSION \
}
@@ -155,30 +153,73 @@ GIT_EXTERN(int) git_commit_graph_writer_options_init(
git_commit_graph_writer_options *opts,
unsigned int version);
+/**
+ * Create a new writer for `commit-graph` files.
+ *
+ * @param out Location to store the writer pointer.
+ * @param objects_info_dir The `objects/info` directory.
+ * The `commit-graph` file will be written in this directory.
+ * @param options The options for the commit graph writer.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_new(
+ git_commit_graph_writer **out,
+ const char *objects_info_dir,
+ const git_commit_graph_writer_options *options);
+
+/**
+ * Free the commit-graph writer and its resources.
+ *
+ * @param w The writer to free. If NULL no action is taken.
+ */
+GIT_EXTERN(void) git_commit_graph_writer_free(git_commit_graph_writer *w);
+
+/**
+ * Add an `.idx` file (associated to a packfile) to the writer.
+ *
+ * @param w The writer.
+ * @param repo The repository that owns the `.idx` file.
+ * @param idx_path The path of an `.idx` file.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_add_index_file(
+ git_commit_graph_writer *w,
+ git_repository *repo,
+ const char *idx_path);
+
+/**
+ * Add a revwalk to the writer. This will add all the commits from the revwalk
+ * to the commit-graph.
+ *
+ * @param w The writer.
+ * @param walk The git_revwalk.
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_commit_graph_writer_add_revwalk(
+ git_commit_graph_writer *w,
+ git_revwalk *walk);
+
/**
* Write a `commit-graph` file to a file.
*
* @param w The writer
- * @param opts Pointer to git_commit_graph_writer_options struct.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_commit_graph_writer_commit(
- git_commit_graph_writer *w,
- git_commit_graph_writer_options *opts);
+ git_commit_graph_writer *w);
/**
* Dump the contents of the `commit-graph` to an in-memory buffer.
*
- * @param buffer Buffer where to store the contents of the `commit-graph`.
+ * @param[out] buffer Buffer where to store the contents of the `commit-graph`.
* @param w The writer.
- * @param opts Pointer to git_commit_graph_writer_options struct.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_commit_graph_writer_dump(
git_buf *buffer,
- git_commit_graph_writer *w,
- git_commit_graph_writer_options *opts);
+ git_commit_graph_writer *w);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h
index 75d20758b84..cc4a3991ddc 100644
--- a/include/git2/sys/config.h
+++ b/include/git2/sys/config.h
@@ -13,13 +13,28 @@
/**
* @file git2/sys/config.h
- * @brief Git config backend routines
- * @defgroup git_backend Git custom backend APIs
+ * @brief Custom configuration database backends
+ * @defgroup git_backend Custom configuration database backends
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/**
+ * An entry in a configuration backend. This is provided so that
+ * backend implementors can have a mechanism to free their data.
+ */
+typedef struct git_config_backend_entry {
+ /** The base configuration entry */
+ struct git_config_entry entry;
+
+ /**
+ * Free function for this entry; for internal purposes. Callers
+ * should call `git_config_entry_free` to free data.
+ */
+ void GIT_CALLBACK(free)(struct git_config_backend_entry *entry);
+} git_config_backend_entry;
+
/**
* Every iterator must have this struct as its first element, so the
* API can talk to it. You'd define your iterator as
@@ -39,7 +54,7 @@ struct git_config_iterator {
* Return the current entry and advance the iterator. The
* memory belongs to the library.
*/
- int GIT_CALLBACK(next)(git_config_entry **entry, git_config_iterator *iter);
+ int GIT_CALLBACK(next)(git_config_backend_entry **entry, git_config_iterator *iter);
/**
* Free the iterator
@@ -59,7 +74,7 @@ struct git_config_backend {
/* Open means open the file/database and parse if necessary */
int GIT_CALLBACK(open)(struct git_config_backend *, git_config_level_t level, const git_repository *repo);
- int GIT_CALLBACK(get)(struct git_config_backend *, const char *key, git_config_entry **entry);
+ int GIT_CALLBACK(get)(struct git_config_backend *, const char *key, git_config_backend_entry **entry);
int GIT_CALLBACK(set)(struct git_config_backend *, const char *key, const char *value);
int GIT_CALLBACK(set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
int GIT_CALLBACK(del)(struct git_config_backend *, const char *key);
@@ -83,7 +98,11 @@ struct git_config_backend {
int GIT_CALLBACK(unlock)(struct git_config_backend *, int success);
void GIT_CALLBACK(free)(struct git_config_backend *);
};
+
+/** Current version for the `git_config_backend_options` structure */
#define GIT_CONFIG_BACKEND_VERSION 1
+
+/** Static constructor for `git_config_backend_options` */
#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
/**
@@ -142,7 +161,10 @@ typedef struct {
const char *origin_path;
} git_config_backend_memory_options;
+/** Current version for the `git_config_backend_memory_options` structure */
#define GIT_CONFIG_BACKEND_MEMORY_OPTIONS_VERSION 1
+
+/** Static constructor for `git_config_backend_memory_options` */
#define GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT { GIT_CONFIG_BACKEND_MEMORY_OPTIONS_VERSION }
@@ -154,6 +176,7 @@ typedef struct {
* @param cfg the configuration that is to be parsed
* @param len the length of the string pointed to by `cfg`
* @param opts the options to initialize this backend with, or NULL
+ * @return 0 on success or an error code
*/
extern int git_config_backend_from_string(
git_config_backend **out,
@@ -169,6 +192,7 @@ extern int git_config_backend_from_string(
* @param values the configuration values to set (in "key=value" format)
* @param len the length of the values array
* @param opts the options to initialize this backend with, or NULL
+ * @return 0 on success or an error code
*/
extern int git_config_backend_from_values(
git_config_backend **out,
@@ -178,4 +202,5 @@ extern int git_config_backend_from_values(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/credential.h b/include/git2/sys/credential.h
index bb4c9f94253..0d573a3231f 100644
--- a/include/git2/sys/credential.h
+++ b/include/git2/sys/credential.h
@@ -11,9 +11,9 @@
#include "git2/credential.h"
/**
- * @file git2/sys/cred.h
- * @brief Git credentials low-level implementation
- * @defgroup git_credential Git credentials low-level implementation
+ * @file git2/sys/credential.h
+ * @brief Low-level credentials implementation
+ * @defgroup git_credential Low-level credentials implementation
* @ingroup Git
* @{
*/
@@ -85,6 +85,7 @@ struct git_credential_ssh_custom {
void *payload; /**< Payload passed to prompt_callback */
};
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/diff.h b/include/git2/sys/diff.h
index aefd7b9973f..a398f5490fb 100644
--- a/include/git2/sys/diff.h
+++ b/include/git2/sys/diff.h
@@ -15,7 +15,7 @@
/**
* @file git2/sys/diff.h
- * @brief Low-level Git diff utilities
+ * @brief Low-level diff utilities
* @ingroup Git
* @{
*/
@@ -33,6 +33,12 @@ GIT_BEGIN_DECL
* must pass a `git_buf *` value as the payload to the `git_diff_print`
* and/or `git_patch_print` function. The data will be appended to the
* buffer (after any existing content).
+ *
+ * @param delta the delta being processed
+ * @param hunk the hunk being processed
+ * @param line the line being processed
+ * @param payload the payload provided by the diff generator
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_diff_print_callback__to_buf(
const git_diff_delta *delta,
@@ -53,6 +59,12 @@ GIT_EXTERN(int) git_diff_print_callback__to_buf(
* value from `fopen()`) as the payload to the `git_diff_print`
* and/or `git_patch_print` function. If you pass NULL, this will write
* data to `stdout`.
+ *
+ * @param delta the delta being processed
+ * @param hunk the hunk being processed
+ * @param line the line being processed
+ * @param payload the payload provided by the diff generator
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_diff_print_callback__to_file_handle(
const git_diff_delta *delta,
@@ -70,7 +82,10 @@ typedef struct {
size_t oid_calculations; /**< Number of ID calculations */
} git_diff_perfdata;
+/** Current version for the `git_diff_perfdata_options` structure */
#define GIT_DIFF_PERFDATA_VERSION 1
+
+/** Static constructor for `git_diff_perfdata_options` */
#define GIT_DIFF_PERFDATA_INIT {GIT_DIFF_PERFDATA_VERSION,0,0}
/**
@@ -85,10 +100,15 @@ GIT_EXTERN(int) git_diff_get_perfdata(
/**
* Get performance data for diffs from a git_status_list
+ *
+ * @param out Structure to be filled with diff performance data
+ * @param status Diff to read performance data from
+ * @return 0 for success, <0 for error
*/
GIT_EXTERN(int) git_status_list_get_perfdata(
git_diff_perfdata *out, const git_status_list *status);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/email.h b/include/git2/sys/email.h
index 5029f9a532c..26e792abf89 100644
--- a/include/git2/sys/email.h
+++ b/include/git2/sys/email.h
@@ -33,6 +33,7 @@ GIT_BEGIN_DECL
* @param body optional text to include above the diffstat
* @param author the person who authored this commit
* @param opts email creation options
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_email_create_from_diff(
git_buf *out,
@@ -47,4 +48,5 @@ GIT_EXTERN(int) git_email_create_from_diff(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/errors.h b/include/git2/sys/errors.h
index 3ae121524d5..44e8ecba84f 100644
--- a/include/git2/sys/errors.h
+++ b/include/git2/sys/errors.h
@@ -10,6 +10,15 @@
#include "git2/common.h"
+/**
+ * @file git2/sys/errors.h
+ * @brief Advanced error handling
+ * @ingroup Git
+ *
+ * Error handling for advanced consumers; those who use callbacks
+ * or those who create custom databases.
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -61,6 +70,7 @@ GIT_EXTERN(int) git_error_set_str(int error_class, const char *string);
*/
GIT_EXTERN(void) git_error_set_oom(void);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h
index b3759416a1d..60466d173fb 100644
--- a/include/git2/sys/filter.h
+++ b/include/git2/sys/filter.h
@@ -11,8 +11,8 @@
/**
* @file git2/sys/filter.h
- * @brief Git filter backend and plugin routines
- * @defgroup git_backend Git custom backend APIs
+ * @brief Custom filter backends and plugins
+ * @defgroup git_backend Custom filter backends and plugins
* @ingroup Git
* @{
*/
@@ -26,7 +26,10 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(git_filter *) git_filter_lookup(const char *name);
+/** The "crlf" filter */
#define GIT_FILTER_CRLF "crlf"
+
+/** The "ident" filter */
#define GIT_FILTER_IDENT "ident"
/**
@@ -53,6 +56,12 @@ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name);
* the filter list for you, but you can use this in combination with the
* `git_filter_lookup` and `git_filter_list_push` functions to assemble
* your own chains of filters.
+ *
+ * @param out the filter list
+ * @param repo the repository to use for configuration
+ * @param mode the filter mode (direction)
+ * @param options the options
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_filter_list_new(
git_filter_list **out,
@@ -72,6 +81,11 @@ GIT_EXTERN(int) git_filter_list_new(
* filter. Using this function, you can either pass in a payload if you
* know the expected payload format, or you can pass NULL. Some filters
* may fail with a NULL payload. Good luck!
+ *
+ * @param fl the filter list
+ * @param filter the filter to push
+ * @param payload the payload for the filter
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_filter_list_push(
git_filter_list *fl, git_filter *filter, void *payload);
@@ -96,17 +110,26 @@ typedef struct git_filter_source git_filter_source;
/**
* Get the repository that the source data is coming from.
+ *
+ * @param src the filter source
+ * @return the repository for the filter information
*/
GIT_EXTERN(git_repository *) git_filter_source_repo(const git_filter_source *src);
/**
* Get the path that the source data is coming from.
+ *
+ * @param src the filter source
+ * @return the path that is being filtered
*/
GIT_EXTERN(const char *) git_filter_source_path(const git_filter_source *src);
/**
* Get the file mode of the source file
* If the mode is unknown, this will return 0
+ *
+ * @param src the filter source
+ * @return the file mode for the file being filtered
*/
GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src);
@@ -114,16 +137,25 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src);
* Get the OID of the source
* If the OID is unknown (often the case with GIT_FILTER_CLEAN) then
* this will return NULL.
+ *
+ * @param src the filter source
+ * @return the object id of the file being filtered
*/
GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src);
/**
* Get the git_filter_mode_t to be used
+ *
+ * @param src the filter source
+ * @return the mode (direction) of the filter
*/
GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *src);
/**
* Get the combination git_filter_flag_t options to be applied
+ *
+ * @param src the filter source
+ * @return the flags of the filter
*/
GIT_EXTERN(uint32_t) git_filter_source_flags(const git_filter_source *src);
@@ -137,6 +169,9 @@ GIT_EXTERN(uint32_t) git_filter_source_flags(const git_filter_source *src);
* before the first use of the filter, so you can defer expensive
* initialization operations (in case libgit2 is being used in a way that
* doesn't need the filter).
+ *
+ * @param self the filter to initialize
+ * @return 0 on success, negative number on failure
*/
typedef int GIT_CALLBACK(git_filter_init_fn)(git_filter *self);
@@ -149,6 +184,8 @@ typedef int GIT_CALLBACK(git_filter_init_fn)(git_filter *self);
* This may be called even if the `initialize` callback was not made.
*
* Typically this function will free the `git_filter` object itself.
+ *
+ * @param self the filter to shutdown
*/
typedef void GIT_CALLBACK(git_filter_shutdown_fn)(git_filter *self);
@@ -171,6 +208,12 @@ typedef void GIT_CALLBACK(git_filter_shutdown_fn)(git_filter *self);
* allocated (not stack), so that it doesn't go away before the `stream`
* callback can use it. If a filter allocates and assigns a value to the
* `payload`, it will need a `cleanup` callback to free the payload.
+ *
+ * @param self the filter check
+ * @param payload a data for future filter functions
+ * @param src the filter source
+ * @param attr_values the attribute values
+ * @return 0 on success or a negative value on error
*/
typedef int GIT_CALLBACK(git_filter_check_fn)(
git_filter *self,
@@ -191,6 +234,12 @@ typedef int GIT_CALLBACK(git_filter_check_fn)(
* The `payload` value will refer to any payload that was set by the
* `check` callback. It may be read from or written to as needed.
*
+ * @param self the filter check
+ * @param payload a data for future filter functions
+ * @param to the input buffer
+ * @param from the output buffer
+ * @param src the filter source
+ * @return 0 on success or a negative value on error
* @deprecated use git_filter_stream_fn
*/
typedef int GIT_CALLBACK(git_filter_apply_fn)(
@@ -209,6 +258,13 @@ typedef int GIT_CALLBACK(git_filter_apply_fn)(
* `git_writestream` that will the original data will be written to;
* with that data, the `git_writestream` will then perform the filter
* translation and stream the filtered data out to the `next` location.
+ *
+ * @param out the write stream
+ * @param self the filter
+ * @param payload a data for future filter functions
+ * @param src the filter source
+ * @param next the output stream
+ * @return 0 on success or a negative value on error
*/
typedef int GIT_CALLBACK(git_filter_stream_fn)(
git_writestream **out,
@@ -225,6 +281,9 @@ typedef int GIT_CALLBACK(git_filter_stream_fn)(
* `stream` callbacks allocated a `payload` to keep per-source filter
* state, use this callback to free that payload and release resources
* as required.
+ *
+ * @param self the filter
+ * @param payload a data for future filter functions
*/
typedef void GIT_CALLBACK(git_filter_cleanup_fn)(
git_filter *self,
@@ -291,7 +350,10 @@ struct git_filter {
git_filter_cleanup_fn cleanup;
};
+/** Current version for the `git_filter_options` structure */
#define GIT_FILTER_VERSION 1
+
+/** Static constructor for `git_filter_options` */
#define GIT_FILTER_INIT {GIT_FILTER_VERSION}
/**
@@ -300,7 +362,7 @@ struct git_filter {
*
* @param filter the `git_filter` struct to initialize.
* @param version Version the struct; pass `GIT_FILTER_VERSION`
- * @return Zero on success; -1 on failure.
+ * @return 0 on success; -1 on failure.
*/
GIT_EXTERN(int) git_filter_init(git_filter *filter, unsigned int version);
@@ -350,4 +412,5 @@ GIT_EXTERN(int) git_filter_unregister(const char *name);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/hashsig.h b/include/git2/sys/hashsig.h
index 09c19aec075..0d7be535ce3 100644
--- a/include/git2/sys/hashsig.h
+++ b/include/git2/sys/hashsig.h
@@ -9,6 +9,16 @@
#include "git2/common.h"
+/**
+ * @file git2/sys/hashsig.h
+ * @brief Signatures for file similarity comparison
+ * @defgroup git_hashsig Git merge routines
+ * @ingroup Git
+ *
+ * Hash signatures are used for file similary comparison; this is
+ * used for git's rename handling.
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -101,6 +111,7 @@ GIT_EXTERN(int) git_hashsig_compare(
const git_hashsig *a,
const git_hashsig *b);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/index.h b/include/git2/sys/index.h
index 1f6d93f7a99..b3b86a04598 100644
--- a/include/git2/sys/index.h
+++ b/include/git2/sys/index.h
@@ -12,8 +12,8 @@
/**
* @file git2/sys/index.h
- * @brief Low-level Git index manipulation routines
- * @defgroup git_backend Git custom backend APIs
+ * @brief Low-level index manipulation routines
+ * @defgroup git_index Low-level index manipulation routines
* @ingroup Git
* @{
*/
@@ -67,6 +67,7 @@ GIT_EXTERN(const git_index_name_entry *) git_index_name_get_byindex(
* @param ancestor the path of the file as it existed in the ancestor
* @param ours the path of the file as it existed in our tree
* @param theirs the path of the file as it existed in their tree
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_index_name_add(git_index *index,
const char *ancestor, const char *ours, const char *theirs);
diff --git a/include/git2/sys/mempack.h b/include/git2/sys/mempack.h
index 17da590a383..be902be254f 100644
--- a/include/git2/sys/mempack.h
+++ b/include/git2/sys/mempack.h
@@ -15,8 +15,8 @@
/**
* @file git2/sys/mempack.h
- * @brief Custom ODB backend that permits packing objects in-memory
- * @defgroup git_backend Git custom backend APIs
+ * @brief A custom object database backend for storing objects in-memory
+ * @defgroup git_mempack A custom object database backend for storing objects in-memory
* @ingroup Git
* @{
*/
@@ -44,6 +44,26 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_mempack_new(git_odb_backend **out);
+/**
+ * Write a thin packfile with the objects in the memory store.
+ *
+ * A thin packfile is a packfile that does not contain its transitive closure of
+ * references. This is useful for efficiently distributing additions to a
+ * repository over the network, but also finds use in the efficient bulk
+ * addition of objects to a repository, locally.
+ *
+ * This operation performs the (shallow) insert operations into the
+ * `git_packbuilder`, but does not write the packfile to disk;
+ * see `git_packbuilder_write_buf`.
+ *
+ * It also does not reset the in-memory object database; see `git_mempack_reset`.
+ *
+ * @param backend The mempack backend
+ * @param pb The packbuilder to use to write the packfile
+ * @return 0 on success or an error code
+ */
+GIT_EXTERN(int) git_mempack_write_thin_pack(git_odb_backend *backend, git_packbuilder *pb);
+
/**
* Dump all the queued in-memory writes to a packfile.
*
@@ -82,6 +102,16 @@ GIT_EXTERN(int) git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_ba
*/
GIT_EXTERN(int) git_mempack_reset(git_odb_backend *backend);
+/**
+ * Get the total number of objects in mempack
+ *
+ * @param count The count of objects in the mempack
+ * @param backend The mempack backend
+ * @return 0 on success, or -1 on error
+ */
+GIT_EXTERN(int) git_mempack_object_count(size_t *count, git_odb_backend *backend);
+
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/merge.h b/include/git2/sys/merge.h
index ef4bc5aca3d..a9f522054ba 100644
--- a/include/git2/sys/merge.h
+++ b/include/git2/sys/merge.h
@@ -14,13 +14,18 @@
/**
* @file git2/sys/merge.h
- * @brief Git merge driver backend and plugin routines
- * @defgroup git_merge Git merge driver APIs
+ * @brief Custom merge drivers
+ * @defgroup git_merge Custom merge drivers
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/**
+ * A "merge driver" is a mechanism that can be configured to handle
+ * conflict resolution for files changed in both the "ours" and "theirs"
+ * side of a merge.
+ */
typedef struct git_merge_driver git_merge_driver;
/**
@@ -31,8 +36,11 @@ typedef struct git_merge_driver git_merge_driver;
*/
GIT_EXTERN(git_merge_driver *) git_merge_driver_lookup(const char *name);
+/** The "text" merge driver */
#define GIT_MERGE_DRIVER_TEXT "text"
+/** The "binary" merge driver */
#define GIT_MERGE_DRIVER_BINARY "binary"
+/** The "union" merge driver */
#define GIT_MERGE_DRIVER_UNION "union"
/**
@@ -40,23 +48,48 @@ GIT_EXTERN(git_merge_driver *) git_merge_driver_lookup(const char *name);
*/
typedef struct git_merge_driver_source git_merge_driver_source;
-/** Get the repository that the source data is coming from. */
+/**
+ * Get the repository that the source data is coming from.
+ *
+ * @param src the merge driver source
+ * @return the repository
+ */
GIT_EXTERN(git_repository *) git_merge_driver_source_repo(
const git_merge_driver_source *src);
-/** Gets the ancestor of the file to merge. */
+/**
+ * Gets the ancestor of the file to merge.
+ *
+ * @param src the merge driver source
+ * @return the ancestor or NULL if there was no ancestor
+ */
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ancestor(
const git_merge_driver_source *src);
-/** Gets the ours side of the file to merge. */
+/**
+ * Gets the ours side of the file to merge.
+ *
+ * @param src the merge driver source
+ * @return the ours side or NULL if there was no ours side
+ */
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ours(
const git_merge_driver_source *src);
-/** Gets the theirs side of the file to merge. */
+/**
+ * Gets the theirs side of the file to merge.
+ *
+ * @param src the merge driver source
+ * @return the theirs side or NULL if there was no theirs side
+ */
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_theirs(
const git_merge_driver_source *src);
-/** Gets the merge file options that the merge was invoked with */
+/**
+ * Gets the merge file options that the merge was invoked with.
+ *
+ * @param src the merge driver source
+ * @return the options
+ */
GIT_EXTERN(const git_merge_file_options *) git_merge_driver_source_file_options(
const git_merge_driver_source *src);
@@ -72,6 +105,9 @@ GIT_EXTERN(const git_merge_file_options *) git_merge_driver_source_file_options(
* right before the first use of the driver, so you can defer expensive
* initialization operations (in case libgit2 is being used in a way that
* doesn't need the merge driver).
+ *
+ * @param self the merge driver to initialize
+ * @return 0 on success, or a negative number on failure
*/
typedef int GIT_CALLBACK(git_merge_driver_init_fn)(git_merge_driver *self);
@@ -84,6 +120,8 @@ typedef int GIT_CALLBACK(git_merge_driver_init_fn)(git_merge_driver *self);
* This may be called even if the `initialize` callback was not made.
*
* Typically this function will free the `git_merge_driver` object itself.
+ *
+ * @param self the merge driver to shutdown
*/
typedef void GIT_CALLBACK(git_merge_driver_shutdown_fn)(git_merge_driver *self);
@@ -104,6 +142,14 @@ typedef void GIT_CALLBACK(git_merge_driver_shutdown_fn)(git_merge_driver *self);
* specified by the file's attributes.
*
* The `src` contains the data about the file to be merged.
+ *
+ * @param self the merge driver
+ * @param path_out the resolved path
+ * @param mode_out the resolved mode
+ * @param merged_out the merged output contents
+ * @param filter_name the filter that was invoked
+ * @param src the data about the unmerged file
+ * @return 0 on success, or an error code
*/
typedef int GIT_CALLBACK(git_merge_driver_apply_fn)(
git_merge_driver *self,
@@ -139,6 +185,7 @@ struct git_merge_driver {
git_merge_driver_apply_fn apply;
};
+/** The version for the `git_merge_driver` */
#define GIT_MERGE_DRIVER_VERSION 1
/**
@@ -179,4 +226,5 @@ GIT_EXTERN(int) git_merge_driver_unregister(const char *name);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/midx.h b/include/git2/sys/midx.h
index 3a87484d2b5..b3a68afbfc5 100644
--- a/include/git2/sys/midx.h
+++ b/include/git2/sys/midx.h
@@ -11,14 +11,52 @@
#include "git2/types.h"
/**
- * @file git2/midx.h
- * @brief Git multi-pack-index routines
- * @defgroup git_midx Git multi-pack-index routines
+ * @file git2/sys/midx.h
+ * @brief Incremental multi-pack indexes
+ * @defgroup git_midx Incremental multi-pack indexes
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+/**
+ * Options structure for `git_midx_writer_options`.
+ *
+ * Initialize with `GIT_MIDX_WRITER_OPTIONS_INIT`. Alternatively,
+ * you can use `git_midx_writer_options_init`.
+ */
+typedef struct {
+ unsigned int version;
+
+#ifdef GIT_EXPERIMENTAL_SHA256
+ /** The object ID type that this commit graph contains. */
+ git_oid_t oid_type;
+#endif
+} git_midx_writer_options;
+
+/** Current version for the `git_midx_writer_options` structure */
+#define GIT_MIDX_WRITER_OPTIONS_VERSION 1
+
+/** Static constructor for `git_midx_writer_options` */
+#define GIT_MIDX_WRITER_OPTIONS_INIT { \
+ GIT_MIDX_WRITER_OPTIONS_VERSION \
+ }
+
+/**
+ * Initialize git_midx_writer_options structure
+ *
+ * Initializes a `git_midx_writer_options` with default values.
+ * Equivalent to creating an instance with
+ * `GIT_MIDX_WRITER_OPTIONS_INIT`.
+ *
+ * @param opts The `git_midx_writer_options` struct to initialize.
+ * @param version The struct version; pass `GIT_MIDX_WRITER_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_midx_writer_options_init(
+ git_midx_writer_options *opts,
+ unsigned int version);
+
/**
* Create a new writer for `multi-pack-index` files.
*
@@ -31,7 +69,7 @@ GIT_EXTERN(int) git_midx_writer_new(
git_midx_writer **out,
const char *pack_dir
#ifdef GIT_EXPERIMENTAL_SHA256
- , git_oid_t oid_type
+ , git_midx_writer_options *options
#endif
);
@@ -75,4 +113,5 @@ GIT_EXTERN(int) git_midx_writer_dump(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h
index c42abd3707e..53d8d060eac 100644
--- a/include/git2/sys/odb_backend.h
+++ b/include/git2/sys/odb_backend.h
@@ -13,9 +13,9 @@
#include "git2/odb.h"
/**
- * @file git2/sys/backend.h
- * @brief Git custom backend implementors functions
- * @defgroup git_backend Git custom backend APIs
+ * @file git2/sys/odb_backend.h
+ * @brief Object database backends for custom object storage
+ * @defgroup git_backend Object database backends for custom object storage
* @ingroup Git
* @{
*/
@@ -106,7 +106,10 @@ struct git_odb_backend {
void GIT_CALLBACK(free)(git_odb_backend *);
};
+/** Current version for the `git_odb_backend_options` structure */
#define GIT_ODB_BACKEND_VERSION 1
+
+/** Static constructor for `git_odb_backend_options` */
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
/**
@@ -167,6 +170,7 @@ GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);
#endif
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/openssl.h b/include/git2/sys/openssl.h
index b41c55c6d7f..8b74a98cd3d 100644
--- a/include/git2/sys/openssl.h
+++ b/include/git2/sys/openssl.h
@@ -9,6 +9,12 @@
#include "git2/common.h"
+/**
+ * @file git2/sys/openssl.h
+ * @brief Custom OpenSSL functionality
+ * @defgroup git_openssl Custom OpenSSL functionality
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -33,6 +39,7 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_openssl_set_locking(void);
+/** @} */
GIT_END_DECL
-#endif
+#endif
diff --git a/include/git2/sys/path.h b/include/git2/sys/path.h
index 2a0c7e00d3e..2963bca3f7f 100644
--- a/include/git2/sys/path.h
+++ b/include/git2/sys/path.h
@@ -10,6 +10,16 @@
#include "git2/common.h"
+/**
+ * @file git2/sys/path.h
+ * @brief Custom path handling
+ * @defgroup git_path Custom path handling
+ * @ingroup Git
+ *
+ * Merge will take two commits and attempt to produce a commit that
+ * includes the changes that were made in both branches.
+ * @{
+ */
GIT_BEGIN_DECL
/**
@@ -59,6 +69,7 @@ typedef enum {
*/
GIT_EXTERN(int) git_path_is_gitfile(const char *path, size_t pathlen, git_path_gitfile gitfile, git_path_fs fs);
+/** @} */
GIT_END_DECL
-#endif /* INCLUDE_sys_git_path */
+#endif
diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h
index c31e26d9558..813822a69bd 100644
--- a/include/git2/sys/refdb_backend.h
+++ b/include/git2/sys/refdb_backend.h
@@ -12,9 +12,9 @@
#include "git2/oid.h"
/**
- * @file git2/refdb_backend.h
- * @brief Git custom refs backend functions
- * @defgroup git_refdb_backend Git custom refs backend API
+ * @file git2/sys/refdb_backend.h
+ * @brief Custom reference database backends for refs storage
+ * @defgroup git_refdb_backend Custom reference database backends for refs storage
* @ingroup Git
* @{
*/
@@ -65,9 +65,9 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg exists The implementation shall set this to `0` if a ref does
+ * @param exists The implementation shall set this to `0` if a ref does
* not exist, otherwise to `1`.
- * @arg ref_name The reference's name that should be checked for
+ * @param ref_name The reference's name that should be checked for
* existence.
* @return `0` on success, a negative error value code.
*/
@@ -81,9 +81,9 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg out The implementation shall set this to the allocated
+ * @param out The implementation shall set this to the allocated
* reference, if it could be found, otherwise to `NULL`.
- * @arg ref_name The reference's name that should be checked for
+ * @param ref_name The reference's name that should be checked for
* existence.
* @return `0` on success, `GIT_ENOTFOUND` if the reference does
* exist, otherwise a negative error code.
@@ -98,12 +98,12 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg out The implementation shall set this to the allocated
+ * @param out The implementation shall set this to the allocated
* reference iterator. A custom structure may be used with an
* embedded `git_reference_iterator` structure. Both `next`
* and `next_name` functions of `git_reference_iterator` need
* to be populated.
- * @arg glob A pattern to filter references by. If given, the iterator
+ * @param glob A pattern to filter references by. If given, the iterator
* shall only return references that match the glob when
* passed to `wildmatch`.
* @return `0` on success, otherwise a negative error code.
@@ -118,20 +118,20 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg ref The reference to persist. May either be a symbolic or
+ * @param ref The reference to persist. May either be a symbolic or
* direct reference.
- * @arg force Whether to write the reference if a reference with the
+ * @param force Whether to write the reference if a reference with the
* same name already exists.
- * @arg who The person updating the reference. Shall be used to create
+ * @param who The person updating the reference. Shall be used to create
* a reflog entry.
- * @arg message The message detailing what kind of reference update is
+ * @param message The message detailing what kind of reference update is
* performed. Shall be used to create a reflog entry.
- * @arg old If not `NULL` and `force` is not set, then the
+ * @param old If not `NULL` and `force` is not set, then the
* implementation needs to ensure that the reference is currently at
* the given OID before writing the new value. If both `old`
* and `old_target` are `NULL`, then the reference should not
* exist at the point of writing.
- * @arg old_target If not `NULL` and `force` is not set, then the
+ * @param old_target If not `NULL` and `force` is not set, then the
* implementation needs to ensure that the symbolic
* reference is currently at the given target before
* writing the new value. If both `old` and
@@ -149,15 +149,15 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg out The implementation shall set this to the newly created
+ * @param out The implementation shall set this to the newly created
* reference or `NULL` on error.
- * @arg old_name The current name of the reference that is to be renamed.
- * @arg new_name The new name that the old reference shall be renamed to.
- * @arg force Whether to write the reference if a reference with the
+ * @param old_name The current name of the reference that is to be renamed.
+ * @param new_name The new name that the old reference shall be renamed to.
+ * @param force Whether to write the reference if a reference with the
* target name already exists.
- * @arg who The person updating the reference. Shall be used to create
+ * @param who The person updating the reference. Shall be used to create
* a reflog entry.
- * @arg message The message detailing what kind of reference update is
+ * @param message The message detailing what kind of reference update is
* performed. Shall be used to create a reflog entry.
* @return `0` on success, otherwise a negative error code.
*/
@@ -173,11 +173,11 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg ref_name The name of the reference name that shall be deleted.
- * @arg old_id If not `NULL` and `force` is not set, then the
+ * @param ref_name The name of the reference name that shall be deleted.
+ * @param old_id If not `NULL` and `force` is not set, then the
* implementation needs to ensure that the reference is currently at
* the given OID before writing the new value.
- * @arg old_target If not `NULL` and `force` is not set, then the
+ * @param old_target If not `NULL` and `force` is not set, then the
* implementation needs to ensure that the symbolic
* reference is currently at the given target before
* writing the new value.
@@ -243,7 +243,7 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg reflog The complete reference log for a given reference. Note
+ * @param reflog The complete reference log for a given reference. Note
* that this may contain entries that have already been
* written to disk.
* @return `0` on success, a negative error code otherwise
@@ -255,8 +255,8 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg old_name The name of old reference whose reflog shall be renamed from.
- * @arg new_name The name of new reference whose reflog shall be renamed to.
+ * @param old_name The name of old reference whose reflog shall be renamed from.
+ * @param new_name The name of new reference whose reflog shall be renamed to.
* @return `0` on success, a negative error code otherwise
*/
int GIT_CALLBACK(reflog_rename)(git_refdb_backend *_backend, const char *old_name, const char *new_name);
@@ -266,7 +266,7 @@ struct git_refdb_backend {
*
* A refdb implementation must provide this function.
*
- * @arg name The name of the reference whose reflog shall be deleted.
+ * @param name The name of the reference whose reflog shall be deleted.
* @return `0` on success, a negative error code otherwise
*/
int GIT_CALLBACK(reflog_delete)(git_refdb_backend *backend, const char *name);
@@ -277,9 +277,9 @@ struct git_refdb_backend {
* A refdb implementation may provide this function; if it is not
* provided, the transaction API will fail to work.
*
- * @arg payload_out Opaque parameter that will be passed verbosely to
+ * @param payload_out Opaque parameter that will be passed verbosely to
* `unlock`.
- * @arg refname Reference that shall be locked.
+ * @param refname Reference that shall be locked.
* @return `0` on success, a negative error code otherwise
*/
int GIT_CALLBACK(lock)(void **payload_out, git_refdb_backend *backend, const char *refname);
@@ -294,16 +294,16 @@ struct git_refdb_backend {
* A refdb implementation must provide this function if a `lock`
* implementation is provided.
*
- * @arg payload The payload returned by `lock`.
- * @arg success `1` if a reference should be updated, `2` if
+ * @param payload The payload returned by `lock`.
+ * @param success `1` if a reference should be updated, `2` if
* a reference should be deleted, `0` if the lock must be
* discarded.
- * @arg update_reflog `1` in case the reflog should be updated, `0`
+ * @param update_reflog `1` in case the reflog should be updated, `0`
* otherwise.
- * @arg ref The reference which should be unlocked.
- * @arg who The person updating the reference. Shall be used to create
+ * @param ref The reference which should be unlocked.
+ * @param who The person updating the reference. Shall be used to create
* a reflog entry in case `update_reflog` is set.
- * @arg message The message detailing what kind of reference update is
+ * @param message The message detailing what kind of reference update is
* performed. Shall be used to create a reflog entry in
* case `update_reflog` is set.
* @return `0` on success, a negative error code otherwise
@@ -312,7 +312,10 @@ struct git_refdb_backend {
const git_reference *ref, const git_signature *sig, const char *message);
};
+/** Current version for the `git_refdb_backend_options` structure */
#define GIT_REFDB_BACKEND_VERSION 1
+
+/** Static constructor for `git_refdb_backend_options` */
#define GIT_REFDB_BACKEND_INIT {GIT_REFDB_BACKEND_VERSION}
/**
@@ -356,6 +359,7 @@ GIT_EXTERN(int) git_refdb_set_backend(
git_refdb *refdb,
git_refdb_backend *backend);
+/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/sys/reflog.h b/include/git2/sys/reflog.h
deleted file mode 100644
index c9d0041b90f..00000000000
--- a/include/git2/sys/reflog.h
+++ /dev/null
@@ -1,21 +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_sys_git_reflog_h__
-#define INCLUDE_sys_git_reflog_h__
-
-#include "git2/common.h"
-#include "git2/types.h"
-#include "git2/oid.h"
-
-GIT_BEGIN_DECL
-
-GIT_EXTERN(git_reflog_entry *) git_reflog_entry__alloc(void);
-GIT_EXTERN(void) git_reflog_entry__free(git_reflog_entry *entry);
-
-GIT_END_DECL
-
-#endif
diff --git a/include/git2/sys/refs.h b/include/git2/sys/refs.h
index d2ce2e0b914..e434e67c34d 100644
--- a/include/git2/sys/refs.h
+++ b/include/git2/sys/refs.h
@@ -13,8 +13,8 @@
/**
* @file git2/sys/refs.h
- * @brief Low-level Git ref creation
- * @defgroup git_backend Git custom backend APIs
+ * @brief Low-level git reference creation
+ * @defgroup git_backend Low-level git reference creation
* @ingroup Git
* @{
*/
@@ -46,4 +46,5 @@ GIT_EXTERN(git_reference *) git_reference__alloc_symbolic(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/remote.h b/include/git2/sys/remote.h
index 58950e1ec77..476965daa72 100644
--- a/include/git2/sys/remote.h
+++ b/include/git2/sys/remote.h
@@ -13,7 +13,7 @@
/**
* @file git2/sys/remote.h
* @brief Low-level remote functionality for custom transports
- * @defgroup git_remote Low-level remote functionality
+ * @defgroup git_remote Low-level remote functionality for custom transports
* @ingroup Git
* @{
*/
@@ -49,4 +49,5 @@ GIT_EXTERN(void) git_remote_connect_options_dispose(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h
index 080a404c413..026ac8a1d1a 100644
--- a/include/git2/sys/repository.h
+++ b/include/git2/sys/repository.h
@@ -13,13 +13,67 @@
/**
* @file git2/sys/repository.h
- * @brief Git repository custom implementation routines
- * @defgroup git_backend Git custom backend APIs
+ * @brief Custom repository handling
+ * @defgroup git_repository Custom repository handling
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
+#ifdef GIT_EXPERIMENTAL_SHA256
+
+/**
+ * The options for creating an repository from scratch.
+ *
+ * Initialize with `GIT_REPOSITORY_NEW_OPTIONS_INIT`. Alternatively,
+ * you can use `git_repository_new_options_init`.
+ *
+ * @options[version] GIT_REPOSITORY_NEW_OPTIONS_VERSION
+ * @options[init_macro] GIT_REPOSITORY_NEW_OPTIONS_INIT
+ * @options[init_function] git_repository_new_options_init
+ */
+typedef struct git_repository_new_options {
+ unsigned int version; /**< The version */
+
+ /**
+ * The object ID type for the object IDs that exist in the index.
+ *
+ * If this is not specified, this defaults to `GIT_OID_SHA1`.
+ */
+ git_oid_t oid_type;
+} git_repository_new_options;
+
+/** Current version for the `git_repository_new_options` structure */
+#define GIT_REPOSITORY_NEW_OPTIONS_VERSION 1
+
+/** Static constructor for `git_repository_new_options` */
+#define GIT_REPOSITORY_NEW_OPTIONS_INIT { GIT_REPOSITORY_NEW_OPTIONS_VERSION }
+
+/**
+ * Initialize git_repository_new_options structure
+ *
+ * Initializes a `git_repository_new_options` with default values.
+ * Equivalent to creating an instance with
+ * `GIT_REPOSITORY_NEW_OPTIONS_INIT`.
+ *
+ * @param opts The `git_repository_new_options` struct to initialize.
+ * @param version The struct version; pass `GIT_REPOSITORY_NEW_OPTIONS_VERSION`.
+ * @return Zero on success; -1 on failure.
+ */
+GIT_EXTERN(int) git_repository_new_options_init(
+ git_repository_new_options *opts,
+ unsigned int version);
+
+/**
+ * Create a new repository with no backends.
+ *
+ * @param[out] out The blank repository
+ * @param opts the options for repository creation, or NULL for defaults
+ * @return 0 on success, or an error code
+ */
+GIT_EXTERN(int) git_repository_new(git_repository **out, git_repository_new_options *opts);
+#else
+
/**
* Create a new repository with neither backends nor config object
*
@@ -30,13 +84,11 @@ GIT_BEGIN_DECL
* can fail to function properly: locations under $GIT_DIR, $GIT_COMMON_DIR,
* or $GIT_INFO_DIR are impacted.
*
- * @param out The blank repository
+ * @param[out] out The blank repository
* @return 0 on success, or an error code
*/
-#ifdef GIT_EXPERIMENTAL_SHA256
-GIT_EXTERN(int) git_repository_new(git_repository **out, git_oid_t oid_type);
-#else
GIT_EXTERN(int) git_repository_new(git_repository **out);
+
#endif
/**
@@ -161,6 +213,7 @@ GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
* and caches them so that subsequent calls to `git_submodule_lookup` are O(1).
*
* @param repo the repository whose submodules will be cached.
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_submodule_cache_all(
git_repository *repo);
@@ -176,10 +229,12 @@ GIT_EXTERN(int) git_repository_submodule_cache_all(
* of these has changed, the cache might become invalid.
*
* @param repo the repository whose submodule cache will be cleared
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_submodule_cache_clear(
git_repository *repo);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/sys/stream.h b/include/git2/sys/stream.h
index 3277088c99c..eabff68643f 100644
--- a/include/git2/sys/stream.h
+++ b/include/git2/sys/stream.h
@@ -11,8 +11,16 @@
#include "git2/types.h"
#include "git2/proxy.h"
+/**
+ * @file git2/sys/stream.h
+ * @brief Streaming file I/O functionality
+ * @defgroup git_stream Streaming file I/O functionality
+ * @ingroup Git
+ * @{
+ */
GIT_BEGIN_DECL
+/** Current version for the `git_stream` structures */
#define GIT_STREAM_VERSION 1
/**
@@ -147,6 +155,7 @@ GIT_EXTERN(int) git_stream_register_tls(git_stream_cb ctor);
#endif
+/**@}*/
GIT_END_DECL
#endif
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h
index 370ca45d570..ad6765c623e 100644
--- a/include/git2/sys/transport.h
+++ b/include/git2/sys/transport.h
@@ -18,14 +18,20 @@
/**
* @file git2/sys/transport.h
- * @brief Git custom transport registration interfaces and functions
- * @defgroup git_transport Git custom transport registration
+ * @brief Custom transport registration interfaces and functions
+ * @defgroup git_transport Custom transport registration
* @ingroup Git
+ *
+ * Callers can override the default HTTPS or SSH implementation by
+ * specifying a custom transport.
* @{
*/
GIT_BEGIN_DECL
+/**
+ * The negotiation state during a fetch smart transport negotiation.
+ */
typedef struct {
const git_remote_head * const *refs;
size_t refs_len;
@@ -146,7 +152,10 @@ struct git_transport {
void GIT_CALLBACK(free)(git_transport *transport);
};
+/** Current version for the `git_transport` structure */
#define GIT_TRANSPORT_VERSION 1
+
+/** Static constructor for `git_transport` */
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
/**
@@ -299,6 +308,7 @@ GIT_EXTERN(int) git_transport_smart_credentials(git_credential **out, git_transp
*
* @param out options struct to fill
* @param transport the transport to extract the data from.
+ * @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_transport_remote_connect_options(
git_remote_connect_options *out,
@@ -386,7 +396,14 @@ struct git_smart_subtransport {
void GIT_CALLBACK(free)(git_smart_subtransport *transport);
};
-/** A function which creates a new subtransport for the smart transport */
+/**
+ * A function that creates a new subtransport for the smart transport
+ *
+ * @param out the smart subtransport
+ * @param owner the transport owner
+ * @param param the input parameter
+ * @return 0 on success, or an error code
+ */
typedef int GIT_CALLBACK(git_smart_subtransport_cb)(
git_smart_subtransport **out,
git_transport *owner,
@@ -429,6 +446,7 @@ typedef struct git_smart_subtransport_definition {
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
+ * @param param custom parameters for the subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_http(
@@ -441,6 +459,7 @@ GIT_EXTERN(int) git_smart_subtransport_http(
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
+ * @param param custom parameters for the subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_git(
@@ -453,6 +472,7 @@ GIT_EXTERN(int) git_smart_subtransport_git(
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
+ * @param param custom parameters for the subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_ssh(
@@ -462,4 +482,5 @@ GIT_EXTERN(int) git_smart_subtransport_ssh(
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/tag.h b/include/git2/tag.h
index 98305365590..3b0c12ebcb8 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -15,7 +15,7 @@
/**
* @file git2/tag.h
- * @brief Git tag parsing routines
+ * @brief A (nearly) immutable pointer to a commit; useful for versioning
* @defgroup git_tag Git tag management
* @ingroup Git
* @{
@@ -335,6 +335,7 @@ typedef int GIT_CALLBACK(git_tag_foreach_cb)(const char *name, git_oid *oid, voi
* @param repo Repository
* @param callback Callback function
* @param payload Pointer to callback data (optional)
+ * @return 0 on success or an error code
*/
GIT_EXTERN(int) git_tag_foreach(
git_repository *repo,
@@ -380,4 +381,5 @@ GIT_EXTERN(int) git_tag_name_is_valid(int *valid, const char *name);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/trace.h b/include/git2/trace.h
index 8cee3a94ecc..62cb87c012c 100644
--- a/include/git2/trace.h
+++ b/include/git2/trace.h
@@ -12,8 +12,8 @@
/**
* @file git2/trace.h
- * @brief Git tracing configuration routines
- * @defgroup git_trace Git tracing configuration routines
+ * @brief Tracing functionality to introspect libgit2 in your application
+ * @defgroup git_trace Tracing functionality to introspect libgit2 in your application
* @ingroup Git
* @{
*/
@@ -48,8 +48,13 @@ typedef enum {
/**
* An instance for a tracing function
+ *
+ * @param level the trace level
+ * @param msg the trace message
*/
-typedef void GIT_CALLBACK(git_trace_cb)(git_trace_level_t level, const char *msg);
+typedef void GIT_CALLBACK(git_trace_cb)(
+ git_trace_level_t level,
+ const char *msg);
/**
* Sets the system tracing configuration to the specified level with the
@@ -64,4 +69,5 @@ GIT_EXTERN(int) git_trace_set(git_trace_level_t level, git_trace_cb cb);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/transaction.h b/include/git2/transaction.h
index 4938570b5a1..212d32919a7 100644
--- a/include/git2/transaction.h
+++ b/include/git2/transaction.h
@@ -12,8 +12,8 @@
/**
* @file git2/transaction.h
- * @brief Git transactional reference routines
- * @defgroup git_transaction Git transactional reference routines
+ * @brief Transactional reference handling
+ * @defgroup git_transaction Transactional reference handling
* @ingroup Git
* @{
*/
@@ -118,4 +118,5 @@ GIT_EXTERN(void) git_transaction_free(git_transaction *tx);
/** @} */
GIT_END_DECL
+
#endif
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 5a27de9a860..04a7390b10f 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -15,8 +15,8 @@
/**
* @file git2/transport.h
- * @brief Git transport interfaces and functions
- * @defgroup git_transport interfaces and functions
+ * @brief Transports are the low-level mechanism to connect to a remote server
+ * @defgroup git_transport Transports are the low-level mechanism to connect to a remote server
* @ingroup Git
* @{
*/
@@ -30,10 +30,18 @@ GIT_BEGIN_DECL
* @param str The message from the transport
* @param len The length of the message
* @param payload Payload provided by the caller
+ * @return 0 on success or an error code
*/
typedef int GIT_CALLBACK(git_transport_message_cb)(const char *str, int len, void *payload);
-/** Signature of a function which creates a transport */
+/**
+ * Signature of a function which creates a transport.
+ *
+ * @param out the transport generate
+ * @param owner the owner for the transport
+ * @param param the param to the transport creation
+ * @return 0 on success or an error code
+ */
typedef int GIT_CALLBACK(git_transport_cb)(git_transport **out, git_remote *owner, void *param);
/** @} */
diff --git a/include/git2/tree.h b/include/git2/tree.h
index ce0a60907fa..b8e2de217ed 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -14,8 +14,8 @@
/**
* @file git2/tree.h
- * @brief Git tree parsing, loading routines
- * @defgroup git_tree Git tree parsing, loading routines
+ * @brief Trees are collections of files and folders to make up the repository hierarchy
+ * @defgroup git_tree Trees are collections of files and folders to make up the repository hierarchy
* @ingroup Git
* @{
*/
@@ -24,7 +24,7 @@ GIT_BEGIN_DECL
/**
* Lookup a tree object from the repository.
*
- * @param out Pointer to the looked up tree
+ * @param[out] out Pointer to the looked up tree
* @param repo The repo to use when locating the tree.
* @param id Identity of the tree to locate.
* @return 0 or an error code
@@ -345,6 +345,10 @@ GIT_EXTERN(int) git_treebuilder_remove(
* The return value is treated as a boolean, with zero indicating that the
* entry should be left alone and any non-zero value meaning that the
* entry should be removed from the treebuilder list (i.e. filtered out).
+ *
+ * @param entry the tree entry for the callback to examine
+ * @param payload the payload from the caller
+ * @return 0 to do nothing, non-zero to remove the entry
*/
typedef int GIT_CALLBACK(git_treebuilder_filter_cb)(
const git_tree_entry *entry, void *payload);
@@ -379,7 +383,14 @@ GIT_EXTERN(int) git_treebuilder_filter(
GIT_EXTERN(int) git_treebuilder_write(
git_oid *id, git_treebuilder *bld);
-/** Callback for the tree traversal method */
+/**
+ * Callback for the tree traversal method.
+ *
+ * @param root the current (relative) root to the entry
+ * @param entry the tree entry
+ * @param payload the caller-provided callback payload
+ * @return a positive value to skip the entry, a negative value to stop the walk
+ */
typedef int GIT_CALLBACK(git_treewalk_cb)(
const char *root, const git_tree_entry *entry, void *payload);
@@ -470,6 +481,6 @@ typedef struct {
GIT_EXTERN(int) git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseline, size_t nupdates, const git_tree_update *updates);
/** @} */
-
GIT_END_DECL
+
#endif
diff --git a/include/git2/types.h b/include/git2/types.h
index d4b033dc770..a4afd18c3bc 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -81,13 +81,18 @@ typedef enum {
GIT_OBJECT_REF_DELTA = 7 /**< A delta, base is given by object id. */
} git_object_t;
-/** An open object database handle. */
+/**
+ * An object database stores the objects (commit, trees, blobs, tags,
+ * etc) for a repository.
+ */
typedef struct git_odb git_odb;
/** A custom backend in an ODB */
typedef struct git_odb_backend git_odb_backend;
-/** An object read from the ODB */
+/**
+ * A "raw" object read from the object database.
+ */
typedef struct git_odb_object git_odb_object;
/** A stream to read/write from the ODB */
@@ -194,7 +199,18 @@ typedef struct git_reference_iterator git_reference_iterator;
/** Transactional interface to references */
typedef struct git_transaction git_transaction;
-/** Annotated commits, the input to merge and rebase. */
+/**
+ * Annotated commits are commits with additional metadata about how the
+ * commit was resolved, which can be used for maintaining the user's
+ * "intent" through commands like merge and rebase.
+ *
+ * For example, if a user wants to conceptually "merge `HEAD`", then the
+ * commit portion of an annotated commit will point to the `HEAD` commit,
+ * but the _annotation_ will denote the ref `HEAD`. This allows git to
+ * perform the internal bookkeeping so that the system knows both the
+ * content of what is being merged but also how the content was looked up
+ * so that it can be recorded in the reflog appropriately.
+ */
typedef struct git_annotated_commit git_annotated_commit;
/** Representation of a status collection */
diff --git a/include/git2/version.h b/include/git2/version.h
index 33c96254cee..6a352e1a53a 100644
--- a/include/git2/version.h
+++ b/include/git2/version.h
@@ -7,23 +7,31 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
+/**
+ * @file git2/version.h
+ * @brief The version of libgit2
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
/**
* The version string for libgit2. This string follows semantic
* versioning (v2) guidelines.
*/
-#define LIBGIT2_VERSION "1.8.1"
+#define LIBGIT2_VERSION "1.9.0"
/** The major version number for this version of libgit2. */
-#define LIBGIT2_VER_MAJOR 1
+#define LIBGIT2_VERSION_MAJOR 1
/** The minor version number for this version of libgit2. */
-#define LIBGIT2_VER_MINOR 8
+#define LIBGIT2_VERSION_MINOR 9
/** The revision ("teeny") version number for this version of libgit2. */
-#define LIBGIT2_VER_REVISION 1
+#define LIBGIT2_VERSION_REVISION 0
/** The Windows DLL patch number for this version of libgit2. */
-#define LIBGIT2_VER_PATCH 0
+#define LIBGIT2_VERSION_PATCH 0
/**
* The prerelease string for this version of libgit2. For development
@@ -31,13 +39,37 @@
* a prerelease name like "beta" or "rc1". For final releases, this will
* be `NULL`.
*/
-#define LIBGIT2_VER_PRERELEASE NULL
+#define LIBGIT2_VERSION_PRERELEASE NULL
/**
* The library ABI soversion for this version of libgit2. This should
* only be changed when the library has a breaking ABI change, and so
- * may trail the library's version number.
+ * may not reflect the library's API version number.
+ */
+#define LIBGIT2_SOVERSION "1.9"
+
+/**
+ * An integer value representing the libgit2 version number. For example,
+ * libgit2 1.6.3 is 1060300.
*/
-#define LIBGIT2_SOVERSION "1.8"
+#define LIBGIT2_VERSION_NUMBER ( \
+ (LIBGIT2_VERSION_MAJOR * 1000000) + \
+ (LIBGIT2_VERSION_MINOR * 10000) + \
+ (LIBGIT2_VERSION_REVISION * 100))
+
+/**
+ * Compare the libgit2 version against a given version. Evaluates to true
+ * if the given major, minor, and revision values are greater than or equal
+ * to the currently running libgit2 version. For example:
+ *
+ * #if LIBGIT2_VERSION_CHECK(1, 6, 3)
+ * # error libgit2 version is >= 1.6.3
+ * #endif
+ */
+#define LIBGIT2_VERSION_CHECK(major, minor, revision) \
+ (LIBGIT2_VERSION_NUMBER >= ((major)*1000000)+((minor)*10000)+((revision)*100))
+
+/** @} */
+GIT_END_DECL
#endif
diff --git a/include/git2/worktree.h b/include/git2/worktree.h
index a6e5d17c4b1..fd3751753b4 100644
--- a/include/git2/worktree.h
+++ b/include/git2/worktree.h
@@ -14,9 +14,9 @@
#include "checkout.h"
/**
- * @file git2/worktrees.h
- * @brief Git worktree related functions
- * @defgroup git_commit Git worktree related functions
+ * @file git2/worktree.h
+ * @brief Additional working directories for a repository
+ * @defgroup git_commit Additional working directories for a repository
* @ingroup Git
* @{
*/
@@ -96,7 +96,10 @@ typedef struct git_worktree_add_options {
git_checkout_options checkout_options;
} git_worktree_add_options;
+/** Current version for the `git_worktree_add_options` structure */
#define GIT_WORKTREE_ADD_OPTIONS_VERSION 1
+
+/** Static constructor for `git_worktree_add_options` */
#define GIT_WORKTREE_ADD_OPTIONS_INIT { GIT_WORKTREE_ADD_OPTIONS_VERSION, \
0, 0, NULL, GIT_CHECKOUT_OPTIONS_INIT }
@@ -211,7 +214,10 @@ typedef struct git_worktree_prune_options {
uint32_t flags;
} git_worktree_prune_options;
+/** Current version for the `git_worktree_prune_options` structure */
#define GIT_WORKTREE_PRUNE_OPTIONS_VERSION 1
+
+/** Static constructor for `git_worktree_prune_options` */
#define GIT_WORKTREE_PRUNE_OPTIONS_INIT {GIT_WORKTREE_PRUNE_OPTIONS_VERSION,0}
/**
@@ -268,4 +274,5 @@ GIT_EXTERN(int) git_worktree_prune(git_worktree *wt,
/** @} */
GIT_END_DECL
+
#endif
diff --git a/package.json b/package.json
index 6c1cb286ebd..2bea37ef30b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "libgit2",
- "version": "1.8.1",
+ "version": "1.9.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/script/api-docs/.gitignore b/script/api-docs/.gitignore
new file mode 100644
index 00000000000..c2658d7d1b3
--- /dev/null
+++ b/script/api-docs/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/script/api-docs/README.md b/script/api-docs/README.md
new file mode 100644
index 00000000000..fb329e2faa1
--- /dev/null
+++ b/script/api-docs/README.md
@@ -0,0 +1,13 @@
+# API Documentation Generator
+
+These scripts generate the "raw API" specs and reference documentation
+for [www.libgit2.org](https://libgit2.org/docs/reference).
+
+The "raw API" specs consists of JSON documents, on per
+released version or branch, that describes the APIs. This is
+suitable for creating documentation from, or may be useful for
+language bindings as well.
+
+The reference documentation is documentation fragments for each
+API in each version, ready to be included in the libgit2 documentation
+website.
diff --git a/script/api-docs/api-generator.js b/script/api-docs/api-generator.js
new file mode 100755
index 00000000000..47c928acf01
--- /dev/null
+++ b/script/api-docs/api-generator.js
@@ -0,0 +1,1558 @@
+#!/usr/bin/env node
+
+const path = require('node:path');
+const child_process = require('node:child_process');
+const fs = require('node:fs').promises;
+const util = require('node:util');
+const process = require('node:process');
+
+const { program } = require('commander');
+
+const includePath = (p) => `${p}/include`;
+const ancientIncludePath = (p) => `${p}/src/git`;
+const legacyIncludePath = (p) => `${p}/src/git2`;
+const standardIncludePath = (p) => `${includePath(p)}/git2`;
+const systemIncludePath = (p) => `${includePath(p)}/git2/sys`;
+
+const fileIgnoreList = [ 'stdint.h', 'inttypes.h' ];
+const apiIgnoreList = [ 'GIT_BEGIN_DECL', 'GIT_END_DECL', 'GIT_WIN32' ];
+
+// Some older versions of libgit2 need some help with includes
+const defaultIncludes = [
+ 'checkout.h', 'common.h', 'diff.h', 'email.h', 'oidarray.h', 'merge.h', 'remote.h', 'types.h'
+];
+
+// We're unable to fully map `types.h` defined types into groups;
+// provide some help.
+const groupMap = {
+ 'filemode': 'tree',
+ 'treebuilder': 'tree',
+ 'note': 'notes',
+ 'packbuilder': 'pack',
+ 'reference': 'refs',
+ 'push': 'remote' };
+
+async function headerPaths(p) {
+ const possibleIncludePaths = [
+ ancientIncludePath(p),
+ legacyIncludePath(p),
+ standardIncludePath(p),
+ systemIncludePath(p)
+ ];
+
+ const includePaths = [ ];
+ const paths = [ ];
+
+ for (const possibleIncludePath of possibleIncludePaths) {
+ try {
+ await fs.stat(possibleIncludePath);
+ includePaths.push(possibleIncludePath);
+ }
+ catch (e) {
+ if (e?.code !== 'ENOENT') {
+ throw e;
+ }
+ }
+ }
+
+ if (!includePaths.length) {
+ throw new Error(`no include paths for ${p}`);
+ }
+
+ for (const fullPath of includePaths) {
+ paths.push(...(await fs.readdir(fullPath)).
+ filter((filename) => filename.endsWith('.h')).
+ filter((filename) => !fileIgnoreList.includes(filename)).
+ filter((filename) => filename !== 'deprecated.h' || !options.deprecateHard).
+ map((filename) => `${fullPath}/${filename}`));
+ }
+
+ return paths;
+}
+
+function trimPath(basePath, headerPath) {
+ const possibleIncludePaths = [
+ ancientIncludePath(basePath),
+ legacyIncludePath(basePath),
+ standardIncludePath(basePath),
+ systemIncludePath(basePath)
+ ];
+
+ for (const possibleIncludePath of possibleIncludePaths) {
+ if (headerPath.startsWith(possibleIncludePath + '/')) {
+ return headerPath.substr(possibleIncludePath.length + 1);
+ }
+ }
+
+ throw new Error("header path is not beneath include root");
+}
+
+function parseFileAst(path, ast) {
+ let currentFile = undefined;
+ const fileData = [ ];
+
+ for (const node of ast.inner) {
+ if (node.loc?.file && currentFile != node.loc.file) {
+ currentFile = node.loc.file;
+ } else if (node.loc?.spellingLoc?.file && currentFile != node.loc.spellingLoc.file) {
+ currentFile = node.loc.spellingLoc.file;
+ }
+
+ if (currentFile != path) {
+ continue;
+ }
+
+ fileData.push(node);
+ }
+
+ return fileData;
+}
+
+function includeBase(path) {
+ const segments = path.split('/');
+
+ while (segments.length > 1) {
+ if (segments[segments.length - 1] === 'git2' ||
+ segments[segments.length - 1] === 'git') {
+ segments.pop();
+ return segments.join('/');
+ }
+
+ segments.pop();
+ }
+
+ throw new Error(`could not resolve include base for ${path}`);
+}
+
+function readAst(path, options) {
+ return new Promise((resolve, reject) => {
+ let errorMessage = '';
+ const chunks = [ ];
+
+ const processArgs = [ path, '-Xclang', '-ast-dump=json', `-I${includeBase(path)}` ];
+
+ if (options?.deprecateHard) {
+ processArgs.push(`-DGIT_DEPRECATE_HARD`);
+ }
+
+ if (options?.includeFiles) {
+ for (const file of options.includeFiles) {
+ processArgs.push(`-include`);
+ processArgs.push(file)
+ }
+ }
+
+ const process = child_process.spawn('clang', processArgs);
+
+ process.stderr.on('data', (message) => {
+ errorMessage += message;
+ });
+ process.stdout.on('data', (chunk) => {
+ chunks.push(chunk);
+ });
+ process.on('close', (code) => {
+ if (code != 0 && options.strict) {
+ reject(new Error(`clang exit code ${code}: ${errorMessage}`));
+ }
+ else if (code != 0) {
+ resolve([ ]);
+ }
+ else {
+ const ast = JSON.parse(Buffer.concat(chunks).toString());
+ resolve(parseFileAst(path, ast));
+ }
+ });
+ process.on('error', function (err) {
+ reject(err);
+ });
+ });
+}
+
+async function readFile(path) {
+ const buf = await fs.readFile(path);
+ return buf.toString();
+}
+
+function ensure(message, test) {
+ if (!test) {
+ throw new Error(message);
+ }
+}
+
+function ensureDefined(name, value) {
+ if (!value) {
+ throw new Error(`could not find ${name} for declaration`);
+ }
+
+ return value;
+}
+
+function groupifyId(location, id) {
+ if (!id) {
+ throw new Error(`could not find id in declaration`);
+ }
+
+ if (!location || !location.file) {
+ throw new Error(`unspecified location`);
+ }
+
+ return `${location.file}-${id}`;
+}
+
+function blockCommentText(block) {
+ ensure('block does not have a single paragraph element', block.inner.length === 1 && block.inner[0].kind === 'ParagraphComment');
+ return commentText(block.inner[0]);
+}
+
+function richBlockCommentText(block) {
+ ensure('block does not have a single paragraph element', block.inner.length === 1 && block.inner[0].kind === 'ParagraphComment');
+ return richCommentText(block.inner[0]);
+}
+
+function paramCommentText(param) {
+ ensure('param does not have a single paragraph element', param.inner.length === 1 && param.inner[0].kind === 'ParagraphComment');
+ return richCommentText(param.inner[0]);
+}
+
+function appendCommentText(chunk) {
+ return chunk.startsWith(' ') ? "\n" + chunk : chunk;
+}
+
+function commentText(para) {
+ let text = '';
+
+ for (const comment of para.inner) {
+ // docbook allows backslash escaped text, and reports it differently.
+ // we restore the literal `\`.
+ if (comment.kind === 'InlineCommandComment') {
+ text += `\\${comment.name}`;
+ }
+ else if (comment.kind === 'TextComment') {
+ text += text ? "\n" + comment.text : comment.text;
+ } else {
+ throw new Error(`unknown paragraph comment element: ${comment.kind}`);
+ }
+ }
+
+ return text.trim();
+}
+
+function nextText(para, idx) {
+ if (!para.inner[idx + 1] || para.inner[idx + 1].kind !== 'TextComment') {
+ throw new Error("expected text comment");
+ }
+
+ return para.inner[idx + 1].text;
+}
+
+function inlineCommandData(data, command) {
+ ensure(`${command} information does not follow @${command}`, data?.kind === 'TextComment');
+
+ const result = data.text.match(/^(?:\[([^\]]+)\])? ((?:[a-zA-Z0-9\_]+)|`[a-zA-Z0-9\_\* ]+`)(.*)/);
+ ensure(`${command} data does not follow @${command}`, result);
+
+ const [ , attr, spec, remain ] = result;
+ return [ attr, spec.replace(/^`(.*)`$/, "$1"), remain ]
+}
+
+function richCommentText(para) {
+ let text = '';
+ let extendedType = undefined;
+ let subkind = undefined;
+ let versionMacro = undefined;
+ let initMacro = undefined;
+ let initFunction = undefined;
+ let lastComment = undefined;
+
+ for (let i = 0; i < para.inner?.length; i++) {
+ const comment = para.inner[i];
+
+ if (comment.kind === 'InlineCommandComment' &&
+ comment.name === 'type') {
+ const [ attr, data, remain ] = inlineCommandData(para.inner[++i], "type");
+
+ extendedType = { kind: attr, type: data };
+ text += remain;
+ }
+ else if (comment.kind === 'InlineCommandComment' &&
+ comment.name === 'flags') {
+ subkind = 'flags';
+ }
+ else if (comment.kind === 'InlineCommandComment' &&
+ comment.name === 'options') {
+ const [ attr, data, remain ] = inlineCommandData(para.inner[++i], "options");
+
+ if (attr === 'version') {
+ versionMacro = data;
+ }
+ else if (attr === 'init_macro') {
+ initMacro = data;
+ }
+ else if (attr === 'init_function') {
+ initFunction = data;
+ }
+
+ subkind = 'options';
+ text += remain;
+ }
+ // docbook allows backslash escaped text, and reports it differently.
+ // we restore the literal `\`.
+ else if (comment.kind === 'InlineCommandComment') {
+ text += `\\${comment.name}`;
+ }
+ else if (comment.kind === 'TextComment') {
+ // clang oddity: it breaks into two
+ // comment blocks, assuming that the trailing > should be a
+ // blockquote newline sort of thing. unbreak them.
+ if (comment.text.startsWith('>') &&
+ lastComment &&
+ lastComment.loc.offset + lastComment.text.length === comment.loc.offset) {
+
+ text += comment.text;
+ } else {
+ text += text ? "\n" + comment.text : comment.text;
+ }
+ }
+ else if (comment.kind === 'HTMLStartTagComment' && comment.name === 'p') {
+ text += "\n";
+ }
+ else {
+ throw new Error(`unknown paragraph comment element: ${comment.kind}`);
+ }
+
+ lastComment = comment;
+ }
+
+ return {
+ text: text.trim(),
+ extendedType: extendedType,
+ subkind: subkind,
+ versionMacro: versionMacro,
+ initMacro: initMacro,
+ initFunction: initFunction
+ }
+}
+
+function join(arr, elem) {
+ if (arr) {
+ return [ ...arr, elem ];
+ }
+
+ return [ elem ];
+}
+
+function joinIfNotEmpty(arr, elem) {
+ if (!elem || elem === '') {
+ return arr;
+ }
+
+ if (arr) {
+ return [ ...arr, elem ];
+ }
+
+ return [ elem ];
+}
+
+function pushIfNotEmpty(arr, elem) {
+ if (elem && elem !== '') {
+ arr.push(elem);
+ }
+}
+
+function single(arr, fn, message) {
+ let result = undefined;
+
+ if (!arr) {
+ return undefined;
+ }
+
+ for (const match of arr.filter(fn)) {
+ if (result) {
+ throw new Error(`multiple matches in array for ${fn}${message ? ' (' + message + ')': ''}`);
+ }
+
+ result = match;
+ }
+
+ return result;
+}
+
+function updateLocation(location, decl) {
+ location.file = trimBase(decl.loc?.spellingLoc?.file || decl.loc?.file) || location.file;
+ location.line = decl.loc?.spellingLoc?.line || decl.loc?.line || location.line;
+ location.column = decl.loc?.spellingLoc?.col || decl.loc?.col || location.column;
+
+ return location;
+}
+
+async function readFileLocation(startLocation, endLocation) {
+ if (startLocation.file != endLocation.file) {
+ throw new Error("cannot read across files");
+ }
+
+ const data = await fs.readFile(startLocation.file, "utf8");
+ const lines = data.split(/\r?\n/).slice(startLocation.line - 1, endLocation.line);
+
+ lines[lines.length - 1] = lines[lines.length - 1].slice(0, endLocation.column);
+ lines[0] = lines[0].slice(startLocation.column - 1);
+
+ return lines
+}
+
+function formatLines(lines) {
+ let result = "";
+ let continuation = false;
+
+ for (const i in lines) {
+ if (!continuation) {
+ lines[i] = lines[i].trimStart();
+ }
+
+ continuation = lines[i].endsWith("\\");
+
+ if (continuation) {
+ lines[i] = lines[i].slice(0, -1);
+ } else {
+ lines[i] = lines[i].trimEnd();
+ }
+
+ result += lines[i];
+ }
+
+ if (continuation) {
+ throw new Error("unterminated literal continuation");
+ }
+
+ return result;
+}
+
+async function parseExternalRange(location, range) {
+ const startLocation = {...location};
+ startLocation.file = trimBase(range.begin.spellingLoc.file || startLocation.file);
+ startLocation.line = range.begin.spellingLoc.line || startLocation.line;
+ startLocation.column = range.begin.spellingLoc.col || startLocation.column;
+
+ const endLocation = {...startLocation};
+ endLocation.file = trimBase(range.end.spellingLoc.file || endLocation.file);
+ endLocation.line = range.end.spellingLoc.line || endLocation.line;
+ endLocation.column = range.end.spellingLoc.col || endLocation.column;
+
+ const lines = await readFileLocation(startLocation, endLocation);
+
+ return formatLines(lines);
+}
+
+async function parseLiteralRange(location, range) {
+ const startLocation = updateLocation({...location}, { loc: range.begin });
+ const endLocation = updateLocation({...location}, { loc: range.end });
+
+ const lines = await readFileLocation(startLocation, endLocation);
+
+ return formatLines(lines);
+}
+
+async function parseRange(location, range) {
+ return range.begin.spellingLoc ? parseExternalRange(location, range) : parseLiteralRange(location, range);
+}
+
+class ParserError extends Error {
+ constructor(message, location) {
+ if (!location) {
+ super(`${message} at (unknown)`);
+ }
+ else {
+ super(`${message} at ${location.file}:${location.line}`);
+ }
+ this.name = 'ParserError';
+ }
+}
+
+function validateParsing(test, message, location) {
+ if (!test) {
+ throw new ParserError(message, location);
+ }
+}
+
+function parseComment(spec, location, comment, options) {
+ let result = { };
+ let last = undefined;
+
+ for (const c of comment.inner.filter(c => c.kind === 'ParagraphComment' || c.kind === 'VerbatimLineComment')) {
+ if (c.kind === 'ParagraphComment') {
+ const commentData = richCommentText(c);
+
+ result.comment = joinIfNotEmpty(result.comment, commentData.text);
+ delete commentData.text;
+
+ result = { ...result, ...commentData };
+ }
+ else if (c.kind === 'VerbatimLineComment') {
+ result.comment = joinIfNotEmpty(result.comment, c.text.trim());
+ }
+ else {
+ throw new Error(`unknown comment ${c.kind}`);
+ }
+ }
+
+ for (const c of comment.inner.filter(c => c.kind !== 'ParagraphComment' && c.kind !== 'VerbatimLineComment')) {
+ if (c.kind === 'BlockCommandComment' && c.name === 'see') {
+ result.see = joinIfNotEmpty(result.see, blockCommentText(c));
+ }
+ else if (c.kind === 'BlockCommandComment' && c.name === 'note') {
+ result.notes = joinIfNotEmpty(result.notes, blockCommentText(c));
+ }
+ else if (c.kind === 'BlockCommandComment' && c.name === 'deprecated') {
+ result.deprecations = joinIfNotEmpty(result.deprecations, blockCommentText(c));
+ }
+ else if (c.kind === 'BlockCommandComment' && c.name === 'warning') {
+ result.warnings = joinIfNotEmpty(result.warnings, blockCommentText(c));
+ }
+ else if (c.kind === 'BlockCommandComment' &&
+ (c.name === 'return' || (c.name === 'returns' && !options.strict))) {
+ const returnData = richBlockCommentText(c);
+
+ result.returns = {
+ extendedType: returnData.extendedType,
+ comment: returnData.text
+ };
+ }
+ else if (c.kind === 'ParamCommandComment') {
+ ensure('param has a name', c.param);
+
+ const paramDetails = paramCommentText(c);
+
+ result.params = join(result.params, {
+ name: c.param,
+ direction: c.direction,
+ values: paramDetails.type,
+ extendedType: paramDetails.extendedType,
+ comment: paramDetails.text
+ });
+ }
+ else if (options.strict) {
+ if (c.kind === 'BlockCommandComment') {
+ throw new ParserError(`unknown block command comment ${c.name}`, location);
+ }
+ else if (c.kind === 'VerbatimBlockComment') {
+ throw new Error(`unknown verbatim command comment ${c.name}`, location);
+ }
+ else {
+ throw new Error(`unknown comment ${c.kind} in ${kind}`);
+ }
+ }
+ }
+
+ return result;
+}
+
+async function parseFunction(location, decl, options) {
+ let result = {
+ kind: 'function',
+ id: groupifyId(location, decl.id),
+ name: ensureDefined('name', decl.name),
+ location: {...location}
+ };
+
+ // prototype
+ const [ , returnType, ] = decl.type.qualType.match(/(.*?)(?: )?\((.*)\)$/) || [ ];
+ ensureDefined('return type declaration', returnType);
+ result.returns = { type: returnType };
+
+ for (const paramDecl of decl.inner.filter(attr => attr.kind === 'ParmVarDecl')) {
+ updateLocation(location, paramDecl);
+
+ const inner = paramDecl.inner || [];
+ const innerLocation = {...location};
+ let paramAnnotations = undefined;
+
+ for (const annotateDecl of inner.filter(attr => attr.kind === 'AnnotateAttr')) {
+ updateLocation(innerLocation, annotateDecl);
+
+ paramAnnotations = join(paramAnnotations, await parseRange(innerLocation, annotateDecl.range));
+ }
+
+ result.params = join(result.params, {
+ name: paramDecl.name,
+ type: paramDecl.type.qualType,
+ annotations: paramAnnotations
+ });
+ }
+
+ // doc comment
+ const commentText = single(decl.inner, (attr => attr.kind === 'FullComment'));
+
+ if (commentText) {
+ const commentData = parseComment(`function:${decl.name}`, location, commentText, options);
+
+ if (result.params) {
+ if (options.strict && (!commentData.params || result.params.length > commentData.params.length)) {
+ throw new ParserError(`not all params are documented`, location);
+ }
+
+ if (options.strict && result.params.length < commentData.params.length) {
+ throw new ParserError(`additional params are documented`, location);
+ }
+ }
+
+ if (commentData.params) {
+ for (const i in result.params) {
+ let match;
+
+ for (const j in commentData.params) {
+ if (result.params[i].name === commentData.params[j].name) {
+ match = j;
+ break;
+ }
+ }
+
+ if (options.strict && (!match || match != i)) {
+ throw new ParserError(
+ `param documentation does not match param name '${result.params[i].name}'`,
+ location);
+ }
+
+ if (match) {
+ result.params[i] = { ...result.params[i], ...commentData.params[match] };
+ }
+ }
+ } else if (options.strict && result.params) {
+ throw new ParserError(`no params documented for ${decl.name}`, location);
+ }
+
+ if (options.strict && !commentData.returns && result.returns.type != 'void') {
+ throw new ParserError(`return information is not documented for ${decl.name}`, location);
+ }
+
+ result.returns = { ...result.returns, ...commentData.returns };
+
+ delete commentData.params;
+ delete commentData.returns;
+
+ result = { ...result, ...commentData };
+ }
+ else if (options.strict) {
+ throw new ParserError(`no documentation for function ${decl.name}`, location);
+ }
+
+ return result;
+}
+
+function parseEnum(location, decl, options) {
+ let result = {
+ kind: 'enum',
+ id: groupifyId(location, decl.id),
+ name: decl.name,
+ referenceName: decl.name ? `enum ${decl.name}` : undefined,
+ members: [ ],
+ comment: undefined,
+ location: {...location}
+ };
+
+ for (const member of decl.inner.filter(attr => attr.kind === 'EnumConstantDecl')) {
+ ensure('enum constant has a name', member.name);
+
+ const explicitValue = single(member.inner, (attr => attr.kind === 'ConstantExpr'));
+ const implicitValue = single(member.inner, (attr => attr.kind === 'ImplicitCastExpr'));
+ const commentText = single(member.inner, (attr => attr.kind === 'FullComment'));
+ const commentData = commentText ? parseComment(`enum:${decl.name}:member:${member.name}`, location, commentText, options) : undefined;
+
+ let value = undefined;
+
+ if (explicitValue && explicitValue.value) {
+ value = explicitValue.value;
+ } else if (implicitValue) {
+ const innerExplicit = single(implicitValue.inner, (attr => attr.kind === 'ConstantExpr'));
+
+ value = innerExplicit?.value;
+ }
+
+ result.members.push({
+ name: member.name,
+ value: value,
+ ...commentData
+ });
+ }
+
+ const commentText = single(decl.inner, (attr => attr.kind === 'FullComment'));
+
+ if (commentText) {
+ result = { ...result, ...parseComment(`enum:${decl.name}`, location, commentText, options) };
+ }
+
+ return result;
+}
+
+function resolveFunctionPointerTypedef(location, typedef) {
+ const signature = typedef.type.match(/^((?:const )?[^\s]+(?:\s+\*+)?)\s*\(\*\)\((.*)\)$/);
+ const [ , returnType, paramData ] = signature;
+ const params = paramData.split(/,\s+/);
+
+ if (options.strict && (!typedef.params || params.length != typedef.params.length)) {
+ throw new ParserError(`not all params are documented for function pointer typedef ${typedef.name}`, typedef.location);
+ }
+
+ if (!typedef.params) {
+ typedef.params = [ ];
+ }
+
+ for (const i in params) {
+ if (!typedef.params[i]) {
+ typedef.params[i] = { };
+ }
+
+ typedef.params[i].type = params[i];
+ }
+
+ if (typedef.returns === undefined && returnType === 'void') {
+ typedef.returns = { type: 'void' };
+ }
+ else if (typedef.returns !== undefined) {
+ typedef.returns.type = returnType;
+ }
+ else if (options.strict) {
+ throw new ParserError(`return type is not documented for function pointer typedef ${typedef.name}`, typedef.location);
+ }
+}
+
+function parseTypedef(location, decl, options) {
+ updateLocation(location, decl);
+
+ let result = {
+ kind: 'typedef',
+ id: groupifyId(location, decl.id),
+ name: ensureDefined('name', decl.name),
+ type: ensureDefined('type.qualType', decl.type.qualType),
+ targetId: undefined,
+ comment: undefined,
+ location: {...location}
+ };
+
+ const elaborated = single(decl.inner, (attr => attr.kind === 'ElaboratedType'));
+ if (elaborated !== undefined && elaborated.ownedTagDecl?.id) {
+ result.targetId = groupifyId(location, elaborated.ownedTagDecl?.id);
+ }
+
+ const commentText = single(decl.inner, (attr => attr.kind === 'FullComment'));
+
+ if (commentText) {
+ const commentData = parseComment(`typedef:${decl.name}`, location, commentText, options);
+ result = { ...result, ...commentData };
+ }
+
+ if (isFunctionPointer(result.type)) {
+ resolveFunctionPointerTypedef(location, result);
+ }
+
+ return result;
+}
+
+function parseStruct(location, decl, options) {
+ let result = {
+ kind: 'struct',
+ id: groupifyId(location, decl.id),
+ name: decl.name,
+ referenceName: decl.name ? `struct ${decl.name}` : undefined,
+ comment: undefined,
+ members: [ ],
+ location: {...location}
+ };
+
+ for (const member of decl.inner.filter(attr => attr.kind === 'FieldDecl')) {
+ let memberData = {
+ 'name': member.name,
+ 'type': member.type.qualType
+ };
+
+ const commentText = single(member.inner, (attr => attr.kind === 'FullComment'));
+
+ if (commentText) {
+ memberData = {...memberData, ...parseComment(`struct:${decl.name}:member:${member.name}`, location, commentText, options)};
+ }
+
+ result.members.push(memberData);
+ }
+
+ const commentText = single(decl.inner, (attr => attr.kind === 'FullComment'));
+
+ if (commentText) {
+ const commentData = parseComment(`struct:${decl.name}`, location, commentText, options);
+ result = { ...result, ...commentData };
+ }
+
+ return result;
+}
+
+function newResults() {
+ return {
+ all: [ ],
+ functions: [ ],
+ enums: [ ],
+ typedefs: [ ],
+ structs: [ ],
+ macros: [ ]
+ };
+};
+
+const returnMap = { };
+const paramMap = { };
+
+function simplifyType(givenType) {
+ let type = givenType;
+
+ if (type.startsWith('const ')) {
+ type = type.substring(6);
+ }
+
+ while (type.endsWith('*') && type !== 'void *' && type !== 'char *') {
+ type = type.substring(0, type.length - 1).trim();
+ }
+
+ if (!type.length) {
+ throw new Error(`invalid type: ${result.returns.extendedType || result.returns.type}`);
+ }
+
+ return type;
+}
+
+function createAndPush(arr, name, value) {
+ if (!arr[name]) {
+ arr[name] = [ ];
+ }
+
+ if (arr[name].length && arr[name][arr[name].length - 1] === value) {
+ return;
+ }
+
+ arr[name].push(value);
+}
+
+function addReturn(result) {
+ if (!result.returns) {
+ return;
+ }
+
+ let type = simplifyType(result.returns.extendedType?.type || result.returns.type);
+
+ createAndPush(returnMap, type, result.name);
+}
+
+function addParameters(result) {
+ if (!result.params) {
+ return;
+ }
+
+ for (const param of result.params) {
+ let type = param.extendedType?.type || param.type;
+
+ if (!type && options.strict) {
+ throw new Error(`parameter ${result.name} erroneously documented when not specified`);
+ } else if (!type) {
+ continue;
+ }
+
+ type = simplifyType(type);
+
+ if (param.direction === 'out') {
+ createAndPush(returnMap, type, result.name);
+ }
+ else {
+ createAndPush(paramMap, type, result.name);
+ }
+ }
+}
+
+function addResult(results, result) {
+ results[`${result.kind}s`].push(result);
+ results.all.push(result);
+
+ addReturn(result);
+ addParameters(result);
+}
+
+function mergeResults(one, two) {
+ const results = newResults();
+
+ for (const inst of Object.keys(results)) {
+ results[inst].push(...one[inst]);
+ results[inst].push(...two[inst]);
+ }
+
+ return results;
+}
+
+function getById(results, id) {
+ ensure("id is set", id !== undefined);
+ return single(results.all.all, (item => item.id === id), id);
+}
+
+function getByKindAndName(results, kind, name) {
+ ensure("kind is set", kind !== undefined);
+ ensure("name is set", name !== undefined);
+ return single(results.all[`${kind}s`], (item => item.name === name), name);
+}
+
+function getByName(results, name) {
+ ensure("name is set", name !== undefined);
+ return single(results.all.all, (item => item.name === name), name);
+}
+
+function isFunctionPointer(type) {
+ return type.match(/^(?:const )?[A-Za-z0-9_]+\s+\**\(\*/);
+}
+
+function resolveCallbacks(results) {
+ // expand callback types
+ for (const fn of results.all.functions) {
+ for (const param of fn.params || [ ]) {
+ const typedef = getByName(results, param.type);
+
+ if (typedef === undefined) {
+ continue;
+ }
+
+ param.referenceType = typedef.type;
+ }
+ }
+
+ for (const struct of results.all.structs) {
+ for (const member of struct.members) {
+ const typedef = getByKindAndName(results, 'typedef', member.type);
+
+ if (typedef === undefined) {
+ continue;
+ }
+
+ member.referenceType = typedef.type;
+ }
+ }
+}
+
+function trimBase(path) {
+ if (!path) {
+ return path;
+ }
+
+ for (const segment of [ 'git2', 'git' ]) {
+ const base = [ includeBase(path), segment ].join('/');
+
+ if (path.startsWith(base + '/')) {
+ return path.substr(base.length + 1);
+ }
+ }
+
+ throw new Error(`header path ${path} is not beneath standard root`);
+}
+
+function resolveTypedefs(results) {
+ for (const typedef of results.all.typedefs) {
+ let target = typedef.targetId ? getById(results, typedef.targetId) : undefined;
+
+ if (target) {
+ // update the target's preferred name with the short name
+ target.referenceName = typedef.name;
+
+ if (target.name === undefined) {
+ target.name = typedef.name;
+ }
+ }
+ else if (typedef.type.startsWith('struct ')) {
+ const path = typedef.location.file;
+
+ /*
+ * See if this is actually a typedef to a declared struct,
+ * then it is not actually opaque.
+ */
+ if (results.all.structs.filter(fn => fn.name === typedef.name).length > 0) {
+ typedef.opaque = false;
+ continue;
+ }
+
+ opaque = {
+ kind: 'struct',
+ id: groupifyId(typedef.location, typedef.id),
+ name: typedef.name,
+ referenceName: typedef.type,
+ opaque: true,
+ comment: typedef.comment,
+ location: typedef.location,
+ group: typedef.group
+ };
+
+ addResult(results.files[path], opaque);
+ addResult(results.all, opaque);
+ }
+ else if (isFunctionPointer(typedef.type) ||
+ typedef.type === 'int64_t' ||
+ typedef.type === 'uint64_t') {
+ // standard types
+ // TODO : make these a list
+ }
+ else {
+ typedef.kind = 'alias';
+ typedef.typedef = true;
+ }
+ }
+}
+
+function lastCommentIsGroupDelimiter(decls) {
+ if (decls[decls.length - 1].inner &&
+ decls[decls.length - 1].inner.length > 0) {
+ return lastCommentIsGroupDelimiter(decls[decls.length - 1].inner);
+ }
+
+ if (decls.length >= 2 &&
+ decls[decls.length - 1].kind.endsWith('Comment') &&
+ decls[decls.length - 2].kind.endsWith('Comment') &&
+ decls[decls.length - 2].text === '@' &&
+ decls[decls.length - 1].text === '{') {
+ return true;
+ }
+
+ return false;
+}
+
+async function parseAst(decls, options) {
+ const location = {
+ file: undefined,
+ line: undefined,
+ column: undefined
+ };
+
+ const results = newResults();
+
+ /* The first decl might have picked up the javadoc _for the file
+ * itself_ based on the file's structure. Remove it.
+ */
+ if (decls.length && decls[0].inner &&
+ decls[0].inner.length > 0 &&
+ decls[0].inner[0].kind === 'FullComment' &&
+ lastCommentIsGroupDelimiter(decls[0].inner[0].inner)) {
+ updateLocation(location, decls[0]);
+ delete decls[0].inner[0];
+ }
+
+ for (const decl of decls) {
+ updateLocation(location, decl);
+
+ ensureDefined('kind', decl.kind);
+
+ if (decl.kind === 'FunctionDecl') {
+ addResult(results, await parseFunction({...location}, decl, options));
+ }
+ else if (decl.kind === 'EnumDecl') {
+ addResult(results, parseEnum({...location}, decl, options));
+ }
+ else if (decl.kind === 'TypedefDecl') {
+ addResult(results, parseTypedef({...location}, decl, options));
+ }
+ else if (decl.kind === 'RecordDecl' && decl.tagUsed === 'struct') {
+ if (decl.completeDefinition) {
+ addResult(results, parseStruct({...location}, decl, options));
+ }
+ }
+ else if (decl.kind === 'VarDecl') {
+ if (options.strict) {
+ throw new Error(`unsupported variable declaration ${decl.kind}`);
+ }
+ }
+ else {
+ throw new Error(`unknown declaration type ${decl.kind}`);
+ }
+ }
+
+ return results;
+}
+
+function parseCommentForMacro(lines, macroIdx, name) {
+ let startIdx = -1, endIdx = 0;
+ const commentLines = [ ];
+
+ while (macroIdx > 0 &&
+ (line = lines[macroIdx - 1].trim()) &&
+ (line.trim() === '' ||
+ line.trim().endsWith('\\') ||
+ line.trim().match(/^#\s*if\s+/) ||
+ line.trim().startsWith('#ifdef ') ||
+ line.trim().startsWith('#ifndef ') ||
+ line.trim().startsWith('#elif ') ||
+ line.trim().startsWith('#else ') ||
+ line.trim().match(/^#\s*define\s+${name}\s+/))) {
+ macroIdx--;
+ }
+
+ if (macroIdx > 0 && lines[macroIdx - 1].trim().endsWith('*/')) {
+ endIdx = macroIdx - 1;
+ } else {
+ return '';
+ }
+
+ for (let i = endIdx; i >= 0; i--) {
+ if (lines[i].trim().startsWith('/**')) {
+ startIdx = i;
+ break;
+ }
+ else if (lines[i].trim().startsWith('/*')) {
+ break;
+ }
+ }
+
+ if (startIdx < 0) {
+ return '';
+ }
+
+ for (let i = startIdx; i <= endIdx; i++) {
+ let line = lines[i].trim();
+
+ if (i == startIdx) {
+ line = line.replace(/^\s*\/\*\*\s*/, '');
+ }
+
+ if (i === endIdx) {
+ line = line.replace(/\s*\*\/\s*$/, '');
+ }
+
+ if (i != startIdx) {
+ line = line.replace(/^\s*\*\s*/, '');
+ }
+
+ if (i == startIdx && (line === '@{' || line.startsWith("@{ "))) {
+ return '';
+ }
+
+ if (line === '') {
+ continue;
+ }
+
+ commentLines.push(line);
+ }
+
+ return commentLines.join(' ');
+}
+
+async function parseInfo(data) {
+ const fileHeader = data.match(/(.*)\n+GIT_BEGIN_DECL.*/s);
+ const headerLines = fileHeader ? fileHeader[1].split(/\n/) : [ ];
+
+ let lines = [ ];
+ const detailsLines = [ ];
+
+ let summary = undefined;
+ let endIdx = headerLines.length - 1;
+
+ for (let i = headerLines.length - 1; i >= 0; i--) {
+ let line = headerLines[i].trim();
+
+ if (line.match(/^\s*\*\/\s*$/)) {
+ endIdx = i;
+ }
+
+ if (line.match(/^\/\*\*(\s+.*)?$/)) {
+ lines = headerLines.slice(i + 1, endIdx);
+ break;
+ }
+ else if (line.match(/^\/\*(\s+.*)?$/)) {
+ break;
+ }
+ }
+
+ for (let line of lines) {
+ line = line.replace(/^\s\*/, '');
+ line = line.trim();
+
+ const comment = line.match(/^\@(\w+|{)\s*(.*)/);
+
+ if (comment) {
+ if (comment[1] === 'brief') {
+ summary = comment[2];
+ }
+ }
+ else if (line != '') {
+ detailsLines.push(line);
+ }
+ }
+
+ const details = detailsLines.length > 0 ? detailsLines.join("\n") : undefined;
+
+ return {
+ 'summary': summary,
+ 'details': details
+ };
+}
+
+async function parseMacros(path, data, options) {
+ const results = newResults();
+ const lines = data.split(/\r?\n/);
+
+ const macros = { };
+
+ for (let i = 0; i < lines.length; i++) {
+ const macro = lines[i].match(/^(\s*#\s*define\s+)([^\s\(]+)(\([^\)]+\))?\s*(.*)/);
+ let more = false;
+
+ if (!macro) {
+ continue;
+ }
+
+ let [ , prefix, name, args, value ] = macro;
+
+ if (name.startsWith('INCLUDE_') || name.startsWith('_INCLUDE_')) {
+ continue;
+ }
+
+ if (args) {
+ name = name + args;
+ }
+
+ if (macros[name]) {
+ continue;
+ }
+
+ macros[name] = true;
+
+ value = value.trim();
+
+ if (value.endsWith('\\')) {
+ value = value.substring(0, value.length - 1).trim();
+ more = true;
+ }
+
+ while (more) {
+ more = false;
+
+ let line = lines[++i];
+
+ if (line.endsWith('\\')) {
+ line = line.substring(0, line.length - 1);
+ more = true;
+ }
+
+ value += ' ' + line.trim();
+ }
+
+ const comment = parseCommentForMacro(lines, i, name);
+ const location = {
+ file: path,
+ line: i + 1,
+ column: prefix.length + 1,
+ };
+
+ if (options.strict && !comment) {
+ throw new ParserError(`no comment for ${name}`, location);
+ }
+
+ addResult(results, {
+ kind: 'macro',
+ name: name,
+ location: location,
+ value: value,
+ comment: comment,
+ });
+ }
+
+ return results;
+}
+
+function resolveUngroupedTypes(results) {
+ const groups = { };
+
+ for (const result of results.all.all) {
+ result.group = result.location.file;
+
+ if (result.group.endsWith('.h')) {
+ result.group = result.group.substring(0, result.group.length - 2);
+ groups[result.group] = true;
+ }
+ }
+
+ for (const result of results.all.all) {
+ if (result.location.file === 'types.h' &&
+ result.name.startsWith('git_')) {
+ let possibleGroup = result.name.substring(4);
+
+ do {
+ if (groupMap[possibleGroup]) {
+ result.group = groupMap[possibleGroup];
+ break;
+ }
+ else if (groups[possibleGroup]) {
+ result.group = possibleGroup;
+ break;
+ }
+ else if (groups[`sys/${possibleGroup}`]) {
+ result.group = `sys/${possibleGroup}`;
+ break;
+ }
+
+ let match = possibleGroup.match(/^(.*)_[^_]+$/);
+
+ if (!match) {
+ break;
+ }
+
+ possibleGroup = match[1];
+ } while (true);
+ }
+ }
+}
+
+function resolveReturns(results) {
+ for (const result of results.all.all) {
+ result.returnedBy = returnMap[result.name];
+ }
+}
+
+function resolveParameters(results) {
+ for (const result of results.all.all) {
+ result.parameterTo = paramMap[result.name];
+ }
+}
+
+async function parseHeaders(sourcePath, options) {
+ const results = { all: newResults(), files: { } };
+
+ for (const fullPath of await headerPaths(sourcePath)) {
+ const path = trimPath(sourcePath, fullPath);
+ const fileContents = await readFile(fullPath);
+
+ const ast = await parseAst(await readAst(fullPath, options), options);
+ const macros = await parseMacros(path, fileContents, options);
+ const info = await parseInfo(fileContents);
+
+ const filedata = mergeResults(ast, macros);
+
+ filedata['info'] = info;
+
+ results.files[path] = filedata;
+ results.all = mergeResults(results.all, filedata);
+ }
+
+ resolveCallbacks(results);
+ resolveTypedefs(results);
+
+ resolveUngroupedTypes(results);
+
+ resolveReturns(results);
+ resolveParameters(results);
+
+ return results;
+}
+
+function isFunctionPointer(type) {
+ return type.match(/^(const\s+)?[A-Za-z0-9_]+\s+\*?\(\*/);
+}
+function isEnum(type) {
+ return type.match(/^enum\s+/);
+}
+function isStruct(type) {
+ return type.match(/^struct\s+/);
+}
+
+/*
+ * We keep the `all` arrays around so that we can lookup; drop them
+ * for the end result.
+ */
+function simplify(results) {
+ const simplified = {
+ 'info': { },
+ 'groups': { }
+ };
+
+ results.all.all.sort((a, b) => {
+ if (!a.group) {
+ throw new Error(`missing group for api ${a.name}`);
+ }
+
+ if (!b.group) {
+ throw new Error(`missing group for api ${b.name}`);
+ }
+
+ const aSystem = a.group.startsWith('sys/');
+ const aName = aSystem ? a.group.substr(4) : a.group;
+
+ const bSystem = b.group.startsWith('sys/');
+ const bName = bSystem ? b.group.substr(4) : b.group;
+
+ if (aName !== bName) {
+ return aName.localeCompare(bName);
+ }
+
+ if (aSystem !== bSystem) {
+ return aSystem ? 1 : -1;
+ }
+
+ if (a.location.file !== b.location.file) {
+ return a.location.file.localeCompare(b.location.file);
+ }
+
+ if (a.location.line !== b.location.line) {
+ return a.location.line - b.location.line;
+ }
+
+ return a.location.column - b.location.column;
+ });
+
+ for (const api of results.all.all) {
+ delete api.id;
+ delete api.targetId;
+
+ const type = api.referenceType || api.type;
+
+ if (api.kind === 'typedef' && isFunctionPointer(type)) {
+ api.kind = 'callback';
+ api.typedef = true;
+ }
+ else if (api.kind === 'typedef' && (!isEnum(type) && !isStruct(type))) {
+ api.kind = 'alias';
+ api.typedef = true;
+ }
+ else if (api.kind === 'typedef') {
+ continue;
+ }
+
+ if (apiIgnoreList.includes(api.name)) {
+ continue;
+ }
+
+ // TODO: do a warning where there's a redefinition of a symbol
+ // There are occasions where we redefine a symbol. First, our
+ // parser is not smart enough to know #ifdef's around #define's.
+ // But also we declared `git_email_create_from_diff` twice (in
+ // email.h and sys/email.h) for several releases.
+
+ if (!simplified['groups'][api.group]) {
+ simplified['groups'][api.group] = { };
+ simplified['groups'][api.group].apis = { };
+ simplified['groups'][api.group].info = results.files[`${api.group}.h`].info;
+ }
+
+ simplified['groups'][api.group].apis[api.name] = api;
+ }
+
+ return simplified;
+}
+
+function joinArguments(next, previous) {
+ if (previous) {
+ return [...previous, next];
+ }
+ return [next];
+}
+
+async function findIncludes() {
+ const includes = [ ];
+
+ for (const possible of defaultIncludes) {
+ const includeFile = `${docsPath}/include/git2/${possible}`;
+
+ try {
+ await fs.stat(includeFile);
+ includes.push(`git2/${possible}`);
+ }
+ catch (e) {
+ if (e?.code !== 'ENOENT') {
+ throw e;
+ }
+ }
+ }
+
+ return includes;
+}
+
+async function execGit(path, command) {
+ const process = child_process.spawn('git', command, { cwd: path });
+ const chunks = [ ];
+
+ return new Promise((resolve, reject) => {
+ process.stdout.on('data', (chunk) => {
+ chunks.push(chunk);
+ });
+ process.on('close', (code) => {
+ resolve(code == 0 ? Buffer.concat(chunks).toString() : undefined);
+ });
+ process.on('error', function (err) {
+ reject(err);
+ });
+ });
+}
+
+async function readMetadata(path) {
+ let commit = await execGit(path, [ 'rev-parse', 'HEAD' ]);
+
+ if (commit) {
+ commit = commit.trimEnd();
+ }
+
+ let version = await execGit(path, [ 'describe', '--tags', '--exact' ]);
+
+ if (!version) {
+ const ref = await execGit(path, [ 'describe', '--all', '--exact' ]);
+
+ if (ref && ref.startsWith('heads/')) {
+ version = ref.substr(6);
+ }
+ }
+
+ if (version) {
+ version = version.trimEnd();
+ }
+
+ return {
+ 'version': version,
+ 'commit': commit
+ };
+}
+
+program.option('--output ')
+ .option('--include ', undefined, joinArguments)
+ .option('--no-includes')
+ .option('--deprecate-hard')
+ .option('--validate-only')
+ .option('--strict');
+program.parse();
+
+const options = program.opts();
+
+if (program.args.length != 1) {
+ console.error(`usage: ${path.basename(process.argv[1])} docs`);
+ process.exit(1);
+}
+
+const docsPath = program.args[0];
+
+if (options['include'] && !options['includes']) {
+ console.error(`usage: cannot combined --include with --no-include`);
+ process.exit(1);
+}
+
+(async () => {
+ try {
+ if (options['include']) {
+ includes = options['include'];
+ }
+ else if (!options['includes']) {
+ includes = [ ];
+ }
+ else {
+ includes = await findIncludes();
+ }
+
+ const parseOptions = {
+ deprecateHard: options.deprecateHard || false,
+ includeFiles: includes,
+ strict: options.strict || false
+ };
+
+ const results = await parseHeaders(docsPath, parseOptions);
+ const metadata = await readMetadata(docsPath);
+
+ const simplified = simplify(results);
+ simplified['info'] = metadata;
+
+ if (!options.validateOnly) {
+ console.log(JSON.stringify(simplified, null, 2));
+ }
+ } catch (e) {
+ console.error(e);
+ process.exit(1);
+ }
+})();
diff --git a/script/api-docs/docs-generator.js b/script/api-docs/docs-generator.js
new file mode 100755
index 00000000000..dcf25e57311
--- /dev/null
+++ b/script/api-docs/docs-generator.js
@@ -0,0 +1,1417 @@
+#!/usr/bin/env node
+
+const markdownit = require('markdown-it');
+const { program } = require('commander');
+
+const path = require('node:path');
+const fs = require('node:fs/promises');
+const process = require('node:process');
+
+const githubPath = 'https://github.com/libgit2/libgit2';
+
+const linkPrefix = '/docs/reference';
+
+const projectTitle = 'libgit2';
+const includePath = 'include/git2';
+
+const fileDenylist = [ 'stdint.h' ];
+const showVersions = true;
+
+const defaultBranch = 'main';
+
+const markdown = markdownit();
+const markdownDefaults = {
+ code_inline: markdown.renderer.rules.code_inline
+};
+markdown.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
+ const version = env.__version || defaultBranch;
+
+ const code = tokens[idx].content;
+ const text = `${nowrap(sanitize(tokens[idx].content))}`;
+ const link = linkForCode(version, code, text);
+
+ return link ? link : text;
+};
+
+// globals
+const apiData = { };
+const versions = [ ];
+const versionDeltas = { };
+
+function produceVersionPicker(version, classes, cb) {
+ let content = "";
+
+ if (!showVersions) {
+ return content;
+ }
+
+ content += `
\n`;
+
+ for (const param of api.params) {
+ let direction = param.direction || 'in';
+ direction = direction.charAt(0).toUpperCase() + direction.slice(1);
+
+ if (!param.type && options.strict) {
+ throw new Error(`param ${param.name} has no type for function ${api.name}`);
+ }
+ else if (!param.type) {
+ continue;
+ }
+
+ content += `