New upstream version 1.7.1+ds

This commit is contained in:
Timo Röhling 2023-09-08 10:34:48 +02:00
parent f1fdcff351
commit d11d1f257e
356 changed files with 9281 additions and 2539 deletions

45
.github/actions/run-build/action.yml vendored Normal file
View File

@ -0,0 +1,45 @@
# Run a build step in a container or directly on the Actions runner
name: Run Build Step
description: Run a build step in a container or directly on the Actions runner
inputs:
command:
description: Command to run
required: true
type: string
container:
description: Optional container to run in
type: string
container-version:
description: Version of the container to run
type: string
runs:
using: 'composite'
steps:
- run: |
if [ -n "${{ inputs.container }}" ]; then
docker run \
--rm \
--user "$(id -u):$(id -g)" \
-v "$(pwd)/source:/home/libgit2/source" \
-v "$(pwd)/build:/home/libgit2/build" \
-w /home/libgit2 \
-e ASAN_SYMBOLIZER_PATH \
-e CC \
-e CFLAGS \
-e CMAKE_GENERATOR \
-e CMAKE_OPTIONS \
-e GITTEST_NEGOTIATE_PASSWORD \
-e GITTEST_FLAKY_STAT \
-e PKG_CONFIG_PATH \
-e SKIP_NEGOTIATE_TESTS \
-e SKIP_SSH_TESTS \
-e TSAN_OPTIONS \
-e UBSAN_OPTIONS \
${{ inputs.container-version }} \
/bin/bash -c "${{ inputs.command }}"
else
${{ inputs.command }}
fi
shell: bash

6
.github/release.yml vendored
View File

@ -3,6 +3,9 @@ changelog:
- title: New features
labels:
- feature
- title: Performance improvements
labels:
- performance
- title: Bug fixes
labels:
- bug
@ -18,6 +21,9 @@ changelog:
- title: Documentation improvements
labels:
- documentation
- title: Git compatibility fixes
labels:
- git compatibility
- title: Other changes
labels:
- '*'

72
.github/workflows/build-containers.yml vendored Normal file
View File

@ -0,0 +1,72 @@
# Generate the containers that we use for builds.
name: Build Containers
on:
workflow_call:
env:
docker-registry: ghcr.io
docker-config-path: source/ci/docker
jobs:
# Build the docker container images that we will use for our Linux
# builds. This will identify the last commit to the repository that
# updated the docker images, and try to download the image tagged with
# that sha. If it does not exist, we'll do a docker build and push
# the image up to GitHub Packages for the actual CI/CD runs. We tag
# with both the sha and "latest" so that the subsequent runs need not
# know the sha. Only do this on CI builds (when the event is a "push")
# because PR builds from forks lack permission to write packages.
containers:
strategy:
matrix:
container:
- name: xenial
- name: bionic
- name: focal
- name: docurium
- name: bionic-x86
dockerfile: bionic
base: multiarch/ubuntu-core:x86-bionic
qemu: true
- name: bionic-arm32
dockerfile: bionic
base: multiarch/ubuntu-core:armhf-bionic
qemu: true
- name: bionic-arm64
dockerfile: bionic
base: multiarch/ubuntu-core:arm64-bionic
qemu: true
- name: centos7
- name: centos8
runs-on: ubuntu-latest
name: "Create container: ${{ matrix.container.name }}"
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
path: source
fetch-depth: 0
if: github.event_name != 'pull_request'
- name: Setup QEMU
run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
if: matrix.container.qemu == true
- name: Download existing container
run: |
"${{ github.workspace }}/source/ci/getcontainer.sh" "${{ matrix.container.name }}" "${{ matrix.container.dockerfile }}"
env:
DOCKER_REGISTRY: ${{ env.docker-registry }}
GITHUB_TOKEN: ${{ secrets.github_token }}
working-directory: ${{ env.docker-config-path }}
if: github.event_name != 'pull_request'
- name: Build and publish image
run: |
if [ "${{ matrix.container.base }}" != "" ]; then
BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
fi
docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
docker tag ${{ env.docker-registry-container-sha }} ${{ env.docker-registry-container-latest }}
docker push ${{ env.docker-registry-container-sha }}
docker push ${{ env.docker-registry-container-latest }}
working-directory: ${{ env.docker-config-path }}
if: github.event_name != 'pull_request' && env.docker-container-exists != 'true'

View File

@ -14,67 +14,8 @@ env:
docker-config-path: source/ci/docker
jobs:
# Build the docker container images that we will use for our Linux
# builds. This will identify the last commit to the repository that
# updated the docker images, and try to download the image tagged with
# that sha. If it does not exist, we'll do a docker build and push
# the image up to GitHub Packages for the actual CI/CD runs. We tag
# with both the sha and "latest" so that the subsequent runs need not
# know the sha. Only do this on CI builds (when the event is a "push")
# because PR builds from forks lack permission to write packages.
containers:
strategy:
matrix:
container:
- name: xenial
- name: bionic
- name: focal
- name: docurium
- name: bionic-x86
dockerfile: bionic
base: multiarch/ubuntu-core:x86-bionic
qemu: true
- name: bionic-arm32
dockerfile: bionic
base: multiarch/ubuntu-core:armhf-bionic
qemu: true
- name: bionic-arm64
dockerfile: bionic
base: multiarch/ubuntu-core:arm64-bionic
qemu: true
- name: centos7
- name: centos8
runs-on: ubuntu-latest
name: "Create container: ${{ matrix.container.name }}"
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
path: source
fetch-depth: 0
if: github.event_name != 'pull_request'
- name: Setup QEMU
run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
if: matrix.container.qemu == true
- name: Download existing container
run: |
"${{ github.workspace }}/source/ci/getcontainer.sh" "${{ matrix.container.name }}" "${{ matrix.container.dockerfile }}"
env:
DOCKER_REGISTRY: ${{ env.docker-registry }}
GITHUB_TOKEN: ${{ secrets.github_token }}
working-directory: ${{ env.docker-config-path }}
if: github.event_name != 'pull_request'
- name: Build and publish image
run: |
if [ "${{ matrix.container.base }}" != "" ]; then
BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
fi
docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
docker tag ${{ env.docker-registry-container-sha }} ${{ env.docker-registry-container-latest }}
docker push ${{ env.docker-registry-container-sha }}
docker push ${{ env.docker-registry-container-latest }}
working-directory: ${{ env.docker-config-path }}
if: github.event_name != 'pull_request' && env.docker-container-exists != 'true'
uses: ./.github/workflows/build-containers.yml
# Run our CI/CD builds. We build a matrix with the various build targets
# and their details. Then we build either in a docker container (Linux)
@ -130,19 +71,19 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
setup-script: osx
- name: "Windows (amd64, Visual Studio)"
- name: "Windows (amd64, Visual Studio, Schannel)"
id: windows-amd64-vs
os: windows-2019
setup-script: win32
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
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
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio)"
- name: "Windows (x86, Visual Studio, WinHTTP)"
id: windows-x86-vs
os: windows-2019
setup-script: win32
@ -154,7 +95,7 @@ jobs:
BUILD_TEMP: D:\Temp
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw)"
- name: "Windows (amd64, mingw, WinHTTP)"
id: windows-amd64-mingw
os: windows-2019
setup-script: mingw
@ -166,14 +107,14 @@ jobs:
BUILD_PATH: D:\Temp\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw)"
- name: "Windows (x86, mingw, Schannel)"
id: windows-x86-mingw
os: windows-2019
setup-script: mingw
env:
ARCH: x86
CMAKE_GENERATOR: MinGW Makefiles
CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel
BUILD_TEMP: D:\Temp
BUILD_PATH: D:\Temp\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
SKIP_SSH_TESTS: true
@ -286,43 +227,20 @@ jobs:
docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
working-directory: ${{ env.docker-config-path }}
if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
- name: Build and test
run: |
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
export GITTEST_GITHUB_SSH_KEY="${{ secrets.GITTEST_GITHUB_SSH_KEY }}"
export GITTEST_GITHUB_SSH_PUBKEY="${{ secrets.GITTEST_GITHUB_SSH_PUBKEY }}"
export GITTEST_GITHUB_SSH_PASSPHRASE="${{ secrets.GITTEST_GITHUB_SSH_PASSPHRASE }}"
export GITTEST_GITHUB_SSH_REMOTE_HOSTKEY="${{ secrets.GITTEST_GITHUB_SSH_REMOTE_HOSTKEY }}"
if [ -n "${{ matrix.platform.container.name }}" ]; then
mkdir build
docker run \
--rm \
--user "$(id -u):$(id -g)" \
-v "$(pwd)/source:/home/libgit2/source" \
-v "$(pwd)/build:/home/libgit2/build" \
-w /home/libgit2 \
-e ASAN_SYMBOLIZER_PATH \
-e CC \
-e CFLAGS \
-e CMAKE_GENERATOR \
-e CMAKE_OPTIONS \
-e GITTEST_NEGOTIATE_PASSWORD \
-e GITTEST_FLAKY_STAT \
-e PKG_CONFIG_PATH \
-e SKIP_NEGOTIATE_TESTS \
-e SKIP_SSH_TESTS \
-e TSAN_OPTIONS \
-e UBSAN_OPTIONS \
${{ env.docker-registry-container-sha }} \
/bin/bash -c "cd build && ../source/ci/build.sh && ../source/ci/test.sh"
else
mkdir build
cd build
../source/ci/build.sh
../source/ci/test.sh
fi
shell: bash
- name: Prepare build
run: mkdir build
- name: Build
uses: ./source/.github/actions/run-build
with:
command: cd build && ../source/ci/build.sh
container: ${{ matrix.platform.container.name }}
container-version: ${{ env.docker-registry-container-sha }}
- name: Test
uses: ./source/.github/actions/run-build
with:
command: cd build && ../source/ci/test.sh
container: ${{ matrix.platform.container.name }}
container-version: ${{ env.docker-registry-container-sha }}
- name: Upload test results
uses: actions/upload-artifact@v3
if: success() || failure()

View File

@ -162,32 +162,39 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
setup-script: osx
- name: "Windows (amd64, Visual Studio)"
- name: "Windows (amd64, Visual Studio, WinHTTP)"
os: windows-2019
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=WinHTTP
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (no mmap)"
os: windows-2019
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
CFLAGS: -DNO_MMAP
CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio)"
- name: "Windows (x86, Visual Studio, WinHTTP)"
os: windows-2019
env:
ARCH: x86
CMAKE_GENERATOR: Visual Studio 16 2019
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=WinHTTP -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw)"
- name: "Windows (amd64, Visual Studio, Schannel)"
os: windows-2019
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio, Schannel)"
os: windows-2019
env:
ARCH: x86
CMAKE_GENERATOR: Visual Studio 16 2019
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel -DUSE_BUNDLED_ZLIB=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw, WinHTTP)"
os: windows-2019
setup-script: mingw
env:
@ -198,17 +205,26 @@ jobs:
BUILD_PATH: D:\Temp\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw)"
- name: "Windows (x86, mingw, Schannel)"
os: windows-2019
setup-script: mingw
env:
ARCH: x86
CMAKE_GENERATOR: MinGW Makefiles
CMAKE_OPTIONS: -DDEPRECATE_HARD=ON
CMAKE_OPTIONS: -DDEPRECATE_HARD=ON -DUSE_HTTPS=Schannel
BUILD_TEMP: D:\Temp
BUILD_PATH: D:\Temp\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (no mmap)"
os: windows-2019
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
CFLAGS: -DNO_MMAP
CMAKE_OPTIONS: -A x64 -DDEPRECATE_HARD=ON
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Linux (Bionic, GCC, dynamically-loaded OpenSSL)"
container:
name: bionic
@ -324,35 +340,20 @@ jobs:
run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ env.dockerfile }} .
working-directory: ${{ env.docker-config-path }}
if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
- name: Build and test
run: |
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
if [ -n "${{ matrix.platform.container.name }}" ]; then
docker run \
--rm \
--user libgit2:libgit2 \
-v "$(pwd)/source:/home/libgit2/source" \
-w /home/libgit2 \
-e ASAN_SYMBOLIZER_PATH \
-e CC \
-e CFLAGS \
-e CMAKE_GENERATOR \
-e CMAKE_OPTIONS \
-e GITTEST_NEGOTIATE_PASSWORD \
-e GITTEST_FLAKY_STAT \
-e PKG_CONFIG_PATH \
-e SKIP_NEGOTIATE_TESTS \
-e SKIP_SSH_TESTS \
-e TSAN_OPTIONS \
${{ env.docker-registry-container-sha }} \
/bin/bash -c "mkdir build && cd build && ../source/ci/build.sh && ../source/ci/test.sh"
else
mkdir build && cd build
../source/ci/build.sh
../source/ci/test.sh
fi
shell: bash
- name: Prepare build
run: mkdir build
- name: Build
uses: ./source/.github/actions/run-build
with:
command: cd build && ../source/ci/build.sh
container: ${{ matrix.platform.container.name }}
container-version: ${{ env.docker-registry-container-sha }}
- name: Test
uses: ./source/.github/actions/run-build
with:
command: cd build && ../source/ci/test.sh
container: ${{ matrix.platform.container.name }}
container-version: ${{ env.docker-registry-container-sha }}
coverity:
# Only run scheduled workflows on the main repository; prevents people

View File

@ -6,7 +6,7 @@
cmake_minimum_required(VERSION 3.5.1)
project(libgit2 VERSION "1.6.4" LANGUAGES C)
project(libgit2 VERSION "1.7.1" LANGUAGES C)
# Add find modules to the path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
@ -36,6 +36,7 @@ option(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(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_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.")
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)
@ -82,12 +83,6 @@ if(MSVC)
option(WIN32_LEAKCHECK "Enable leak reporting via crtdbg" OFF)
endif()
if(WIN32)
# By default, libgit2 is built with WinHTTP. To use the built-in
# HTTP transport, invoke CMake with the "-DUSE_WINHTTP=OFF" argument.
option(USE_WINHTTP "Use Win32 WinHTTP routines" ON)
endif()
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()
@ -99,7 +94,7 @@ include(CheckLibraryExists)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckStructHasMember)
include(CheckPrototypeDefinition)
include(CheckPrototypeDefinitionSafe)
include(AddCFlagIfSupported)
include(FindPkgLibraries)
include(FindThreads)

View File

@ -4,8 +4,8 @@ libgit2 - the Git linkable library
| Build Status | |
| ------------ | - |
| **main** branch CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush) |
| **v1.7 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.7&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.7) |
| **v1.6 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.6&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.6) |
| **v1.5 branch** CI builds | [![CI Build](https://github.com/libgit2/libgit2/workflows/CI%20Build/badge.svg?branch=maint%2Fv1.5&event=push)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.5) |
| **Nightly** builds | [![Nightly Build](https://github.com/libgit2/libgit2/workflows/Nightly%20Build/badge.svg)](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22Nightly+Build%22) [![Coverity Scan Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) |
`libgit2` is a portable, pure C implementation of the Git core methods

View File

@ -171,7 +171,7 @@ if [ -z "$SKIP_PROXY_TESTS" ]; then
fi
if [ -z "$SKIP_NTLM_TESTS" -o -z "$SKIP_ONLINE_TESTS" ]; then
curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.5.1/poxygit-0.5.1.jar >poxygit.jar
curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.6.0/poxygit-0.6.0.jar >poxygit.jar
echo "Starting HTTP server..."
HTTP_DIR=`mktemp -d ${TMPDIR}/http.XXXXXXXX`
@ -271,9 +271,13 @@ if [ -z "$SKIP_ONLINE_TESTS" ]; then
export GITTEST_REMOTE_REDIRECT_INITIAL="http://localhost:9000/initial-redirect/libgit2/TestGitRepository"
export GITTEST_REMOTE_REDIRECT_SUBSEQUENT="http://localhost:9000/subsequent-redirect/libgit2/TestGitRepository"
export GITTEST_REMOTE_SPEED_SLOW="http://localhost:9000/speed-9600/test.git"
export GITTEST_REMOTE_SPEED_TIMESOUT="http://localhost:9000/speed-0.5/test.git"
run_test online
unset GITTEST_REMOTE_REDIRECT_INITIAL
unset GITTEST_REMOTE_REDIRECT_SUBSEQUENT
unset GITTEST_REMOTE_SPEED_SLOW
unset GITTEST_REMOTE_SPEED_TIMESOUT
# Run the online tests that immutably change global state separately
# to avoid polluting the test environment.

View File

@ -0,0 +1,16 @@
include(CheckPrototypeDefinition)
function(check_prototype_definition_safe function prototype return header variable)
# temporarily save CMAKE_C_FLAGS and disable warnings about unused
# unused functions and parameters, otherwise they will always fail
# if ENABLE_WERROR is on
set(SAVED_CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
disable_warnings(unused-function)
disable_warnings(unused-parameter)
check_prototype_definition("${function}" "${prototype}" "${return}" "${header}" "${variable}")
# restore CMAKE_C_FLAGS
set(CMAKE_C_FLAGS "${SAVED_CMAKE_C_FLAGS}")
endfunction()

View File

@ -29,7 +29,7 @@ if(USE_GSSAPI)
list(APPEND LIBGIT2_SYSTEM_LIBS ${GSSFRAMEWORK_LIBRARIES})
set(GIT_GSSFRAMEWORK 1)
add_feature_info(SPNEGO GIT_GSSFRAMEWORK "SPNEGO authentication support (${USE_GSSAPI})")
add_feature_info(GSSAPI GIT_GSSFRAMEWORK "GSSAPI support for SPNEGO authentication (${USE_GSSAPI})")
elseif(USE_GSSAPI STREQUAL "gssapi")
if(NOT GSSAPI_FOUND)
message(FATAL_ERROR "Asked for gssapi GSS backend, but it wasn't found")
@ -38,11 +38,11 @@ if(USE_GSSAPI)
list(APPEND LIBGIT2_SYSTEM_LIBS ${GSSAPI_LIBRARIES})
set(GIT_GSSAPI 1)
add_feature_info(SPNEGO GIT_GSSAPI "SPNEGO authentication support (${USE_GSSAPI})")
add_feature_info(GSSAPI GIT_GSSAPI "GSSAPI support for SPNEGO authentication (${USE_GSSAPI})")
else()
message(FATAL_ERROR "Asked for backend ${USE_GSSAPI} but it wasn't found")
endif()
else()
set(GIT_GSSAPI 0)
add_feature_info(SPNEGO NO "SPNEGO authentication support")
add_feature_info(GSSAPI NO "GSSAPI support for SPNEGO authentication")
endif()

View File

@ -19,7 +19,7 @@ if(USE_HTTPS)
message(STATUS "Security framework is too old, falling back to OpenSSL")
set(USE_HTTPS "OpenSSL")
endif()
elseif(USE_WINHTTP)
elseif(WIN32)
set(USE_HTTPS "WinHTTP")
elseif(OPENSSL_FOUND)
set(USE_HTTPS "OpenSSL")
@ -106,8 +106,27 @@ if(USE_HTTPS)
# https://github.com/ARMmbed/mbedtls/issues/228
# For now, pass its link flags as our own
list(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
elseif(USE_HTTPS STREQUAL "Schannel")
set(GIT_SCHANNEL 1)
list(APPEND LIBGIT2_SYSTEM_LIBS "rpcrt4" "crypt32" "ole32" "secur32")
list(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32" "-lsecur32")
elseif(USE_HTTPS STREQUAL "WinHTTP")
# WinHTTP setup was handled in the WinHTTP-specific block above
set(GIT_WINHTTP 1)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
if(MINGW)
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/winhttp" "${PROJECT_BINARY_DIR}/deps/winhttp")
list(APPEND LIBGIT2_SYSTEM_LIBS winhttp)
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/winhttp")
else()
list(APPEND LIBGIT2_SYSTEM_LIBS "winhttp")
list(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
endif()
list(APPEND LIBGIT2_SYSTEM_LIBS "rpcrt4" "crypt32" "ole32" "secur32")
list(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32" "-lsecur32")
elseif(USE_HTTPS STREQUAL "OpenSSL-Dynamic")
set(GIT_OPENSSL 1)
set(GIT_OPENSSL_DYNAMIC 1)

View File

@ -13,6 +13,8 @@ if(USE_SHA1 STREQUAL ON)
elseif(USE_SHA1 STREQUAL "HTTPS")
if(USE_HTTPS STREQUAL "SecureTransport")
set(USE_SHA1 "CommonCrypto")
elseif(USE_HTTPS STREQUAL "Schannel")
set(USE_SHA1 "Win32")
elseif(USE_HTTPS STREQUAL "WinHTTP")
set(USE_SHA1 "Win32")
elseif(USE_HTTPS)
@ -51,6 +53,8 @@ endif()
if(USE_SHA256 STREQUAL "HTTPS")
if(USE_HTTPS STREQUAL "SecureTransport")
set(USE_SHA256 "CommonCrypto")
elseif(USE_HTTPS STREQUAL "Schannel")
set(USE_SHA256 "Win32")
elseif(USE_HTTPS STREQUAL "WinHTTP")
set(USE_SHA256 "Win32")
elseif(USE_HTTPS)

View File

@ -1,17 +0,0 @@
if(WIN32 AND USE_WINHTTP)
set(GIT_WINHTTP 1)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
if(MINGW)
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/winhttp" "${PROJECT_BINARY_DIR}/deps/winhttp")
list(APPEND LIBGIT2_SYSTEM_LIBS winhttp)
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/winhttp")
else()
list(APPEND LIBGIT2_SYSTEM_LIBS "winhttp")
list(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
endif()
list(APPEND LIBGIT2_SYSTEM_LIBS "rpcrt4" "crypt32" "ole32")
list(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
endif()

9
cmake/SelectXdiff.cmake Normal file
View File

@ -0,0 +1,9 @@
# Optional external dependency: xdiff
if(USE_XDIFF STREQUAL "system")
message(FATAL_ERROR "external/system xdiff is not yet supported")
else()
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/xdiff" "${PROJECT_BINARY_DIR}/deps/xdiff")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/xdiff")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$<TARGET_OBJECTS:xdiff>")
add_feature_info(xdiff ON "xdiff support (bundled)")
endif()

28
deps/xdiff/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,28 @@
file(GLOB SRC_XDIFF "*.c" "*.h")
list(SORT SRC_XDIFF)
add_library(xdiff OBJECT ${SRC_XDIFF})
target_include_directories(xdiff SYSTEM PRIVATE
"${PROJECT_SOURCE_DIR}/include"
"${PROJECT_SOURCE_DIR}/src/util"
"${PROJECT_BINARY_DIR}/src/util"
${LIBGIT2_SYSTEM_INCLUDES}
${LIBGIT2_DEPENDENCY_INCLUDES})
# the xdiff dependency is not (yet) warning-free, disable warnings
# as errors for the xdiff sources until we've sorted them out
if(MSVC)
set_source_files_properties(xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xemit.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xutils.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
else()
set_source_files_properties(xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
endif()

View File

@ -27,11 +27,14 @@
# endif
#endif
#define XDL_UNUSED GIT_UNUSED_ARG
#define xdl_malloc(x) git__malloc(x)
#define xdl_calloc(n, sz) git__calloc(n, sz)
#define xdl_free(ptr) git__free(ptr)
#define xdl_realloc(ptr, x) git__realloc(ptr, x)
#define XDL_BUG(msg) GIT_ASSERT(msg)
#define XDL_BUG(msg) GIT_ASSERT(!msg)
#define xdl_regex_t git_regexp
#define xdl_regmatch_t git_regmatch

View File

@ -315,16 +315,19 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
long *kvd, *kvdf, *kvdb;
xdalgoenv_t xenv;
diffdata_t dd1, dd2;
int res;
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)
return xdl_do_patience_diff(mf1, mf2, xpp, xe);
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0)
return -1;
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF) {
res = xdl_do_patience_diff(xpp, xe);
goto out;
}
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) {
res = xdl_do_histogram_diff(xpp, xe);
goto out;
}
/*
@ -334,7 +337,7 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
* One is to store the forward path and one to store the backward path.
*/
ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) {
if (!XDL_ALLOC_ARRAY(kvd, 2 * ndiags + 2)) {
xdl_free_env(xe);
return -1;
@ -359,17 +362,15 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
dd2.rchg = xe->xdf2.rchg;
dd2.rindex = xe->xdf2.rindex;
if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) {
xdl_free(kvd);
xdl_free_env(xe);
return -1;
}
res = xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0,
&xenv);
xdl_free(kvd);
out:
if (res < 0)
xdl_free_env(xe);
return 0;
return res;
}
@ -972,7 +973,7 @@ void xdl_free_script(xdchange_t *xscr) {
}
}
static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
static int xdl_call_hunk_func(xdfenv_t *xe XDL_UNUSED, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg)
{
xdchange_t *xch, *xche;

View File

@ -56,9 +56,7 @@ int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr);
void xdl_free_script(xdchange_t *xscr);
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg);
int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdfenv_t *env);
int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdfenv_t *env);
int xdl_do_patience_diff(xpparam_t const *xpp, xdfenv_t *env);
int xdl_do_histogram_diff(xpparam_t const *xpp, xdfenv_t *env);
#endif /* #if !defined(XDIFFI_H) */

View File

@ -65,7 +65,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
*xscr = xch;
}
if (*xscr == NULL)
if (!*xscr)
return NULL;
lxch = *xscr;
@ -95,7 +95,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
}
static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
static long def_ff(const char *rec, long len, char *buf, long sz)
{
if (len > 0 &&
(isalpha((unsigned char)*rec) || /* identifier? */
@ -117,7 +117,7 @@ static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri,
const char *rec;
long len = xdl_get_rec(xdf, ri, &rec);
if (!xecfg->find_func)
return def_ff(rec, len, buf, sz, xecfg->find_func_priv);
return def_ff(rec, len, buf, sz);
return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv);
}

View File

@ -251,7 +251,7 @@ static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
int line1, int count1, int line2, int count2)
{
int b_ptr;
int sz, ret = -1;
int ret = -1;
struct histindex index;
memset(&index, 0, sizeof(index));
@ -265,23 +265,16 @@ static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
index.rcha.head = NULL;
index.table_bits = xdl_hashbits(count1);
sz = index.records_size = 1 << index.table_bits;
sz *= sizeof(struct record *);
if (!(index.records = (struct record **) xdl_malloc(sz)))
index.records_size = 1 << index.table_bits;
if (!XDL_CALLOC_ARRAY(index.records, index.records_size))
goto cleanup;
memset(index.records, 0, sz);
sz = index.line_map_size = count1;
sz *= sizeof(struct record *);
if (!(index.line_map = (struct record **) xdl_malloc(sz)))
index.line_map_size = count1;
if (!XDL_CALLOC_ARRAY(index.line_map, index.line_map_size))
goto cleanup;
memset(index.line_map, 0, sz);
sz = index.line_map_size;
sz *= sizeof(unsigned int);
if (!(index.next_ptrs = (unsigned int *) xdl_malloc(sz)))
if (!XDL_CALLOC_ARRAY(index.next_ptrs, index.line_map_size))
goto cleanup;
memset(index.next_ptrs, 0, sz);
/* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */
if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 0)
@ -369,12 +362,8 @@ out:
return result;
}
int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2,
xpparam_t const *xpp, xdfenv_t *env)
int xdl_do_histogram_diff(xpparam_t const *xpp, xdfenv_t *env)
{
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
return -1;
return histogram_diff(xpp, env,
env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);

View File

@ -34,7 +34,6 @@
#define XDL_ADDBITS(v,b) ((v) + ((v) >> (b)))
#define XDL_MASKBITS(b) ((1UL << (b)) - 1)
#define XDL_HASHLONG(v,b) (XDL_ADDBITS((unsigned long)(v), b) & XDL_MASKBITS(b))
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
#define XDL_LE32_PUT(p, v) \
do { \
unsigned char *__p = (unsigned char *) (p); \
@ -50,5 +49,23 @@ do { \
((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 24; \
} while (0)
/* Allocate an array of nr elements, returns NULL on failure */
#define XDL_ALLOC_ARRAY(p, nr) \
((p) = SIZE_MAX / sizeof(*(p)) >= (size_t)(nr) \
? xdl_malloc((nr) * sizeof(*(p))) \
: NULL)
/* Allocate an array of nr zeroed out elements, returns NULL on failure */
#define XDL_CALLOC_ARRAY(p, nr) ((p) = xdl_calloc(nr, sizeof(*(p))))
/*
* Ensure array p can accommodate at least nr elements, growing the
* array and updating alloc (which is the number of allocated
* elements) as necessary. Frees p and returns -1 on failure, returns
* 0 on success
*/
#define XDL_ALLOC_GROW(p, nr, alloc) \
(-!((nr) <= (alloc) || \
((p) = xdl_alloc_grow_helper((p), (nr), &(alloc), sizeof(*(p))))))
#endif /* #if !defined(XMACROS_H) */

View File

@ -88,7 +88,7 @@ static int xdl_cleanup_merge(xdmerge_t *c)
if (c->mode == 0)
count++;
next_c = c->next;
xdl_free(c);
free(c);
}
return count;
}
@ -456,7 +456,7 @@ static void xdl_merge_two_conflicts(xdmerge_t *m)
m->chg1 = next_m->i1 + next_m->chg1 - m->i1;
m->chg2 = next_m->i2 + next_m->chg2 - m->i2;
m->next = next_m->next;
xdl_free(next_m);
free(next_m);
}
/*
@ -684,42 +684,42 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
xmparam_t const *xmp, mmbuffer_t *result)
{
xdchange_t *xscr1, *xscr2;
xdchange_t *xscr1 = NULL, *xscr2 = NULL;
xdfenv_t xe1, xe2;
int status;
int status = -1;
xpparam_t const *xpp = &xmp->xpp;
result->ptr = NULL;
result->size = 0;
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0) {
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0)
return -1;
}
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0) {
xdl_free_env(&xe1);
return -1;
}
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0)
goto free_xe1; /* avoid double free of xe2 */
if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
xdl_build_script(&xe1, &xscr1) < 0) {
xdl_free_env(&xe1);
return -1;
}
xdl_build_script(&xe1, &xscr1) < 0)
goto out;
if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
xdl_build_script(&xe2, &xscr2) < 0) {
xdl_free_script(xscr1);
xdl_free_env(&xe1);
xdl_free_env(&xe2);
return -1;
}
status = 0;
xdl_build_script(&xe2, &xscr2) < 0)
goto out;
if (!xscr1) {
result->ptr = xdl_malloc(mf2->size);
if (!result->ptr)
goto out;
status = 0;
memcpy(result->ptr, mf2->ptr, mf2->size);
result->size = mf2->size;
} else if (!xscr2) {
result->ptr = xdl_malloc(mf1->size);
if (!result->ptr)
goto out;
status = 0;
memcpy(result->ptr, mf1->ptr, mf1->size);
result->size = mf1->size;
} else {
@ -727,11 +727,13 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
&xe2, xscr2,
xmp, result);
}
out:
xdl_free_script(xscr1);
xdl_free_script(xscr2);
xdl_free_env(&xe1);
xdl_free_env(&xe2);
free_xe1:
xdl_free_env(&xe1);
return status;
}

View File

@ -69,7 +69,6 @@ struct hashmap {
} *entries, *first, *last;
/* were common records found? */
unsigned long has_matches;
mmfile_t *file1, *file2;
xdfenv_t *env;
xpparam_t const *xpp;
};
@ -139,23 +138,17 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
*
* It is assumed that env has been prepared using xdl_prepare().
*/
static int fill_hashmap(mmfile_t *file1, mmfile_t *file2,
xpparam_t const *xpp, xdfenv_t *env,
static int fill_hashmap(xpparam_t const *xpp, xdfenv_t *env,
struct hashmap *result,
int line1, int count1, int line2, int count2)
{
result->file1 = file1;
result->file2 = file2;
result->xpp = xpp;
result->env = env;
/* We know exactly how large we want the hash map */
result->alloc = count1 * 2;
result->entries = (struct entry *)
xdl_malloc(result->alloc * sizeof(struct entry));
if (!result->entries)
if (!XDL_CALLOC_ARRAY(result->entries, result->alloc))
return -1;
memset(result->entries, 0, result->alloc * sizeof(struct entry));
/* First, fill with entries from the first file */
while (count1--)
@ -198,9 +191,9 @@ static int binary_search(struct entry **sequence, int longest,
* item per sequence length: the sequence with the smallest last
* element (in terms of line2).
*/
static struct entry *find_longest_common_sequence(struct hashmap *map)
static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
{
struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
struct entry **sequence;
int longest = 0, i;
struct entry *entry;
@ -211,6 +204,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
*/
int anchor_i = -1;
if (!XDL_ALLOC_ARRAY(sequence, map->nr))
return -1;
for (entry = map->first; entry; entry = entry->next) {
if (!entry->line2 || entry->line2 == NON_UNIQUE)
continue;
@ -230,8 +226,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
/* No common unique lines were found */
if (!longest) {
*res = NULL;
xdl_free(sequence);
return NULL;
return 0;
}
/* Iterate starting at the last element, adjusting the "next" members */
@ -241,8 +238,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
entry->previous->next = entry;
entry = entry->previous;
}
*res = entry;
xdl_free(sequence);
return entry;
return 0;
}
static int match(struct hashmap *map, int line1, int line2)
@ -252,8 +250,7 @@ static int match(struct hashmap *map, int line1, int line2)
return record1->ha == record2->ha;
}
static int patience_diff(mmfile_t *file1, mmfile_t *file2,
xpparam_t const *xpp, xdfenv_t *env,
static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
int line1, int count1, int line2, int count2);
static int walk_common_sequence(struct hashmap *map, struct entry *first,
@ -284,8 +281,7 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first,
/* Recurse */
if (next1 > line1 || next2 > line2) {
if (patience_diff(map->file1, map->file2,
map->xpp, map->env,
if (patience_diff(map->xpp, map->env,
line1, next1 - line1,
line2, next2 - line2))
return -1;
@ -324,8 +320,7 @@ static int fall_back_to_classic_diff(struct hashmap *map,
*
* This function assumes that env was prepared with xdl_prepare_env().
*/
static int patience_diff(mmfile_t *file1, mmfile_t *file2,
xpparam_t const *xpp, xdfenv_t *env,
static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
int line1, int count1, int line2, int count2)
{
struct hashmap map;
@ -344,7 +339,7 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
}
memset(&map, 0, sizeof(map));
if (fill_hashmap(file1, file2, xpp, env, &map,
if (fill_hashmap(xpp, env, &map,
line1, count1, line2, count2))
return -1;
@ -358,25 +353,21 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
return 0;
}
first = find_longest_common_sequence(&map);
result = find_longest_common_sequence(&map, &first);
if (result)
goto out;
if (first)
result = walk_common_sequence(&map, first,
line1, count1, line2, count2);
else
result = fall_back_to_classic_diff(&map,
line1, count1, line2, count2);
out:
xdl_free(map.entries);
return result;
}
int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
xpparam_t const *xpp, xdfenv_t *env)
int xdl_do_patience_diff(xpparam_t const *xpp, xdfenv_t *env)
{
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
return -1;
/* environment is cleaned up in xdl_diff() */
return patience_diff(file1, file2, xpp, env,
1, env->xdf1.nrec, 1, env->xdf2.nrec);
return patience_diff(xpp, env, 1, env->xdf1.nrec, 1, env->xdf2.nrec);
}

View File

@ -78,15 +78,14 @@ static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) {
return -1;
}
if (!(cf->rchash = (xdlclass_t **) xdl_malloc(cf->hsize * sizeof(xdlclass_t *)))) {
if (!XDL_CALLOC_ARRAY(cf->rchash, cf->hsize)) {
xdl_cha_free(&cf->ncha);
return -1;
}
memset(cf->rchash, 0, cf->hsize * sizeof(xdlclass_t *));
cf->alloc = size;
if (!(cf->rcrecs = (xdlclass_t **) xdl_malloc(cf->alloc * sizeof(xdlclass_t *)))) {
if (!XDL_ALLOC_ARRAY(cf->rcrecs, cf->alloc)) {
xdl_free(cf->rchash);
xdl_cha_free(&cf->ncha);
@ -112,7 +111,6 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
long hi;
char const *line;
xdlclass_t *rcrec;
xdlclass_t **rcrecs;
line = rec->ptr;
hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
@ -128,14 +126,8 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
return -1;
}
rcrec->idx = cf->count++;
if (cf->count > cf->alloc) {
cf->alloc *= 2;
if (!(rcrecs = (xdlclass_t **) xdl_realloc(cf->rcrecs, cf->alloc * sizeof(xdlclass_t *)))) {
if (XDL_ALLOC_GROW(cf->rcrecs, cf->count, cf->alloc))
return -1;
}
cf->rcrecs = rcrecs;
}
cf->rcrecs[rcrec->idx] = rcrec;
rcrec->line = line;
rcrec->size = rec->size;
@ -164,7 +156,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
unsigned long hav;
char const *blk, *cur, *top, *prev;
xrecord_t *crec;
xrecord_t **recs, **rrecs;
xrecord_t **recs;
xrecord_t **rhash;
unsigned long *ha;
char *rchg;
@ -178,26 +170,21 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
goto abort;
if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
if (!XDL_ALLOC_ARRAY(recs, narec))
goto abort;
hbits = xdl_hashbits((unsigned int) narec);
hsize = 1 << hbits;
if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *))))
if (!XDL_CALLOC_ARRAY(rhash, hsize))
goto abort;
memset(rhash, 0, hsize * sizeof(xrecord_t *));
nrec = 0;
if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
if ((cur = blk = xdl_mmfile_first(mf, &bsize))) {
for (top = blk + bsize; cur < top; ) {
prev = cur;
hav = xdl_hash_record(&cur, top, xpp->flags);
if (nrec >= narec) {
narec *= 2;
if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *))))
goto abort;
recs = rrecs;
}
if (XDL_ALLOC_GROW(recs, nrec + 1, narec))
goto abort;
if (!(crec = xdl_cha_alloc(&xdf->rcha)))
goto abort;
crec->ptr = prev;
@ -209,15 +196,14 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
}
}
if (!(rchg = (char *) xdl_malloc((nrec + 2) * sizeof(char))))
if (!XDL_CALLOC_ARRAY(rchg, nrec + 2))
goto abort;
memset(rchg, 0, (nrec + 2) * sizeof(char));
if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
(XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
if (!(rindex = xdl_malloc((nrec + 1) * sizeof(*rindex))))
if (!XDL_ALLOC_ARRAY(rindex, nrec + 1))
goto abort;
if (!(ha = xdl_malloc((nrec + 1) * sizeof(*ha))))
if (!XDL_ALLOC_ARRAY(ha, nrec + 1))
goto abort;
}
@ -383,11 +369,8 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd
xdlclass_t *rcrec;
char *dis, *dis1, *dis2;
if (!(dis = (char *) xdl_malloc(xdf1->nrec + xdf2->nrec + 2))) {
if (!XDL_CALLOC_ARRAY(dis, xdf1->nrec + xdf2->nrec + 2))
return -1;
}
memset(dis, 0, xdf1->nrec + xdf2->nrec + 2);
dis1 = dis;
dis2 = dis1 + xdf1->nrec + 1;

View File

@ -122,7 +122,7 @@ long xdl_guess_lines(mmfile_t *mf, long sample) {
long nl = 0, size, tsize = 0;
char const *data, *cur, *top;
if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) {
if ((cur = data = xdl_mmfile_first(mf, &size))) {
for (top = data + size; nl < sample && cur < top; ) {
nl++;
if (!(cur = memchr(cur, '\n', top - cur)))
@ -432,3 +432,20 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
return 0;
}
void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size)
{
void *tmp = NULL;
size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX;
if (nr > n)
n = nr;
if (SIZE_MAX / size >= n)
tmp = xdl_realloc(p, n * size);
if (tmp) {
*alloc = n;
} else {
xdl_free(p);
*alloc = 0;
}
return tmp;
}

View File

@ -42,6 +42,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
int line1, int count1, int line2, int count2);
/* Do not call this function, use XDL_ALLOC_GROW instead */
void* xdl_alloc_grow_helper(void* p, long nr, long* alloc, size_t size);
#endif /* #if !defined(XUTILS_H) */

View File

@ -1,12 +1,153 @@
v1.6.4
v1.7.1
------
## What's Changed
### Bug fixes
* config: return `GIT_ENOTFOUND` for missing programdata by @ethomson in https://github.com/libgit2/libgit2/pull/6547
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.6.3...v1.6.4
* proxy: Return an error for invalid proxy URLs instead of crashing. by @lrm29 in https://github.com/libgit2/libgit2/pull/6597
* ssh: fix known_hosts leak in _git_ssh_setup_conn by @steven9724 in https://github.com/libgit2/libgit2/pull/6599
* repository: make cleanup safe for re-use with grafts by @carlosmn in https://github.com/libgit2/libgit2/pull/6600
* fix: Add missing include for oidarray. by @dvzrv in https://github.com/libgit2/libgit2/pull/6608
* Revert "CMake: Search for ssh2 instead of libssh2." by @ethomson in https://github.com/libgit2/libgit2/pull/6619
### Compatibility improvements
* stransport: macOS: replace errSSLNetworkTimeout, with hard-coded value by @mascguy in https://github.com/libgit2/libgit2/pull/6610
## New Contributors
* @dvzrv made their first contribution in https://github.com/libgit2/libgit2/pull/6608
* @steven9724 made their first contribution in https://github.com/libgit2/libgit2/pull/6599
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.7.0...v1.7.1
v1.7
----
This is release v1.7.0, "Kleine Raupe Nimmersatt". This release adds
shallow clone support, completes the experimental SHA256 support,
adds Schannel support for Windows, and includes many other new
features and bugfixes.
## Major changes
* **Shallow clone support**
libgit2 now supports shallow clone and shallow repositories, thanks
to a significant investment from many community members -- hundreds
of commits by many contributors.
* Shallow (#6396) with some fixes from review by @ethomson in
https://github.com/libgit2/libgit2/pull/6557
* Shallow Clone Support by @lya001 in
https://github.com/libgit2/libgit2/pull/6396
* Shallow support v2 by @pks-t in
https://github.com/libgit2/libgit2/pull/5254
* **SHA256 support**
libgit2 should now support SHA256 repositories using the
`extensions.objectFormat` configuration option when the library is
built with `EXPERIMENTAL_SHA256=ON`. Users are encouraged to begin
testing their applications with this option and provide bug reports
and feedback. This _is_ a breaking API change; SHA256 support will
be enabled by default in libgit2 v2.0.
* sha256: less hardcoded SHA1 types and lengths by @ethomson in
https://github.com/libgit2/libgit2/pull/6549
* Support SHA256 in git_repository_wrap_odb by @ethomson in
https://github.com/libgit2/libgit2/pull/6556
* **Schannel and SSPI for Windows**
libgit2 now supports the Windows Schannel and SSPI APIs for HTTPS
support on Windows, when configured with `USE_HTTPS=Schannel`.
Setting this option will not use the existing WinHTTP support, but
will use libgit2's standard HTTP client stack with Windows TLS
primitives. Windows users are encouraged to begin testing their
applications with this option and provide bug reports and feedback.
This will be enabled by default in a future version of libgit2.
* Introduce Schannel and SSPI for Windows by @ethomson in
https://github.com/libgit2/libgit2/pull/6533
## Breaking changes
* **Simplify custom pluggable allocator** (System API / ABI breaking change)
The `git_allocator` structure (configurable by the
`GIT_OPT_SET_ALLOCATOR` option) now only contains `gmalloc`,
`grealloc` and `gfree` members. This simplifies both the work needed
by an implementer _and_ allows more flexibility and correctness in
libgit2 itself, especially during out-of-memory situations and
errors during bootstrapping.
* tests: add allocator with limited number of bytes by @ethomson in
https://github.com/libgit2/libgit2/pull/6563
## Other changes
### New features
* repo: honor environment variables for more scenarios by @ethomson in
https://github.com/libgit2/libgit2/pull/6544
* Introduce timeouts on sockets by @ethomson in
https://github.com/libgit2/libgit2/pull/6535
### Performance improvements
* midx: do not try to look at every object in the index by @carlosmn in
https://github.com/libgit2/libgit2/pull/6585
* Partial fix for #6532: insert-by-date order. by @arroz in
https://github.com/libgit2/libgit2/pull/6539
### Bug fixes
* repo: don't allow repeated extensions by @ethomson in
https://github.com/libgit2/libgit2/pull/6505
* config: return `GIT_ENOTFOUND` for missing programdata by @ethomson in
https://github.com/libgit2/libgit2/pull/6547
* Fix missing oid type for "fake" repositories by @oreiche in
https://github.com/libgit2/libgit2/pull/6554
* Thread-local storage: handle failure cases by @ethomson in
https://github.com/libgit2/libgit2/pull/5722
* midx: allow unknown chunk ids in multi-pack index files by @carlosmn in
https://github.com/libgit2/libgit2/pull/6583
* pack: cast the number of objects to size_t by @carlosmn in
https://github.com/libgit2/libgit2/pull/6584
* Fixes #6344: git_branch_move now renames the reflog instead of deleting
by @arroz in https://github.com/libgit2/libgit2/pull/6345
* #6576 git_diff_index_to_workdir reverse now loads untracked content by
@arroz in https://github.com/libgit2/libgit2/pull/6577
### Build and CI improvements
* meta: the main branch is now v1.7.0 by @ethomson in
https://github.com/libgit2/libgit2/pull/6516
* xdiff: move xdiff to 'deps' by @ethomson in
https://github.com/libgit2/libgit2/pull/6482
* util: detect all possible qsort_r and qsort_s variants by
@DimitryAndric in https://github.com/libgit2/libgit2/pull/6555
* Work around -Werror problems when detecting qsort variants by
@DimitryAndric in https://github.com/libgit2/libgit2/pull/6558
* actions: simplify execution with composite action by @ethomson in
https://github.com/libgit2/libgit2/pull/6488
* CMake: Search for ssh2 instead of libssh2. by @Faless in
https://github.com/libgit2/libgit2/pull/6586
### Documentation improvements
* docs: fix IRC server from freenode to libera by @vincenzopalazzo in
https://github.com/libgit2/libgit2/pull/6590
### Dependency upgrades
* Update xdiff to git 2.40.1's version by @ethomson in
https://github.com/libgit2/libgit2/pull/6561
* deps: update pcre to 8.45 by @ethomson in
https://github.com/libgit2/libgit2/pull/6593
## New Contributors
* @oreiche made their first contribution in
https://github.com/libgit2/libgit2/pull/6554
* @DimitryAndric made their first contribution in
https://github.com/libgit2/libgit2/pull/6555
* @vincenzopalazzo made their first contribution in
https://github.com/libgit2/libgit2/pull/6590
* @Faless made their first contribution in
https://github.com/libgit2/libgit2/pull/6586
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.6.3...v1.7.0
v1.6.3
------

View File

@ -24,9 +24,8 @@ by the following licenses:
## Discussion & Chat
We hang out in the
[`#libgit2`](http://webchat.freenode.net/?channels=#libgit2)) channel on
irc.freenode.net.
We hang out in the [#libgit2](https://web.libera.chat/#libgit2) channel on
[libera](https://libera.chat).
Also, feel free to open an
[Issue](https://github.com/libgit2/libgit2/issues/new) to start a discussion

View File

@ -188,9 +188,17 @@ static void compute_diff_no_index(git_diff **diff, struct diff_options *o) {
check_lg2(
git_patch_to_buf(&buf, patch),
"patch to buf", NULL);
#ifdef GIT_EXPERIMENTAL_SHA256
check_lg2(
git_diff_from_buffer(diff, buf.ptr, buf.size, NULL),
"diff from patch", NULL);
#else
check_lg2(
git_diff_from_buffer(diff, buf.ptr, buf.size),
"diff from patch", NULL);
#endif
git_patch_free(patch);
git_buf_dispose(&buf);
free(file1_str);

View File

@ -30,7 +30,11 @@ 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);
#else
check_lg2(git_index_open(&index, dir), "could not open index", dir);
#endif
} else {
check_lg2(git_repository_open_ext(&repo, dir, 0, NULL), "could not open repository", dir);
check_lg2(git_repository_index(&index, repo), "could not open repository index", NULL);

View File

@ -224,7 +224,11 @@ typedef enum {
GIT_OPT_GET_OWNER_VALIDATION,
GIT_OPT_SET_OWNER_VALIDATION,
GIT_OPT_GET_HOMEDIR,
GIT_OPT_SET_HOMEDIR
GIT_OPT_SET_HOMEDIR,
GIT_OPT_SET_SERVER_CONNECT_TIMEOUT,
GIT_OPT_GET_SERVER_CONNECT_TIMEOUT,
GIT_OPT_SET_SERVER_TIMEOUT,
GIT_OPT_GET_SERVER_TIMEOUT
} git_libgit2_opt_t;
/**
@ -480,6 +484,27 @@ typedef enum {
* >
* > - `path` directory of home directory.
*
* opts(GIT_OPT_GET_SERVER_CONNECT_TIMEOUT, int *timeout)
* > Gets the timeout (in milliseconds) to attempt connections to
* > a remote server.
*
* opts(GIT_OPT_SET_SERVER_CONNECT_TIMEOUT, int timeout)
* > Sets the timeout (in milliseconds) to attempt connections to
* > a remote server. This is supported only for HTTP(S) connections
* > and is not supported by SSH. Set to 0 to use the system default.
* > Note that this may not be able to be configured longer than the
* > system default, typically 75 seconds.
*
* opts(GIT_OPT_GET_SERVER_TIMEOUT, int *timeout)
* > Gets the timeout (in milliseconds) for reading from and writing
* > to a remote server.
*
* opts(GIT_OPT_SET_SERVER_TIMEOUT, int timeout)
* > Sets the timeout (in milliseconds) for reading from and writing
* > to a remote server. This is supported only for HTTP(S)
* > connections and is not supported by SSH. 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

View File

@ -421,6 +421,22 @@ typedef struct {
*/
uint32_t interhunk_lines;
/**
* The object ID type to emit in diffs; this is used by functions
* that operate without a repository - namely `git_diff_buffers`,
* or `git_diff_blobs` and `git_diff_blob_to_buffer` when one blob
* is `NULL`.
*
* This may be omitted (set to `0`). If a repository is available,
* the object ID format of the repository will be used. If no
* repository is available then the default is `GIT_OID_SHA`.
*
* If this is specified and a repository is available, then the
* specified `oid_type` must match the repository's object ID
* format.
*/
git_oid_t oid_type;
/**
* The abbreviation length to use when formatting object ids.
* Defaults to the value of 'core.abbrev' from the config, or 7 if unset.
@ -1153,9 +1169,8 @@ GIT_EXTERN(int) git_diff_to_buf(
/**@}*/
/*
* Misc
* Low-level file comparison, invoking callbacks per difference.
*/
/**
@ -1271,6 +1286,25 @@ GIT_EXTERN(int) git_diff_buffers(
git_diff_line_cb line_cb,
void *payload);
/* Patch file parsing. */
/**
* Options for parsing a diff / patch file.
*/
typedef struct {
unsigned int version;
git_oid_t oid_type;
} git_diff_parse_options;
/* The current version of the diff parse options structure */
#define GIT_DIFF_PARSE_OPTIONS_VERSION 1
/* Stack initializer for diff parse options. Alternatively use
* `git_diff_parse_options_init` programmatic initialization.
*/
#define GIT_DIFF_PARSE_OPTIONS_INIT \
{ GIT_DIFF_PARSE_OPTIONS_VERSION, GIT_OID_DEFAULT }
/**
* Read the contents of a git patch file into a `git_diff` object.
*
@ -1293,7 +1327,11 @@ GIT_EXTERN(int) git_diff_buffers(
GIT_EXTERN(int) git_diff_from_buffer(
git_diff **out,
const char *content,
size_t content_len);
size_t content_len
#ifdef GIT_EXPERIMENTAL_SHA256
, git_diff_parse_options *opts
#endif
);
/**
* This is an opaque structure which is allocated by `git_diff_get_stats`.

View File

@ -58,7 +58,8 @@ typedef enum {
GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
GIT_EINDEXDIRTY = -34, /**< Unsaved changes in the index would be overwritten */
GIT_EAPPLYFAIL = -35, /**< Patch application failed */
GIT_EOWNER = -36 /**< The object is not owned by the current user */
GIT_EOWNER = -36, /**< The object is not owned by the current user */
GIT_TIMEOUT = -37 /**< The operation timed out */
} git_error_code;
/**
@ -109,7 +110,8 @@ typedef enum {
GIT_ERROR_WORKTREE,
GIT_ERROR_SHA,
GIT_ERROR_HTTP,
GIT_ERROR_INTERNAL
GIT_ERROR_INTERNAL,
GIT_ERROR_GRAFTS
} git_error_t;
/**

View File

@ -184,7 +184,12 @@ typedef enum {
* @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
/**
* Create an in-memory index object.
@ -197,7 +202,11 @@ GIT_EXTERN(int) git_index_open(git_index **out, const char *index_path);
* @param 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);
#endif
/**
* Free an existing index object.

View File

@ -225,7 +225,7 @@ GIT_EXTERN(int) git_oid_pathfmt(char *out, const git_oid *id);
* concurrent calls of the function.
*
* @param oid The oid structure to format
* @return the c-string
* @return the c-string or NULL on failure
*/
GIT_EXTERN(char *) git_oid_tostr_s(const git_oid *oid);

View File

@ -702,6 +702,15 @@ typedef enum {
GIT_REMOTE_DOWNLOAD_TAGS_ALL
} git_remote_autotag_option_t;
/** Constants for fetch depth (shallowness of fetch). */
typedef enum {
/** The fetch is "full" (not shallow). This is the default. */
GIT_FETCH_DEPTH_FULL = 0,
/** The fetch should "unshallow" and fetch missing data. */
GIT_FETCH_DEPTH_UNSHALLOW = 2147483647
} git_fetch_depth_t;
/**
* Fetch options structure.
*
@ -743,6 +752,15 @@ typedef struct {
*/
git_proxy_options proxy_opts;
/**
* Depth of the fetch to perform, or `GIT_FETCH_DEPTH_FULL`
* (or `0`) for full history, or `GIT_FETCH_DEPTH_UNSHALLOW`
* to "unshallow" a shallow repository.
*
* The default is full (`GIT_FETCH_DEPTH_FULL` or `0`).
*/
int depth;
/**
* Whether to allow off-site redirects. If this is not
* specified, the `http.followRedirects` configuration setting

View File

@ -56,9 +56,19 @@ 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
*/
GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
#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.
@ -536,7 +546,7 @@ GIT_EXTERN(const char *) git_repository_workdir(const git_repository *repo);
/**
* Get the path of the shared common directory for this repository.
*
*
* If the repository is bare, it is the root directory for the repository.
* If the repository is a worktree, it is the parent repo's gitdir.
* Otherwise, it is the gitdir.

View File

@ -24,28 +24,6 @@ typedef struct {
/** Allocate `n` bytes of memory */
void * GIT_CALLBACK(gmalloc)(size_t n, const char *file, int line);
/**
* Allocate memory for an array of `nelem` elements, where each element
* has a size of `elsize`. Returned memory shall be initialized to
* all-zeroes
*/
void * GIT_CALLBACK(gcalloc)(size_t nelem, size_t elsize, const char *file, int line);
/** Allocate memory for the string `str` and duplicate its contents. */
char * GIT_CALLBACK(gstrdup)(const char *str, const char *file, int line);
/**
* Equivalent to the `gstrdup` function, but only duplicating at most
* `n + 1` bytes
*/
char * GIT_CALLBACK(gstrndup)(const char *str, size_t n, const char *file, int line);
/**
* Equivalent to `gstrndup`, but will always duplicate exactly `n` bytes
* of `str`. Thus, out of bounds reads at `str` may happen.
*/
char * GIT_CALLBACK(gsubstrdup)(const char *str, size_t n, const char *file, int line);
/**
* This function shall deallocate the old object `ptr` and return a
* pointer to a new object that has the size specified by `size`. In
@ -53,18 +31,6 @@ typedef struct {
*/
void * GIT_CALLBACK(grealloc)(void *ptr, size_t size, const char *file, int line);
/**
* This function shall be equivalent to `grealloc`, but allocating
* `neleme * elsize` bytes.
*/
void * GIT_CALLBACK(greallocarray)(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
/**
* This function shall allocate a new array of `nelem` elements, where
* each element has a size of `elsize` bytes.
*/
void * GIT_CALLBACK(gmallocarray)(size_t nelem, size_t elsize, const char *file, int line);
/**
* This function shall free the memory pointed to by `ptr`. In case
* `ptr` is `NULL`, this shall be a no-op.

View File

@ -28,7 +28,13 @@ GIT_BEGIN_DECL
* @param objects_dir the path to a git objects directory.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir);
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
#endif
);
/**
* Frees commit-graph data. This should only be called when memory allocated
@ -50,7 +56,11 @@ GIT_EXTERN(void) git_commit_graph_free(git_commit_graph *cgraph);
*/
GIT_EXTERN(int) git_commit_graph_writer_new(
git_commit_graph_writer **out,
const char *objects_info_dir);
const char *objects_info_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
);
/**
* Free the commit-graph writer and its resources.

View File

@ -29,7 +29,11 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_midx_writer_new(
git_midx_writer **out,
const char *pack_dir);
const char *pack_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
);
/**
* Free the multi-pack-index writer and its resources.

View File

@ -29,8 +29,22 @@ GIT_BEGIN_DECL
typedef struct git_stream {
int version;
int encrypted;
int proxy_support;
int encrypted : 1,
proxy_support : 1;
/**
* Timeout for read and write operations; can be set to `0` to
* block indefinitely.
*/
int timeout;
/**
* Timeout to connect to the remote server; can be set to `0`
* to use the system defaults. This can be shorter than the
* system default - often 75 seconds - but cannot be longer.
*/
int connect_timeout;
int GIT_CALLBACK(connect)(struct git_stream *);
int GIT_CALLBACK(certificate)(git_cert **, struct git_stream *);
int GIT_CALLBACK(set_proxy)(struct git_stream *, const git_proxy_options *proxy_opts);

View File

@ -9,6 +9,7 @@
#define INCLUDE_sys_git_transport_h
#include "git2/net.h"
#include "git2/oidarray.h"
#include "git2/proxy.h"
#include "git2/remote.h"
#include "git2/strarray.h"
@ -25,6 +26,14 @@
GIT_BEGIN_DECL
typedef struct {
const git_remote_head * const *refs;
size_t refs_len;
git_oid *shallow_roots;
size_t shallow_roots_len;
int depth;
} git_fetch_negotiation;
struct git_transport {
unsigned int version; /**< The struct version */
@ -96,8 +105,17 @@ struct git_transport {
int GIT_CALLBACK(negotiate_fetch)(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count);
const git_fetch_negotiation *fetch_data);
/**
* Return the shallow roots of the remote.
*
* This function may be called after a successful call to
* `negotiate_fetch`.
*/
int GIT_CALLBACK(shallow_roots)(
git_oidarray *out,
git_transport *transport);
/**
* Start downloading the packfile from the remote repository.

View File

@ -11,16 +11,16 @@
* The version string for libgit2. This string follows semantic
* versioning (v2) guidelines.
*/
#define LIBGIT2_VERSION "1.6.4"
#define LIBGIT2_VERSION "1.7.1"
/** The major version number for this version of libgit2. */
#define LIBGIT2_VER_MAJOR 1
/** The minor version number for this version of libgit2. */
#define LIBGIT2_VER_MINOR 6
#define LIBGIT2_VER_MINOR 7
/** The revision ("teeny") version number for this version of libgit2. */
#define LIBGIT2_VER_REVISION 4
#define LIBGIT2_VER_REVISION 1
/** The Windows DLL patch number for this version of libgit2. */
#define LIBGIT2_VER_PATCH 0
@ -34,6 +34,6 @@
#define LIBGIT2_VER_PRERELEASE NULL
/** The library ABI soversion for this version of libgit2. */
#define LIBGIT2_SOVERSION "1.6"
#define LIBGIT2_SOVERSION "1.7"
#endif

View File

@ -237,7 +237,9 @@ GIT_EXTERN(int) git_worktree_prune_options_init(
*
* If the worktree is not valid and not locked or if the above
* flags have been passed in, this function will return a
* positive value.
* positive value. If the worktree is not prunable, an error
* message will be set (visible in `giterr_last`) with details about
* why.
*
* @param wt Worktree to check.
* @param opts The prunable options.

View File

@ -1,6 +1,6 @@
{
"name": "libgit2",
"version": "1.6.4",
"version": "1.7.1",
"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 ."

View File

@ -41,8 +41,8 @@ include(SelectHTTPSBackend)
include(SelectHashes)
include(SelectHTTPParser)
include(SelectRegex)
include(SelectXdiff)
include(SelectSSH)
include(SelectWinHTTP)
include(SelectZlib)
#
@ -58,20 +58,43 @@ add_feature_info(futimens GIT_USE_FUTIMENS "futimens support")
# qsort
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" GIT_QSORT_R_BSD)
# old-style FreeBSD qsort_r() has the 'context' parameter as the first argument
# of the comparison function:
check_prototype_definition_safe(qsort_r
"void (qsort_r)(void *base, size_t nmemb, size_t size, void *context, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" GIT_QSORT_BSD)
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
"" "stdlib.h" GIT_QSORT_R_GNU)
# GNU or POSIX qsort_r() has the 'context' parameter as the last argument of the
# comparison function:
check_prototype_definition_safe(qsort_r
"void (qsort_r)(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *context)"
"" "stdlib.h" GIT_QSORT_GNU)
check_function_exists(qsort_s GIT_QSORT_S)
# C11 qsort_s() has the 'context' parameter as the last argument of the
# comparison function, and returns an error status:
check_prototype_definition_safe(qsort_s
"errno_t (qsort_s)(void *base, rsize_t nmemb, rsize_t size, int (*compar)(const void *, const void *, void *), void *context)"
"0" "stdlib.h" GIT_QSORT_C11)
# MSC qsort_s() has the 'context' parameter as the first argument of the
# comparison function, and as the last argument of qsort_s():
check_prototype_definition_safe(qsort_s
"void (qsort_s)(void *base, size_t num, size_t width, int (*compare )(void *, const void *, const void *), void *context)"
"" "stdlib.h" GIT_QSORT_MSC)
# random / entropy data
check_function_exists(getentropy GIT_RAND_GETENTROPY)
check_function_exists(getloadavg GIT_RAND_GETLOADAVG)
check_symbol_exists(getentropy unistd.h GIT_RAND_GETENTROPY)
check_symbol_exists(getloadavg stdlib.h GIT_RAND_GETLOADAVG)
# poll
if(WIN32)
set(GIT_IO_WSAPOLL 1)
else()
check_symbol_exists(poll poll.h GIT_IO_POLL)
check_symbol_exists(select sys/select.h GIT_IO_SELECT)
endif()
# determine architecture of the machine

View File

@ -18,7 +18,7 @@
#define COMMAND_NAME "clone"
static char *branch, *remote_path, *local_path;
static char *branch, *remote_path, *local_path, *depth;
static int show_help, quiet, checkout = 1, bare;
static bool local_path_exists;
static cli_progress progress = CLI_PROGRESS_INIT;
@ -36,6 +36,8 @@ static const cli_opt_spec opts[] = {
CLI_OPT_USAGE_DEFAULT, NULL, "don't create a working directory" },
{ CLI_OPT_TYPE_VALUE, "branch", 'b', &branch, 0,
CLI_OPT_USAGE_DEFAULT, "name", "branch to check out" },
{ CLI_OPT_TYPE_VALUE, "depth", 0, &depth, 0,
CLI_OPT_USAGE_DEFAULT, "depth", "commit depth to check out " },
{ CLI_OPT_TYPE_LITERAL },
{ CLI_OPT_TYPE_ARG, "repository", 0, &remote_path, 0,
CLI_OPT_USAGE_REQUIRED, "repository", "repository path" },
@ -71,6 +73,22 @@ static char *compute_local_path(const char *orig_path)
return local_path;
}
static int compute_depth(const char *depth)
{
int64_t i;
const char *endptr;
if (!depth)
return 0;
if (git__strntol64(&i, depth, strlen(depth), &endptr, 10) < 0 || i < 0 || i > INT_MAX || *endptr) {
fprintf(stderr, "fatal: depth '%s' is not valid.\n", depth);
exit(128);
}
return (int)i;
}
static bool validate_local_path(const char *path)
{
if (!git_fs_path_exists(path))
@ -127,11 +145,9 @@ int cmd_clone(int argc, char **argv)
goto done;
}
if (bare)
clone_opts.bare = 1;
if (branch)
clone_opts.checkout_branch = branch;
clone_opts.bare = !!bare;
clone_opts.checkout_branch = branch;
clone_opts.fetch_opts.depth = compute_depth(depth);
if (!checkout)
clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;

View File

@ -15,10 +15,10 @@
/*
* Show updates to the percentage and number of objects received
* separately from the throughput to give an accurate progress while
* avoiding too much noise on the screen.
* avoiding too much noise on the screen. (In milliseconds.)
*/
#define PROGRESS_UPDATE_TIME 0.10
#define THROUGHPUT_UPDATE_TIME 1.00
#define PROGRESS_UPDATE_TIME 60
#define THROUGHPUT_UPDATE_TIME 500
#define is_nl(c) ((c) == '\r' || (c) == '\n')
@ -54,7 +54,7 @@ static int progress_write(cli_progress *progress, bool force, git_str *line)
bool has_nl;
size_t no_nl = no_nl_len(line->ptr, line->size);
size_t nl = nl_len(&has_nl, line->ptr + no_nl, line->size - no_nl);
double now = git__timer();
uint64_t now = git_time_monotonic();
size_t i;
/* Avoid spamming the console with progress updates */
@ -191,20 +191,21 @@ static int fetch_receiving(
{
char *recv_units[] = { "B", "KiB", "MiB", "GiB", "TiB", NULL };
char *rate_units[] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", NULL };
uint64_t now, elapsed;
double now, recv_len, rate, elapsed;
double recv_len, rate;
size_t recv_unit_idx = 0, rate_unit_idx = 0;
bool done = (stats->received_objects == stats->total_objects);
if (!progress->action_start)
progress->action_start = git__timer();
progress->action_start = git_time_monotonic();
if (done && progress->action_finish)
now = progress->action_finish;
else if (done)
progress->action_finish = now = git__timer();
progress->action_finish = now = git_time_monotonic();
else
now = git__timer();
now = git_time_monotonic();
if (progress->throughput_update &&
now - progress->throughput_update < THROUGHPUT_UPDATE_TIME) {

View File

@ -30,11 +30,11 @@ typedef struct {
cli_progress_t action;
/* Actions may time themselves (eg fetch) but are not required to */
double action_start;
double action_finish;
uint64_t action_start;
uint64_t action_finish;
/* Last console update, avoid too frequent updates. */
double last_update;
uint64_t last_update;
/* Accumulators for partial output and deferred updates. */
git_str sideband;
@ -42,7 +42,7 @@ typedef struct {
git_str deferred;
/* Last update about throughput */
double throughput_update;
uint64_t throughput_update;
double throughput_bytes;
} cli_progress;

View File

@ -24,8 +24,7 @@ target_sources(libgit2 PRIVATE ${SRC_H})
file(GLOB SRC_GIT2 *.c *.h
streams/*.c streams/*.h
transports/*.c transports/*.h
xdiff/*.c xdiff/*.h)
transports/*.c transports/*.h)
list(SORT SRC_GIT2)
target_sources(libgit2 PRIVATE ${SRC_GIT2})
@ -39,23 +38,6 @@ if(APPLE)
set_source_files_properties(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
endif()
# the xdiff dependency is not (yet) warning-free, disable warnings
# as errors for the xdiff sources until we've sorted them out
if(MSVC)
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
else()
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
endif()
ide_split_sources(libgit2)
list(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:util> $<TARGET_OBJECTS:libgit2> ${LIBGIT2_DEPENDENCY_OBJECTS})
list(APPEND LIBGIT2_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES})

View File

@ -39,8 +39,8 @@ static int annotated_commit_init(
if ((error = git_commit_dup(&annotated_commit->commit, commit)) < 0)
goto done;
git_oid_fmt(annotated_commit->id_str, git_commit_id(commit));
annotated_commit->id_str[GIT_OID_SHA1_HEXSIZE] = '\0';
git_oid_tostr(annotated_commit->id_str, GIT_OID_MAX_HEXSIZE + 1,
git_commit_id(commit));
if (!description)
description = annotated_commit->id_str;

View File

@ -41,7 +41,7 @@ struct git_annotated_commit {
const char *ref_name;
const char *remote_url;
char id_str[GIT_OID_SHA1_HEXSIZE+1];
char id_str[GIT_OID_MAX_HEXSIZE + 1];
};
extern int git_annotated_commit_from_head(git_annotated_commit **out,

View File

@ -19,6 +19,7 @@
#include "zstream.h"
#include "reader.h"
#include "index.h"
#include "repository.h"
#include "apply.h"
typedef struct {
@ -644,7 +645,7 @@ int git_apply_to_tree(
* put the current tree into the postimage as-is - the diff will
* replace any entries contained therein
*/
if ((error = git_index_new(&postimage)) < 0 ||
if ((error = git_index__new(&postimage, repo->oid_type)) < 0 ||
(error = git_index_read_tree(postimage, preimage)) < 0 ||
(error = git_reader_for_index(&post_reader, repo, postimage)) < 0)
goto done;
@ -851,8 +852,8 @@ int git_apply(
* having the full repo index, so we will limit our checkout
* to only write these files that were affected by the diff.
*/
if ((error = git_index_new(&preimage)) < 0 ||
(error = git_index_new(&postimage)) < 0 ||
if ((error = git_index__new(&preimage, repo->oid_type)) < 0 ||
(error = git_index__new(&postimage, repo->oid_type)) < 0 ||
(error = git_reader_for_index(&post_reader, repo, postimage)) < 0)
goto done;

View File

@ -60,10 +60,11 @@ static bool hunk_starts_at_or_after_line(git_blame_hunk *hunk, size_t line)
}
static git_blame_hunk *new_hunk(
size_t start,
size_t lines,
size_t orig_start,
const char *path)
size_t start,
size_t lines,
size_t orig_start,
const char *path,
git_blame *blame)
{
git_blame_hunk *hunk = git__calloc(1, sizeof(git_blame_hunk));
if (!hunk) return NULL;
@ -72,8 +73,8 @@ static git_blame_hunk *new_hunk(
hunk->final_start_line_number = start;
hunk->orig_start_line_number = orig_start;
hunk->orig_path = path ? git__strdup(path) : NULL;
git_oid_clear(&hunk->orig_commit_id, GIT_OID_SHA1);
git_oid_clear(&hunk->final_commit_id, GIT_OID_SHA1);
git_oid_clear(&hunk->orig_commit_id, blame->repository->oid_type);
git_oid_clear(&hunk->final_commit_id, blame->repository->oid_type);
return hunk;
}
@ -86,13 +87,14 @@ static void free_hunk(git_blame_hunk *hunk)
git__free(hunk);
}
static git_blame_hunk *dup_hunk(git_blame_hunk *hunk)
static git_blame_hunk *dup_hunk(git_blame_hunk *hunk, git_blame *blame)
{
git_blame_hunk *newhunk = new_hunk(
hunk->final_start_line_number,
hunk->lines_in_hunk,
hunk->orig_start_line_number,
hunk->orig_path);
hunk->orig_path,
blame);
if (!newhunk)
return NULL;
@ -237,7 +239,8 @@ static git_blame_hunk *split_hunk_in_vector(
git_vector *vec,
git_blame_hunk *hunk,
size_t rel_line,
bool return_new)
bool return_new,
git_blame *blame)
{
size_t new_line_count;
git_blame_hunk *nh;
@ -250,8 +253,9 @@ static git_blame_hunk *split_hunk_in_vector(
}
new_line_count = hunk->lines_in_hunk - rel_line;
nh = new_hunk(hunk->final_start_line_number + rel_line, new_line_count,
hunk->orig_start_line_number + rel_line, hunk->orig_path);
nh = new_hunk(hunk->final_start_line_number + rel_line,
new_line_count, hunk->orig_start_line_number + rel_line,
hunk->orig_path, blame);
if (!nh)
return NULL;
@ -304,7 +308,8 @@ static int index_blob_lines(git_blame *blame)
static git_blame_hunk *hunk_from_entry(git_blame__entry *e, git_blame *blame)
{
git_blame_hunk *h = new_hunk(
e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path);
e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path,
blame);
if (!h)
return NULL;
@ -445,14 +450,16 @@ static int buffer_hunk_cb(
blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byline(blame, wedge_line);
if (!blame->current_hunk) {
/* Line added at the end of the file */
blame->current_hunk = new_hunk(wedge_line, 0, wedge_line, blame->path);
blame->current_hunk = new_hunk(wedge_line, 0, wedge_line,
blame->path, blame);
GIT_ERROR_CHECK_ALLOC(blame->current_hunk);
git_vector_insert(&blame->hunks, blame->current_hunk);
} else if (!hunk_starts_at_or_after_line(blame->current_hunk, wedge_line)){
/* If this hunk doesn't start between existing hunks, split a hunk up so it does */
blame->current_hunk = split_hunk_in_vector(&blame->hunks, blame->current_hunk,
wedge_line - blame->current_hunk->orig_start_line_number, true);
wedge_line - blame->current_hunk->orig_start_line_number, true,
blame);
GIT_ERROR_CHECK_ALLOC(blame->current_hunk);
}
@ -481,7 +488,7 @@ static int buffer_line_cb(
} else {
/* Create a new buffer-blame hunk with this line */
shift_hunks_by(&blame->hunks, blame->current_diff_line, 1);
blame->current_hunk = new_hunk(blame->current_diff_line, 1, 0, blame->path);
blame->current_hunk = new_hunk(blame->current_diff_line, 1, 0, blame->path, blame);
GIT_ERROR_CHECK_ALLOC(blame->current_hunk);
git_vector_insert_sorted(&blame->hunks, blame->current_hunk, NULL);
@ -529,7 +536,7 @@ int git_blame_buffer(
/* Duplicate all of the hunk structures in the reference blame */
git_vector_foreach(&reference->hunks, i, hunk) {
git_blame_hunk *h = dup_hunk(hunk);
git_blame_hunk *h = dup_hunk(hunk, blame);
GIT_ERROR_CHECK_ALLOC(h);
git_vector_insert(&blame->hunks, h);

View File

@ -9,7 +9,6 @@
#include "commit.h"
#include "blob.h"
#include "xdiff/xinclude.h"
#include "diff_xdiff.h"
/*

View File

@ -134,9 +134,9 @@ int git_branch_create(
const git_commit *commit,
int force)
{
char commit_id[GIT_OID_SHA1_HEXSIZE + 1];
char commit_id[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(commit_id, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit));
git_oid_tostr(commit_id, GIT_OID_MAX_HEXSIZE + 1, git_commit_id(commit));
return create_branch(ref_out, repository, branch_name, commit, commit_id, force);
}

View File

@ -106,10 +106,10 @@ static int cherrypick_state_cleanup(git_repository *repo)
static int cherrypick_seterr(git_commit *commit, const char *fmt)
{
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
char commit_oidstr[GIT_OID_MAX_HEXSIZE + 1];
git_error_set(GIT_ERROR_CHERRYPICK, fmt,
git_oid_tostr(commit_oidstr, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit)));
git_oid_tostr(commit_oidstr, GIT_OID_MAX_HEXSIZE + 1, git_commit_id(commit)));
return -1;
}
@ -173,7 +173,7 @@ int git_cherrypick(
git_cherrypick_options opts;
git_reference *our_ref = NULL;
git_commit *our_commit = NULL;
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
char commit_oidstr[GIT_OID_MAX_HEXSIZE + 1];
const char *commit_msg, *commit_summary;
git_str their_label = GIT_STR_INIT;
git_index *index = NULL;

View File

@ -420,7 +420,9 @@ static int clone_into(
memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
fetch_opts.update_fetchhead = 0;
fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
if (!opts->depth)
fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
if ((error = git_remote_connect_options__from_fetch_opts(&connect_opts, remote, &fetch_opts)) < 0)
goto cleanup;

View File

@ -22,6 +22,7 @@
#include "object.h"
#include "array.h"
#include "oidarray.h"
#include "grafts.h"
void git_commit__free(void *_commit)
{
@ -427,10 +428,6 @@ static int commit_parse(
buffer += tree_len;
}
/*
* TODO: commit grafts!
*/
while (git_object__parse_oid_header(&parent_id,
&buffer, buffer_end, "parent ",
opts->oid_type) == 0) {
@ -532,16 +529,41 @@ int git_commit__parse_raw(
return commit_parse(commit, data, size, &parse_options);
}
static int assign_commit_parents_from_graft(git_commit *commit, git_commit_graft *graft) {
size_t idx;
git_oid *oid;
git_array_clear(commit->parent_ids);
git_array_init_to_size(commit->parent_ids, git_array_size(graft->parents));
git_array_foreach(graft->parents, idx, oid) {
git_oid *id = git_array_alloc(commit->parent_ids);
GIT_ERROR_CHECK_ALLOC(id);
git_oid_cpy(id, oid);
}
return 0;
}
int git_commit__parse_ext(
git_commit *commit,
git_odb_object *odb_obj,
git_commit__parse_options *parse_opts)
{
return commit_parse(
commit,
git_odb_object_data(odb_obj),
git_odb_object_size(odb_obj),
parse_opts);
git_repository *repo = git_object_owner((git_object *)commit);
git_commit_graft *graft;
int error;
if ((error = commit_parse(commit, git_odb_object_data(odb_obj),
git_odb_object_size(odb_obj), parse_opts)) < 0)
return error;
/* Perform necessary grafts */
if (git_grafts_get(&graft, repo->grafts, git_odb_object_id(odb_obj)) != 0 &&
git_grafts_get(&graft, repo->shallow_grafts, git_odb_object_id(odb_obj)) != 0)
return 0;
return assign_commit_parents_from_graft(commit, graft);
}
#define GIT_COMMIT_GETTER(_rvalue, _name, _return, _invalid) \

View File

@ -138,19 +138,22 @@ static int commit_graph_parse_oid_lookup(
struct git_commit_graph_chunk *chunk_oid_lookup)
{
uint32_t i;
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_SHA1_SIZE] = {0};
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_MAX_SIZE] = {0};
size_t oid_size;
oid_size = git_oid_size(file->oid_type);
if (chunk_oid_lookup->offset == 0)
return commit_graph_error("missing OID Lookup chunk");
if (chunk_oid_lookup->length == 0)
return commit_graph_error("empty OID Lookup chunk");
if (chunk_oid_lookup->length != file->num_commits * GIT_OID_SHA1_SIZE)
if (chunk_oid_lookup->length != file->num_commits * oid_size)
return commit_graph_error("OID Lookup chunk has wrong length");
file->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
prev_oid = zero_oid;
for (i = 0; i < file->num_commits; ++i, oid += GIT_OID_SHA1_SIZE) {
if (git_oid_raw_cmp(prev_oid, oid, GIT_OID_SHA1_SIZE) >= 0)
for (i = 0; i < file->num_commits; ++i, oid += oid_size) {
if (git_oid_raw_cmp(prev_oid, oid, oid_size) >= 0)
return commit_graph_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
@ -163,11 +166,13 @@ static int commit_graph_parse_commit_data(
const unsigned char *data,
struct git_commit_graph_chunk *chunk_commit_data)
{
size_t oid_size = git_oid_size(file->oid_type);
if (chunk_commit_data->offset == 0)
return commit_graph_error("missing Commit Data chunk");
if (chunk_commit_data->length == 0)
return commit_graph_error("empty Commit Data chunk");
if (chunk_commit_data->length != file->num_commits * (GIT_OID_SHA1_SIZE + 16))
if (chunk_commit_data->length != file->num_commits * (oid_size + 16))
return commit_graph_error("Commit Data chunk has wrong length");
file->commit_data = data + chunk_commit_data->offset;
@ -209,7 +214,9 @@ int git_commit_graph_file_parse(
GIT_ASSERT_ARG(file);
if (size < sizeof(struct git_commit_graph_header) + GIT_OID_SHA1_SIZE)
checksum_size = git_oid_size(file->oid_type);
if (size < sizeof(struct git_commit_graph_header) + checksum_size)
return commit_graph_error("commit-graph is too short");
hdr = ((struct git_commit_graph_header *)data);
@ -226,8 +233,7 @@ int git_commit_graph_file_parse(
* headers, and a special zero chunk.
*/
last_chunk_offset = sizeof(struct git_commit_graph_header) + (1 + hdr->chunks) * 12;
trailer_offset = size - GIT_OID_SHA1_SIZE;
checksum_size = GIT_HASH_SHA1_SIZE;
trailer_offset = size - checksum_size;
if (trailer_offset < last_chunk_offset)
return commit_graph_error("wrong commit-graph size");
@ -295,25 +301,35 @@ int git_commit_graph_file_parse(
return 0;
}
int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file)
int git_commit_graph_new(
git_commit_graph **cgraph_out,
const char *objects_dir,
bool open_file,
git_oid_t oid_type)
{
git_commit_graph *cgraph = NULL;
int error = 0;
GIT_ASSERT_ARG(cgraph_out);
GIT_ASSERT_ARG(objects_dir);
GIT_ASSERT_ARG(oid_type);
cgraph = git__calloc(1, sizeof(git_commit_graph));
GIT_ERROR_CHECK_ALLOC(cgraph);
cgraph->oid_type = oid_type;
error = git_str_joinpath(&cgraph->filename, objects_dir, "info/commit-graph");
if (error < 0)
goto error;
if (open_file) {
error = git_commit_graph_file_open(&cgraph->file, git_str_cstr(&cgraph->filename));
error = git_commit_graph_file_open(&cgraph->file,
git_str_cstr(&cgraph->filename), oid_type);
if (error < 0)
goto error;
cgraph->checked = 1;
}
@ -326,14 +342,18 @@ error:
}
int git_commit_graph_validate(git_commit_graph *cgraph) {
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size = GIT_HASH_SHA1_SIZE;
size_t trailer_offset = cgraph->file->graph_map.len - checksum_size;
unsigned char checksum[GIT_HASH_MAX_SIZE];
git_hash_algorithm_t checksum_type;
size_t checksum_size, trailer_offset;
checksum_type = git_oid_algorithm(cgraph->oid_type);
checksum_size = git_hash_size(checksum_type);
trailer_offset = cgraph->file->graph_map.len - checksum_size;
if (cgraph->file->graph_map.len < checksum_size)
return commit_graph_error("map length too small");
if (git_hash_buf(checksum, cgraph->file->graph_map.data, trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
if (git_hash_buf(checksum, cgraph->file->graph_map.data, trailer_offset, checksum_type) < 0)
return commit_graph_error("could not calculate signature");
if (memcmp(checksum, cgraph->file->checksum, checksum_size) != 0)
return commit_graph_error("index signature mismatch");
@ -341,16 +361,32 @@ int git_commit_graph_validate(git_commit_graph *cgraph) {
return 0;
}
int git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir)
int git_commit_graph_open(
git_commit_graph **cgraph_out,
const char *objects_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
)
{
int error = git_commit_graph_new(cgraph_out, objects_dir, true);
if (!error) {
#ifndef GIT_EXPERIMENTAL_SHA256
git_oid_t oid_type = GIT_OID_SHA1;
#endif
int error;
error = git_commit_graph_new(cgraph_out, objects_dir, true,
oid_type);
if (!error)
return git_commit_graph_validate(*cgraph_out);
}
return error;
}
int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path)
int git_commit_graph_file_open(
git_commit_graph_file **file_out,
const char *path,
git_oid_t oid_type)
{
git_commit_graph_file *file;
git_file fd = -1;
@ -379,6 +415,8 @@ int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *pat
file = git__calloc(1, sizeof(git_commit_graph_file));
GIT_ERROR_CHECK_ALLOC(file);
file->oid_type = oid_type;
error = git_futils_mmap_ro(&file->graph_map, fd, 0, cgraph_size);
p_close(fd);
if (error < 0) {
@ -395,7 +433,9 @@ int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *pat
return 0;
}
int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph *cgraph)
int git_commit_graph_get_file(
git_commit_graph_file **file_out,
git_commit_graph *cgraph)
{
if (!cgraph->checked) {
int error = 0;
@ -405,7 +445,8 @@ int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph
cgraph->checked = 1;
/* Best effort */
error = git_commit_graph_file_open(&result, git_str_cstr(&cgraph->filename));
error = git_commit_graph_file_open(&result,
git_str_cstr(&cgraph->filename), cgraph->oid_type);
if (error < 0)
return error;
@ -441,6 +482,7 @@ static int git_commit_graph_entry_get_byindex(
size_t pos)
{
const unsigned char *commit_data;
size_t oid_size = git_oid_size(file->oid_type);
GIT_ASSERT_ARG(e);
GIT_ASSERT_ARG(file);
@ -450,15 +492,15 @@ static int git_commit_graph_entry_get_byindex(
return GIT_ENOTFOUND;
}
commit_data = file->commit_data + pos * (GIT_OID_SHA1_SIZE + 4 * sizeof(uint32_t));
git_oid__fromraw(&e->tree_oid, commit_data, GIT_OID_SHA1);
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE)));
commit_data = file->commit_data + pos * (oid_size + 4 * sizeof(uint32_t));
git_oid__fromraw(&e->tree_oid, commit_data, file->oid_type);
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + oid_size)));
e->parent_indices[1] = ntohl(
*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + sizeof(uint32_t))));
*((uint32_t *)(commit_data + oid_size + sizeof(uint32_t))));
e->parent_count = (e->parent_indices[0] != GIT_COMMIT_GRAPH_MISSING_PARENT)
+ (e->parent_indices[1] != GIT_COMMIT_GRAPH_MISSING_PARENT);
e->generation = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + 2 * sizeof(uint32_t))));
e->commit_time = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + 3 * sizeof(uint32_t))));
e->generation = ntohl(*((uint32_t *)(commit_data + oid_size + 2 * sizeof(uint32_t))));
e->commit_time = ntohl(*((uint32_t *)(commit_data + oid_size + 3 * sizeof(uint32_t))));
e->commit_time |= (e->generation & UINT64_C(0x3)) << UINT64_C(32);
e->generation >>= 2u;
@ -485,7 +527,7 @@ static int git_commit_graph_entry_get_byindex(
}
}
git_oid__fromraw(&e->sha1, &file->oid_lookup[pos * GIT_OID_SHA1_SIZE], GIT_OID_SHA1);
git_oid__fromraw(&e->sha1, &file->oid_lookup[pos * oid_size], file->oid_type);
return 0;
}
@ -494,8 +536,8 @@ bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, cons
git_file fd = -1;
struct stat st;
ssize_t bytes_read;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size = GIT_HASH_SHA1_SIZE;
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size = git_oid_size(file->oid_type);
/* TODO: properly open the file without access time using O_NOATIME */
fd = git_futils_open_ro(path);
@ -530,35 +572,40 @@ int git_commit_graph_entry_find(
int pos, found = 0;
uint32_t hi, lo;
const unsigned char *current = NULL;
size_t oid_size, oid_hexsize;
GIT_ASSERT_ARG(e);
GIT_ASSERT_ARG(file);
GIT_ASSERT_ARG(short_oid);
oid_size = git_oid_size(file->oid_type);
oid_hexsize = git_oid_hexsize(file->oid_type);
hi = ntohl(file->oid_fanout[(int)short_oid->id[0]]);
lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(file->oid_fanout[(int)short_oid->id[0] - 1]));
pos = git_pack__lookup_id(file->oid_lookup, GIT_OID_SHA1_SIZE, lo, hi, short_oid->id, GIT_OID_SHA1);
pos = git_pack__lookup_id(file->oid_lookup, oid_size, lo, hi,
short_oid->id, file->oid_type);
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
current = file->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
current = file->oid_lookup + (pos * oid_size);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)file->num_commits) {
current = file->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
current = file->oid_lookup + (pos * oid_size);
if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int)file->num_commits) {
if (found && len != oid_hexsize && pos + 1 < (int)file->num_commits) {
/* Check for ambiguousity */
const unsigned char *next = current + GIT_OID_SHA1_SIZE;
const unsigned char *next = current + oid_size;
if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
@ -637,11 +684,27 @@ static int packed_commit__cmp(const void *a_, const void *b_)
return git_oid_cmp(&a->sha1, &b->sha1);
}
int git_commit_graph_writer_new(git_commit_graph_writer **out, const char *objects_info_dir)
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
)
{
git_commit_graph_writer *w = git__calloc(1, sizeof(git_commit_graph_writer));
git_commit_graph_writer *w;
#ifndef GIT_EXPERIMENTAL_SHA256
git_oid_t oid_type = GIT_OID_SHA1;
#endif
GIT_ASSERT_ARG(out && objects_info_dir && oid_type);
w = git__calloc(1, sizeof(git_commit_graph_writer));
GIT_ERROR_CHECK_ALLOC(w);
w->oid_type = oid_type;
if (git_str_sets(&w->objects_info_dir, objects_info_dir) < 0) {
git__free(w);
return -1;
@ -993,8 +1056,9 @@ static int commit_graph_write(
off64_t offset;
git_str oid_lookup = GIT_STR_INIT, commit_data = GIT_STR_INIT,
extra_edge_list = GIT_STR_INIT;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size;
unsigned char checksum[GIT_HASH_MAX_SIZE];
git_hash_algorithm_t checksum_type;
size_t checksum_size, oid_size;
git_hash_ctx ctx;
struct commit_graph_write_hash_context hash_cb_data = {0};
@ -1007,8 +1071,11 @@ static int commit_graph_write(
hash_cb_data.cb_data = cb_data;
hash_cb_data.ctx = &ctx;
checksum_size = GIT_HASH_SHA1_SIZE;
error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
oid_size = git_oid_size(w->oid_type);
checksum_type = git_oid_algorithm(w->oid_type);
checksum_size = git_hash_size(checksum_type);
error = git_hash_ctx_init(&ctx, checksum_type);
if (error < 0)
return error;
cb_data = &hash_cb_data;
@ -1035,7 +1102,7 @@ static int commit_graph_write(
git_vector_foreach (&w->commits, i, packed_commit) {
error = git_str_put(&oid_lookup,
(const char *)&packed_commit->sha1.id,
GIT_OID_SHA1_SIZE);
oid_size);
if (error < 0)
goto cleanup;
@ -1052,7 +1119,7 @@ static int commit_graph_write(
error = git_str_put(&commit_data,
(const char *)&packed_commit->tree_oid.id,
GIT_OID_SHA1_SIZE);
oid_size);
if (error < 0)
goto cleanup;

View File

@ -30,6 +30,9 @@
typedef struct git_commit_graph_file {
git_map graph_map;
/* The type of object IDs in the commit graph file. */
git_oid_t oid_type;
/* The OID Fanout table. */
const uint32_t *oid_fanout;
/* The total number of commits in the graph. */
@ -84,10 +87,10 @@ typedef struct git_commit_graph_entry {
/* The index within the Extra Edge List of any parent after the first two. */
size_t extra_parents_index;
/* The SHA-1 hash of the root tree of the commit. */
/* The object ID of the root tree of the commit. */
git_oid tree_oid;
/* The SHA-1 hash of the requested commit. */
/* The object ID hash of the requested commit. */
git_oid sha1;
} git_commit_graph_entry;
@ -99,18 +102,28 @@ struct git_commit_graph {
/* The underlying commit-graph file. */
git_commit_graph_file *file;
/* The object ID types in the commit graph. */
git_oid_t oid_type;
/* Whether the commit-graph file was already checked for validity. */
bool checked;
};
/** Create a new commit-graph, optionally opening the underlying file. */
int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file);
int git_commit_graph_new(
git_commit_graph **cgraph_out,
const char *objects_dir,
bool open_file,
git_oid_t oid_type);
/** Validate the checksum of a commit graph */
int git_commit_graph_validate(git_commit_graph *cgraph);
/** Open and validate a commit-graph file. */
int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path);
int git_commit_graph_file_open(
git_commit_graph_file **file_out,
const char *path,
git_oid_t oid_type);
/*
* Attempt to get the git_commit_graph's commit-graph file. This object is
@ -134,6 +147,9 @@ struct git_commit_graph_writer {
*/
git_str objects_info_dir;
/* The object ID type of the commit graph. */
git_oid_t oid_type;
/* The list of packed commits. */
git_vector commits;
};

View File

@ -43,13 +43,18 @@ int git_commit_list_time_cmp(const void *a, const void *b)
return 0;
}
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
{
git_commit_list *git_commit_list_create(git_commit_list_node *item, git_commit_list *next) {
git_commit_list *new_list = git__malloc(sizeof(git_commit_list));
if (new_list != NULL) {
new_list->item = item;
new_list->next = *list_p;
new_list->next = next;
}
return new_list;
}
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
{
git_commit_list *new_list = git_commit_list_create(item, *list_p);
*list_p = new_list;
return new_list;
}
@ -125,7 +130,7 @@ static int commit_quick_parse(
git_oid *parent_oid;
git_commit *commit;
git_commit__parse_options parse_opts = {
GIT_OID_SHA1,
walk->repo->oid_type,
GIT_COMMIT_PARSE_QUICK
};
size_t i;
@ -176,7 +181,9 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
if (cgraph_file) {
git_commit_graph_entry e;
error = git_commit_graph_entry_find(&e, cgraph_file, &commit->oid, GIT_OID_SHA1_SIZE);
error = git_commit_graph_entry_find(&e, cgraph_file,
&commit->oid, git_oid_size(walk->repo->oid_type));
if (error == 0 && git__is_uint16(e.parent_count)) {
size_t i;
commit->generation = (uint32_t)e.generation;

View File

@ -49,6 +49,7 @@ git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk);
int git_commit_list_generation_cmp(const void *a, const void *b);
int git_commit_list_time_cmp(const void *a, const void *b);
void git_commit_list_free(git_commit_list **list_p);
git_commit_list *git_commit_list_create(git_commit_list_node *item, git_commit_list *next);
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p);
git_commit_list *git_commit_list_insert_by_date(git_commit_list_node *item, git_commit_list **list_p);
int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit);

View File

@ -26,7 +26,7 @@
typedef struct config_file {
git_futils_filestamp stamp;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
unsigned char checksum[GIT_HASH_SHA256_SIZE];
char *path;
git_array_t(struct config_file) includes;
} config_file;
@ -133,7 +133,7 @@ static int config_file_is_modified(int *modified, config_file *file)
{
config_file *include;
git_str buf = GIT_STR_INIT;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
unsigned char checksum[GIT_HASH_SHA256_SIZE];
uint32_t i;
int error = 0;
@ -145,10 +145,10 @@ static int config_file_is_modified(int *modified, config_file *file)
if ((error = git_futils_readbuffer(&buf, file->path)) < 0)
goto out;
if ((error = git_hash_buf(checksum, buf.ptr, buf.size, GIT_HASH_ALGORITHM_SHA1)) < 0)
if ((error = git_hash_buf(checksum, buf.ptr, buf.size, GIT_HASH_ALGORITHM_SHA256)) < 0)
goto out;
if (memcmp(checksum, file->checksum, GIT_HASH_SHA1_SIZE) != 0) {
if (memcmp(checksum, file->checksum, GIT_HASH_SHA256_SIZE) != 0) {
*modified = 1;
goto out;
}
@ -881,7 +881,7 @@ static int config_file_read(
goto out;
git_futils_filestamp_set_from_stat(&file->stamp, &st);
if ((error = git_hash_buf(file->checksum, contents.ptr, contents.size, GIT_HASH_ALGORITHM_SHA1)) < 0)
if ((error = git_hash_buf(file->checksum, contents.ptr, contents.size, GIT_HASH_ALGORITHM_SHA256)) < 0)
goto out;
if ((error = config_file_read_buffer(entries, repo, file, level, depth,
@ -1116,7 +1116,12 @@ static int write_on_eof(
/*
* This is pretty much the parsing, except we write out anything we don't have
*/
static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char *value)
static int config_file_write(
config_file_backend *cfg,
const char *orig_key,
const char *key,
const git_regexp *preg,
const char *value)
{
char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
@ -1131,8 +1136,9 @@ static int config_file_write(config_file_backend *cfg, const char *orig_key, con
if (cfg->locked) {
error = git_str_puts(&contents, git_str_cstr(&cfg->locked_content) == NULL ? "" : git_str_cstr(&cfg->locked_content));
} else {
if ((error = git_filebuf_open(&file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS,
GIT_CONFIG_FILE_MODE)) < 0)
if ((error = git_filebuf_open(&file, cfg->file.path,
GIT_FILEBUF_HASH_SHA256,
GIT_CONFIG_FILE_MODE)) < 0)
goto done;
/* We need to read in our own config file */

View File

@ -363,12 +363,15 @@ static int find_unique_abbrev_size(
size_t size = abbreviated_size;
git_odb *odb;
git_oid dummy;
size_t hexsize;
int error;
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
return error;
while (size < GIT_OID_SHA1_HEXSIZE) {
hexsize = git_oid_hexsize(repo->oid_type);
while (size < hexsize) {
if ((error = git_odb_exists_prefix(&dummy, odb, oid_in, size)) == 0) {
*out = (int) size;
return 0;
@ -383,7 +386,7 @@ static int find_unique_abbrev_size(
}
/* If we didn't find any shorter prefix, we have to do the whole thing */
*out = GIT_OID_SHA1_HEXSIZE;
*out = (int)hexsize;
return 0;
}
@ -397,7 +400,7 @@ static int show_suffix(
{
int error, size = 0;
char hex_oid[GIT_OID_SHA1_HEXSIZE];
char hex_oid[GIT_OID_MAX_HEXSIZE];
if ((error = find_unique_abbrev_size(&size, repo, id, abbrev_size)) < 0)
return error;
@ -414,7 +417,7 @@ static int show_suffix(
#define MAX_CANDIDATES_TAGS FLAG_BITS - 1
static int describe_not_found(const git_oid *oid, const char *message_format) {
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
char oid_str[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(oid_str, sizeof(oid_str), oid);
git_error_set(GIT_ERROR_DESCRIBE, message_format, oid_str);
@ -525,7 +528,7 @@ static int describe(
if (annotated_cnt && (git_pqueue_size(&list) == 0)) {
/*
if (debug) {
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
char oid_str[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(oid_str, sizeof(oid_str), &c->oid);
fprintf(stderr, "finished search at %s\n", oid_str);
@ -592,7 +595,7 @@ static int describe(
"head", "lightweight", "annotated",
};
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
char oid_str[GIT_OID_MAX_HEXSIZE + 1];
if (debug) {
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
@ -816,7 +819,7 @@ static int git_describe__format(
/* If we didn't find *any* tags, we fall back to the commit's id */
if (result->fallback_to_id) {
char hex_oid[GIT_OID_SHA1_HEXSIZE + 1] = {0};
char hex_oid[GIT_OID_MAX_HEXSIZE + 1] = {0};
int size = 0;
if ((error = find_unique_abbrev_size(

View File

@ -19,8 +19,10 @@
#include "git2/email.h"
struct patch_id_args {
git_diff *diff;
git_hash_ctx ctx;
git_oid result;
git_oid_t oid_type;
int first_file;
};
@ -280,17 +282,19 @@ int git_diff_find_options_init(
return 0;
}
static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
static int flush_hunk(git_oid *result, struct patch_id_args *args)
{
git_hash_ctx *ctx = &args->ctx;
git_oid hash;
unsigned short carry = 0;
int error, i;
size_t i;
int error;
if ((error = git_hash_final(hash.id, ctx)) < 0 ||
(error = git_hash_init(ctx)) < 0)
return error;
for (i = 0; i < GIT_OID_SHA1_SIZE; i++) {
for (i = 0; i < git_oid_size(args->oid_type); i++) {
carry += result->id[i] + hash.id[i];
result->id[i] = (unsigned char)carry;
carry >>= 8;
@ -338,7 +342,7 @@ static int diff_patchid_print_callback_to_buf(
if (line->origin == GIT_DIFF_LINE_FILE_HDR &&
!args->first_file &&
(error = flush_hunk(&args->result, &args->ctx) < 0))
(error = flush_hunk(&args->result, args) < 0))
goto out;
if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0)
@ -362,14 +366,19 @@ int git_diff_patchid_options_init(git_diff_patchid_options *opts, unsigned int v
int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts)
{
struct patch_id_args args;
git_hash_algorithm_t algorithm;
int error;
GIT_ERROR_CHECK_VERSION(
opts, GIT_DIFF_PATCHID_OPTIONS_VERSION, "git_diff_patchid_options");
algorithm = git_oid_algorithm(diff->opts.oid_type);
memset(&args, 0, sizeof(args));
args.diff = diff;
args.first_file = 1;
if ((error = git_hash_ctx_init(&args.ctx, GIT_HASH_ALGORITHM_SHA1)) < 0)
args.oid_type = diff->opts.oid_type;
if ((error = git_hash_ctx_init(&args.ctx, algorithm)) < 0)
goto out;
if ((error = git_diff_print(diff,
@ -378,11 +387,11 @@ int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opt
&args)) < 0)
goto out;
if ((error = (flush_hunk(&args.result, &args.ctx))) < 0)
if ((error = (flush_hunk(&args.result, &args))) < 0)
goto out;
#ifdef GIT_EXPERIMENTAL_SHA256
args.result.type = GIT_OID_SHA1;
args.result.type = diff->opts.oid_type;
#endif
git_oid_cpy(out, &args.result);

View File

@ -30,15 +30,15 @@ typedef enum {
} git_diff_origin_t;
struct git_diff {
git_refcount rc;
git_refcount rc;
git_repository *repo;
git_attr_session attrsession;
git_attr_session attrsession;
git_diff_origin_t type;
git_diff_options opts;
git_vector deltas; /* vector of git_diff_delta */
git_diff_options opts;
git_vector deltas; /* vector of git_diff_delta */
git_pool pool;
git_iterator_t old_src;
git_iterator_t new_src;
git_iterator_t old_src;
git_iterator_t new_src;
git_diff_perfdata perf;
int (*strcomp)(const char *, const char *);

View File

@ -112,7 +112,7 @@ int git_diff_file_content__init_from_diff(
case GIT_DELTA_DELETED:
has_data = use_old; break;
case GIT_DELTA_UNTRACKED:
has_data = !use_old &&
has_data = (use_old == (diff->opts.flags & GIT_DIFF_REVERSE)) &&
(diff->opts.flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) != 0;
break;
case GIT_DELTA_UNREADABLE:
@ -144,7 +144,7 @@ int git_diff_file_content__init_from_src(
if (!src->blob && !src->buf) {
fc->flags |= GIT_DIFF_FLAG__NO_DATA;
git_oid_clear(&fc->file->id, GIT_OID_SHA1);
git_oid_clear(&fc->file->id, opts->oid_type);
} else {
fc->flags |= GIT_DIFF_FLAG__LOADED;
fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
@ -154,7 +154,7 @@ int git_diff_file_content__init_from_src(
git_blob_dup((git_blob **)&fc->blob, (git_blob *) src->blob);
fc->file->size = git_blob_rawsize(src->blob);
git_oid_cpy(&fc->file->id, git_blob_id(src->blob));
fc->file->id_abbrev = GIT_OID_SHA1_HEXSIZE;
fc->file->id_abbrev = (uint16_t)git_oid_hexsize(repo->oid_type);
fc->map.len = (size_t)fc->file->size;
fc->map.data = (char *)git_blob_rawcontent(src->blob);
@ -162,10 +162,10 @@ int git_diff_file_content__init_from_src(
fc->flags |= GIT_DIFF_FLAG__FREE_BLOB;
} else {
int error;
if ((error = git_odb__hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB, GIT_OID_SHA1)) < 0)
if ((error = git_odb__hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB, opts->oid_type)) < 0)
return error;
fc->file->size = src->buflen;
fc->file->id_abbrev = GIT_OID_SHA1_HEXSIZE;
fc->file->id_abbrev = (uint16_t)git_oid_hexsize(opts->oid_type);
fc->map.len = src->buflen;
fc->map.data = (char *)src->buf;
@ -178,7 +178,7 @@ int git_diff_file_content__init_from_src(
static int diff_file_content_commit_to_str(
git_diff_file_content *fc, bool check_status)
{
char oid[GIT_OID_SHA1_HEXSIZE+1];
char oid[GIT_OID_MAX_HEXSIZE+1];
git_str content = GIT_STR_INIT;
const char *status = "";
@ -420,7 +420,7 @@ static int diff_file_content_load_workdir(
if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) {
error = git_odb__hash(
&fc->file->id, fc->map.data, fc->map.len,
GIT_OBJECT_BLOB, GIT_OID_SHA1);
GIT_OBJECT_BLOB, diff_opts->oid_type);
fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
}

View File

@ -61,8 +61,8 @@ static git_diff_delta *diff_delta__alloc(
}
delta->status = status;
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
git_oid_clear(&delta->new_file.id, GIT_OID_SHA1);
git_oid_clear(&delta->old_file.id, diff->base.opts.oid_type);
git_oid_clear(&delta->new_file.id, diff->base.opts.oid_type);
return delta;
}
@ -149,10 +149,13 @@ static int diff_delta__from_one(
const git_index_entry *entry = nitem;
bool has_old = false;
git_diff_delta *delta;
git_oid_t oid_type;
const char *matched_pathspec;
GIT_ASSERT_ARG((oitem != NULL) ^ (nitem != NULL));
oid_type = diff->base.opts.oid_type;
if (oitem) {
entry = oitem;
has_old = true;
@ -186,20 +189,23 @@ static int diff_delta__from_one(
GIT_ASSERT(status != GIT_DELTA_MODIFIED);
delta->nfiles = 1;
git_oid_clear(&delta->old_file.id, diff->base.opts.oid_type);
git_oid_clear(&delta->new_file.id, diff->base.opts.oid_type);
if (has_old) {
delta->old_file.mode = entry->mode;
delta->old_file.size = entry->file_size;
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
git_oid_cpy(&delta->old_file.id, &entry->id);
git_oid_clear(&delta->new_file.id, GIT_OID_SHA1);
delta->old_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
git_oid_clear(&delta->new_file.id, oid_type);
delta->old_file.id_abbrev = (uint16_t)git_oid_hexsize(oid_type);
} else /* ADDED, IGNORED, UNTRACKED */ {
delta->new_file.mode = entry->mode;
delta->new_file.size = entry->file_size;
delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS;
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
git_oid_clear(&delta->old_file.id, oid_type);
git_oid_cpy(&delta->new_file.id, &entry->id);
delta->new_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
delta->new_file.id_abbrev = (uint16_t)git_oid_hexsize(oid_type);
}
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
@ -225,6 +231,9 @@ static int diff_delta__from_two(
const git_oid *old_id = &old_entry->id;
git_diff_delta *delta;
const char *canonical_path = old_entry->path;
git_oid_t oid_type;
oid_type = diff->base.opts.oid_type;
if (status == GIT_DELTA_UNMODIFIED &&
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNMODIFIED))
@ -254,14 +263,14 @@ static int diff_delta__from_two(
delta->old_file.size = old_entry->file_size;
delta->old_file.mode = old_mode;
git_oid_cpy(&delta->old_file.id, old_id);
delta->old_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
delta->old_file.id_abbrev = (uint16_t)git_oid_hexsize(oid_type);
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID |
GIT_DIFF_FLAG_EXISTS;
}
if (!git_index_entry_is_conflict(new_entry)) {
git_oid_cpy(&delta->new_file.id, new_id);
delta->new_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
delta->new_file.id_abbrev = (uint16_t)git_oid_hexsize(oid_type);
delta->new_file.size = new_entry->file_size;
delta->new_file.mode = new_mode;
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
@ -490,6 +499,14 @@ static int diff_generated_apply_options(
return -1;
}
if (!diff->base.opts.oid_type) {
diff->base.opts.oid_type = repo->oid_type;
} else if (diff->base.opts.oid_type != repo->oid_type) {
git_error_set(GIT_ERROR_INVALID,
"specified object ID type does not match repository object ID type");
return -1;
}
/* flag INCLUDE_TYPECHANGE_TREES implies INCLUDE_TYPECHANGE */
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE_TREES))
diff->base.opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE;
@ -603,7 +620,7 @@ int git_diff__oid_for_file(
entry.mode = mode;
entry.file_size = (uint32_t)size;
entry.path = (char *)path;
git_oid_clear(&entry.id, GIT_OID_SHA1);
git_oid_clear(&entry.id, diff->opts.oid_type);
return git_diff__oid_for_entry(out, diff, &entry, mode, NULL);
}
@ -624,7 +641,7 @@ int git_diff__oid_for_entry(
GIT_ASSERT(d->type == GIT_DIFF_TYPE_GENERATED);
diff = (git_diff_generated *)d;
git_oid_clear(out, GIT_OID_SHA1);
git_oid_clear(out, diff->base.opts.oid_type);
if (git_repository_workdir_path(&full_path, diff->base.repo, entry.path) < 0)
return -1;
@ -660,7 +677,8 @@ int git_diff__oid_for_entry(
git_error_clear();
}
} else if (S_ISLNK(mode)) {
error = git_odb__hashlink(out, full_path.ptr, GIT_OID_SHA1);
error = git_odb__hashlink(out, full_path.ptr,
diff->base.opts.oid_type);
diff->base.perf.oid_calculations++;
} else if (!git__is_sizet(entry.file_size)) {
git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'",
@ -676,7 +694,8 @@ int git_diff__oid_for_entry(
else {
error = git_odb__hashfd_filtered(
out, fd, (size_t)entry.file_size,
GIT_OBJECT_BLOB, GIT_OID_SHA1, fl);
GIT_OBJECT_BLOB, diff->base.opts.oid_type,
fl);
p_close(fd);
diff->base.perf.oid_calculations++;
}
@ -785,7 +804,7 @@ static int maybe_modified(
git_diff_generated *diff,
diff_in_progress *info)
{
git_oid noid = GIT_OID_SHA1_ZERO;
git_oid noid;
git_delta_t status = GIT_DELTA_MODIFIED;
const git_index_entry *oitem = info->oitem;
const git_index_entry *nitem = info->nitem;
@ -796,6 +815,8 @@ static int maybe_modified(
const char *matched_pathspec;
int error = 0;
git_oid_clear(&noid, diff->base.opts.oid_type);
if (!diff_pathspec_match(&matched_pathspec, diff, oitem))
return 0;
@ -1700,11 +1721,11 @@ int git_diff__commit(
*out = NULL;
if ((parents = git_commit_parentcount(commit)) > 1) {
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
char commit_oidstr[GIT_OID_MAX_HEXSIZE + 1];
error = -1;
git_error_set(GIT_ERROR_INVALID, "commit %s is a merge commit",
git_oid_tostr(commit_oidstr, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit)));
git_oid_tostr(commit_oidstr, GIT_OID_MAX_HEXSIZE + 1, git_commit_id(commit)));
goto on_error;
}

View File

@ -29,7 +29,7 @@ static void diff_parsed_free(git_diff *d)
git__free(diff);
}
static git_diff_parsed *diff_parsed_alloc(void)
static git_diff_parsed *diff_parsed_alloc(git_oid_t oid_type)
{
git_diff_parsed *diff;
@ -51,6 +51,7 @@ static git_diff_parsed *diff_parsed_alloc(void)
}
diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
diff->base.opts.oid_type = oid_type;
if (git_pool_init(&diff->base.pool, 1) < 0 ||
git_vector_init(&diff->patches, 0, NULL) < 0 ||
@ -67,19 +68,34 @@ static git_diff_parsed *diff_parsed_alloc(void)
int git_diff_from_buffer(
git_diff **out,
const char *content,
size_t content_len)
size_t content_len
#ifdef GIT_EXPERIMENTAL_SHA256
, git_diff_parse_options *opts
#endif
)
{
git_diff_parsed *diff;
git_patch *patch;
git_patch_parse_ctx *ctx = NULL;
git_patch_options patch_opts = GIT_PATCH_OPTIONS_INIT;
git_oid_t oid_type;
int error = 0;
*out = NULL;
diff = diff_parsed_alloc();
#ifdef GIT_EXPERIMENTAL_SHA256
oid_type = (opts && opts->oid_type) ? opts->oid_type :
GIT_OID_DEFAULT;
#else
oid_type = GIT_OID_DEFAULT;
#endif
patch_opts.oid_type = oid_type;
diff = diff_parsed_alloc(oid_type);
GIT_ERROR_CHECK_ALLOC(diff);
ctx = git_patch_parse_ctx_init(content, content_len, NULL);
ctx = git_patch_parse_ctx_init(content, content_len, &patch_opts);
GIT_ERROR_CHECK_ALLOC(ctx);
while (ctx->parse_ctx.remain_len) {

View File

@ -29,6 +29,7 @@ typedef struct {
const char *new_prefix;
uint32_t flags;
int id_strlen;
git_oid_t oid_type;
int (*strcomp)(const char *, const char *);
} diff_print_info;
@ -46,6 +47,8 @@ static int diff_print_info_init__common(
pi->payload = payload;
pi->buf = out;
GIT_ASSERT(pi->oid_type);
if (!pi->id_strlen) {
if (!repo)
pi->id_strlen = GIT_ABBREV_DEFAULT;
@ -53,8 +56,9 @@ static int diff_print_info_init__common(
return -1;
}
if (pi->id_strlen > GIT_OID_SHA1_HEXSIZE)
pi->id_strlen = GIT_OID_SHA1_HEXSIZE;
if (pi->id_strlen > 0 &&
(size_t)pi->id_strlen > git_oid_hexsize(pi->oid_type))
pi->id_strlen = (int)git_oid_hexsize(pi->oid_type);
memset(&pi->line, 0, sizeof(pi->line));
pi->line.old_lineno = -1;
@ -78,6 +82,7 @@ static int diff_print_info_init_fromdiff(
if (diff) {
pi->flags = diff->opts.flags;
pi->oid_type = diff->opts.oid_type;
pi->id_strlen = diff->opts.id_abbrev;
pi->old_prefix = diff->opts.old_prefix;
pi->new_prefix = diff->opts.new_prefix;
@ -101,6 +106,7 @@ static int diff_print_info_init_frompatch(
memset(pi, 0, sizeof(diff_print_info));
pi->flags = patch->diff_opts.flags;
pi->oid_type = patch->diff_opts.oid_type;
pi->id_strlen = patch->diff_opts.id_abbrev;
pi->old_prefix = patch->diff_opts.old_prefix;
pi->new_prefix = patch->diff_opts.new_prefix;
@ -212,7 +218,10 @@ static int diff_print_one_raw(
git_str *out = pi->buf;
int id_abbrev;
char code = git_diff_status_char(delta->status);
char start_oid[GIT_OID_SHA1_HEXSIZE+1], end_oid[GIT_OID_SHA1_HEXSIZE+1];
char start_oid[GIT_OID_MAX_HEXSIZE + 1],
end_oid[GIT_OID_MAX_HEXSIZE + 1];
size_t oid_hexsize;
bool id_is_abbrev;
GIT_UNUSED(progress);
@ -231,12 +240,21 @@ static int diff_print_one_raw(
return -1;
}
#ifdef GIT_EXPERIMENTAL_SHA256
GIT_ASSERT(delta->old_file.id.type == delta->new_file.id.type);
oid_hexsize = git_oid_hexsize(delta->old_file.id.type);
#else
oid_hexsize = GIT_OID_SHA1_HEXSIZE;
#endif
id_is_abbrev = (pi->id_strlen > 0 &&
(size_t)pi->id_strlen <= oid_hexsize);
git_oid_tostr(start_oid, pi->id_strlen + 1, &delta->old_file.id);
git_oid_tostr(end_oid, pi->id_strlen + 1, &delta->new_file.id);
git_str_printf(
out, (pi->id_strlen <= GIT_OID_SHA1_HEXSIZE) ?
":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
git_str_printf(out,
id_is_abbrev ? ":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
if (delta->similarity > 0)
@ -273,7 +291,8 @@ static int diff_print_oid_range(
git_str *out, const git_diff_delta *delta, int id_strlen,
bool print_index)
{
char start_oid[GIT_OID_SHA1_HEXSIZE+1], end_oid[GIT_OID_SHA1_HEXSIZE+1];
char start_oid[GIT_OID_MAX_HEXSIZE + 1],
end_oid[GIT_OID_MAX_HEXSIZE + 1];
if (delta->old_file.mode &&
id_strlen > delta->old_file.id_abbrev) {

View File

@ -364,7 +364,7 @@ static int insert_delete_side_of_split(
memset(&deleted->new_file, 0, sizeof(deleted->new_file));
deleted->new_file.path = deleted->old_file.path;
deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
git_oid_clear(&deleted->new_file.id, GIT_OID_SHA1);
git_oid_clear(&deleted->new_file.id, diff->opts.oid_type);
return git_vector_insert(onto, deleted);
}
@ -398,7 +398,7 @@ static int apply_splits_and_deletes(
memset(&delta->old_file, 0, sizeof(delta->old_file));
delta->old_file.path = delta->new_file.path;
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
git_oid_clear(&delta->old_file.id, diff->opts.oid_type);
}
/* clean up delta before inserting into new list */
@ -997,7 +997,7 @@ find_best_matches:
memset(&src->new_file, 0, sizeof(src->new_file));
src->new_file.path = src->old_file.path;
src->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
git_oid_clear(&src->new_file.id, GIT_OID_SHA1);
git_oid_clear(&src->new_file.id, diff->opts.oid_type);
num_updates++;
@ -1023,7 +1023,7 @@ find_best_matches:
memset(&src->old_file, 0, sizeof(src->old_file));
src->old_file.path = src->new_file.path;
src->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
git_oid_clear(&src->old_file.id, GIT_OID_SHA1);
git_oid_clear(&src->old_file.id, diff->opts.oid_type);
src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
num_rewrites--;

View File

@ -10,7 +10,7 @@
#include "common.h"
#include "diff.h"
#include "xdiff/xdiff.h"
#include "xdiff.h"
#include "patch_generate.h"
/* xdiff cannot cope with large files. these files should not be passed to

View File

@ -130,11 +130,12 @@ static int append_header(
const git_signature *author,
git_email_create_options *opts)
{
char id[GIT_OID_SHA1_HEXSIZE];
char id[GIT_OID_MAX_HEXSIZE + 1];
int error;
if ((error = git_oid_fmt(id, commit_id)) < 0 ||
(error = git_str_printf(out, "From %.*s %s\n", GIT_OID_SHA1_HEXSIZE, id, EMAIL_TIMESTAMP)) < 0 ||
git_oid_tostr(id, GIT_OID_MAX_HEXSIZE + 1, commit_id);
if ((error = git_str_printf(out, "From %s %s\n", id, EMAIL_TIMESTAMP)) < 0 ||
(error = git_str_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
(error = append_date(out, &author->when)) < 0 ||
(error = append_subject(out, patch_idx, patch_count, summary, opts)) < 0)

View File

@ -16,32 +16,51 @@
* New error handling
********************************************/
static git_error g_git_oom_error = {
static git_error oom_error = {
"Out of memory",
GIT_ERROR_NOMEMORY
};
static git_error g_git_uninitialized_error = {
static git_error uninitialized_error = {
"libgit2 has not been initialized; you must call git_libgit2_init",
GIT_ERROR_INVALID
};
static git_error tlsdata_error = {
"thread-local data initialization failure",
GIT_ERROR
};
static void set_error_from_buffer(int error_class)
{
git_error *error = &GIT_THREADSTATE->error_t;
git_str *buf = &GIT_THREADSTATE->error_buf;
git_threadstate *threadstate = git_threadstate_get();
git_error *error;
git_str *buf;
if (!threadstate)
return;
error = &threadstate->error_t;
buf = &threadstate->error_buf;
error->message = buf->ptr;
error->klass = error_class;
GIT_THREADSTATE->last_error = error;
threadstate->last_error = error;
}
static void set_error(int error_class, char *string)
{
git_str *buf = &GIT_THREADSTATE->error_buf;
git_threadstate *threadstate = git_threadstate_get();
git_str *buf;
if (!threadstate)
return;
buf = &threadstate->error_buf;
git_str_clear(buf);
if (string) {
git_str_puts(buf, string);
git__free(string);
@ -52,7 +71,12 @@ static void set_error(int error_class, char *string)
void git_error_set_oom(void)
{
GIT_THREADSTATE->last_error = &g_git_oom_error;
git_threadstate *threadstate = git_threadstate_get();
if (!threadstate)
return;
threadstate->last_error = &oom_error;
}
void git_error_set(int error_class, const char *fmt, ...)
@ -69,10 +93,18 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
#ifdef GIT_WIN32
DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;
#endif
git_threadstate *threadstate = git_threadstate_get();
int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;
git_str *buf = &GIT_THREADSTATE->error_buf;
git_str *buf;
if (!threadstate)
return;
buf = &threadstate->error_buf;
git_str_clear(buf);
if (fmt) {
git_str_vprintf(buf, fmt, ap);
if (error_class == GIT_ERROR_OS)
@ -81,7 +113,7 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
if (error_class == GIT_ERROR_OS) {
#ifdef GIT_WIN32
char * win32_error = git_win32_get_error_message(win32_error_code);
char *win32_error = git_win32_get_error_message(win32_error_code);
if (win32_error) {
git_str_puts(buf, win32_error);
git__free(win32_error);
@ -103,10 +135,16 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
int git_error_set_str(int error_class, const char *string)
{
git_str *buf = &GIT_THREADSTATE->error_buf;
git_threadstate *threadstate = git_threadstate_get();
git_str *buf;
GIT_ASSERT_ARG(string);
if (!threadstate)
return -1;
buf = &threadstate->error_buf;
git_str_clear(buf);
git_str_puts(buf, string);
@ -119,9 +157,14 @@ int git_error_set_str(int error_class, const char *string)
void git_error_clear(void)
{
if (GIT_THREADSTATE->last_error != NULL) {
git_threadstate *threadstate = git_threadstate_get();
if (!threadstate)
return;
if (threadstate->last_error != NULL) {
set_error(0, NULL);
GIT_THREADSTATE->last_error = NULL;
threadstate->last_error = NULL;
}
errno = 0;
@ -132,17 +175,29 @@ void git_error_clear(void)
const git_error *git_error_last(void)
{
git_threadstate *threadstate;
/* If the library is not initialized, return a static error. */
if (!git_libgit2_init_count())
return &g_git_uninitialized_error;
return &uninitialized_error;
return GIT_THREADSTATE->last_error;
if ((threadstate = git_threadstate_get()) == NULL)
return &tlsdata_error;
return threadstate->last_error;
}
int git_error_state_capture(git_error_state *state, int error_code)
{
git_error *error = GIT_THREADSTATE->last_error;
git_str *error_buf = &GIT_THREADSTATE->error_buf;
git_threadstate *threadstate = git_threadstate_get();
git_error *error;
git_str *error_buf;
if (!threadstate)
return -1;
error = threadstate->last_error;
error_buf = &threadstate->error_buf;
memset(state, 0, sizeof(git_error_state));
@ -150,13 +205,13 @@ int git_error_state_capture(git_error_state *state, int error_code)
return 0;
state->error_code = error_code;
state->oom = (error == &g_git_oom_error);
state->oom = (error == &oom_error);
if (error) {
state->error_msg.klass = error->klass;
if (state->oom)
state->error_msg.message = g_git_oom_error.message;
state->error_msg.message = oom_error.message;
else
state->error_msg.message = git_str_detach(error_buf);
}

View File

@ -17,9 +17,9 @@
#include "remote.h"
#include "refspec.h"
#include "pack.h"
#include "netops.h"
#include "repository.h"
#include "refs.h"
#include "transports/smart.h"
static int maybe_want(git_remote *remote, git_remote_head *head, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
{
@ -59,8 +59,10 @@ static int mark_local(git_remote *remote)
return -1;
git_vector_foreach(&remote->refs, i, head) {
/* If we have the object, mark it so we don't ask for it */
if (git_odb_exists(odb, &head->oid))
/* If we have the object, mark it so we don't ask for it.
However if we are unshallowing, we need to ask for it
even though the head exists locally. */
if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid))
head->local = 1;
else
remote->need_pack = 1;
@ -76,7 +78,7 @@ static int maybe_want_oid(git_remote *remote, git_refspec *spec)
oid_head = git__calloc(1, sizeof(git_remote_head));
GIT_ERROR_CHECK_ALLOC(oid_head);
git_oid__fromstr(&oid_head->oid, spec->src, GIT_OID_SHA1);
git_oid__fromstr(&oid_head->oid, spec->src, remote->repo->oid_type);
if (spec->dst) {
oid_head->name = git__strdup(spec->dst);
@ -137,7 +139,7 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
/* Handle explicitly specified OID specs */
git_vector_foreach(&remote->active_refspecs, i, spec) {
if (!git_oid__is_hexstr(spec->src, GIT_OID_SHA1))
if (!git_oid__is_hexstr(spec->src, remote->repo->oid_type))
continue;
if (!(remote_caps & oid_mask)) {
@ -166,9 +168,15 @@ cleanup:
int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
{
git_transport *t = remote->transport;
int error;
remote->need_pack = 0;
if (opts) {
GIT_ASSERT_ARG(opts->depth >= 0);
remote->nego.depth = opts->depth;
}
if (filter_wants(remote, opts) < 0)
return -1;
@ -180,20 +188,40 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
* Now we have everything set up so we can start tell the
* server what we want and what we have.
*/
return t->negotiate_fetch(t,
remote->nego.refs = (const git_remote_head * const *)remote->refs.contents;
remote->nego.refs_len = remote->refs.length;
if (git_repository__shallow_roots(&remote->nego.shallow_roots,
&remote->nego.shallow_roots_len,
remote->repo) < 0)
return -1;
error = t->negotiate_fetch(t,
remote->repo,
(const git_remote_head * const *)remote->refs.contents,
remote->refs.length);
&remote->nego);
git__free(remote->nego.shallow_roots);
return error;
}
int git_fetch_download_pack(git_remote *remote)
{
git_oidarray shallow_roots = { NULL };
git_transport *t = remote->transport;
int error;
if (!remote->need_pack)
return 0;
return t->download_pack(t, remote->repo, &remote->stats);
if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0 ||
(error = t->shallow_roots(&shallow_roots, t)) != 0)
return error;
error = git_repository__shallow_roots_write(remote->repo, &shallow_roots);
git_oidarray_dispose(&shallow_roots);
return error;
}
int git_fetch_options_init(git_fetch_options *opts, unsigned int version)

View File

@ -11,8 +11,6 @@
#include "git2/remote.h"
#include "netops.h"
int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts);
int git_fetch_download_pack(git_remote *remote);

View File

@ -105,15 +105,14 @@ static int fetchhead_ref_write(
git_filebuf *file,
git_fetchhead_ref *fetchhead_ref)
{
char oid[GIT_OID_SHA1_HEXSIZE + 1];
char oid[GIT_OID_MAX_HEXSIZE + 1];
const char *type, *name;
int head = 0;
GIT_ASSERT_ARG(file);
GIT_ASSERT_ARG(fetchhead_ref);
git_oid_fmt(oid, &fetchhead_ref->oid);
oid[GIT_OID_SHA1_HEXSIZE] = '\0';
git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, &fetchhead_ref->oid);
if (git__prefixcmp(fetchhead_ref->ref_name, GIT_REFS_HEADS_DIR) == 0) {
type = "branch ";
@ -174,7 +173,8 @@ static int fetchhead_ref_parse(
git_str *ref_name,
const char **remote_url,
char *line,
size_t line_num)
size_t line_num,
git_oid_t oid_type)
{
char *oid_str, *is_merge_str, *desc, *name = NULL;
const char *type = NULL;
@ -196,13 +196,13 @@ static int fetchhead_ref_parse(
*is_merge = 1;
}
if (strlen(oid_str) != GIT_OID_SHA1_HEXSIZE) {
if (strlen(oid_str) != git_oid_hexsize(oid_type)) {
git_error_set(GIT_ERROR_FETCHHEAD,
"invalid object ID in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
if (git_oid__fromstr(oid, oid_str, GIT_OID_SHA1) < 0) {
if (git_oid__fromstr(oid, oid_str, oid_type) < 0) {
const git_error *oid_err = git_error_last();
const char *err_msg = oid_err ? oid_err->message : "invalid object ID";
@ -269,7 +269,8 @@ static int fetchhead_ref_parse(
return error;
}
int git_repository_fetchhead_foreach(git_repository *repo,
int git_repository_fetchhead_foreach(
git_repository *repo,
git_repository_fetchhead_foreach_cb cb,
void *payload)
{
@ -296,8 +297,9 @@ int git_repository_fetchhead_foreach(git_repository *repo,
while ((line = git__strsep(&buffer, "\n")) != NULL) {
++line_num;
if ((error = fetchhead_ref_parse(
&oid, &is_merge, &name, &remote_url, line, line_num)) < 0)
if ((error = fetchhead_ref_parse(&oid, &is_merge, &name,
&remote_url, line, line_num,
repo->oid_type)) < 0)
goto done;
if (git_str_len(&name) > 0)

272
src/libgit2/grafts.c Normal file
View File

@ -0,0 +1,272 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "grafts.h"
#include "futils.h"
#include "oid.h"
#include "oidarray.h"
#include "parse.h"
struct git_grafts {
/* Map of `git_commit_graft`s */
git_oidmap *commits;
/* Type of object IDs */
git_oid_t oid_type;
/* File backing the graft. NULL if it's an in-memory graft */
char *path;
unsigned char path_checksum[GIT_HASH_SHA256_SIZE];
};
int git_grafts_new(git_grafts **out, git_oid_t oid_type)
{
git_grafts *grafts;
GIT_ASSERT_ARG(out && oid_type);
grafts = git__calloc(1, sizeof(*grafts));
GIT_ERROR_CHECK_ALLOC(grafts);
if ((git_oidmap_new(&grafts->commits)) < 0) {
git__free(grafts);
return -1;
}
grafts->oid_type = oid_type;
*out = grafts;
return 0;
}
int git_grafts_open(
git_grafts **out,
const char *path,
git_oid_t oid_type)
{
git_grafts *grafts = NULL;
int error;
GIT_ASSERT_ARG(out && path && oid_type);
if ((error = git_grafts_new(&grafts, oid_type)) < 0)
goto error;
grafts->path = git__strdup(path);
GIT_ERROR_CHECK_ALLOC(grafts->path);
if ((error = git_grafts_refresh(grafts)) < 0)
goto error;
*out = grafts;
error:
if (error < 0)
git_grafts_free(grafts);
return error;
}
int git_grafts_open_or_refresh(
git_grafts **out,
const char *path,
git_oid_t oid_type)
{
GIT_ASSERT_ARG(out && path && oid_type);
return *out ? git_grafts_refresh(*out) : git_grafts_open(out, path, oid_type);
}
void git_grafts_free(git_grafts *grafts)
{
if (!grafts)
return;
git__free(grafts->path);
git_grafts_clear(grafts);
git_oidmap_free(grafts->commits);
git__free(grafts);
}
void git_grafts_clear(git_grafts *grafts)
{
git_commit_graft *graft;
if (!grafts)
return;
git_oidmap_foreach_value(grafts->commits, graft, {
git__free(graft->parents.ptr);
git__free(graft);
});
git_oidmap_clear(grafts->commits);
}
int git_grafts_refresh(git_grafts *grafts)
{
git_str contents = GIT_STR_INIT;
int error, updated = 0;
GIT_ASSERT_ARG(grafts);
if (!grafts->path)
return 0;
if ((error = git_futils_readbuffer_updated(&contents, grafts->path,
grafts->path_checksum, &updated)) < 0) {
if (error == GIT_ENOTFOUND) {
git_grafts_clear(grafts);
error = 0;
}
goto cleanup;
}
if (!updated) {
goto cleanup;
}
if ((error = git_grafts_parse(grafts, contents.ptr, contents.size)) < 0)
goto cleanup;
cleanup:
git_str_dispose(&contents);
return error;
}
int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len)
{
git_array_oid_t parents = GIT_ARRAY_INIT;
git_parse_ctx parser;
int error;
git_grafts_clear(grafts);
if ((error = git_parse_ctx_init(&parser, buf, len)) < 0)
goto error;
for (; parser.remain_len; git_parse_advance_line(&parser)) {
git_oid graft_oid;
if ((error = git_parse_advance_oid(&graft_oid, &parser, grafts->oid_type)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid graft OID at line %" PRIuZ, parser.line_num);
goto error;
}
while (parser.line_len && git_parse_advance_expected(&parser, "\n", 1) != 0) {
git_oid *id = git_array_alloc(parents);
GIT_ERROR_CHECK_ALLOC(id);
if ((error = git_parse_advance_expected(&parser, " ", 1)) < 0 ||
(error = git_parse_advance_oid(id, &parser, grafts->oid_type)) < 0) {
git_error_set(GIT_ERROR_GRAFTS, "invalid parent OID at line %" PRIuZ, parser.line_num);
goto error;
}
}
if ((error = git_grafts_add(grafts, &graft_oid, parents)) < 0)
goto error;
git_array_clear(parents);
}
error:
git_array_clear(parents);
return error;
}
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents)
{
git_commit_graft *graft;
git_oid *parent_oid;
int error;
size_t i;
GIT_ASSERT_ARG(grafts && oid);
graft = git__calloc(1, sizeof(*graft));
GIT_ERROR_CHECK_ALLOC(graft);
git_array_init_to_size(graft->parents, git_array_size(parents));
git_array_foreach(parents, i, parent_oid) {
git_oid *id = git_array_alloc(graft->parents);
GIT_ERROR_CHECK_ALLOC(id);
git_oid_cpy(id, parent_oid);
}
git_oid_cpy(&graft->oid, oid);
if ((error = git_grafts_remove(grafts, &graft->oid)) < 0 && error != GIT_ENOTFOUND)
goto cleanup;
if ((error = git_oidmap_set(grafts->commits, &graft->oid, graft)) < 0)
goto cleanup;
return 0;
cleanup:
git_array_clear(graft->parents);
git__free(graft);
return error;
}
int git_grafts_remove(git_grafts *grafts, const git_oid *oid)
{
git_commit_graft *graft;
int error;
GIT_ASSERT_ARG(grafts && oid);
if ((graft = git_oidmap_get(grafts->commits, oid)) == NULL)
return GIT_ENOTFOUND;
if ((error = git_oidmap_delete(grafts->commits, oid)) < 0)
return error;
git__free(graft->parents.ptr);
git__free(graft);
return 0;
}
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid)
{
GIT_ASSERT_ARG(out && grafts && oid);
if ((*out = git_oidmap_get(grafts->commits, oid)) == NULL)
return GIT_ENOTFOUND;
return 0;
}
int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts)
{
git_array_oid_t array = GIT_ARRAY_INIT;
const git_oid *oid;
size_t existing, i = 0;
GIT_ASSERT_ARG(out && grafts);
if ((existing = git_oidmap_size(grafts->commits)) > 0)
git_array_init_to_size(array, existing);
while (git_oidmap_iterate(NULL, grafts->commits, &i, &oid) == 0) {
git_oid *cpy = git_array_alloc(array);
GIT_ERROR_CHECK_ALLOC(cpy);
git_oid_cpy(cpy, oid);
}
*out = array.ptr;
*out_len = array.size;
return 0;
}
size_t git_grafts_size(git_grafts *grafts)
{
return git_oidmap_size(grafts->commits);
}

36
src/libgit2/grafts.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_graft_h__
#define INCLUDE_graft_h__
#include "common.h"
#include "oidarray.h"
#include "oidmap.h"
/** graft commit */
typedef struct {
git_oid oid;
git_array_oid_t parents;
} git_commit_graft;
typedef struct git_grafts git_grafts;
int git_grafts_new(git_grafts **out, git_oid_t oid_type);
int git_grafts_open(git_grafts **out, const char *path, git_oid_t oid_type);
int git_grafts_open_or_refresh(git_grafts **out, const char *path, git_oid_t oid_type);
void git_grafts_free(git_grafts *grafts);
void git_grafts_clear(git_grafts *grafts);
int git_grafts_refresh(git_grafts *grafts);
int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len);
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents);
int git_grafts_remove(git_grafts *grafts, const git_oid *oid);
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid);
int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts);
size_t git_grafts_size(git_grafts *grafts);
#endif

View File

@ -42,7 +42,7 @@ static int ident_find_id(
static int ident_insert_id(
git_str *to, const git_str *from, const git_filter_source *src)
{
char oid[GIT_OID_SHA1_HEXSIZE+1];
char oid[GIT_OID_MAX_HEXSIZE + 1];
const char *id_start, *id_end, *from_end = from->ptr + from->size;
size_t need_size;
@ -57,7 +57,7 @@ static int ident_insert_id(
return GIT_PASSTHROUGH;
need_size = (size_t)(id_start - from->ptr) +
5 /* "$Id: " */ + GIT_OID_SHA1_HEXSIZE + 2 /* " $" */ +
5 /* "$Id: " */ + GIT_OID_MAX_HEXSIZE + 2 /* " $" */ +
(size_t)(from_end - id_end);
if (git_str_grow(to, need_size) < 0)
@ -65,7 +65,7 @@ static int ident_insert_id(
git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
git_str_put(to, "$Id: ", 5);
git_str_put(to, oid, GIT_OID_SHA1_HEXSIZE);
git_str_puts(to, oid);
git_str_put(to, " $", 2);
git_str_put(to, id_end, (size_t)(from_end - id_end));

View File

@ -32,8 +32,6 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
unsigned int flags,
git_index_matched_path_cb cb, void *payload);
#define minimal_entry_size (offsetof(struct entry_short, path))
static const size_t INDEX_HEADER_SIZE = 12;
static const unsigned int INDEX_VERSION_NUMBER_DEFAULT = 2;
@ -65,7 +63,7 @@ struct entry_time {
uint32_t nanoseconds;
};
struct entry_short {
struct entry_common {
struct entry_time ctime;
struct entry_time mtime;
uint32_t dev;
@ -74,25 +72,35 @@ struct entry_short {
uint32_t uid;
uint32_t gid;
uint32_t file_size;
unsigned char oid[GIT_OID_SHA1_SIZE];
uint16_t flags;
char path[1]; /* arbitrary length */
};
struct entry_long {
struct entry_time ctime;
struct entry_time mtime;
uint32_t dev;
uint32_t ino;
uint32_t mode;
uint32_t uid;
uint32_t gid;
uint32_t file_size;
unsigned char oid[GIT_OID_SHA1_SIZE];
uint16_t flags;
uint16_t flags_extended;
char path[1]; /* arbitrary length */
};
#define entry_short(oid_size) \
struct { \
struct entry_common common; \
unsigned char oid[oid_size]; \
uint16_t flags; \
char path[1]; /* arbitrary length */ \
}
#define entry_long(oid_size) \
struct { \
struct entry_common common; \
unsigned char oid[oid_size]; \
uint16_t flags; \
uint16_t flags_extended; \
char path[1]; /* arbitrary length */ \
}
typedef entry_short(GIT_OID_SHA1_SIZE) index_entry_short_sha1;
typedef entry_long(GIT_OID_SHA1_SIZE) index_entry_long_sha1;
#ifdef GIT_EXPERIMENTAL_SHA256
typedef entry_short(GIT_OID_SHA256_SIZE) index_entry_short_sha256;
typedef entry_long(GIT_OID_SHA256_SIZE) index_entry_long_sha256;
#endif
#undef entry_short
#undef entry_long
struct entry_srch_key {
const char *path;
@ -115,12 +123,12 @@ struct reuc_entry_internal {
bool git_index__enforce_unsaved_safety = false;
/* local declarations */
static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size);
static int read_extension(size_t *read_len, git_index *index, size_t checksum_size, const char *buffer, size_t buffer_size);
static int read_header(struct index_header *dest, const void *buffer);
static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
static bool is_index_extended(git_index *index);
static int write_index(unsigned char checksum[GIT_HASH_SHA1_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file);
static int write_index(unsigned char checksum[GIT_HASH_MAX_SIZE], size_t *checksum_size, git_index *index, git_filebuf *file);
static void index_entry_free(git_index_entry *entry);
static void index_entry_reuc_free(git_index_reuc_entry *reuc);
@ -401,7 +409,10 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case)
git_vector_sort(&index->reuc);
}
int git_index_open(git_index **index_out, const char *index_path)
int git_index__open(
git_index **index_out,
const char *index_path,
git_oid_t oid_type)
{
git_index *index;
int error = -1;
@ -411,6 +422,8 @@ int git_index_open(git_index **index_out, const char *index_path)
index = git__calloc(1, sizeof(git_index));
GIT_ERROR_CHECK_ALLOC(index);
index->oid_type = oid_type;
if (git_pool_init(&index->tree_pool, 1) < 0)
goto fail;
@ -451,10 +464,34 @@ fail:
return error;
}
#ifdef GIT_EXPERIMENTAL_SHA256
int git_index_open(git_index **index_out, const char *index_path, git_oid_t oid_type)
{
return git_index__open(index_out, index_path, oid_type);
}
#else
int git_index_open(git_index **index_out, const char *index_path)
{
return git_index__open(index_out, index_path, GIT_OID_SHA1);
}
#endif
int git_index__new(git_index **out, git_oid_t oid_type)
{
return git_index__open(out, NULL, oid_type);
}
#ifdef GIT_EXPERIMENTAL_SHA256
int git_index_new(git_index **out, git_oid_t oid_type)
{
return git_index__new(out, oid_type);
}
#else
int git_index_new(git_index **out)
{
return git_index_open(out, NULL);
return git_index__new(out, GIT_OID_SHA1);
}
#endif
static void index_free(git_index *index)
{
@ -620,8 +657,8 @@ static int compare_checksum(git_index *index)
{
int fd;
ssize_t bytes_read;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size = GIT_HASH_SHA1_SIZE;
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size = git_oid_size(index->oid_type);
if ((fd = p_open(index->index_file_path, O_RDONLY)) < 0)
return fd;
@ -2306,6 +2343,7 @@ static int index_error_invalid(const char *message)
static int read_reuc(git_index *index, const char *buffer, size_t size)
{
const char *endptr;
size_t oid_size = git_oid_size(index->oid_type);
size_t len;
int i;
@ -2354,16 +2392,16 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
for (i = 0; i < 3; i++) {
if (!lost->mode[i])
continue;
if (size < GIT_OID_SHA1_SIZE) {
if (size < oid_size) {
index_entry_reuc_free(lost);
return index_error_invalid("reading reuc entry oid");
}
if (git_oid__fromraw(&lost->oid[i], (const unsigned char *) buffer, GIT_OID_SHA1) < 0)
if (git_oid__fromraw(&lost->oid[i], (const unsigned char *) buffer, index->oid_type) < 0)
return -1;
size -= GIT_OID_SHA1_SIZE;
buffer += GIT_OID_SHA1_SIZE;
size -= oid_size;
buffer += oid_size;
}
/* entry was read successfully - insert into reuc vector */
@ -2433,73 +2471,157 @@ out_err:
return 0;
}
static size_t index_entry_size(size_t path_len, size_t varint_len, uint32_t flags)
GIT_INLINE(size_t) index_entry_path_offset(
git_oid_t oid_type,
uint32_t flags)
{
if (oid_type == GIT_OID_SHA1)
return (flags & GIT_INDEX_ENTRY_EXTENDED) ?
offsetof(index_entry_long_sha1, path) :
offsetof(index_entry_short_sha1, path);
#ifdef GIT_EXPERIMENTAL_SHA256
else if (oid_type == GIT_OID_SHA256)
return (flags & GIT_INDEX_ENTRY_EXTENDED) ?
offsetof(index_entry_long_sha256, path) :
offsetof(index_entry_short_sha256, path);
#endif
git_error_set(GIT_ERROR_INTERNAL, "invalid oid type");
return 0;
}
GIT_INLINE(size_t) index_entry_flags_offset(git_oid_t oid_type)
{
if (oid_type == GIT_OID_SHA1)
return offsetof(index_entry_long_sha1, flags_extended);
#ifdef GIT_EXPERIMENTAL_SHA256
else if (oid_type == GIT_OID_SHA256)
return offsetof(index_entry_long_sha256, flags_extended);
#endif
git_error_set(GIT_ERROR_INTERNAL, "invalid oid type");
return 0;
}
static size_t index_entry_size(
size_t path_len,
size_t varint_len,
git_oid_t oid_type,
uint32_t flags)
{
size_t offset, size;
if (!(offset = index_entry_path_offset(oid_type, flags)))
return 0;
if (varint_len) {
if (flags & GIT_INDEX_ENTRY_EXTENDED)
return offsetof(struct entry_long, path) + path_len + 1 + varint_len;
else
return offsetof(struct entry_short, path) + path_len + 1 + varint_len;
if (GIT_ADD_SIZET_OVERFLOW(&size, offset, path_len) ||
GIT_ADD_SIZET_OVERFLOW(&size, size, 1) ||
GIT_ADD_SIZET_OVERFLOW(&size, size, varint_len))
return 0;
} else {
#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
if (flags & GIT_INDEX_ENTRY_EXTENDED)
return entry_size(struct entry_long, path_len);
else
return entry_size(struct entry_short, path_len);
#undef entry_size
if (GIT_ADD_SIZET_OVERFLOW(&size, offset, path_len) ||
GIT_ADD_SIZET_OVERFLOW(&size, size, 8))
return 0;
size &= ~7;
}
return size;
}
static int read_entry(
git_index_entry **out,
size_t *out_size,
git_index *index,
size_t checksum_size,
const void *buffer,
size_t buffer_size,
const char *last)
{
size_t path_length, entry_size;
size_t path_length, path_offset, entry_size;
const char *path_ptr;
struct entry_short source;
struct entry_common *source_common;
index_entry_short_sha1 source_sha1;
#ifdef GIT_EXPERIMENTAL_SHA256
index_entry_short_sha256 source_sha256;
#endif
git_index_entry entry = {{0}};
bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP;
char *tmp_path = NULL;
size_t checksum_size = GIT_HASH_SHA1_SIZE;
size_t minimal_entry_size = index_entry_path_offset(index->oid_type, 0);
if (checksum_size + minimal_entry_size > buffer_size)
return -1;
/* buffer is not guaranteed to be aligned */
memcpy(&source, buffer, sizeof(struct entry_short));
switch (index->oid_type) {
case GIT_OID_SHA1:
source_common = &source_sha1.common;
memcpy(&source_sha1, buffer, sizeof(source_sha1));
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
source_common = &source_sha256.common;
memcpy(&source_sha256, buffer, sizeof(source_sha256));
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
entry.ctime.seconds = (git_time_t)ntohl(source.ctime.seconds);
entry.ctime.nanoseconds = ntohl(source.ctime.nanoseconds);
entry.mtime.seconds = (git_time_t)ntohl(source.mtime.seconds);
entry.mtime.nanoseconds = ntohl(source.mtime.nanoseconds);
entry.dev = ntohl(source.dev);
entry.ino = ntohl(source.ino);
entry.mode = ntohl(source.mode);
entry.uid = ntohl(source.uid);
entry.gid = ntohl(source.gid);
entry.file_size = ntohl(source.file_size);
entry.flags = ntohs(source.flags);
entry.ctime.seconds = (git_time_t)ntohl(source_common->ctime.seconds);
entry.ctime.nanoseconds = ntohl(source_common->ctime.nanoseconds);
entry.mtime.seconds = (git_time_t)ntohl(source_common->mtime.seconds);
entry.mtime.nanoseconds = ntohl(source_common->mtime.nanoseconds);
entry.dev = ntohl(source_common->dev);
entry.ino = ntohl(source_common->ino);
entry.mode = ntohl(source_common->mode);
entry.uid = ntohl(source_common->uid);
entry.gid = ntohl(source_common->gid);
entry.file_size = ntohl(source_common->file_size);
if (git_oid__fromraw(&entry.id, source.oid, GIT_OID_SHA1) < 0)
switch (index->oid_type) {
case GIT_OID_SHA1:
if (git_oid__fromraw(&entry.id, source_sha1.oid,
GIT_OID_SHA1) < 0)
return -1;
entry.flags = ntohs(source_sha1.flags);
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
if (git_oid__fromraw(&entry.id, source_sha256.oid,
GIT_OID_SHA256) < 0)
return -1;
entry.flags = ntohs(source_sha256.flags);
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
if (!(path_offset = index_entry_path_offset(index->oid_type, entry.flags)))
return -1;
if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) {
uint16_t flags_raw;
size_t flags_offset;
flags_offset = offsetof(struct entry_long, flags_extended);
memcpy(&flags_raw, (const char *) buffer + flags_offset,
sizeof(flags_raw));
if (!(flags_offset = index_entry_flags_offset(index->oid_type)))
return -1;
memcpy(&flags_raw, (const char *)buffer + flags_offset, sizeof(flags_raw));
flags_raw = ntohs(flags_raw);
memcpy(&entry.flags_extended, &flags_raw, sizeof(flags_raw));
path_ptr = (const char *) buffer + offsetof(struct entry_long, path);
} else
path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
path_ptr = (const char *)buffer + path_offset;
} else {
path_ptr = (const char *)buffer + path_offset;
}
if (!compressed) {
path_length = entry.flags & GIT_INDEX_ENTRY_NAMEMASK;
@ -2511,12 +2633,12 @@ static int read_entry(
path_end = memchr(path_ptr, '\0', buffer_size);
if (path_end == NULL)
return -1;
return index_error_invalid("invalid path name");
path_length = path_end - path_ptr;
}
entry_size = index_entry_size(path_length, 0, entry.flags);
entry_size = index_entry_size(path_length, 0, index->oid_type, entry.flags);
entry.path = (char *)path_ptr;
} else {
size_t varint_len, last_len, prefix_len, suffix_len, path_len;
@ -2542,15 +2664,18 @@ static int read_entry(
memcpy(tmp_path, last, prefix_len);
memcpy(tmp_path + prefix_len, path_ptr + varint_len, suffix_len + 1);
entry_size = index_entry_size(suffix_len, varint_len, entry.flags);
entry_size = index_entry_size(suffix_len, varint_len, index->oid_type, entry.flags);
entry.path = tmp_path;
}
if (entry_size == 0)
return -1;
if (checksum_size + entry_size > buffer_size)
if (checksum_size + entry_size > buffer_size) {
git_error_set(GIT_ERROR_INTERNAL, "invalid index checksum");
return -1;
}
if (index_entry_dup(out, index, &entry) < 0) {
git__free(tmp_path);
@ -2579,11 +2704,10 @@ static int read_header(struct index_header *dest, const void *buffer)
return 0;
}
static int read_extension(size_t *read_len, git_index *index, const char *buffer, size_t buffer_size)
static int read_extension(size_t *read_len, git_index *index, size_t checksum_size, const char *buffer, size_t buffer_size)
{
struct index_extension dest;
size_t total_size;
size_t checksum_size = GIT_HASH_SHA1_SIZE;
/* buffer is not guaranteed to be aligned */
memcpy(&dest, buffer, sizeof(struct index_extension));
@ -2602,7 +2726,7 @@ static int read_extension(size_t *read_len, git_index *index, const char *buffer
if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') {
/* tree cache */
if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) {
if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, &index->tree_pool) < 0)
if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size, index->oid_type, &index->tree_pool) < 0)
return -1;
} else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
if (read_reuc(index, buffer + 8, dest.extension_size) < 0)
@ -2630,8 +2754,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
int error = 0;
unsigned int i;
struct index_header header = { 0 };
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size = GIT_HASH_SHA1_SIZE;
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size = git_hash_size(git_oid_algorithm(index->oid_type));
const char *last = NULL;
const char *empty = "";
@ -2646,9 +2770,12 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
if (buffer_size < INDEX_HEADER_SIZE + checksum_size)
return index_error_invalid("insufficient buffer space");
/* Precalculate the SHA1 of the files's contents -- we'll match it to
* the provided SHA1 in the footer */
git_hash_buf(checksum, buffer, buffer_size - checksum_size, GIT_HASH_ALGORITHM_SHA1);
/*
* Precalculate the hash of the files's contents -- we'll match
* it to the provided checksum in the footer.
*/
git_hash_buf(checksum, buffer, buffer_size - checksum_size,
git_oid_algorithm(index->oid_type));
/* Parse header */
if ((error = read_header(&header, buffer)) < 0)
@ -2670,7 +2797,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
git_index_entry *entry = NULL;
size_t entry_size;
if ((error = read_entry(&entry, &entry_size, index, buffer, buffer_size, last)) < 0) {
if ((error = read_entry(&entry, &entry_size, index, checksum_size, buffer, buffer_size, last)) < 0) {
error = index_error_invalid("invalid entry");
goto done;
}
@ -2701,7 +2828,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
while (buffer_size > checksum_size) {
size_t extension_size;
if ((error = read_extension(&extension_size, index, buffer, buffer_size)) < 0) {
if ((error = read_extension(&extension_size, index, checksum_size, buffer, buffer_size)) < 0) {
goto done;
}
@ -2714,7 +2841,10 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
goto done;
}
/* 160-bit SHA-1 over the content of the index file before this checksum. */
/*
* SHA-1 or SHA-256 (depending on the repository's object format)
* over the content of the index file before this checksum.
*/
if (memcmp(checksum, buffer, checksum_size) != 0) {
error = index_error_invalid(
"calculated checksum does not match expected");
@ -2754,16 +2884,40 @@ static bool is_index_extended(git_index *index)
return (extended > 0);
}
static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char *last)
static int write_disk_entry(
git_index *index,
git_filebuf *file,
git_index_entry *entry,
const char *last)
{
void *mem = NULL;
struct entry_short ondisk;
size_t path_len, disk_size;
struct entry_common *ondisk_common;
size_t path_len, path_offset, disk_size;
int varint_len = 0;
char *path;
const char *path_start = entry->path;
size_t same_len = 0;
index_entry_short_sha1 ondisk_sha1;
index_entry_long_sha1 ondisk_ext_sha1;
#ifdef GIT_EXPERIMENTAL_SHA256
index_entry_short_sha256 ondisk_sha256;
index_entry_long_sha256 ondisk_ext_sha256;
#endif
switch (index->oid_type) {
case GIT_OID_SHA1:
ondisk_common = &ondisk_sha1.common;
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
ondisk_common = &ondisk_sha256.common;
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
path_len = ((struct entry_internal *)entry)->pathlen;
if (last) {
@ -2780,9 +2934,9 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
varint_len = git_encode_varint(NULL, 0, strlen(last) - same_len);
}
disk_size = index_entry_size(path_len, varint_len, entry->flags);
disk_size = index_entry_size(path_len, varint_len, index->oid_type, entry->flags);
if (git_filebuf_reserve(file, &mem, disk_size) < 0)
if (!disk_size || git_filebuf_reserve(file, &mem, disk_size) < 0)
return -1;
memset(mem, 0x0, disk_size);
@ -2797,35 +2951,77 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
*
* In 2038 I will be either too dead or too rich to care about this
*/
ondisk.ctime.seconds = htonl((uint32_t)entry->ctime.seconds);
ondisk.mtime.seconds = htonl((uint32_t)entry->mtime.seconds);
ondisk.ctime.nanoseconds = htonl(entry->ctime.nanoseconds);
ondisk.mtime.nanoseconds = htonl(entry->mtime.nanoseconds);
ondisk.dev = htonl(entry->dev);
ondisk.ino = htonl(entry->ino);
ondisk.mode = htonl(entry->mode);
ondisk.uid = htonl(entry->uid);
ondisk.gid = htonl(entry->gid);
ondisk.file_size = htonl((uint32_t)entry->file_size);
git_oid_raw_cpy(ondisk.oid, entry->id.id, GIT_OID_SHA1_SIZE);
ondisk.flags = htons(entry->flags);
ondisk_common->ctime.seconds = htonl((uint32_t)entry->ctime.seconds);
ondisk_common->mtime.seconds = htonl((uint32_t)entry->mtime.seconds);
ondisk_common->ctime.nanoseconds = htonl(entry->ctime.nanoseconds);
ondisk_common->mtime.nanoseconds = htonl(entry->mtime.nanoseconds);
ondisk_common->dev = htonl(entry->dev);
ondisk_common->ino = htonl(entry->ino);
ondisk_common->mode = htonl(entry->mode);
ondisk_common->uid = htonl(entry->uid);
ondisk_common->gid = htonl(entry->gid);
ondisk_common->file_size = htonl((uint32_t)entry->file_size);
switch (index->oid_type) {
case GIT_OID_SHA1:
git_oid_raw_cpy(ondisk_sha1.oid, entry->id.id, GIT_OID_SHA1_SIZE);
ondisk_sha1.flags = htons(entry->flags);
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
git_oid_raw_cpy(ondisk_sha256.oid, entry->id.id, GIT_OID_SHA256_SIZE);
ondisk_sha256.flags = htons(entry->flags);
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
path_offset = index_entry_path_offset(index->oid_type, entry->flags);
if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
const size_t path_offset = offsetof(struct entry_long, path);
struct entry_long ondisk_ext;
memcpy(&ondisk_ext, &ondisk, sizeof(struct entry_short));
ondisk_ext.flags_extended = htons(entry->flags_extended &
struct entry_common *ondisk_ext;
uint16_t flags_extended = htons(entry->flags_extended &
GIT_INDEX_ENTRY_EXTENDED_FLAGS);
memcpy(mem, &ondisk_ext, path_offset);
path = (char *)mem + path_offset;
disk_size -= path_offset;
switch (index->oid_type) {
case GIT_OID_SHA1:
memcpy(&ondisk_ext_sha1, &ondisk_sha1,
sizeof(index_entry_short_sha1));
ondisk_ext_sha1.flags_extended = flags_extended;
ondisk_ext = &ondisk_ext_sha1.common;
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
memcpy(&ondisk_ext_sha256, &ondisk_sha256,
sizeof(index_entry_short_sha256));
ondisk_ext_sha256.flags_extended = flags_extended;
ondisk_ext = &ondisk_ext_sha256.common;
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
memcpy(mem, ondisk_ext, path_offset);
} else {
const size_t path_offset = offsetof(struct entry_short, path);
memcpy(mem, &ondisk, path_offset);
path = (char *)mem + path_offset;
disk_size -= path_offset;
switch (index->oid_type) {
case GIT_OID_SHA1:
memcpy(mem, &ondisk_sha1, path_offset);
break;
#ifdef GIT_EXPERIMENTAL_SHA256
case GIT_OID_SHA256:
memcpy(mem, &ondisk_sha256, path_offset);
break;
#endif
default:
GIT_ASSERT(!"invalid oid type");
}
}
path = (char *)mem + path_offset;
disk_size -= path_offset;
if (last) {
varint_len = git_encode_varint((unsigned char *) path,
disk_size, strlen(last) - same_len);
@ -2877,7 +3073,7 @@ static int write_entries(git_index *index, git_filebuf *file)
last = "";
git_vector_foreach(entries, i, entry) {
if ((error = write_disk_entry(file, entry, last)) < 0)
if ((error = write_disk_entry(index, file, entry, last)) < 0)
break;
if (index->version >= INDEX_VERSION_NUMBER_COMP)
last = entry->path;
@ -2955,8 +3151,9 @@ done:
return error;
}
static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *reuc)
static int create_reuc_extension_data(git_str *reuc_buf, git_index *index, git_index_reuc_entry *reuc)
{
size_t oid_size = git_oid_size(index->oid_type);
int i;
int error = 0;
@ -2970,7 +3167,7 @@ static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *r
}
for (i = 0; i < 3; i++) {
if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_SHA1_SIZE)) < 0)
if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, oid_size)) < 0)
return error;
}
@ -2987,7 +3184,7 @@ static int write_reuc_extension(git_index *index, git_filebuf *file)
int error = 0;
git_vector_foreach(out, i, reuc) {
if ((error = create_reuc_extension_data(&reuc_buf, reuc)) < 0)
if ((error = create_reuc_extension_data(&reuc_buf, index, reuc)) < 0)
goto done;
}
@ -3036,7 +3233,7 @@ static void clear_uptodate(git_index *index)
}
static int write_index(
unsigned char checksum[GIT_HASH_SHA1_SIZE],
unsigned char checksum[GIT_HASH_MAX_SIZE],
size_t *checksum_size,
git_index *index,
git_filebuf *file)
@ -3048,7 +3245,9 @@ static int write_index(
GIT_ASSERT_ARG(index);
GIT_ASSERT_ARG(file);
*checksum_size = GIT_HASH_SHA1_SIZE;
GIT_ASSERT(index->oid_type);
*checksum_size = git_hash_size(git_oid_algorithm(index->oid_type));
if (index->version <= INDEX_VERSION_NUMBER_EXT) {
is_extended = is_index_extended(index);
@ -3209,7 +3408,7 @@ cleanup:
if (error < 0)
return error;
error = git_tree_cache_read_tree(&index->tree, tree, &index->tree_pool);
error = git_tree_cache_read_tree(&index->tree, tree, index->oid_type, &index->tree_pool);
return error;
}
@ -3668,19 +3867,23 @@ int git_indexwriter_init(
git_indexwriter *writer,
git_index *index)
{
int error;
int filebuf_hash, error;
GIT_REFCOUNT_INC(index);
writer->index = index;
filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(index->oid_type));
GIT_ASSERT(filebuf_hash);
if (!index->index_file_path)
return create_index_error(-1,
"failed to write index: The index is in-memory only");
if ((error = git_filebuf_open(
&writer->file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) {
if ((error = git_filebuf_open(&writer->file,
index->index_file_path,
git_filebuf_hash_flags(filebuf_hash),
GIT_INDEX_FILE_MODE)) < 0) {
if (error == GIT_ELOCKED)
git_error_set(GIT_ERROR_INDEX, "the index is locked; this might be due to a concurrent or crashed process");
@ -3712,7 +3915,7 @@ int git_indexwriter_init_for_operation(
int git_indexwriter_commit(git_indexwriter *writer)
{
unsigned char checksum[GIT_HASH_SHA1_SIZE];
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size;
int error;

View File

@ -27,7 +27,7 @@ struct git_index {
char *index_file_path;
git_futils_filestamp stamp;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
unsigned char checksum[GIT_HASH_MAX_SIZE];
git_vector entries;
git_idxmap *entries_map;
@ -35,6 +35,8 @@ struct git_index {
git_vector deleted; /* deleted entries if readers > 0 */
git_atomic32 readers; /* number of active iterators */
git_oid_t oid_type;
unsigned int on_disk:1;
unsigned int ignore_case:1;
unsigned int distrust_filemode:1;
@ -141,6 +143,17 @@ GIT_INLINE(unsigned char *) git_index__checksum(git_index *index)
return index->checksum;
}
/* SHA256-aware internal functions */
extern int git_index__new(
git_index **index_out,
git_oid_t oid_type);
extern int git_index__open(
git_index **index_out,
const char *index_path,
git_oid_t oid_type);
/* Copy the current entries vector *and* increment the index refcount.
* Call `git_index__release_snapshot` when done.
*/

View File

@ -519,7 +519,13 @@ static int store_object(git_indexer *idx)
pentry->offset = entry_start;
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->id)) {
git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->id));
const char *idstr = git_oid_tostr_s(&pentry->id);
if (!idstr)
git_error_set(GIT_ERROR_INDEXER, "failed to parse object id");
else
git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", idstr);
git__free(pentry);
goto on_error;
}
@ -1232,6 +1238,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
git_filebuf index_file = {0};
void *packfile_trailer;
size_t checksum_size;
int filebuf_hash;
bool mismatch;
if (!idx->parsed_header) {
@ -1240,6 +1247,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
}
checksum_size = git_hash_size(indexer_hash_algorithm(idx));
filebuf_hash = git_filebuf_hash_flags(indexer_hash_algorithm(idx));
GIT_ASSERT(checksum_size);
/* Test for this before resolve_deltas(), as it plays with idx->off */
@ -1314,8 +1322,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
return -1;
if (git_filebuf_open(&index_file, filename.ptr,
GIT_FILEBUF_HASH_CONTENTS |
(idx->do_fsync ? GIT_FILEBUF_FSYNC : 0),
filebuf_hash | (idx->do_fsync ? GIT_FILEBUF_FSYNC : 0),
idx->mode) < 0)
goto on_error;

View File

@ -1036,6 +1036,8 @@ typedef struct {
git_index *index;
git_vector index_snapshot;
git_oid_t oid_type;
git_array_t(filesystem_iterator_frame) frames;
git_ignores ignores;
@ -1271,7 +1273,7 @@ static int filesystem_iterator_entry_hash(
int error;
if (S_ISDIR(entry->st.st_mode)) {
memset(&entry->id, 0, GIT_OID_SHA1_SIZE);
memset(&entry->id, 0, git_oid_size(iter->oid_type));
return 0;
}
@ -1281,7 +1283,7 @@ static int filesystem_iterator_entry_hash(
if (!(error = git_str_joinpath(&fullpath, iter->root, entry->path)) &&
!(error = git_path_validate_str_length(iter->base.repo, &fullpath)))
error = git_odb__hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB, GIT_OID_SHA1);
error = git_odb__hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB, iter->oid_type);
git_str_dispose(&fullpath);
return error;
@ -1530,7 +1532,7 @@ static void filesystem_iterator_set_current(
if (iter->base.flags & GIT_ITERATOR_INCLUDE_HASH)
git_oid_cpy(&iter->entry.id, &entry->id);
else
git_oid_clear(&iter->entry.id, GIT_OID_SHA1);
git_oid_clear(&iter->entry.id, iter->oid_type);
iter->entry.path = entry->path;
@ -1975,6 +1977,8 @@ static int iterator_for_filesystem(
(iterator__flag(&iter->base, PRECOMPOSE_UNICODE) ?
GIT_FS_PATH_DIR_PRECOMPOSE_UNICODE : 0);
iter->oid_type = options->oid_type;
if ((error = filesystem_iterator_init(iter)) < 0)
goto on_error;
@ -1989,10 +1993,15 @@ on_error:
int git_iterator_for_filesystem(
git_iterator **out,
const char *root,
git_iterator_options *options)
git_iterator_options *given_opts)
{
git_iterator_options options = GIT_ITERATOR_OPTIONS_INIT;
if (given_opts)
memcpy(&options, given_opts, sizeof(git_iterator_options));
return iterator_for_filesystem(out,
NULL, root, NULL, NULL, GIT_ITERATOR_FS, options);
NULL, root, NULL, NULL, GIT_ITERATOR_FS, &options);
}
int git_iterator_for_workdir_ext(
@ -2019,6 +2028,12 @@ int git_iterator_for_workdir_ext(
options.flags |= GIT_ITERATOR_HONOR_IGNORES |
GIT_ITERATOR_IGNORE_DOT_GIT;
if (!options.oid_type)
options.oid_type = repo->oid_type;
else if (options.oid_type != repo->oid_type)
git_error_set(GIT_ERROR_INVALID,
"specified object ID type does not match repository object ID type");
return iterator_for_filesystem(out,
repo, repo_workdir, index, tree, GIT_ITERATOR_WORKDIR, &options);
}

View File

@ -63,6 +63,9 @@ typedef struct {
/* flags, from above */
unsigned int flags;
/* oid type - necessary for non-workdir filesystem iterators */
git_oid_t oid_type;
} git_iterator_options;
#define GIT_ITERATOR_OPTIONS_INIT {0}

View File

@ -13,6 +13,7 @@
#include "cache.h"
#include "common.h"
#include "filter.h"
#include "grafts.h"
#include "hash.h"
#include "index.h"
#include "merge_driver.h"
@ -30,6 +31,7 @@
#include "streams/registry.h"
#include "streams/mbedtls.h"
#include "streams/openssl.h"
#include "streams/socket.h"
#include "transports/smart.h"
#include "transports/http.h"
#include "transports/ssh.h"
@ -46,6 +48,8 @@ extern size_t git_indexer__max_objects;
extern bool git_disable_pack_keep_file_checks;
extern int git_odb__packed_priority;
extern int git_odb__loose_priority;
extern int git_socket_stream__connect_timeout;
extern int git_socket_stream__timeout;
char *git__user_agent;
char *git__ssl_ciphers;
@ -78,6 +82,7 @@ int git_libgit2_init(void)
git_merge_driver_global_init,
git_transport_ssh_global_init,
git_stream_registry_global_init,
git_socket_stream_global_init,
git_openssl_stream_global_init,
git_mbedtls_stream_global_init,
git_mwindow_global_init,
@ -433,6 +438,40 @@ int git_libgit2_opts(int key, ...)
error = git_sysdir_set(GIT_SYSDIR_HOME, va_arg(ap, const char *));
break;
case GIT_OPT_GET_SERVER_CONNECT_TIMEOUT:
*(va_arg(ap, int *)) = git_socket_stream__connect_timeout;
break;
case GIT_OPT_SET_SERVER_CONNECT_TIMEOUT:
{
int timeout = va_arg(ap, int);
if (timeout < 0) {
git_error_set(GIT_ERROR_INVALID, "invalid connect timeout");
error = -1;
} else {
git_socket_stream__connect_timeout = timeout;
}
}
break;
case GIT_OPT_GET_SERVER_TIMEOUT:
*(va_arg(ap, int *)) = git_socket_stream__timeout;
break;
case GIT_OPT_SET_SERVER_TIMEOUT:
{
int timeout = va_arg(ap, int);
if (timeout < 0) {
git_error_set(GIT_ERROR_INVALID, "invalid timeout");
error = -1;
} else {
git_socket_stream__timeout = timeout;
}
}
break;
default:
git_error_set(GIT_ERROR_INVALID, "invalid option key");
error = -1;

View File

@ -611,13 +611,13 @@ int git_repository_mergehead_foreach(
buffer = merge_head_file.ptr;
while ((line = git__strsep(&buffer, "\n")) != NULL) {
if (strlen(line) != GIT_OID_SHA1_HEXSIZE) {
if (strlen(line) != git_oid_hexsize(repo->oid_type)) {
git_error_set(GIT_ERROR_INVALID, "unable to parse OID - invalid length");
error = -1;
goto cleanup;
}
if ((error = git_oid__fromstr(&oid, line, GIT_OID_SHA1)) < 0)
if ((error = git_oid__fromstr(&oid, line, repo->oid_type)) < 0)
goto cleanup;
if ((error = cb(&oid, payload)) != 0) {
@ -1061,7 +1061,7 @@ static int index_entry_similarity_calc(
const git_merge_options *opts)
{
git_blob *blob;
git_diff_file diff_file = { GIT_OID_SHA1_ZERO };
git_diff_file diff_file;
git_object_size_t blobsize;
int error;
@ -1070,6 +1070,8 @@ static int index_entry_similarity_calc(
*out = NULL;
git_oid_clear(&diff_file.id, repo->oid_type);
if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0)
return error;
@ -1997,8 +1999,11 @@ static int index_update_reuc(git_index *index, git_merge_diff_list *diff_list)
return 0;
}
static int index_from_diff_list(git_index **out,
git_merge_diff_list *diff_list, bool skip_reuc)
static int index_from_diff_list(
git_index **out,
git_merge_diff_list *diff_list,
git_oid_t oid_type,
bool skip_reuc)
{
git_index *index;
size_t i;
@ -2007,7 +2012,7 @@ static int index_from_diff_list(git_index **out,
*out = NULL;
if ((error = git_index_new(&index)) < 0)
if ((error = git_index__new(&index, oid_type)) < 0)
return error;
if ((error = git_index__fill(index, &diff_list->staged)) < 0)
@ -2157,7 +2162,7 @@ int git_merge__iterators(
}
}
error = index_from_diff_list(out, diff_list,
error = index_from_diff_list(out, diff_list, repo->oid_type,
(opts.flags & GIT_MERGE_SKIP_REUC));
done:
@ -2200,8 +2205,8 @@ int git_merge_trees(
result = our_tree;
if (result) {
if ((error = git_index_new(out)) == 0)
error = git_index_read_tree(*out, result);
if ((error = git_index__new(out, repo->oid_type)) == 0)
error = git_index_read_tree(*out, result);
return error;
}

View File

@ -19,8 +19,6 @@
#include "git2/index.h"
#include "git2/merge.h"
#include "xdiff/xdiff.h"
/* only examine the first 8000 bytes for binaryness.
* https://github.com/git/git/blob/77bd3ea9f54f1584147b594abc04c26ca516d987/xdiff-interface.c#L197
*/

View File

@ -114,23 +114,16 @@ static int midx_parse_oid_lookup(
const unsigned char *data,
struct git_midx_chunk *chunk_oid_lookup)
{
uint32_t i;
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_SHA1_SIZE] = {0};
size_t oid_size = git_oid_size(idx->oid_type);
if (chunk_oid_lookup->offset == 0)
return midx_error("missing OID Lookup chunk");
if (chunk_oid_lookup->length == 0)
return midx_error("empty OID Lookup chunk");
if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_SHA1_SIZE)
if (chunk_oid_lookup->length != idx->num_objects * oid_size)
return midx_error("OID Lookup chunk has wrong length");
idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
prev_oid = zero_oid;
for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_SHA1_SIZE) {
if (git_oid_raw_cmp(prev_oid, oid, GIT_OID_SHA1_SIZE) >= 0)
return midx_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
idx->oid_lookup = (unsigned char *)(data + chunk_oid_lookup->offset);
return 0;
}
@ -178,17 +171,20 @@ int git_midx_parse(
struct git_midx_chunk *last_chunk;
uint32_t i;
off64_t last_chunk_offset, chunk_offset, trailer_offset;
size_t checksum_size;
size_t checksum_size, oid_size;
int error;
struct git_midx_chunk chunk_packfile_names = {0},
chunk_oid_fanout = {0},
chunk_oid_lookup = {0},
chunk_object_offsets = {0},
chunk_object_large_offsets = {0};
chunk_object_large_offsets = {0},
chunk_unknown = {0};
GIT_ASSERT_ARG(idx);
if (size < sizeof(struct git_midx_header) + GIT_OID_SHA1_SIZE)
oid_size = git_oid_size(idx->oid_type);
if (size < sizeof(struct git_midx_header) + oid_size)
return midx_error("multi-pack index is too short");
hdr = ((struct git_midx_header *)data);
@ -209,7 +205,7 @@ int git_midx_parse(
sizeof(struct git_midx_header) +
(1 + hdr->chunks) * 12;
checksum_size = GIT_HASH_SHA1_SIZE;
checksum_size = oid_size;
trailer_offset = size - checksum_size;
if (trailer_offset < last_chunk_offset)
@ -261,7 +257,9 @@ int git_midx_parse(
break;
default:
return midx_error("unrecognized chunk ID");
chunk_unknown.offset = last_chunk_offset;
last_chunk = &chunk_unknown;
break;
}
}
last_chunk->length = (size_t)(trailer_offset - last_chunk_offset);
@ -287,8 +285,9 @@ int git_midx_parse(
}
int git_midx_open(
git_midx_file **idx_out,
const char *path)
git_midx_file **idx_out,
const char *path,
git_oid_t oid_type)
{
git_midx_file *idx;
git_file fd = -1;
@ -296,6 +295,8 @@ int git_midx_open(
struct stat st;
int error;
GIT_ASSERT_ARG(idx_out && path && oid_type);
/* TODO: properly open the file without access time using O_NOATIME */
fd = git_futils_open_ro(path);
if (fd < 0)
@ -317,6 +318,8 @@ int git_midx_open(
idx = git__calloc(1, sizeof(git_midx_file));
GIT_ERROR_CHECK_ALLOC(idx);
idx->oid_type = oid_type;
error = git_str_sets(&idx->filename, path);
if (error < 0)
return error;
@ -344,7 +347,7 @@ bool git_midx_needs_refresh(
git_file fd = -1;
struct stat st;
ssize_t bytes_read;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size;
/* TODO: properly open the file without access time using O_NOATIME */
@ -364,8 +367,8 @@ bool git_midx_needs_refresh(
return true;
}
checksum_size = GIT_HASH_SHA1_SIZE;
bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - GIT_OID_SHA1_SIZE);
checksum_size = git_oid_size(idx->oid_type);
bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - checksum_size);
p_close(fd);
if (bytes_read != (ssize_t)checksum_size)
@ -381,7 +384,7 @@ int git_midx_entry_find(
size_t len)
{
int pos, found = 0;
size_t pack_index;
size_t pack_index, oid_size, oid_hexsize;
uint32_t hi, lo;
unsigned char *current = NULL;
const unsigned char *object_offset;
@ -389,30 +392,33 @@ int git_midx_entry_find(
GIT_ASSERT_ARG(idx);
oid_size = git_oid_size(idx->oid_type);
oid_hexsize = git_oid_hexsize(idx->oid_type);
hi = ntohl(idx->oid_fanout[(int)short_oid->id[0]]);
lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(idx->oid_fanout[(int)short_oid->id[0] - 1]));
pos = git_pack__lookup_id(idx->oid_lookup, GIT_OID_SHA1_SIZE, lo, hi, short_oid->id, GIT_OID_SHA1);
pos = git_pack__lookup_id(idx->oid_lookup, oid_size, lo, hi, short_oid->id, idx->oid_type);
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
current = idx->oid_lookup + (pos * oid_size);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)idx->num_objects) {
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
current = idx->oid_lookup + (pos * oid_size);
if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int)idx->num_objects) {
if (found && len != oid_hexsize && pos + 1 < (int)idx->num_objects) {
/* Check for ambiguousity */
const unsigned char *next = current + GIT_OID_SHA1_SIZE;
const unsigned char *next = current + oid_size;
if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
@ -443,7 +449,7 @@ int git_midx_entry_find(
return midx_error("invalid index into the packfile names table");
e->pack_index = pack_index;
e->offset = offset;
git_oid__fromraw(&e->sha1, current, GIT_OID_SHA1);
git_oid__fromraw(&e->sha1, current, idx->oid_type);
return 0;
}
@ -453,13 +459,15 @@ int git_midx_foreach_entry(
void *data)
{
git_oid oid;
size_t i;
size_t oid_size, i;
int error;
GIT_ASSERT_ARG(idx);
oid_size = git_oid_size(idx->oid_type);
for (i = 0; i < idx->num_objects; ++i) {
if ((error = git_oid__fromraw(&oid, &idx->oid_lookup[i * GIT_OID_SHA1_SIZE], GIT_OID_SHA1)) < 0)
if ((error = git_oid__fromraw(&oid, &idx->oid_lookup[i * oid_size], idx->oid_type)) < 0)
return error;
if ((error = cb(&oid, data)) != 0)
@ -501,9 +509,21 @@ static int packfile__cmp(const void *a_, const void *b_)
int git_midx_writer_new(
git_midx_writer **out,
const char *pack_dir)
const char *pack_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
)
{
git_midx_writer *w = git__calloc(1, sizeof(git_midx_writer));
git_midx_writer *w;
#ifndef GIT_EXPERIMENTAL_SHA256
git_oid_t oid_type = GIT_OID_SHA1;
#endif
GIT_ASSERT_ARG(out && pack_dir && oid_type);
w = git__calloc(1, sizeof(git_midx_writer));
GIT_ERROR_CHECK_ALLOC(w);
if (git_str_sets(&w->pack_dir, pack_dir) < 0) {
@ -518,6 +538,8 @@ int git_midx_writer_new(
return -1;
}
w->oid_type = oid_type;
*out = w;
return 0;
}
@ -662,12 +684,13 @@ static int midx_write(
oid_lookup = GIT_STR_INIT,
object_offsets = GIT_STR_INIT,
object_large_offsets = GIT_STR_INIT;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
size_t checksum_size;
unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size, oid_size;
git_midx_entry *entry;
object_entry_array_t object_entries_array = GIT_ARRAY_INIT;
git_vector object_entries = GIT_VECTOR_INIT;
git_hash_ctx ctx;
git_hash_algorithm_t checksum_type;
struct midx_write_hash_context hash_cb_data = {0};
hdr.signature = htonl(MIDX_SIGNATURE);
@ -679,10 +702,14 @@ static int midx_write(
hash_cb_data.cb_data = cb_data;
hash_cb_data.ctx = &ctx;
checksum_size = GIT_HASH_SHA1_SIZE;
error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
if (error < 0)
oid_size = git_oid_size(w->oid_type);
GIT_ASSERT((checksum_type = git_oid_algorithm(w->oid_type)));
checksum_size = git_hash_size(checksum_type);
if ((error = git_hash_ctx_init(&ctx, checksum_type)) < 0)
return error;
cb_data = &hash_cb_data;
write_cb = midx_write_hash;
@ -749,7 +776,9 @@ static int midx_write(
/* Fill the OID Lookup table. */
git_vector_foreach (&object_entries, i, entry) {
error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_SHA1_SIZE);
error = git_str_put(&oid_lookup,
(char *)&entry->sha1.id, oid_size);
if (error < 0)
goto cleanup;
}

View File

@ -51,8 +51,14 @@ typedef struct git_midx_file {
/* The number of entries in the Object Large Offsets table. Each entry has an 8-byte with an offset */
size_t num_object_large_offsets;
/* The trailer of the file. Contains the SHA1-checksum of the whole file. */
unsigned char checksum[GIT_HASH_SHA1_SIZE];
/*
* The trailer of the file. Contains the checksum of the whole
* file, in the repository's object format hash.
*/
unsigned char checksum[GIT_HASH_MAX_SIZE];
/* The type of object IDs in the midx. */
git_oid_t oid_type;
/* something like ".git/objects/pack/multi-pack-index". */
git_str filename;
@ -82,11 +88,15 @@ struct git_midx_writer {
/* The list of `git_pack_file`s. */
git_vector packs;
/* The object ID type of the writer. */
git_oid_t oid_type;
};
int git_midx_open(
git_midx_file **idx_out,
const char *path);
const char *path,
git_oid_t oid_type);
bool git_midx_needs_refresh(
const git_midx_file *idx,
const char *path);

View File

@ -1,124 +0,0 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "netops.h"
#include <ctype.h>
#include "git2/errors.h"
#include "posix.h"
#include "str.h"
#include "runtime.h"
int gitno_recv(gitno_buffer *buf)
{
return buf->recv(buf);
}
void gitno_buffer_setup_callback(
gitno_buffer *buf,
char *data,
size_t len,
int (*recv)(gitno_buffer *buf), void *cb_data)
{
memset(data, 0x0, len);
buf->data = data;
buf->len = len;
buf->offset = 0;
buf->recv = recv;
buf->cb_data = cb_data;
}
static int recv_stream(gitno_buffer *buf)
{
git_stream *io = (git_stream *) buf->cb_data;
size_t readlen = buf->len - buf->offset;
ssize_t ret;
readlen = min(readlen, INT_MAX);
ret = git_stream_read(io, buf->data + buf->offset, (int)readlen);
if (ret < 0)
return -1;
buf->offset += ret;
return (int)ret;
}
void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len)
{
memset(data, 0x0, len);
buf->data = data;
buf->len = len;
buf->offset = 0;
buf->recv = recv_stream;
buf->cb_data = st;
}
/* Consume up to ptr and move the rest of the buffer to the beginning */
int gitno_consume(gitno_buffer *buf, const char *ptr)
{
size_t consumed;
GIT_ASSERT(ptr - buf->data >= 0);
GIT_ASSERT(ptr - buf->data <= (int) buf->len);
consumed = ptr - buf->data;
memmove(buf->data, ptr, buf->offset - consumed);
memset(buf->data + buf->offset, 0x0, buf->len - buf->offset);
buf->offset -= consumed;
return 0;
}
/* Consume const bytes and move the rest of the buffer to the beginning */
void gitno_consume_n(gitno_buffer *buf, size_t cons)
{
memmove(buf->data, buf->data + cons, buf->len - buf->offset);
memset(buf->data + cons, 0x0, buf->len - buf->offset);
buf->offset -= cons;
}
/* Match host names according to RFC 2818 rules */
int gitno__match_host(const char *pattern, const char *host)
{
for (;;) {
char c = git__tolower(*pattern++);
if (c == '\0')
return *host ? -1 : 0;
if (c == '*') {
c = *pattern;
/* '*' at the end matches everything left */
if (c == '\0')
return 0;
/*
* We've found a pattern, so move towards the next matching
* char. The '.' is handled specially because wildcards aren't
* allowed to cross subdomains.
*/
while(*host) {
char h = git__tolower(*host);
if (c == h)
return gitno__match_host(pattern, host++);
if (h == '.')
return gitno__match_host(pattern, host);
host++;
}
return -1;
}
if (c != git__tolower(*host++))
return -1;
}
return -1;
}

View File

@ -1,68 +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_netops_h__
#define INCLUDE_netops_h__
#include "common.h"
#include "posix.h"
#include "stream.h"
#include "net.h"
#ifdef GIT_OPENSSL
# include "streams/openssl.h"
#endif
typedef struct gitno_ssl {
#ifdef GIT_OPENSSL
SSL *ssl;
#else
size_t dummy;
#endif
} gitno_ssl;
/* Represents a socket that may or may not be using SSL */
typedef struct gitno_socket {
GIT_SOCKET socket;
gitno_ssl ssl;
} gitno_socket;
typedef struct gitno_buffer {
char *data;
size_t len;
size_t offset;
int (*recv)(struct gitno_buffer *buffer);
void *cb_data;
} gitno_buffer;
/* Flags to gitno_connect */
enum {
/* Attempt to create an SSL connection. */
GITNO_CONNECT_SSL = 1
};
/**
* Check if the name in a cert matches the wanted hostname
*
* Check if a pattern from a certificate matches the hostname we
* wanted to connect to according to RFC2818 rules (which specifies
* HTTP over TLS). Mainly, an asterisk matches anything, but is
* limited to a single url component.
*
* Note that this does not set an error message. It expects the user
* to provide the message for the user.
*/
int gitno__match_host(const char *pattern, const char *host);
void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len);
void gitno_buffer_setup_callback(gitno_buffer *buf, char *data, size_t len, int (*recv)(gitno_buffer *buf), void *cb_data);
int gitno_recv(gitno_buffer *buf);
int gitno_consume(gitno_buffer *buf, const char *ptr);
void gitno_consume_n(gitno_buffer *buf, size_t cons);
#endif

View File

@ -460,7 +460,7 @@ int git_note_commit_read(
{
int error;
git_tree *tree = NULL;
char target[GIT_OID_SHA1_HEXSIZE + 1];
char target[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(target, sizeof(target), oid);
@ -507,7 +507,7 @@ int git_note_commit_create(
{
int error;
git_tree *tree = NULL;
char target[GIT_OID_SHA1_HEXSIZE + 1];
char target[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(target, sizeof(target), oid);
@ -578,7 +578,7 @@ int git_note_commit_remove(
{
int error;
git_tree *tree = NULL;
char target[GIT_OID_SHA1_HEXSIZE + 1];
char target[GIT_OID_MAX_HEXSIZE + 1];
git_oid_tostr(target, sizeof(target), oid);
@ -665,8 +665,9 @@ void git_note_free(git_note *note)
}
static int process_entry_path(
const char *entry_path,
git_oid *annotated_object_id)
git_oid *annotated_object_id,
git_note_iterator *it,
const char *entry_path)
{
int error = 0;
size_t i = 0, j = 0, len;
@ -698,12 +699,12 @@ static int process_entry_path(
buf.ptr[j] = '\0';
buf.size = j;
if (j != GIT_OID_SHA1_HEXSIZE) {
if (j != git_oid_hexsize(it->repo->oid_type)) {
/* This is not a note entry */
goto cleanup;
}
error = git_oid__fromstr(annotated_object_id, buf.ptr, GIT_OID_SHA1);
error = git_oid__fromstr(annotated_object_id, buf.ptr, it->repo->oid_type);
cleanup:
git_str_dispose(&buf);
@ -799,7 +800,7 @@ int git_note_next(
git_oid_cpy(note_id, &item->id);
if ((error = process_entry_path(item->path, annotated_id)) < 0)
if ((error = process_entry_path(annotated_id, it, item->path)) < 0)
return error;
if ((error = git_iterator_advance(NULL, it)) < 0 && error != GIT_ITEROVER)

View File

@ -108,15 +108,13 @@ int git_object__from_raw(
return 0;
}
int git_object__from_odb_object(
int git_object__init_from_odb_object(
git_object **object_out,
git_repository *repo,
git_odb_object *odb_obj,
git_object_t type)
{
int error;
size_t object_size;
git_object_def *def;
git_object *object = NULL;
GIT_ASSERT_ARG(object_out);
@ -143,6 +141,23 @@ int git_object__from_odb_object(
object->cached.size = odb_obj->cached.size;
object->repo = repo;
*object_out = object;
return 0;
}
int git_object__from_odb_object(
git_object **object_out,
git_repository *repo,
git_odb_object *odb_obj,
git_object_t type)
{
int error;
git_object_def *def;
git_object *object = NULL;
if ((error = git_object__init_from_odb_object(&object, repo, odb_obj, type)) < 0)
return error;
/* Parse raw object data */
def = &git_objects_table[odb_obj->cached.type];
GIT_ASSERT(def->free && def->parse);
@ -181,6 +196,7 @@ int git_object_lookup_prefix(
git_object *object = NULL;
git_odb *odb = NULL;
git_odb_object *odb_obj = NULL;
size_t oid_hexsize;
int error = 0;
GIT_ASSERT_ARG(repo);
@ -196,10 +212,12 @@ int git_object_lookup_prefix(
if (error < 0)
return error;
if (len > GIT_OID_SHA1_HEXSIZE)
len = GIT_OID_SHA1_HEXSIZE;
oid_hexsize = git_oid_hexsize(repo->oid_type);
if (len == GIT_OID_SHA1_HEXSIZE) {
if (len > oid_hexsize)
len = oid_hexsize;
if (len == oid_hexsize) {
git_cached_obj *cached = NULL;
/* We want to match the full id : we can first look up in the cache,
@ -233,8 +251,9 @@ int git_object_lookup_prefix(
error = git_odb_read(&odb_obj, odb, id);
}
} else {
git_oid short_oid = GIT_OID_SHA1_ZERO;
git_oid short_oid;
git_oid_clear(&short_oid, repo->oid_type);
git_oid__cpy_prefix(&short_oid, id, len);
/* If len < GIT_OID_SHA1_HEXSIZE (a strict short oid was given), we have
@ -262,7 +281,8 @@ int git_object_lookup_prefix(
}
int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_object_t type) {
return git_object_lookup_prefix(object_out, repo, id, GIT_OID_SHA1_HEXSIZE, type);
return git_object_lookup_prefix(object_out,
repo, id, git_oid_hexsize(repo->oid_type), type);
}
void git_object_free(git_object *object)
@ -503,31 +523,36 @@ cleanup:
static int git_object__short_id(git_str *out, const git_object *obj)
{
git_repository *repo;
int len = GIT_ABBREV_DEFAULT, error;
git_oid id = GIT_OID_SHA1_ZERO;
git_oid id;
git_odb *odb;
size_t oid_hexsize;
int len = GIT_ABBREV_DEFAULT, error;
GIT_ASSERT_ARG(out);
GIT_ASSERT_ARG(obj);
repo = git_object_owner(obj);
git_oid_clear(&id, repo->oid_type);
oid_hexsize = git_oid_hexsize(repo->oid_type);
if ((error = git_repository__configmap_lookup(&len, repo, GIT_CONFIGMAP_ABBREV)) < 0)
return error;
if (len < 0 || (size_t)len > oid_hexsize) {
git_error_set(GIT_ERROR_CONFIG, "invalid oid abbreviation setting: '%d'", len);
return -1;
}
if ((error = git_repository_odb(&odb, repo)) < 0)
return error;
while (len < GIT_OID_SHA1_HEXSIZE) {
while ((size_t)len < oid_hexsize) {
/* set up short oid */
memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
if (len & 1)
id.id[len / 2] &= 0xf0;
#ifdef GIT_EXPERIMENTAL_SHA256
id.type = GIT_OID_SHA1;
#endif
error = git_odb_exists_prefix(NULL, odb, &id, len);
if (error != GIT_EAMBIGUOUS)
break;

Some files were not shown because too many files have changed in this diff Show More