diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/bash.yml libgit2-1.1.0+dfsg.1/azure-pipelines/bash.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines/bash.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/bash.yml 2020-10-12 18:53:06.000000000 +0000 @@ -1,10 +1,10 @@ # These are the steps used for building on machines with bash. steps: -- bash: . '$(Build.SourcesDirectory)/ci/build.sh' +- bash: . '$(Build.SourcesDirectory)/azure-pipelines/build.sh' displayName: Build workingDirectory: '$(Build.BinariesDirectory)' env: ${{ parameters.environmentVariables }} -- bash: . '$(Build.SourcesDirectory)/ci/test.sh' +- bash: . '$(Build.SourcesDirectory)/azure-pipelines/test.sh' displayName: Test workingDirectory: '$(Build.BinariesDirectory)' env: ${{ parameters.environmentVariables }} diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/build.sh libgit2-1.1.0+dfsg.1/azure-pipelines/build.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/build.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/build.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Environment variables: +# +# SOURCE_DIR: Set to the directory of the libgit2 source (optional) +# If not set, it will be derived relative to this script. + +set -e + +SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} +BUILD_DIR=$(pwd) +BUILD_PATH=${BUILD_PATH:=$PATH} +CMAKE=$(which cmake) +CMAKE_GENERATOR=${CMAKE_GENERATOR:-Unix Makefiles} + +if [[ "$(uname -s)" == MINGW* ]]; then + BUILD_PATH=$(cygpath "$BUILD_PATH") +fi + +indent() { sed "s/^/ /"; } + +echo "Source directory: ${SOURCE_DIR}" +echo "Build directory: ${BUILD_DIR}" +echo "" + +if [ "$(uname -s)" = "Darwin" ]; then + echo "macOS version:" + sw_vers | indent +fi + +if [ -f "/etc/debian_version" ]; then + echo "Debian version:" + (source /etc/lsb-release && echo "${DISTRIB_DESCRIPTION}") | indent +fi + +echo "Kernel version:" +uname -a 2>&1 | indent + +echo "CMake version:" +env PATH="${BUILD_PATH}" "${CMAKE}" --version 2>&1 | indent + +if test -n "${CC}"; then + echo "Compiler version:" + "${CC}" --version 2>&1 | indent +fi +echo "Environment:" +if test -n "${CC}"; then + echo "CC=${CC}" | indent +fi +if test -n "${CFLAGS}"; then + echo "CFLAGS=${CFLAGS}" | indent +fi +echo "" + +echo "##############################################################################" +echo "## Configuring build environment" +echo "##############################################################################" + +echo cmake -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G \"${CMAKE_GENERATOR}\" ${CMAKE_OPTIONS} -S \"${SOURCE_DIR}\" +env PATH="${BUILD_PATH}" "${CMAKE}" -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON -G "${CMAKE_GENERATOR}" ${CMAKE_OPTIONS} -S "${SOURCE_DIR}" + +echo "" +echo "##############################################################################" +echo "## Building libgit2" +echo "##############################################################################" + +env PATH="${BUILD_PATH}" "${CMAKE}" --build . diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/coverity.sh libgit2-1.1.0+dfsg.1/azure-pipelines/coverity.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/coverity.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/coverity.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,62 @@ +#!/bin/bash -e + +if test -z "$COVERITY_TOKEN" +then + echo "Need to set a coverity token" + exit 1 +fi + +case $(uname -m) in + i?86) + BITS=32;; + amd64|x86_64) + BITS=64;; + *) + echo "Unsupported arch '$(uname -m)'" + exit 1;; +esac + +SCAN_TOOL=https://scan.coverity.com/download/cxx/linux${BITS} +SOURCE_DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")"/..) +BUILD_DIR=${SOURCE_DIR}/coverity-build +TOOL_DIR=${BUILD_DIR}/coverity-tools + +# Install coverity tools +if ! test -d "$TOOL_DIR" +then + mkdir -p "$TOOL_DIR" + curl --silent --show-error --location --data "project=libgit2&token=$COVERITY_TOKEN" "$SCAN_TOOL" | + tar -xzC "$TOOL_DIR" + ln -s "$(find "$TOOL_DIR" -type d -name 'cov-analysis*')" "$TOOL_DIR"/cov-analysis +fi + +cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_DIR"/cov-analysis/config/ + +# Build libgit2 with Coverity +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" +cmake "$SOURCE_DIR" +COVERITY_UNSUPPORTED=1 \ + "$TOOL_DIR/cov-analysis/bin/cov-build" --dir cov-int \ + cmake --build . + +# Upload results +tar -czf libgit2.tgz cov-int +REVISION=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD) +HTML="$(curl \ + --silent --show-error \ + --write-out "\n%{http_code}" \ + --form token="$COVERITY_TOKEN" \ + --form email=libgit2@gmail.com \ + --form file=@libgit2.tgz \ + --form version="$REVISION" \ + --form description="libgit2 build" \ + https://scan.coverity.com/builds?project=libgit2)" + +# Status code is the last line +STATUS_CODE="$(echo "$HTML" | tail -n1)" +if test "${STATUS_CODE}" != 200 && test "${STATUS_CODE}" != 201 +then + echo "Received error code ${STATUS_CODE} from Coverity" + exit 1 +fi diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/coverity.yml libgit2-1.1.0+dfsg.1/azure-pipelines/coverity.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines/coverity.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/coverity.yml 2020-10-12 18:53:06.000000000 +0000 @@ -5,32 +5,22 @@ - job: coverity displayName: 'Coverity' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: + - script: | + cd $(Build.SourcesDirectory)/azure-pipelines/docker + docker build -t libgit2/xenial --build-arg BASE=ubuntu:xenial -f xenial . + displayName: 'Build Docker image' - task: Docker@0 - displayName: Build + displayName: Analyze inputs: action: 'Run an image' - imageName: 'libgit2/trusty-openssl:latest' + imageName: libgit2/xenial volumes: | - $(Build.SourcesDirectory):/src - $(Build.BinariesDirectory):/build + $(Build.SourcesDirectory):/home/libgit2/source + $(Build.BinariesDirectory):/home/libgit2/build envVars: | COVERITY_TOKEN=$(COVERITY_TOKEN) - workDir: '/build' - containerCommand: '/src/ci/coverity-build.sh' + workDir: '/home/libgit2/build' + containerCommand: '/home/libgit2/source/azure-pipelines/coverity.sh' detached: false - - task: Docker@0 - displayName: Publish - inputs: - action: 'Run an image' - imageName: 'libgit2/trusty-openssl:latest' - volumes: | - $(Build.SourcesDirectory):/src - $(Build.BinariesDirectory):/build - envVars: | - COVERITY_TOKEN=$(COVERITY_TOKEN) - workDir: '/build' - containerCommand: '/src/ci/coverity-publish.sh' - detached: false - continueOnError: true diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker/bionic libgit2-1.1.0+dfsg.1/azure-pipelines/docker/bionic --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker/bionic 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker/bionic 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,41 @@ +FROM ubuntu:bionic AS apt +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + clang \ + cmake \ + curl \ + gcc \ + git \ + libcurl4-openssl-dev \ + libpcre3-dev \ + libssh2-1-dev \ + libssl-dev \ + libz-dev \ + ninja-build \ + openjdk-8-jre-headless \ + openssh-server \ + openssl \ + pkgconf \ + python \ + sudo \ + valgrind \ + && \ + rm -rf /var/lib/apt/lists/* + +FROM apt AS mbedtls +RUN cd /tmp && \ + curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \ + tar -xz && \ + cd mbedtls-2.16.2 && \ + scripts/config.pl set MBEDTLS_MD4_C 1 && \ + CFLAGS=-fPIC cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON . && \ + ninja install && \ + cd .. && \ + rm -rf mbedtls-2.16.2 + +FROM mbedtls AS configure +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh +RUN mkdir /var/run/sshd + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker/docurium libgit2-1.1.0+dfsg.1/azure-pipelines/docker/docurium --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker/docurium 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker/docurium 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,3 @@ +FROM ubuntu:bionic +RUN apt update && apt install -y cmake pkg-config ruby ruby-dev llvm libclang-dev libssl-dev python-pygments +RUN gem install docurium diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker/entrypoint.sh libgit2-1.1.0+dfsg.1/azure-pipelines/docker/entrypoint.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker/entrypoint.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker/entrypoint.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,4 @@ +#!/bin/bash -e +useradd --shell /bin/bash libgit2 +chown --recursive libgit2:libgit2 /home/libgit2 +exec sudo --preserve-env --set-home --user=libgit2 "$@" diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker/focal libgit2-1.1.0+dfsg.1/azure-pipelines/docker/focal --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker/focal 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker/focal 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,79 @@ +FROM ubuntu:focal AS apt +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + bzip2 \ + clang-10 \ + cmake \ + curl \ + gcc-10 \ + git \ + krb5-user \ + libcurl4-gnutls-dev \ + libgcrypt20-dev \ + libkrb5-dev \ + libpcre3-dev \ + libssl-dev \ + libz-dev \ + llvm-10 \ + make \ + ninja-build \ + openjdk-8-jre-headless \ + openssh-server \ + openssl \ + pkgconf \ + python \ + sudo \ + valgrind \ + && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir /usr/local/msan + +FROM apt AS mbedtls +RUN cd /tmp && \ + curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \ + tar -xz && \ + cd mbedtls-2.16.2 && \ + scripts/config.pl unset MBEDTLS_AESNI_C && \ + scripts/config.pl set MBEDTLS_MD4_C 1 && \ + mkdir build build-msan && \ + cd build && \ + CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \ + ninja install && \ + cd ../build-msan && \ + CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF -DCMAKE_BUILD_TYPE=MemSanDbg -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \ + ninja install && \ + cd .. && \ + rm -rf mbedtls-2.16.2 + +FROM mbedtls AS libssh2 +RUN cd /tmp && \ + curl --insecure --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.2.tar.gz | \ + tar -xz && \ + cd libssh2-1.8.2 && \ + mkdir build build-msan && \ + cd build && \ + CC=clang-10 CFLAGS="-fPIC" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=Libgcrypt -DCMAKE_PREFIX_PATH=/usr/local -DCMAKE_INSTALL_PREFIX=/usr/local .. && \ + ninja install && \ + cd ../build-msan && \ + CC=clang-10 CFLAGS="-fPIC -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" LDFLAGS="-fsanitize=memory" cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=mbedTLS -DCMAKE_PREFIX_PATH=/usr/local/msan -DCMAKE_INSTALL_PREFIX=/usr/local/msan .. && \ + ninja install && \ + cd .. && \ + rm -rf libssh2-1.8.2 + +FROM libssh2 AS valgrind +RUN cd /tmp && \ + curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2 | \ + tar -xj && \ + cd valgrind-3.15.0 && \ + CC=clang-10 ./configure && \ + make MAKEFLAGS="-j -l$(grep -c ^processor /proc/cpuinfo)" && \ + make install && \ + cd .. && \ + rm -rf valgrind-3.15.0 + +FROM valgrind AS configure +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh +RUN mkdir /var/run/sshd + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker/xenial libgit2-1.1.0+dfsg.1/azure-pipelines/docker/xenial --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker/xenial 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker/xenial 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,66 @@ +FROM ubuntu:xenial AS apt +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + bzip2 \ + clang \ + cmake \ + curl \ + gcc \ + git \ + krb5-user \ + libcurl4-gnutls-dev \ + libgcrypt20-dev \ + libkrb5-dev \ + libpcre3-dev \ + libssl-dev \ + libz-dev \ + make \ + ninja-build \ + openjdk-8-jre-headless \ + openssh-server \ + openssl \ + pkgconf \ + python \ + sudo \ + valgrind \ + && \ + rm -rf /var/lib/apt/lists/* + +FROM apt AS mbedtls +RUN cd /tmp && \ + curl --location --silent --show-error https://tls.mbed.org/download/mbedtls-2.16.2-apache.tgz | \ + tar -xz && \ + cd mbedtls-2.16.2 && \ + scripts/config.pl set MBEDTLS_MD4_C 1 && \ + CFLAGS=-fPIC cmake -G Ninja -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON . && \ + ninja install && \ + cd .. && \ + rm -rf mbedtls-2.16.2 + +FROM mbedtls AS libssh2 +RUN cd /tmp && \ + curl --insecure --location --silent --show-error https://www.libssh2.org/download/libssh2-1.8.2.tar.gz | \ + tar -xz && \ + cd libssh2-1.8.2 && \ + CFLAGS=-fPIC cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCRYPTO_BACKEND=Libgcrypt . && \ + ninja install && \ + cd .. && \ + rm -rf libssh2-1.8.2 + +FROM libssh2 AS valgrind +RUN cd /tmp && \ + curl --insecure --location --silent --show-error https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2 | \ + tar -xj && \ + cd valgrind-3.15.0 && \ + ./configure && \ + make && \ + make install && \ + cd .. && \ + rm -rf valgrind-3.15.0 + +FROM valgrind AS configure +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh +RUN mkdir /var/run/sshd + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/docker.yml libgit2-1.1.0+dfsg.1/azure-pipelines/docker.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines/docker.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/docker.yml 2020-10-12 18:53:06.000000000 +0000 @@ -4,29 +4,43 @@ - script: docker run --rm --privileged multiarch/qemu-user-static:register --reset displayName: 'Register Docker QEMU' +- task: cache@2 + displayName: Cache Docker layers + inputs: + key: docker + path: /tmp/dockercache +- script: | + if [ -f /tmp/dockercache/${{parameters.docker.image}}.tar ]; then docker load < /tmp/dockercache/${{parameters.docker.image}}.tar; fi + displayName: 'Load Docker cache' +- script: | + cd $(Build.SourcesDirectory)/azure-pipelines/docker && + docker build -t libgit2/${{parameters.docker.image}} --build-arg BASE=${{parameters.docker.base}} -f ${{parameters.docker.image}} . && + if [ ! -d /tmp/dockercache ]; then mkdir /tmp/dockercache; fi && + docker save libgit2/${{parameters.docker.image}} $(docker history -q libgit2/${{parameters.docker.image}} | grep -v '') > /tmp/dockercache/${{parameters.docker.image}}.tar + displayName: 'Build Docker image' - task: docker@0 displayName: Build inputs: action: 'Run an image' - imageName: ${{ parameters.imageName }} + imageName: libgit2/${{ parameters.docker.image }} volumes: | - $(Build.SourcesDirectory):/src - $(Build.BinariesDirectory):/build + $(Build.SourcesDirectory):/home/libgit2/source + $(Build.BinariesDirectory):/home/libgit2/build envVars: ${{ parameters.environmentVariables }} - workDir: '/build' - containerCommand: '/src/ci/build.sh' + workDir: '/home/libgit2/build' + containerCommand: '/home/libgit2/source/azure-pipelines/build.sh' detached: false - task: docker@0 displayName: Test inputs: action: 'Run an image' - imageName: ${{ parameters.imageName }} + imageName: libgit2/${{ parameters.docker.image }} volumes: | - $(Build.SourcesDirectory):/src - $(Build.BinariesDirectory):/build + $(Build.SourcesDirectory):/home/libgit2/source + $(Build.BinariesDirectory):/home/libgit2/build envVars: ${{ parameters.environmentVariables }} - workDir: '/build' - containerCommand: '/src/ci/test.sh' + workDir: '/home/libgit2/build' + containerCommand: '/home/libgit2/source/azure-pipelines/test.sh' detached: false - task: publishtestresults@2 displayName: Publish Test Results diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/getcontainer.sh libgit2-1.1.0+dfsg.1/azure-pipelines/getcontainer.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/getcontainer.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/getcontainer.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e + +DOCKERFILE_PATH=$1 + +if [ "${DOCKERFILE_PATH}" = "" ]; then + echo "usage: $0 dockerfile" + exit 1 +fi + +if [ "${DOCKER_REGISTRY}" = "" ]; then + echo "DOCKER_REGISTRY environment variable is unset." + echo "Not running inside GitHub Actions or misconfigured?" + exit 1 +fi + +DOCKER_CONTAINER="${GITHUB_REPOSITORY}/$(basename ${DOCKERFILE_PATH})" +DOCKER_REGISTRY_CONTAINER="${DOCKER_REGISTRY}/${DOCKER_CONTAINER}" + +echo "::set-env name=docker-container::${DOCKER_CONTAINER}" +echo "::set-env name=docker-registry-container::${DOCKER_REGISTRY_CONTAINER}" + +# Identify the last git commit that touched the Dockerfiles +# Use this as a hash to identify the resulting docker containers +DOCKER_SHA=$(git log -1 --pretty=format:"%h" -- "${DOCKERFILE_PATH}") +echo "::set-env name=docker-sha::${DOCKER_SHA}" + +DOCKER_REGISTRY_CONTAINER_SHA="${DOCKER_REGISTRY_CONTAINER}:${DOCKER_SHA}" + +echo "::set-env name=docker-registry-container-sha::${DOCKER_REGISTRY_CONTAINER_SHA}" +echo "::set-env name=docker-registry-container-latest::${DOCKER_REGISTRY_CONTAINER}:latest" + +exists="true" +docker login https://${DOCKER_REGISTRY} -u ${GITHUB_ACTOR} -p ${GITHUB_TOKEN} || exists="false" + +if [ "${exists}" != "false" ]; then + docker pull ${DOCKER_REGISTRY_CONTAINER_SHA} || exists="false" +fi + +if [ "${exists}" = "true" ]; then + echo "::set-env name=docker-container-exists::true" +else + echo "::set-env name=docker-container-exists::false" +fi diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/nightly.yml libgit2-1.1.0+dfsg.1/azure-pipelines/nightly.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines/nightly.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/nightly.yml 2020-10-12 18:53:06.000000000 +0000 @@ -2,76 +2,84 @@ - repo: self jobs: -- job: linux_amd64_trusty_gcc_openssl - displayName: 'Linux (amd64; Trusty; GCC; OpenSSL)' +- job: linux_amd64_xenial_gcc_openssl + displayName: 'Linux (amd64; Xenial; GCC; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=gcc - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true -- job: linux_amd64_trusty_gcc_mbedtls - displayName: 'Linux (amd64; Trusty; GCC; mbedTLS)' +- job: linux_amd64_xenial_gcc_mbedtls + displayName: 'Linux (amd64; Xenial; GCC; mbedTLS)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=gcc - CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DSHA1_BACKEND=mbedTLS -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true -- job: linux_amd64_trusty_clang_openssl - displayName: 'Linux (amd64; Trusty; Clang; OpenSSL)' +- job: linux_amd64_xenial_clang_openssl + displayName: 'Linux (amd64; Xenial; Clang; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=clang - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true -- job: linux_amd64_trusty_clang_mbedtls - displayName: 'Linux (amd64; Trusty; Clang; mbedTLS)' +- job: linux_amd64_xenial_clang_mbedtls + displayName: 'Linux (amd64; Xenial; Clang; mbedTLS)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=clang - CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DSHA1_BACKEND=mbedTLS -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true - job: macos - displayName: 'macOS' + displayName: 'macOS (amd64; 10.15)' pool: - vmImage: 'macOS-10.14' + vmImage: 'macOS-10.15' steps: - - bash: . '$(Build.SourcesDirectory)/ci/setup-osx.sh' + - bash: . '$(Build.SourcesDirectory)/azure-pipelines/setup-osx.sh' displayName: Setup - template: bash.yml parameters: environmentVariables: TMPDIR: $(Agent.TempDirectory) PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig - LEAK_CHECK: leaks - CMAKE_OPTIONS: -G Ninja -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Ninja + CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON RUN_INVASIVE_TESTS: true SKIP_SSH_TESTS: true @@ -80,99 +88,114 @@ pool: vmImage: 'vs2017-win2016' steps: - - template: powershell.yml + - template: bash.yml parameters: environmentVariables: - CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 15 2017" -A x64 -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Visual Studio 15 2017 + CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON RUN_INVASIVE_TESTS: true + SKIP_SSH_TESTS: true - job: windows_vs_x86 displayName: 'Windows (x86; Visual Studio)' pool: vmImage: 'vs2017-win2016' steps: - - template: powershell.yml + - template: bash.yml parameters: environmentVariables: - CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 15 2017" -A Win32 -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Visual Studio 15 2017 + CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS RUN_INVASIVE_TESTS: true + SKIP_SSH_TESTS: true - job: windows_mingw_amd64 displayName: 'Windows (amd64; MinGW)' pool: vmImage: 'vs2017-win2016' steps: - - powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1' + - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh' displayName: Setup env: TEMP: $(Agent.TempDirectory) ARCH: amd64 - - template: powershell.yml + - template: bash.yml parameters: environmentVariables: - BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin - CMAKE_OPTIONS: -G"MinGW Makefiles" -DDEPRECATE_HARD=ON + BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON RUN_INVASIVE_TESTS: true + SKIP_SSH_TESTS: true - job: windows_mingw_x86 displayName: 'Windows (x86; MinGW)' pool: vmImage: 'vs2017-win2016' steps: - - powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1' + - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh' displayName: Setup workingDirectory: '$(Build.BinariesDirectory)' env: TEMP: $(Agent.TempDirectory) ARCH: x86 - - template: powershell.yml + - template: bash.yml parameters: environmentVariables: - BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin - CMAKE_OPTIONS: -G"MinGW Makefiles" -DDEPRECATE_HARD=ON + BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON RUN_INVASIVE_TESTS: true + SKIP_SSH_TESTS: true - job: linux_x86_bionic_gcc_openssl displayName: 'Linux (x86; Bionic; GCC; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: qemu: 'true' - imageName: 'libgit2/bionic-x86:latest' + docker: + image: bionic + base: multiarch/ubuntu-core:x86-bionic environmentVariables: | CC=gcc - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true - job: linux_x86_bionic_clang_openssl displayName: 'Linux (x86; Bionic; Clang; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: qemu: 'true' - imageName: 'libgit2/bionic-x86:latest' + docker: + image: bionic + base: multiarch/ubuntu-core:x86-bionic environmentVariables: | CC=clang - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind RUN_INVASIVE_TESTS=true - job: linux_arm32_bionic_gcc_openssl displayName: 'Linux (arm32; Bionic; GCC; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: qemu: 'true' - imageName: 'libgit2/bionic-arm32:latest' + docker: + image: bionic + base: multiarch/ubuntu-core:armhf-bionic environmentVariables: | CC=gcc + CMAKE_GENERATOR=Ninja CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON RUN_INVASIVE_TESTS=true SKIP_PROXY_TESTS=true @@ -180,14 +203,17 @@ - job: linux_arm64_bionic_gcc_openssl displayName: 'Linux (arm64; Bionic; GCC; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: docker.yml parameters: qemu: 'true' - imageName: 'libgit2/bionic-arm64:latest' + docker: + image: bionic + base: multiarch/ubuntu-core:arm64-bionic environmentVariables: | CC=gcc + CMAKE_GENERATOR=Ninja CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON RUN_INVASIVE_TESTS=true SKIP_PROXY_TESTS=true diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/powershell.yml libgit2-1.1.0+dfsg.1/azure-pipelines/powershell.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines/powershell.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/powershell.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# These are the steps used for building on machines with PowerShell. -steps: -- powershell: . '$(Build.SourcesDirectory)\ci\build.ps1' - displayName: Build - workingDirectory: '$(Build.BinariesDirectory)' - env: ${{ parameters.environmentVariables }} -- powershell: . '$(Build.SourcesDirectory)\ci\test.ps1' - displayName: Test - workingDirectory: '$(Build.BinariesDirectory)' - env: ${{ parameters.environmentVariables }} -- task: PublishTestResults@2 - displayName: Publish Test Results - condition: succeededOrFailed() - inputs: - testResultsFiles: 'results_*.xml' - searchFolder: '$(Build.BinariesDirectory)' - mergeTestResults: true diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/setup-mingw.sh libgit2-1.1.0+dfsg.1/azure-pipelines/setup-mingw.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/setup-mingw.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/setup-mingw.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,25 @@ +#!/bin/sh -e + +echo "##############################################################################" +echo "## Downloading mingw" +echo "##############################################################################" + +BUILD_TEMP=${BUILD_TEMP:=$TEMP} +BUILD_TEMP=$(cygpath $BUILD_TEMP) + +case "$ARCH" in + amd64) + MINGW_URI="https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip";; + x86) + MINGW_URI="https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";; +esac + +if [ -z "$MINGW_URI" ]; then + echo "No URL" + exit 1 +fi + +mkdir -p "$BUILD_TEMP" + +curl -s -L "$MINGW_URI" -o "$BUILD_TEMP"/mingw-"$ARCH".zip +unzip -q "$BUILD_TEMP"/mingw-"$ARCH".zip -d "$BUILD_TEMP" diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/setup-osx.sh libgit2-1.1.0+dfsg.1/azure-pipelines/setup-osx.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/setup-osx.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/setup-osx.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,8 @@ +#!/bin/sh + +set -x + +brew update +brew install pkgconfig zlib curl openssl libssh2 ninja + +ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines/test.sh libgit2-1.1.0+dfsg.1/azure-pipelines/test.sh --- libgit2-0.28.5+dfsg.1/azure-pipelines/test.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines/test.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,325 @@ +#!/usr/bin/env bash + +set -e + +if [ -n "$SKIP_TESTS" ]; then + exit 0 +fi + +# Windows doesn't run the NTLM tests properly (yet) +if [[ "$(uname -s)" == MINGW* ]]; then + SKIP_NTLM_TESTS=1 +fi + +SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} +BUILD_DIR=$(pwd) +TMPDIR=${TMPDIR:-/tmp} +USER=${USER:-$(whoami)} + +SUCCESS=1 + +cleanup() { + echo "Cleaning up..." + + if [ ! -z "$GITDAEMON_PID" ]; then + echo "Stopping git daemon..." + kill $GITDAEMON_PID + fi + + if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then + echo "Stopping SSH..." + kill $(cat "${SSHD_DIR}/pid") + fi + + echo "Done." +} + +run_test() { + if [[ "$GITTEST_FLAKY_RETRY" > 0 ]]; then + ATTEMPTS_REMAIN=$GITTEST_FLAKY_RETRY + else + ATTEMPTS_REMAIN=1 + fi + + FAILED=0 + while [[ "$ATTEMPTS_REMAIN" > 0 ]]; do + if [ "$FAILED" -eq 1 ]; then + echo "" + echo "Re-running flaky ${1} tests..." + echo "" + fi + + RETURN_CODE=0 + + CLAR_SUMMARY="${BUILD_DIR}/results_${1}.xml" ctest -V -R "^${1}$" || RETURN_CODE=$? && true + + if [ "$RETURN_CODE" -eq 0 ]; then + FAILED=0 + break + fi + + echo "Test exited with code: $RETURN_CODE" + ATTEMPTS_REMAIN="$(($ATTEMPTS_REMAIN-1))" + FAILED=1 + done + + if [ "$FAILED" -ne 0 ]; then + SUCCESS=0 + fi +} + +# Configure the test environment; run them early so that we're certain +# that they're started by the time we need them. + +echo "##############################################################################" +echo "## Configuring test environment" +echo "##############################################################################" + +if [ -z "$SKIP_GITDAEMON_TESTS" ]; then + echo "Starting git daemon..." + GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX` + git init --bare "${GITDAEMON_DIR}/test.git" + git daemon --listen=localhost --export-all --enable=receive-pack --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null & + GITDAEMON_PID=$! + disown $GITDAEMON_PID +fi + +if [ -z "$SKIP_PROXY_TESTS" ]; then + curl --location --silent --show-error https://github.com/ethomson/poxyproxy/releases/download/v0.7.0/poxyproxy-0.7.0.jar >poxyproxy.jar + + echo "" + echo "Starting HTTP proxy (Basic)..." + java -jar poxyproxy.jar --address 127.0.0.1 --port 8080 --credentials foo:bar --auth-type basic --quiet & + + echo "" + echo "Starting HTTP proxy (NTLM)..." + java -jar poxyproxy.jar --address 127.0.0.1 --port 8090 --credentials foo:bar --auth-type ntlm --quiet & +fi + +if [ -z "$SKIP_NTLM_TESTS" ]; then + curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.4.0/poxygit-0.4.0.jar >poxygit.jar + + echo "" + echo "Starting HTTP server..." + NTLM_DIR=`mktemp -d ${TMPDIR}/ntlm.XXXXXXXX` + git init --bare "${NTLM_DIR}/test.git" + java -jar poxygit.jar --address 127.0.0.1 --port 9000 --credentials foo:baz --quiet "${NTLM_DIR}" & +fi + +if [ -z "$SKIP_SSH_TESTS" ]; then + echo "Starting ssh daemon..." + HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX` + SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX` + git init --bare "${SSHD_DIR}/test.git" + cat >"${SSHD_DIR}/sshd_config" <<-EOF + Port 2222 + ListenAddress 0.0.0.0 + Protocol 2 + HostKey ${SSHD_DIR}/id_rsa + PidFile ${SSHD_DIR}/pid + AuthorizedKeysFile ${HOME}/.ssh/authorized_keys + LogLevel DEBUG + RSAAuthentication yes + PasswordAuthentication yes + PubkeyAuthentication yes + ChallengeResponseAuthentication no + StrictModes no + # Required here as sshd will simply close connection otherwise + UsePAM no + EOF + ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q + /usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log" + + # Set up keys + mkdir "${HOME}/.ssh" + ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q + cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys" + while read algorithm key comment; do + echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts" + done <"${SSHD_DIR}/id_rsa.pub" + + # Get the fingerprint for localhost and remove the colons so we can + # parse it as a hex number. Older versions have a different output + # format. + if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then + SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':') + else + SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :) + fi +fi + +# Run the tests that do not require network connectivity. + +if [ -z "$SKIP_OFFLINE_TESTS" ]; then + echo "" + echo "##############################################################################" + echo "## Running (offline) tests" + echo "##############################################################################" + + run_test offline +fi + +if [ -n "$RUN_INVASIVE_TESTS" ]; then + echo "" + echo "Running invasive tests" + echo "" + + export GITTEST_INVASIVE_FS_SIZE=1 + export GITTEST_INVASIVE_MEMORY=1 + export GITTEST_INVASIVE_SPEED=1 + run_test invasive + unset GITTEST_INVASIVE_FS_SIZE + unset GITTEST_INVASIVE_MEMORY + unset GITTEST_INVASIVE_SPEED +fi + +if [ -z "$SKIP_ONLINE_TESTS" ]; then + # Run the various online tests. The "online" test suite only includes the + # default online tests that do not require additional configuration. The + # "proxy" and "ssh" test suites require further setup. + + echo "" + echo "##############################################################################" + echo "## Running (online) tests" + echo "##############################################################################" + + export GITTEST_FLAKY_RETRY=5 + run_test online + unset GITTEST_FLAKY_RETRY +fi + +if [ -z "$SKIP_GITDAEMON_TESTS" ]; then + echo "" + echo "Running gitdaemon tests" + echo "" + + export GITTEST_REMOTE_URL="git://localhost/test.git" + run_test gitdaemon + unset GITTEST_REMOTE_URL +fi + +if [ -z "$SKIP_PROXY_TESTS" ]; then + echo "" + echo "Running proxy tests (Basic authentication)" + echo "" + + export GITTEST_REMOTE_PROXY_HOST="localhost:8080" + export GITTEST_REMOTE_PROXY_USER="foo" + export GITTEST_REMOTE_PROXY_PASS="bar" + run_test proxy + unset GITTEST_REMOTE_PROXY_HOST + unset GITTEST_REMOTE_PROXY_USER + unset GITTEST_REMOTE_PROXY_PASS + + echo "" + echo "Running proxy tests (NTLM authentication)" + echo "" + + export GITTEST_REMOTE_PROXY_HOST="localhost:8090" + export GITTEST_REMOTE_PROXY_USER="foo" + export GITTEST_REMOTE_PROXY_PASS="bar" + export GITTEST_FLAKY_RETRY=5 + run_test proxy + unset GITTEST_FLAKY_RETRY + unset GITTEST_REMOTE_PROXY_HOST + unset GITTEST_REMOTE_PROXY_USER + unset GITTEST_REMOTE_PROXY_PASS +fi + +if [ -z "$SKIP_NTLM_TESTS" ]; then + echo "" + echo "Running NTLM tests (IIS emulation)" + echo "" + + export GITTEST_REMOTE_URL="http://localhost:9000/ntlm/test.git" + export GITTEST_REMOTE_USER="foo" + export GITTEST_REMOTE_PASS="baz" + run_test auth_clone_and_push + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_USER + unset GITTEST_REMOTE_PASS + + echo "" + echo "Running NTLM tests (Apache emulation)" + echo "" + + export GITTEST_REMOTE_URL="http://localhost:9000/broken-ntlm/test.git" + export GITTEST_REMOTE_USER="foo" + export GITTEST_REMOTE_PASS="baz" + run_test auth_clone_and_push + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_USER + unset GITTEST_REMOTE_PASS +fi + +if [ -z "$SKIP_NEGOTIATE_TESTS" -a -n "$GITTEST_NEGOTIATE_PASSWORD" ]; then + echo "" + echo "Running SPNEGO tests" + echo "" + + if [ "$(uname -s)" = "Darwin" ]; then + KINIT_FLAGS="--password-file=STDIN" + fi + + echo $GITTEST_NEGOTIATE_PASSWORD | kinit $KINIT_FLAGS test@LIBGIT2.ORG + klist -5f + + export GITTEST_REMOTE_URL="https://test.libgit2.org/kerberos/empty.git" + export GITTEST_REMOTE_DEFAULT="true" + run_test auth_clone + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_DEFAULT + + echo "" + echo "Running SPNEGO tests (expect/continue)" + echo "" + + export GITTEST_REMOTE_URL="https://test.libgit2.org/kerberos/empty.git" + export GITTEST_REMOTE_DEFAULT="true" + export GITTEST_REMOTE_EXPECTCONTINUE="true" + run_test auth_clone + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_DEFAULT + unset GITTEST_REMOTE_EXPECTCONTINUE + + kdestroy -A +fi + +if [ -z "$SKIP_SSH_TESTS" ]; then + echo "" + echo "Running ssh tests" + echo "" + + export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git" + export GITTEST_REMOTE_USER=$USER + export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa" + export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub" + export GITTEST_REMOTE_SSH_PASSPHRASE="" + export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}" + run_test ssh + unset GITTEST_REMOTE_URL + unset GITTEST_REMOTE_USER + unset GITTEST_REMOTE_SSH_KEY + unset GITTEST_REMOTE_SSH_PUBKEY + unset GITTEST_REMOTE_SSH_PASSPHRASE + unset GITTEST_REMOTE_SSH_FINGERPRINT +fi + +if [ -z "$SKIP_FUZZERS" ]; then + echo "" + echo "##############################################################################" + echo "## Running fuzzers" + echo "##############################################################################" + + ctest -V -R 'fuzzer' +fi + +cleanup + +if [ "$SUCCESS" -ne 1 ]; then + echo "Some tests failed." + exit 1 +fi + +echo "Success." +exit 0 diff -Nru libgit2-0.28.5+dfsg.1/azure-pipelines.yml libgit2-1.1.0+dfsg.1/azure-pipelines.yml --- libgit2-0.28.5+dfsg.1/azure-pipelines.yml 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/azure-pipelines.yml 2020-10-12 18:53:06.000000000 +0000 @@ -6,146 +6,148 @@ - maint/* jobs: -- job: linux_amd64_trusty_gcc_openssl - displayName: 'Linux (amd64; Trusty; GCC; OpenSSL)' +- job: linux_amd64_xenial_gcc_openssl + displayName: 'Linux (amd64; Xenial; GCC; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: azure-pipelines/docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=gcc - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }} -- job: linux_amd64_trusty_gcc_mbedtls - displayName: 'Linux (amd64; Trusty; GCC; mbedTLS)' +- job: linux_amd64_xenial_gcc_mbedtls + displayName: 'Linux (amd64; Xenial; GCC; mbedTLS)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: azure-pipelines/docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=gcc - CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DSHA1_BACKEND=mbedTLS -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }} -- job: linux_amd64_trusty_clang_openssl - displayName: 'Linux (amd64; Trusty; Clang; OpenSSL)' +- job: linux_amd64_xenial_clang_openssl + displayName: 'Linux (amd64; Xenial; Clang; OpenSSL)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: azure-pipelines/docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=clang - CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }} -- job: linux_amd64_trusty_clang_mbedtls - displayName: 'Linux (amd64; Trusty; Clang; mbedTLS)' +- job: linux_amd64_xenial_clang_mbedtls + displayName: 'Linux (amd64; Xenial; Clang; mbedTLS)' pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'ubuntu-18.04' steps: - template: azure-pipelines/docker.yml parameters: - imageName: 'libgit2/trusty-amd64:latest' + docker: + image: xenial + base: ubuntu:xenial environmentVariables: | CC=clang - CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DSHA1_BACKEND=mbedTLS -DDEPRECATE_HARD=ON - LEAK_CHECK=valgrind + CMAKE_GENERATOR=Ninja + CMAKE_OPTIONS=-DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + GITTEST_NEGOTIATE_PASSWORD=${{ variables.GITTEST_NEGOTIATE_PASSWORD }} - job: macos - displayName: 'macOS' + displayName: 'macOS (amd64; 10.15)' pool: - vmImage: 'macOS-10.14' + vmImage: 'macOS-10.15' steps: - - bash: . '$(Build.SourcesDirectory)/ci/setup-osx.sh' + - bash: . '$(Build.SourcesDirectory)/azure-pipelines/setup-osx.sh' displayName: Setup - template: azure-pipelines/bash.yml parameters: environmentVariables: TMPDIR: $(Agent.TempDirectory) PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig - LEAK_CHECK: leaks - CMAKE_OPTIONS: -G Ninja -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Ninja + CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON SKIP_SSH_TESTS: true + GITTEST_NEGOTIATE_PASSWORD: ${{ variables.GITTEST_NEGOTIATE_PASSWORD }} - job: windows_vs_amd64 displayName: 'Windows (amd64; Visual Studio)' pool: vmImage: 'vs2017-win2016' steps: - - template: azure-pipelines/powershell.yml + - template: azure-pipelines/bash.yml parameters: environmentVariables: - CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 15 2017" -A x64 -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Visual Studio 15 2017 + CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true - job: windows_vs_x86 displayName: 'Windows (x86; Visual Studio)' pool: vmImage: 'vs2017-win2016' steps: - - template: azure-pipelines/powershell.yml + - template: azure-pipelines/bash.yml parameters: environmentVariables: - CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 15 2017" -A Win32 -DDEPRECATE_HARD=ON + CMAKE_GENERATOR: Visual Studio 15 2017 + CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true - job: windows_mingw_amd64 displayName: 'Windows (amd64; MinGW)' pool: vmImage: 'vs2017-win2016' steps: - - powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1' + - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh' displayName: Setup env: TEMP: $(Agent.TempDirectory) ARCH: amd64 - - template: azure-pipelines/powershell.yml + - template: azure-pipelines/bash.yml parameters: environmentVariables: - BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin - CMAKE_OPTIONS: -G"MinGW Makefiles" -DDEPRECATE_HARD=ON + BUILD_PATH: $(Agent.TempDirectory)\mingw64\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true - job: windows_mingw_x86 displayName: 'Windows (x86; MinGW)' pool: vmImage: 'vs2017-win2016' steps: - - powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1' + - bash: . '$(Build.SourcesDirectory)\azure-pipelines\setup-mingw.sh' displayName: Setup workingDirectory: '$(Build.BinariesDirectory)' env: TEMP: $(Agent.TempDirectory) ARCH: x86 - - template: azure-pipelines/powershell.yml + - template: azure-pipelines/bash.yml parameters: environmentVariables: - BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin - CMAKE_OPTIONS: -G"MinGW Makefiles" -DDEPRECATE_HARD=ON - -- job: documentation - displayName: 'Generate Documentation' - pool: - vmImage: 'Ubuntu 16.04' - steps: - - script: | - git config user.name 'Documentation Generation' - git config user.email 'noreply@libgit2.org' - docker run --rm -v /home/vsts/work/1/s:/src -w /src libgit2/docurium:test cm doc api.docurium - git checkout gh-pages - cp -R * '$(Build.BinariesDirectory)' - - task: archivefiles@2 - displayName: 'Archive Documentation' - inputs: - rootFolderOrFile: '$(Build.BinariesDirectory)' - includeRootFolder: false - archiveFile: '$(Build.ArtifactStagingDirectory)/api-documentation.zip' - - task: publishbuildartifacts@1 - displayName: 'Upload Documentation' - inputs: - pathToPublish: '$(Build.ArtifactStagingDirectory)' - artifactName: 'docs' + BUILD_PATH: $(Agent.TempDirectory)\mingw32\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true diff -Nru libgit2-0.28.5+dfsg.1/ci/build.ps1 libgit2-1.1.0+dfsg.1/ci/build.ps1 --- libgit2-0.28.5+dfsg.1/ci/build.ps1 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/build.ps1 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -Set-StrictMode -Version Latest - -$ErrorActionPreference = "Stop" -$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' - -if ($Env:SOURCE_DIR) { $SourceDirectory = $Env:SOURCE_DIR } else { $SourceDirectory = Split-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) -Parent } -$BuildDirectory = $(Get-Location).Path - -# Resolve CMake before modifying PATH -$CMAKE = (Get-Command cmake).Path - -# Prepend BUILD_PATH to make available our own tools -if ($Env:BUILD_PATH) { $Env:PATH = $Env:BUILD_PATH } - -Write-Host "Source directory: ${SourceDirectory}" -Write-Host "Build directory: ${BuildDirectory}" -Write-Host "" -Write-Host "Operating system version:" -Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, BuildNumber, OSArchitecture | Format-List -Write-Host "PATH: ${Env:PATH}" -Write-Host "" - -Write-Host "##############################################################################" -Write-Host "## Configuring build environment" -Write-Host "##############################################################################" - -Invoke-Expression "& '${CMAKE}' ${SourceDirectory} -DBUILD_EXAMPLES=ON ${Env:CMAKE_OPTIONS}" -if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) } - -Write-Host "" -Write-Host "##############################################################################" -Write-Host "## Building libgit2" -Write-Host "##############################################################################" - -Invoke-Expression "& '${CMAKE}' --build ." -if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) } diff -Nru libgit2-0.28.5+dfsg.1/ci/build.sh libgit2-1.1.0+dfsg.1/ci/build.sh --- libgit2-0.28.5+dfsg.1/ci/build.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/build.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -# -# Environment variables: -# -# SOURCE_DIR: Set to the directory of the libgit2 source (optional) -# If not set, it will be derived relative to this script. - -set -e - -SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} -BUILD_DIR=$(pwd) -CC=${CC:-cc} - -indent() { sed "s/^/ /"; } - -echo "Source directory: ${SOURCE_DIR}" -echo "Build directory: ${BUILD_DIR}" -echo "" - -if [ "$(uname -s)" = "Darwin" ]; then - echo "macOS version:" - sw_vers | indent -fi - -if [ -f "/etc/debian_version" ]; then - echo "Debian version:" - lsb_release -a | indent -fi - -echo "Kernel version:" -uname -a 2>&1 | indent - -echo "CMake version:" -cmake --version 2>&1 | indent -echo "Compiler version:" -$CC --version 2>&1 | indent -echo "" - -echo "##############################################################################" -echo "## Configuring build environment" -echo "##############################################################################" - -echo cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON ${CMAKE_OPTIONS} -cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON -DBUILD_FUZZERS=ON -DUSE_STANDALONE_FUZZERS=ON ${CMAKE_OPTIONS} - -echo "" -echo "##############################################################################" -echo "## Building libgit2" -echo "##############################################################################" - -cmake --build . diff -Nru libgit2-0.28.5+dfsg.1/ci/coverity-build.sh libgit2-1.1.0+dfsg.1/ci/coverity-build.sh --- libgit2-0.28.5+dfsg.1/ci/coverity-build.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/coverity-build.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -#!/bin/bash - -set -e - -# Environment check -[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1 - -SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} -BUILD_DIR=$(pwd) - -case $(uname -m) in - i?86) BITS=32 ;; - amd64|x86_64) BITS=64 ;; -esac -SCAN_TOOL=https://scan.coverity.com/download/cxx/linux${BITS} -TOOL_BASE=$(pwd)/_coverity-scan - -# Install coverity tools -if [ ! -d "$TOOL_BASE" ]; then - echo "Downloading coverity..." - mkdir -p "$TOOL_BASE" - pushd "$TOOL_BASE" - wget -O coverity_tool.tgz $SCAN_TOOL \ - --post-data "project=libgit2&token=$COVERITY_TOKEN" - tar xzf coverity_tool.tgz - popd - TOOL_DIR=$(find "$TOOL_BASE" -type d -name 'cov-analysis*') - ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis -fi - -cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_BASE"/cov-analysis/config/user_nodefs.h - -COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build" - -# Configure and build -cmake ${SOURCE_DIR} - -COVERITY_UNSUPPORTED=1 \ - $COV_BUILD --dir cov-int \ - cmake --build . - diff -Nru libgit2-0.28.5+dfsg.1/ci/coverity-publish.sh libgit2-1.1.0+dfsg.1/ci/coverity-publish.sh --- libgit2-0.28.5+dfsg.1/ci/coverity-publish.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/coverity-publish.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -#!/bin/bash - -set -e - -# Results check -[ ! -d "cov-int" ] && echo "Coverity directory not found" && exit 1 - -# Upload results -tar czf libgit2.tgz cov-int - -SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} -SHA=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD) - -HTML="$(curl \ - --silent \ - --write-out "\n%{http_code}" \ - --form token="$COVERITY_TOKEN" \ - --form email=libgit2@gmail.com \ - --form file=@libgit2.tgz \ - --form version="$SHA" \ - --form description="libgit2 build" \ - https://scan.coverity.com/builds?project=libgit2)" - -# Body is everything up to the last line -BODY="$(echo "$HTML" | head -n-1)" - -# Status code is the last line -STATUS_CODE="$(echo "$HTML" | tail -n1)" - -if [ "${STATUS_CODE}" != "200" -a "${STATUS_CODE}" != "201" ]; then - echo "Received error code ${STATUS_CODE} from Coverity" - exit 1 -fi diff -Nru libgit2-0.28.5+dfsg.1/ci/setup-linux.sh libgit2-1.1.0+dfsg.1/ci/setup-linux.sh --- libgit2-0.28.5+dfsg.1/ci/setup-linux.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/setup-linux.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#!/bin/sh - -set -e -set -x - -TMPDIR=${TMPDIR:-/tmp} - -if [ -z "$SKIP_APT" ]; then - apt-get update - apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server -fi - -mkdir -p /var/run/sshd - -if [ "$MBEDTLS" ]; then - MBEDTLS_DIR=${MBEDTLS_DIR:-$(mktemp -d ${TMPDIR}/mbedtls.XXXXXXXX)} - - git clone --depth 10 --single-branch --branch mbedtls-2.6.1 https://github.com/ARMmbed/mbedtls.git ${MBEDTLS_DIR} - cd ${MBEDTLS_DIR} - - CFLAGS=-fPIC cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DUSE_STATIC_MBEDTLS_LIBRARY=ON . - cmake --build . - - if [ -z "$SKIP_MBEDTLS_INSTALL" ]; then - make install - fi -fi diff -Nru libgit2-0.28.5+dfsg.1/ci/setup-mingw.ps1 libgit2-1.1.0+dfsg.1/ci/setup-mingw.ps1 --- libgit2-0.28.5+dfsg.1/ci/setup-mingw.ps1 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/setup-mingw.ps1 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Set-StrictMode -Version Latest - -$ErrorActionPreference = "Stop" -$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' - -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - -[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem"); - -Write-Host "##############################################################################" -Write-Host "## Downloading mingw" -Write-Host "##############################################################################" - -if ($env:ARCH -eq "amd64") { - $mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip" - $platform = "x86_64" -} else { - $mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip" - $platform = "x86" -} - -$wc = New-Object net.webclient -$wc.Downloadfile($mingw_uri, "${Env:TEMP}/mingw-${Env:ARCH}.zip") - -[System.IO.Compression.ZipFile]::ExtractToDirectory("${Env:TEMP}/mingw-${Env:ARCH}.zip", $Env:TEMP) diff -Nru libgit2-0.28.5+dfsg.1/ci/setup-osx.sh libgit2-1.1.0+dfsg.1/ci/setup-osx.sh --- libgit2-0.28.5+dfsg.1/ci/setup-osx.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/setup-osx.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#!/bin/sh - -set -x - -brew update -brew install pkgconfig zlib curl openssl libssh2 ninja - -ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib diff -Nru libgit2-0.28.5+dfsg.1/ci/test.ps1 libgit2-1.1.0+dfsg.1/ci/test.ps1 --- libgit2-0.28.5+dfsg.1/ci/test.ps1 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/test.ps1 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -Set-StrictMode -Version Latest - -$ErrorActionPreference = "Stop" -$PSDefaultParameterValues['*:ErrorAction'] = 'Stop' - -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - -$SourceDir = Split-Path (Split-Path (Get-Variable MyInvocation).Value.MyCommand.Path) -$BuildDir = Get-Location -$global:Success = $true - -if ($Env:SKIP_TESTS) { exit } - -# Ask ctest what it would run if we were to invoke it directly. This lets -# us manage the test configuration in a single place (tests/CMakeLists.txt) -# instead of running clar here as well. But it allows us to wrap our test -# harness with a leak checker like valgrind. Append the option to write -# JUnit-style XML files. -function run_test { - $TestName = $args[0] - - $TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" - - if (-Not ($TestCommand -match "(?ms).*\n^[0-9]*: Test command: ")) { - echo "Could not find tests: $TestName" - exit - } - - $TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" -replace "(?ms).*\n^[0-9]*: Test command: ","" -replace "\n.*","" - $TestCommand += " -r${BuildDir}\results_${TestName}.xml" - - if ($Env:GITTEST_FLAKY_RETRY -gt 0) { - $AttemptsRemain = $Env:GITTEST_FLAKY_RETRY - } else { - $AttemptsRemain = 1 - } - - $Failed = 0 - while ($AttemptsRemain -ne 0) { - if ($Failed -eq 1) { - Write-Host "" - Write-Host "Re-running flaky $TestName tests..." - Write-Host "" - } - - Invoke-Expression $TestCommand - if ($LastExitCode -eq 0) { - $Failed = 0 - break - } else { - $Failed = 1 - } - - $AttemptsRemain = $AttemptsRemain - 1 - } - - if ($Failed -eq 1) { $global:Success = $false } -} - -Write-Host "##############################################################################" -Write-Host "## Configuring test environment" -Write-Host "##############################################################################" - -if (-not $Env:SKIP_PROXY_TESTS) { - Write-Host "" - Write-Host "Starting HTTP proxy..." - Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.4.0/poxyproxy-0.4.0.jar -OutFile poxyproxy.jar - javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar --quiet -} - -Write-Host "" -Write-Host "##############################################################################" -Write-Host "## Running (offline) tests" -Write-Host "##############################################################################" - -run_test offline - -if ($Env:RUN_INVASIVE_TESTS) { - Write-Host "" - Write-Host "##############################################################################" - Write-Host "## Running (invasive) tests" - Write-Host "##############################################################################" - - $Env:GITTEST_INVASIVE_FS_SIZE=1 - $Env:GITTEST_INVASIVE_MEMORY=1 - $Env:GITTEST_INVASIVE_SPEED=1 - run_test invasive - $Env:GITTEST_INVASIVE_FS_SIZE=$null - $Env:GITTEST_INVASIVE_MEMORY=$null - $Env:GITTEST_INVASIVE_SPEED=$null -} - -if (-not $Env:SKIP_ONLINE_TESTS) { - Write-Host "" - Write-Host "##############################################################################" - Write-Host "## Running (online) tests" - Write-Host "##############################################################################" - - $Env:GITTEST_FLAKY_RETRY=5 - run_test online - $Env:GITTEST_FLAKY_RETRY=0 -} - -if (-not $Env:SKIP_PROXY_TESTS) { - Write-Host "" - Write-Host "Running proxy tests" - Write-Host "" - - $Env:GITTEST_REMOTE_PROXY_HOST="localhost:8080" - $Env:GITTEST_REMOTE_PROXY_USER="foo" - $Env:GITTEST_REMOTE_PROXY_PASS="bar" - - run_test proxy - - $Env:GITTEST_REMOTE_PROXY_HOST=$null - $Env:GITTEST_REMOTE_PROXY_USER=$null - $Env:GITTEST_REMOTE_PROXY_PASS=$null - - taskkill /F /IM javaw.exe -} - -if (-Not $global:Success) { exit 1 } diff -Nru libgit2-0.28.5+dfsg.1/ci/test.sh libgit2-1.1.0+dfsg.1/ci/test.sh --- libgit2-0.28.5+dfsg.1/ci/test.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/ci/test.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,254 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ -n "$SKIP_TESTS" ]; then - exit 0 -fi - -SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )} -BUILD_DIR=$(pwd) -TMPDIR=${TMPDIR:-/tmp} -USER=${USER:-$(whoami)} - -SUCCESS=1 - -VALGRIND="valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions=\"$SOURCE_DIR/libgit2_clar.supp\"" -LEAKS="MallocStackLogging=1 MallocScribble=1 MallocLogFile=/dev/null CLAR_AT_EXIT=\"leaks -quiet \$PPID\"" - -cleanup() { - echo "Cleaning up..." - - if [ ! -z "$GITDAEMON_DIR" -a -f "${GITDAEMON_DIR}/pid" ]; then - echo "Stopping git daemon..." - kill $(cat "${GITDAEMON_DIR}/pid") - fi - - if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then - echo "Stopping SSH..." - kill $(cat "${SSHD_DIR}/pid") - fi - - echo "Done." -} - -# Ask ctest what it would run if we were to invoke it directly. This lets -# us manage the test configuration in a single place (tests/CMakeLists.txt) -# instead of running clar here as well. But it allows us to wrap our test -# harness with a leak checker like valgrind. Append the option to write -# JUnit-style XML files. -run_test() { - TEST_CMD=$(ctest -N -V -R "^${1}$" | sed -n 's/^[0-9]*: Test command: //p') - - if [ -z "$TEST_CMD" ]; then - echo "Could not find tests: $1" - exit 1 - fi - - TEST_CMD="${TEST_CMD} -r${BUILD_DIR}/results_${1}.xml" - - if [ "$LEAK_CHECK" = "valgrind" ]; then - RUNNER="$VALGRIND $TEST_CMD" - elif [ "$LEAK_CHECK" = "leaks" ]; then - RUNNER="$LEAKS $TEST_CMD" - else - RUNNER="$TEST_CMD" - fi - - if [[ "$GITTEST_FLAKY_RETRY" > 0 ]]; then - ATTEMPTS_REMAIN=$GITTEST_FLAKY_RETRY - else - ATTEMPTS_REMAIN=1 - fi - - FAILED=0 - while [[ "$ATTEMPTS_REMAIN" > 0 ]]; do - if [ "$FAILED" -eq 1 ]; then - echo "" - echo "Re-running flaky ${1} tests..." - echo "" - fi - - RETURN_CODE=0 - eval $RUNNER || RETURN_CODE=$? && true - - if [ "$RETURN_CODE" -eq 0 ]; then - break - fi - - echo "Test exited with code: $RETURN_CODE" - ATTEMPTS_REMAIN="$(($ATTEMPTS_REMAIN-1))" - FAILED=1 - done - - if [ "$FAILED" -ne 0 ]; then - SUCCESS=0 - fi -} - -# Configure the test environment; run them early so that we're certain -# that they're started by the time we need them. - -echo "##############################################################################" -echo "## Configuring test environment" -echo "##############################################################################" - -if [ -z "$SKIP_GITDAEMON_TESTS" ]; then - echo "Starting git daemon..." - GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX` - git init --bare "${GITDAEMON_DIR}/test.git" - git daemon --listen=localhost --export-all --enable=receive-pack --pid-file="${GITDAEMON_DIR}/pid" --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null & -fi - -if [ -z "$SKIP_PROXY_TESTS" ]; then - echo "Starting HTTP proxy..." - curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.4.0/poxyproxy-0.4.0.jar >poxyproxy.jar - java -jar poxyproxy.jar -d --address 127.0.0.1 --port 8080 --credentials foo:bar --quiet & -fi - -if [ -z "$SKIP_SSH_TESTS" ]; then - echo "Starting ssh daemon..." - HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX` - SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX` - git init --bare "${SSHD_DIR}/test.git" - cat >"${SSHD_DIR}/sshd_config" <<-EOF - Port 2222 - ListenAddress 0.0.0.0 - Protocol 2 - HostKey ${SSHD_DIR}/id_rsa - PidFile ${SSHD_DIR}/pid - AuthorizedKeysFile ${HOME}/.ssh/authorized_keys - LogLevel DEBUG - RSAAuthentication yes - PasswordAuthentication yes - PubkeyAuthentication yes - ChallengeResponseAuthentication no - StrictModes no - # Required here as sshd will simply close connection otherwise - UsePAM no - EOF - ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q - /usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log" - - # Set up keys - mkdir "${HOME}/.ssh" - ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q - cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys" - while read algorithm key comment; do - echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts" - done <"${SSHD_DIR}/id_rsa.pub" - - # Get the fingerprint for localhost and remove the colons so we can - # parse it as a hex number. Older versions have a different output - # format. - if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then - SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':') - else - SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :) - fi -fi - -# Run the tests that do not require network connectivity. - -if [ -z "$SKIP_OFFLINE_TESTS" ]; then - echo "" - echo "##############################################################################" - echo "## Running (offline) tests" - echo "##############################################################################" - - run_test offline -fi - -if [ -n "$RUN_INVASIVE_TESTS" ]; then - echo "" - echo "Running invasive tests" - echo "" - - export GITTEST_INVASIVE_FS_SIZE=1 - export GITTEST_INVASIVE_MEMORY=1 - export GITTEST_INVASIVE_SPEED=1 - run_test invasive - unset GITTEST_INVASIVE_FS_SIZE - unset GITTEST_INVASIVE_MEMORY - unset GITTEST_INVASIVE_SPEED -fi - -if [ -z "$SKIP_ONLINE_TESTS" ]; then - # Run the various online tests. The "online" test suite only includes the - # default online tests that do not require additional configuration. The - # "proxy" and "ssh" test suites require further setup. - - echo "" - echo "##############################################################################" - echo "## Running (online) tests" - echo "##############################################################################" - - export GITTEST_FLAKY_RETRY=5 - run_test online - unset GITTEST_FLAKY_RETRY -fi - -if [ -z "$SKIP_GITDAEMON_TESTS" ]; then - echo "" - echo "Running gitdaemon tests" - echo "" - - export GITTEST_REMOTE_URL="git://localhost/test.git" - run_test gitdaemon - unset GITTEST_REMOTE_URL -fi - -if [ -z "$SKIP_PROXY_TESTS" ]; then - echo "" - echo "Running proxy tests" - echo "" - - export GITTEST_REMOTE_PROXY_HOST="localhost:8080" - export GITTEST_REMOTE_PROXY_USER="foo" - export GITTEST_REMOTE_PROXY_PASS="bar" - run_test proxy - unset GITTEST_REMOTE_PROXY_HOST - unset GITTEST_REMOTE_PROXY_USER - unset GITTEST_REMOTE_PROXY_PASS -fi - -if [ -z "$SKIP_SSH_TESTS" ]; then - echo "" - echo "Running ssh tests" - echo "" - - export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git" - export GITTEST_REMOTE_USER=$USER - export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa" - export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub" - export GITTEST_REMOTE_SSH_PASSPHRASE="" - export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}" - run_test ssh - unset GITTEST_REMOTE_URL - unset GITTEST_REMOTE_USER - unset GITTEST_REMOTE_SSH_KEY - unset GITTEST_REMOTE_SSH_PUBKEY - unset GITTEST_REMOTE_SSH_PASSPHRASE - unset GITTEST_REMOTE_SSH_FINGERPRINT -fi - -if [ -z "$SKIP_FUZZERS" ]; then - echo "" - echo "##############################################################################" - echo "## Running fuzzers" - echo "##############################################################################" - - for fuzzer in fuzzers/*_fuzzer; do - "${fuzzer}" "${SOURCE_DIR}/fuzzers/corpora/$(basename "${fuzzer%_fuzzer}")" || failure - done -fi - -cleanup - -if [ "$SUCCESS" -ne 1 ]; then - echo "Some tests failed." - exit 1 -fi - -echo "Success." -exit 0 diff -Nru libgit2-0.28.5+dfsg.1/cmake/AddCFlagIfSupported.cmake libgit2-1.1.0+dfsg.1/cmake/AddCFlagIfSupported.cmake --- libgit2-0.28.5+dfsg.1/cmake/AddCFlagIfSupported.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/AddCFlagIfSupported.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,30 @@ +# - Append compiler flag to CMAKE_C_FLAGS if compiler supports it +# ADD_C_FLAG_IF_SUPPORTED() +# - the compiler flag to test +# This internally calls the CHECK_C_COMPILER_FLAG macro. + +INCLUDE(CheckCCompilerFlag) + +MACRO(ADD_C_FLAG _FLAG) + STRING(TOUPPER ${_FLAG} UPCASE) + STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE}) + STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY}) + CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED) + + IF(IS_${UPCASE_PRETTY}_SUPPORTED) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}") + ELSE() + MESSAGE(FATAL_ERROR "Required flag ${_FLAG} is not supported") + ENDIF() +ENDMACRO() + +MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG) + STRING(TOUPPER ${_FLAG} UPCASE) + STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE}) + STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY}) + CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED) + + IF(IS_${UPCASE_PRETTY}_SUPPORTED) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}") + ENDIF() +ENDMACRO() diff -Nru libgit2-0.28.5+dfsg.1/cmake/EnableWarnings.cmake libgit2-1.1.0+dfsg.1/cmake/EnableWarnings.cmake --- libgit2-0.28.5+dfsg.1/cmake/EnableWarnings.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/EnableWarnings.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,15 @@ +MACRO(ENABLE_WARNINGS flag) + ADD_C_FLAG_IF_SUPPORTED(-W${flag}) +ENDMACRO() + +MACRO(DISABLE_WARNINGS flag) + ADD_C_FLAG_IF_SUPPORTED(-Wno-${flag}) +ENDMACRO() + +IF(ENABLE_WERROR) + IF(MSVC) + ADD_COMPILE_OPTIONS(-WX) + ELSE() + ADD_C_FLAG_IF_SUPPORTED(-Werror) + ENDIF() +ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindCoreFoundation.cmake libgit2-1.1.0+dfsg.1/cmake/FindCoreFoundation.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindCoreFoundation.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindCoreFoundation.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,26 @@ +# Find CoreFoundation.framework +# This will define : +# +# COREFOUNDATION_FOUND +# COREFOUNDATION_LIBRARIES +# COREFOUNDATION_LDFLAGS +# + +FIND_PATH(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h) +FIND_LIBRARY(COREFOUNDATION_LIBRARIES NAMES CoreFoundation) +IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_LIBRARIES) + IF (NOT CoreFoundation_FIND_QUIETLY) + MESSAGE(STATUS "Found CoreFoundation ${COREFOUNDATION_LIBRARIES}") + ENDIF() + SET(COREFOUNDATION_FOUND TRUE) + SET(COREFOUNDATION_LDFLAGS "-framework CoreFoundation") +ENDIF () + +IF (CoreFoundation_FIND_REQUIRED AND NOT COREFOUNDATION_FOUND) + MESSAGE(FATAL_ERROR "CoreFoundation not found") +ENDIF() + +MARK_AS_ADVANCED( + COREFOUNDATION_INCLUDE_DIR + COREFOUNDATION_LIBRARIES +) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindGSSAPI.cmake libgit2-1.1.0+dfsg.1/cmake/FindGSSAPI.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindGSSAPI.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindGSSAPI.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,324 @@ +# - Try to find GSSAPI +# Once done this will define +# +# KRB5_CONFIG - Path to krb5-config +# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI +# +# Read-Only variables: +# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found +# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Kerberos has been found +# GSSAPI_FOUND - system has GSSAPI +# GSSAPI_INCLUDE_DIR - the GSSAPI include directory +# GSSAPI_LIBRARIES - Link these to use GSSAPI +# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI +# +#============================================================================= +# Copyright (c) 2013 Andreas Schneider +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# + +find_path(GSSAPI_ROOT_DIR + NAMES + include/gssapi.h + include/gssapi/gssapi.h + HINTS + ${_GSSAPI_ROOT_HINTS} + PATHS + ${_GSSAPI_ROOT_PATHS} +) +mark_as_advanced(GSSAPI_ROOT_DIR) + +if (UNIX) + find_program(KRB5_CONFIG + NAMES + krb5-config + PATHS + ${GSSAPI_ROOT_DIR}/bin + /opt/local/bin) + mark_as_advanced(KRB5_CONFIG) + + if (KRB5_CONFIG) + # Check if we have MIT KRB5 + execute_process( + COMMAND + ${KRB5_CONFIG} --vendor + RESULT_VARIABLE + _GSSAPI_VENDOR_RESULT + OUTPUT_VARIABLE + _GSSAPI_VENDOR_STRING) + + if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") + set(GSSAPI_FLAVOR_MIT TRUE) + else() + execute_process( + COMMAND + ${KRB5_CONFIG} --libs gssapi + RESULT_VARIABLE + _GSSAPI_LIBS_RESULT + OUTPUT_VARIABLE + _GSSAPI_LIBS_STRING) + + if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*") + set(GSSAPI_FLAVOR_HEIMDAL TRUE) + endif() + endif() + + # Get the include dir + execute_process( + COMMAND + ${KRB5_CONFIG} --cflags gssapi + RESULT_VARIABLE + _GSSAPI_INCLUDE_RESULT + OUTPUT_VARIABLE + _GSSAPI_INCLUDE_STRING) + string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}") + string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}") + endif() + + if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL) + # Check for HEIMDAL + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(_GSSAPI heimdal-gssapi) + endif (PKG_CONFIG_FOUND) + + if (_GSSAPI_FOUND) + set(GSSAPI_FLAVOR_HEIMDAL TRUE) + else() + find_path(_GSSAPI_ROKEN + NAMES + roken.h + PATHS + ${GSSAPI_ROOT_DIR}/include + ${_GSSAPI_INCLUDEDIR}) + if (_GSSAPI_ROKEN) + set(GSSAPI_FLAVOR_HEIMDAL TRUE) + endif() + endif () + endif() +endif (UNIX) + +find_path(GSSAPI_INCLUDE_DIR + NAMES + gssapi.h + gssapi/gssapi.h + PATHS + ${GSSAPI_ROOT_DIR}/include + ${_GSSAPI_INCLUDEDIR} +) + +if (GSSAPI_FLAVOR_MIT) + find_library(GSSAPI_LIBRARY + NAMES + gssapi_krb5 + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(KRB5_LIBRARY + NAMES + krb5 + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(K5CRYPTO_LIBRARY + NAMES + k5crypto + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(COM_ERR_LIBRARY + NAMES + com_err + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + if (GSSAPI_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${GSSAPI_LIBRARY} + ) + endif (GSSAPI_LIBRARY) + + if (KRB5_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${KRB5_LIBRARY} + ) + endif (KRB5_LIBRARY) + + if (K5CRYPTO_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${K5CRYPTO_LIBRARY} + ) + endif (K5CRYPTO_LIBRARY) + + if (COM_ERR_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${COM_ERR_LIBRARY} + ) + endif (COM_ERR_LIBRARY) +endif (GSSAPI_FLAVOR_MIT) + +if (GSSAPI_FLAVOR_HEIMDAL) + find_library(GSSAPI_LIBRARY + NAMES + gssapi + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(KRB5_LIBRARY + NAMES + krb5 + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(HCRYPTO_LIBRARY + NAMES + hcrypto + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(COM_ERR_LIBRARY + NAMES + com_err + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(HEIMNTLM_LIBRARY + NAMES + heimntlm + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(HX509_LIBRARY + NAMES + hx509 + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(ASN1_LIBRARY + NAMES + asn1 + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(WIND_LIBRARY + NAMES + wind + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + find_library(ROKEN_LIBRARY + NAMES + roken + PATHS + ${GSSAPI_ROOT_DIR}/lib + ${_GSSAPI_LIBDIR} + ) + + if (GSSAPI_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${GSSAPI_LIBRARY} + ) + endif (GSSAPI_LIBRARY) + + if (KRB5_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${KRB5_LIBRARY} + ) + endif (KRB5_LIBRARY) + + if (HCRYPTO_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${HCRYPTO_LIBRARY} + ) + endif (HCRYPTO_LIBRARY) + + if (COM_ERR_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${COM_ERR_LIBRARY} + ) + endif (COM_ERR_LIBRARY) + + if (HEIMNTLM_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${HEIMNTLM_LIBRARY} + ) + endif (HEIMNTLM_LIBRARY) + + if (HX509_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${HX509_LIBRARY} + ) + endif (HX509_LIBRARY) + + if (ASN1_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${ASN1_LIBRARY} + ) + endif (ASN1_LIBRARY) + + if (WIND_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${WIND_LIBRARY} + ) + endif (WIND_LIBRARY) + + if (ROKEN_LIBRARY) + set(GSSAPI_LIBRARIES + ${GSSAPI_LIBRARIES} + ${WIND_LIBRARY} + ) + endif (ROKEN_LIBRARY) +endif (GSSAPI_FLAVOR_HEIMDAL) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR) + +if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) + set(GSSAPI_FOUND TRUE) +endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) + +# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view +mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindGSSFramework.cmake libgit2-1.1.0+dfsg.1/cmake/FindGSSFramework.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindGSSFramework.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindGSSFramework.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,28 @@ +# Find GSS.framework +# This will define : +# +# GSSFRAMEWORK_FOUND +# GSSFRAMEWORK_INCLUDE_DIR +# GSSFRAMEWORK_LIBRARIES +# GSSFRAMEWORK_LDFLAGS +# + +FIND_PATH(GSSFRAMEWORK_INCLUDE_DIR NAMES GSS.h) +FIND_LIBRARY(GSSFRAMEWORK_LIBRARIES NAMES GSS) +IF (GSSFRAMEWORK_INCLUDE_DIR AND GSSFRAMEWORK_LIBRARIES) + IF (NOT CoreFoundation_FIND_QUIETLY) + MESSAGE(STATUS "Found GSS.framework ${GSSFRAMEWORK_LIBRARIES}") + ENDIF() + SET(GSSFRAMEWORK_FOUND TRUE) + SET(GSSFRAMEWORK_LDFLAGS "-framework GSS") +ENDIF () + +IF (GSS_FIND_REQUIRED AND NOT GSSFRAMEWORK_FOUND) + MESSAGE(FATAL_ERROR "CoreFoundation not found") +ENDIF() + +MARK_AS_ADVANCED( + GSSFRAMEWORK_INCLUDE_DIR + GSSFRAMEWORK_LIBRARIES + GSSFRAMEWORK_LDFLAGS +) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindHTTP_Parser.cmake libgit2-1.1.0+dfsg.1/cmake/FindHTTP_Parser.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindHTTP_Parser.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindHTTP_Parser.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,39 @@ +# - Try to find http-parser +# +# Defines the following variables: +# +# HTTP_PARSER_FOUND - system has http-parser +# HTTP_PARSER_INCLUDE_DIR - the http-parser include directory +# HTTP_PARSER_LIBRARIES - Link these to use http-parser +# HTTP_PARSER_VERSION_MAJOR - major version +# HTTP_PARSER_VERSION_MINOR - minor version +# HTTP_PARSER_VERSION_STRING - the version of http-parser found + +# Find the header and library +FIND_PATH(HTTP_PARSER_INCLUDE_DIR NAMES http_parser.h) +FIND_LIBRARY(HTTP_PARSER_LIBRARY NAMES http_parser libhttp_parser) + +# Found the header, read version +if (HTTP_PARSER_INCLUDE_DIR AND EXISTS "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h") + FILE(READ "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h" HTTP_PARSER_H) + IF (HTTP_PARSER_H) + STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MAJOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MAJOR "${HTTP_PARSER_H}") + STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MINOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MINOR "${HTTP_PARSER_H}") + SET(HTTP_PARSER_VERSION_STRING "${HTTP_PARSER_VERSION_MAJOR}.${HTTP_PARSER_VERSION_MINOR}") + ENDIF() + UNSET(HTTP_PARSER_H) +ENDIF() + +# Handle the QUIETLY and REQUIRED arguments and set HTTP_PARSER_FOUND +# to TRUE if all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(HTTP_Parser REQUIRED_VARS HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY) + +# Hide advanced variables +MARK_AS_ADVANCED(HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY) + +# Set standard variables +IF (HTTP_PARSER_FOUND) + SET(HTTP_PARSER_LIBRARIES ${HTTP_PARSER_LIBRARY}) + set(HTTP_PARSER_INCLUDE_DIRS ${HTTP_PARSER_INCLUDE_DIR}) +ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindIconv.cmake libgit2-1.1.0+dfsg.1/cmake/FindIconv.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindIconv.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindIconv.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,45 @@ +# - Try to find Iconv +# Once done this will define +# +# ICONV_FOUND - system has Iconv +# ICONV_INCLUDE_DIR - the Iconv include directory +# ICONV_LIBRARIES - Link these to use Iconv +# + +IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) + # Already in cache, be silent + SET(ICONV_FIND_QUIETLY TRUE) +ENDIF() + +FIND_PATH(ICONV_INCLUDE_DIR iconv.h) +CHECK_FUNCTION_EXISTS(iconv_open libc_has_iconv) +FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c) + +IF(ICONV_INCLUDE_DIR AND libc_has_iconv) + SET(ICONV_FOUND TRUE) + SET(ICONV_LIBRARIES "") + IF(NOT ICONV_FIND_QUIETLY) + MESSAGE(STATUS "Found Iconv: provided by libc") + ENDIF(NOT ICONV_FIND_QUIETLY) +ELSEIF(ICONV_INCLUDE_DIR AND iconv_lib) + SET(ICONV_FOUND TRUE) + # split iconv into -L and -l linker options, so we can + # set them for pkg-config + GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH) + GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE) + STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name}) + SET(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}") + + IF(NOT ICONV_FIND_QUIETLY) + MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}") + ENDIF(NOT ICONV_FIND_QUIETLY) +ELSE() + IF(Iconv_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Iconv") + ENDIF(Iconv_FIND_REQUIRED) +ENDIF() + +MARK_AS_ADVANCED( + ICONV_INCLUDE_DIR + ICONV_LIBRARIES +) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindmbedTLS.cmake libgit2-1.1.0+dfsg.1/cmake/FindmbedTLS.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindmbedTLS.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindmbedTLS.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,93 @@ +# - Try to find mbedTLS +# Once done this will define +# +# Read-Only variables +# MBEDTLS_FOUND - system has mbedTLS +# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory +# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory +# MBEDTLS_LIBRARIES - Link these to use mbedTLS +# MBEDTLS_LIBRARY - path to mbedTLS library +# MBEDX509_LIBRARY - path to mbedTLS X.509 library +# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library +# +# Hint +# MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation. + +SET(_MBEDTLS_ROOT_HINTS + ${MBEDTLS_ROOT_DIR} + ENV MBEDTLS_ROOT_DIR +) + +SET(_MBEDTLS_ROOT_HINTS_AND_PATHS + HINTS ${_MBEDTLS_ROOT_HINTS} + PATHS ${_MBEDTLS_ROOT_PATHS} +) + +FIND_PATH(MBEDTLS_INCLUDE_DIR + NAMES mbedtls/version.h + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES include +) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) + # Already in cache, be silent + SET(MBEDTLS_FIND_QUIETLY TRUE) +ENDIF() + +FIND_LIBRARY(MBEDTLS_LIBRARY + NAMES mbedtls libmbedtls + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) +FIND_LIBRARY(MBEDX509_LIBRARY + NAMES mbedx509 libmbedx509 + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) +FIND_LIBRARY(MBEDCRYPTO_LIBRARY + NAMES mbedcrypto libmbedcrypto + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) + SET(MBEDTLS_FOUND TRUE) +ENDIF() + +IF(MBEDTLS_FOUND) + # split mbedTLS into -L and -l linker options, so we can set them for pkg-config + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH) + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) + STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) + SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}") + + IF(NOT MBEDTLS_FIND_QUIETLY) + MESSAGE(STATUS "Found mbedTLS:") + FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) + STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) + IF (MBEDTLSMATCH) + STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) + MESSAGE(STATUS " version ${MBEDTLS_VERSION}") + ENDIF(MBEDTLSMATCH) + MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") + MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") + MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") + ENDIF(NOT MBEDTLS_FIND_QUIETLY) +ELSE(MBEDTLS_FOUND) + IF(MBEDTLS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find mbedTLS") + ENDIF(MBEDTLS_FIND_REQUIRED) +ENDIF(MBEDTLS_FOUND) + +MARK_AS_ADVANCED( + MBEDTLS_INCLUDE_DIR + MBEDTLS_LIBRARY_DIR + MBEDTLS_LIBRARIES + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY +) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindPCRE2.cmake libgit2-1.1.0+dfsg.1/cmake/FindPCRE2.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindPCRE2.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindPCRE2.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,37 @@ +# Copyright (C) 2007-2009 LuaDist. +# Created by Peter Kapec +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# For details see the COPYRIGHT file distributed with LuaDist. +# Note: +# Searching headers and libraries is very simple and is NOT as powerful as scripts +# distributed with CMake, because LuaDist defines directories to search for. +# Everyone is encouraged to contact the author with improvements. Maybe this file +# becomes part of CMake distribution sometimes. + +# - Find pcre +# Find the native PCRE2 headers and libraries. +# +# PCRE2_INCLUDE_DIRS - where to find pcre.h, etc. +# PCRE2_LIBRARIES - List of libraries when using pcre. +# PCRE2_FOUND - True if pcre found. + +# Look for the header file. +FIND_PATH(PCRE2_INCLUDE_DIR NAMES pcre2posix.h) + +# Look for the library. +FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8) + +# Handle the QUIETLY and REQUIRED arguments and set PCRE2_FOUND to TRUE if all listed variables are TRUE. +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY PCRE2_INCLUDE_DIR) + +# Copy the results to the output variables. +IF(PCRE2_FOUND) + SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) + SET(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR}) +ELSE(PCRE2_FOUND) + SET(PCRE2_LIBRARIES) + SET(PCRE2_INCLUDE_DIRS) +ENDIF(PCRE2_FOUND) + +MARK_AS_ADVANCED(PCRE2_INCLUDE_DIRS PCRE2_LIBRARIES) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindPCRE.cmake libgit2-1.1.0+dfsg.1/cmake/FindPCRE.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindPCRE.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindPCRE.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,38 @@ +# Copyright (C) 2007-2009 LuaDist. +# Created by Peter Kapec +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# For details see the COPYRIGHT file distributed with LuaDist. +# Note: +# Searching headers and libraries is very simple and is NOT as powerful as scripts +# distributed with CMake, because LuaDist defines directories to search for. +# Everyone is encouraged to contact the author with improvements. Maybe this file +# becomes part of CMake distribution sometimes. + +# - Find pcre +# Find the native PCRE headers and libraries. +# +# PCRE_INCLUDE_DIRS - where to find pcre.h, etc. +# PCRE_LIBRARIES - List of libraries when using pcre. +# PCRE_FOUND - True if pcre found. + +# Look for the header file. +FIND_PATH(PCRE_INCLUDE_DIR NAMES pcreposix.h) + +# Look for the library. +FIND_LIBRARY(PCRE_LIBRARY NAMES pcre) +FIND_LIBRARY(PCRE_POSIX_LIBRARY NAMES pcreposix) + +# Handle the QUIETLY and REQUIRED arguments and set PCRE_FOUND to TRUE if all listed variables are TRUE. +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY PCRE_POSIX_LIBRARY PCRE_INCLUDE_DIR) + +# Copy the results to the output variables. +IF(PCRE_FOUND) + SET(PCRE_LIBRARIES ${PCRE_LIBRARY} ${PCRE_POSIX_LIBRARY}) + SET(PCRE_INCLUDE_DIRS ${PCRE_INCLUDE_DIR}) +ELSE(PCRE_FOUND) + SET(PCRE_LIBRARIES) + SET(PCRE_INCLUDE_DIRS) +ENDIF(PCRE_FOUND) + +MARK_AS_ADVANCED(PCRE_INCLUDE_DIRS PCRE_LIBRARIES) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindPkgLibraries.cmake libgit2-1.1.0+dfsg.1/cmake/FindPkgLibraries.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindPkgLibraries.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindPkgLibraries.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,28 @@ +INCLUDE(FindPkgConfig) + +# This function will find and set up a pkg-config based module. +# If a pc-file was found, it will resolve library paths to +# absolute paths. Furthermore, the function will automatically +# fall back to use static libraries in case no dynamic libraries +# were found. +FUNCTION(FIND_PKGLIBRARIES prefix package) + PKG_CHECK_MODULES(${prefix} ${package}) + IF(NOT ${prefix}_FOUND) + RETURN() + ENDIF() + + FOREACH(LIBRARY ${${prefix}_LIBRARIES}) + FIND_LIBRARY(${LIBRARY}_RESOLVED ${LIBRARY} PATHS ${${prefix}_LIBRARY_DIRS}) + IF(${${LIBRARY}_RESOLVED} STREQUAL "${LIBRARY}_RESOLVED-NOTFOUND") + MESSAGE(FATAL_ERROR "could not resolve ${LIBRARY}") + ENDIF() + LIST(APPEND RESOLVED_LIBRARIES ${${LIBRARY}_RESOLVED}) + ENDFOREACH(LIBRARY) + + SET(${prefix}_FOUND 1 PARENT_SCOPE) + SET(${prefix}_LIBRARIES ${RESOLVED_LIBRARIES} PARENT_SCOPE) + SET(${prefix}_INCLUDE_DIRS ${${prefix}_INCLUDE_DIRS} PARENT_SCOPE) + SET(${prefix}_LDFLAGS ${${prefix}_LDFLAGS} PARENT_SCOPE) + + MESSAGE(STATUS " Resolved libraries: ${RESOLVED_LIBRARIES}") +ENDFUNCTION() diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindSecurity.cmake libgit2-1.1.0+dfsg.1/cmake/FindSecurity.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindSecurity.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindSecurity.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,28 @@ +# Find Security.framework +# This will define : +# +# SECURITY_FOUND +# SECURITY_LIBRARIES +# SECURITY_LDFLAGS +# SECURITY_HAS_SSLCREATECONTEXT +# + +FIND_PATH(SECURITY_INCLUDE_DIR NAMES Security/Security.h) +FIND_LIBRARY(SECURITY_LIBRARIES NAMES Security) +IF (SECURITY_INCLUDE_DIR AND SECURITY_LIBRARIES) + IF (NOT Security_FIND_QUIETLY) + MESSAGE(STATUS "Found Security ${SECURITY_LIBRARIES}") + ENDIF() + SET(SECURITY_FOUND TRUE) + SET(SECURITY_LDFLAGS "-framework Security") + CHECK_LIBRARY_EXISTS("${SECURITY_LIBRARIES}" SSLCreateContext "Security/SecureTransport.h" SECURITY_HAS_SSLCREATECONTEXT) +ENDIF () + +IF (Security_FIND_REQUIRED AND NOT SECURITY_FOUND) + MESSAGE(FATAL_ERROR "Security not found") +ENDIF() + +MARK_AS_ADVANCED( + SECURITY_INCLUDE_DIR + SECURITY_LIBRARIES +) diff -Nru libgit2-0.28.5+dfsg.1/cmake/FindStatNsec.cmake libgit2-1.1.0+dfsg.1/cmake/FindStatNsec.cmake --- libgit2-0.28.5+dfsg.1/cmake/FindStatNsec.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/FindStatNsec.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,26 @@ +INCLUDE(FeatureSummary) + +CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h" + HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C) +CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h" + HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_nsec sys/stat.h + HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C) + +IF (HAVE_STRUCT_STAT_ST_MTIM) + CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h + HAVE_STRUCT_STAT_NSEC LANGUAGE C) +ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC) + CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h + HAVE_STRUCT_STAT_NSEC LANGUAGE C) +ELSE () + SET( HAVE_STRUCT_STAT_NSEC ON ) +ENDIF() + +IF (HAVE_STRUCT_STAT_NSEC OR WIN32) + OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) +ELSE() + SET(USE_NSEC OFF) +ENDIF() + +ADD_FEATURE_INFO(nanoseconds USE_NSEC "whether to use sub-second file mtimes and ctimes") diff -Nru libgit2-0.28.5+dfsg.1/cmake/IdeSplitSources.cmake libgit2-1.1.0+dfsg.1/cmake/IdeSplitSources.cmake --- libgit2-0.28.5+dfsg.1/cmake/IdeSplitSources.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/IdeSplitSources.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,22 @@ +# This function splits the sources files up into their appropriate +# subdirectories. This is especially useful for IDEs like Xcode and +# Visual Studio, so that you can navigate into the libgit2_clar project, +# and see the folders within the tests folder (instead of just seeing all +# source and tests in a single folder.) +FUNCTION(IDE_SPLIT_SOURCES target) + IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode) + GET_TARGET_PROPERTY(sources ${target} SOURCES) + FOREACH(source ${sources}) + IF(source MATCHES ".*/") + STRING(REPLACE ${libgit2_SOURCE_DIR}/ "" rel ${source}) + IF(rel) + STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel}) + IF(rel) + STRING(REPLACE "/" "\\\\" rel ${rel}) + SOURCE_GROUP(${rel} FILES ${source}) + ENDIF() + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() +ENDFUNCTION() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/AddCFlagIfSupported.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/AddCFlagIfSupported.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/AddCFlagIfSupported.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/AddCFlagIfSupported.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -# - Append compiler flag to CMAKE_C_FLAGS if compiler supports it -# ADD_C_FLAG_IF_SUPPORTED() -# - the compiler flag to test -# This internally calls the CHECK_C_COMPILER_FLAG macro. - -INCLUDE(CheckCCompilerFlag) - -MACRO(ADD_C_FLAG _FLAG) - STRING(TOUPPER ${_FLAG} UPCASE) - STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE}) - STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY}) - CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED) - - IF(IS_${UPCASE_PRETTY}_SUPPORTED) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}") - ELSE() - MESSAGE(FATAL_ERROR "Required flag ${_FLAG} is not supported") - ENDIF() -ENDMACRO() - -MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG) - STRING(TOUPPER ${_FLAG} UPCASE) - STRING(REGEX REPLACE "[-=]" "_" UPCASE_PRETTY ${UPCASE}) - STRING(REGEX REPLACE "^_+" "" UPCASE_PRETTY ${UPCASE_PRETTY}) - CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED) - - IF(IS_${UPCASE_PRETTY}_SUPPORTED) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}") - ENDIF() -ENDMACRO() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/CheckPrototypeDefinition.c.in libgit2-1.1.0+dfsg.1/cmake/Modules/CheckPrototypeDefinition.c.in --- libgit2-0.28.5+dfsg.1/cmake/Modules/CheckPrototypeDefinition.c.in 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/CheckPrototypeDefinition.c.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -@CHECK_PROTOTYPE_DEFINITION_HEADER@ - -static void cmakeRequireSymbol(int dummy, ...) { - (void) dummy; -} - -static void checkSymbol(void) { -#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@ - cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@); -#endif -} - -@CHECK_PROTOTYPE_DEFINITION_PROTO@ { - return @CHECK_PROTOTYPE_DEFINITION_RETURN@; -} - -#ifdef __CLASSIC_C__ -int main() { - int ac; - char*av[]; -#else -int main(int ac, char *av[]) { -#endif - checkSymbol(); - if (ac > 1000) { - return *av[0]; - } - return 0; -} diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/CheckPrototypeDefinition.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/CheckPrototypeDefinition.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/CheckPrototypeDefinition.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/CheckPrototypeDefinition.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -# - Check if the protoype we expect is correct. -# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE) -# FUNCTION - The name of the function (used to check if prototype exists) -# PROTOTYPE- The prototype to check. -# RETURN - The return value of the function. -# HEADER - The header files required. -# VARIABLE - The variable to store the result. -# Example: -# check_prototype_definition(getpwent_r -# "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)" -# "NULL" -# "unistd.h;pwd.h" -# SOLARIS_GETPWENT_R) -# The following variables may be set before calling this macro to -# modify the way the check is run: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link - -#============================================================================= -# Copyright 2005-2009 Kitware, Inc. -# Copyright 2010-2011 Andreas Schneider -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) -# - -get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) - -function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE) - - if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$") - set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n") - - set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS}) - if (CMAKE_REQUIRED_LIBRARIES) - set(CHECK_PROTOTYPE_DEFINITION_LIBS - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - else(CMAKE_REQUIRED_LIBRARIES) - set(CHECK_PROTOTYPE_DEFINITION_LIBS) - endif(CMAKE_REQUIRED_LIBRARIES) - if (CMAKE_REQUIRED_INCLUDES) - set(CMAKE_SYMBOL_EXISTS_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - else(CMAKE_REQUIRED_INCLUDES) - set(CMAKE_SYMBOL_EXISTS_INCLUDES) - endif(CMAKE_REQUIRED_INCLUDES) - - foreach(_FILE ${_HEADER}) - set(CHECK_PROTOTYPE_DEFINITION_HEADER - "${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n") - endforeach(_FILE) - - set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION}) - set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE}) - set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN}) - - configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY) - - file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE) - - try_compile(${_VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c - COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS} - "${CHECK_PROTOTYPE_DEFINITION_LIBS}" - "${CMAKE_SYMBOL_EXISTS_INCLUDES}" - OUTPUT_VARIABLE OUTPUT) - - if (${_VARIABLE}) - set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") - message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n" - "${OUTPUT}\n\n") - else (${_VARIABLE}) - message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False") - set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n" - "${OUTPUT}\n\n${_SOURCE}\n\n") - endif (${_VARIABLE}) - endif("${_VARIABLE}" MATCHES "^${_VARIABLE}$") - -endfunction(CHECK_PROTOTYPE_DEFINITION) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/EnableWarnings.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/EnableWarnings.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/EnableWarnings.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/EnableWarnings.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -MACRO(ENABLE_WARNINGS flag) - ADD_C_FLAG_IF_SUPPORTED(-W${flag}) -ENDMACRO() - -MACRO(DISABLE_WARNINGS flag) - ADD_C_FLAG_IF_SUPPORTED(-Wno-${flag}) -ENDMACRO() - -IF(ENABLE_WERROR) - ADD_C_FLAG_IF_SUPPORTED(-Werror) -ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindCoreFoundation.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindCoreFoundation.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindCoreFoundation.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindCoreFoundation.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -# Find CoreFoundation.framework -# This will define : -# -# COREFOUNDATION_FOUND -# COREFOUNDATION_LIBRARIES -# COREFOUNDATION_LDFLAGS -# - -FIND_PATH(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h) -FIND_LIBRARY(COREFOUNDATION_LIBRARIES NAMES CoreFoundation) -IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_LIBRARIES) - IF (NOT CoreFoundation_FIND_QUIETLY) - MESSAGE("-- Found CoreFoundation ${COREFOUNDATION_LIBRARIES}") - ENDIF() - SET(COREFOUNDATION_FOUND TRUE) - SET(COREFOUNDATION_LDFLAGS "-framework CoreFoundation") -ENDIF () - -IF (CoreFoundation_FIND_REQUIRED AND NOT COREFOUNDATION_FOUND) - MESSAGE(FATAL "-- CoreFoundation not found") -ENDIF() - -MARK_AS_ADVANCED( - COREFOUNDATION_INCLUDE_DIR - COREFOUNDATION_LIBRARIES -) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindGSSAPI.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindGSSAPI.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindGSSAPI.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindGSSAPI.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,324 +0,0 @@ -# - Try to find GSSAPI -# Once done this will define -# -# KRB5_CONFIG - Path to krb5-config -# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI -# -# Read-Only variables: -# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found -# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found -# GSSAPI_FOUND - system has GSSAPI -# GSSAPI_INCLUDE_DIR - the GSSAPI include directory -# GSSAPI_LIBRARIES - Link these to use GSSAPI -# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI -# -#============================================================================= -# Copyright (c) 2013 Andreas Schneider -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# - -find_path(GSSAPI_ROOT_DIR - NAMES - include/gssapi.h - include/gssapi/gssapi.h - HINTS - ${_GSSAPI_ROOT_HINTS} - PATHS - ${_GSSAPI_ROOT_PATHS} -) -mark_as_advanced(GSSAPI_ROOT_DIR) - -if (UNIX) - find_program(KRB5_CONFIG - NAMES - krb5-config - PATHS - ${GSSAPI_ROOT_DIR}/bin - /opt/local/bin) - mark_as_advanced(KRB5_CONFIG) - - if (KRB5_CONFIG) - # Check if we have MIT KRB5 - execute_process( - COMMAND - ${KRB5_CONFIG} --vendor - RESULT_VARIABLE - _GSSAPI_VENDOR_RESULT - OUTPUT_VARIABLE - _GSSAPI_VENDOR_STRING) - - if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") - set(GSSAPI_FLAVOR_MIT TRUE) - else() - execute_process( - COMMAND - ${KRB5_CONFIG} --libs gssapi - RESULT_VARIABLE - _GSSAPI_LIBS_RESULT - OUTPUT_VARIABLE - _GSSAPI_LIBS_STRING) - - if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*") - set(GSSAPI_FLAVOR_HEIMDAL TRUE) - endif() - endif() - - # Get the include dir - execute_process( - COMMAND - ${KRB5_CONFIG} --cflags gssapi - RESULT_VARIABLE - _GSSAPI_INCLUDE_RESULT - OUTPUT_VARIABLE - _GSSAPI_INCLUDE_STRING) - string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}") - string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}") - endif() - - if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL) - # Check for HEIMDAL - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(_GSSAPI heimdal-gssapi) - endif (PKG_CONFIG_FOUND) - - if (_GSSAPI_FOUND) - set(GSSAPI_FLAVOR_HEIMDAL TRUE) - else() - find_path(_GSSAPI_ROKEN - NAMES - roken.h - PATHS - ${GSSAPI_ROOT_DIR}/include - ${_GSSAPI_INCLUDEDIR}) - if (_GSSAPI_ROKEN) - set(GSSAPI_FLAVOR_HEIMDAL TRUE) - endif() - endif () - endif() -endif (UNIX) - -find_path(GSSAPI_INCLUDE_DIR - NAMES - gssapi.h - gssapi/gssapi.h - PATHS - ${GSSAPI_ROOT_DIR}/include - ${_GSSAPI_INCLUDEDIR} -) - -if (GSSAPI_FLAVOR_MIT) - find_library(GSSAPI_LIBRARY - NAMES - gssapi_krb5 - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(KRB5_LIBRARY - NAMES - krb5 - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(K5CRYPTO_LIBRARY - NAMES - k5crypto - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(COM_ERR_LIBRARY - NAMES - com_err - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - if (GSSAPI_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${GSSAPI_LIBRARY} - ) - endif (GSSAPI_LIBRARY) - - if (KRB5_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${KRB5_LIBRARY} - ) - endif (KRB5_LIBRARY) - - if (K5CRYPTO_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${K5CRYPTO_LIBRARY} - ) - endif (K5CRYPTO_LIBRARY) - - if (COM_ERR_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${COM_ERR_LIBRARY} - ) - endif (COM_ERR_LIBRARY) -endif (GSSAPI_FLAVOR_MIT) - -if (GSSAPI_FLAVOR_HEIMDAL) - find_library(GSSAPI_LIBRARY - NAMES - gssapi - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(KRB5_LIBRARY - NAMES - krb5 - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(HCRYPTO_LIBRARY - NAMES - hcrypto - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(COM_ERR_LIBRARY - NAMES - com_err - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(HEIMNTLM_LIBRARY - NAMES - heimntlm - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(HX509_LIBRARY - NAMES - hx509 - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(ASN1_LIBRARY - NAMES - asn1 - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(WIND_LIBRARY - NAMES - wind - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - find_library(ROKEN_LIBRARY - NAMES - roken - PATHS - ${GSSAPI_ROOT_DIR}/lib - ${_GSSAPI_LIBDIR} - ) - - if (GSSAPI_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${GSSAPI_LIBRARY} - ) - endif (GSSAPI_LIBRARY) - - if (KRB5_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${KRB5_LIBRARY} - ) - endif (KRB5_LIBRARY) - - if (HCRYPTO_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${HCRYPTO_LIBRARY} - ) - endif (HCRYPTO_LIBRARY) - - if (COM_ERR_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${COM_ERR_LIBRARY} - ) - endif (COM_ERR_LIBRARY) - - if (HEIMNTLM_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${HEIMNTLM_LIBRARY} - ) - endif (HEIMNTLM_LIBRARY) - - if (HX509_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${HX509_LIBRARY} - ) - endif (HX509_LIBRARY) - - if (ASN1_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${ASN1_LIBRARY} - ) - endif (ASN1_LIBRARY) - - if (WIND_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${WIND_LIBRARY} - ) - endif (WIND_LIBRARY) - - if (ROKEN_LIBRARY) - set(GSSAPI_LIBRARIES - ${GSSAPI_LIBRARIES} - ${WIND_LIBRARY} - ) - endif (ROKEN_LIBRARY) -endif (GSSAPI_FLAVOR_HEIMDAL) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR) - -if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) - set(GSSAPI_FOUND TRUE) -endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) - -# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view -mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindHTTP_Parser.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindHTTP_Parser.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindHTTP_Parser.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindHTTP_Parser.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -# - Try to find http-parser -# -# Defines the following variables: -# -# HTTP_PARSER_FOUND - system has http-parser -# HTTP_PARSER_INCLUDE_DIR - the http-parser include directory -# HTTP_PARSER_LIBRARIES - Link these to use http-parser -# HTTP_PARSER_VERSION_MAJOR - major version -# HTTP_PARSER_VERSION_MINOR - minor version -# HTTP_PARSER_VERSION_STRING - the version of http-parser found - -# Find the header and library -FIND_PATH(HTTP_PARSER_INCLUDE_DIR NAMES http_parser.h) -FIND_LIBRARY(HTTP_PARSER_LIBRARY NAMES http_parser libhttp_parser) - -# Found the header, read version -if (HTTP_PARSER_INCLUDE_DIR AND EXISTS "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h") - FILE(READ "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h" HTTP_PARSER_H) - IF (HTTP_PARSER_H) - STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MAJOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MAJOR "${HTTP_PARSER_H}") - STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MINOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MINOR "${HTTP_PARSER_H}") - SET(HTTP_PARSER_VERSION_STRING "${HTTP_PARSER_VERSION_MAJOR}.${HTTP_PARSER_VERSION_MINOR}") - ENDIF() - UNSET(HTTP_PARSER_H) -ENDIF() - -# Handle the QUIETLY and REQUIRED arguments and set HTTP_PARSER_FOUND -# to TRUE if all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(HTTP_Parser REQUIRED_VARS HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY) - -# Hide advanced variables -MARK_AS_ADVANCED(HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY) - -# Set standard variables -IF (HTTP_PARSER_FOUND) - SET(HTTP_PARSER_LIBRARIES ${HTTP_PARSER_LIBRARY}) - set(HTTP_PARSER_INCLUDE_DIRS ${HTTP_PARSER_INCLUDE_DIR}) -ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindIconv.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindIconv.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindIconv.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindIconv.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -# - Try to find Iconv -# Once done this will define -# -# ICONV_FOUND - system has Iconv -# ICONV_INCLUDE_DIR - the Iconv include directory -# ICONV_LIBRARIES - Link these to use Iconv -# - -IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) - # Already in cache, be silent - SET(ICONV_FIND_QUIETLY TRUE) -ENDIF() - -FIND_PATH(ICONV_INCLUDE_DIR iconv.h) -CHECK_FUNCTION_EXISTS(iconv_open libc_has_iconv) -FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c) - -IF(ICONV_INCLUDE_DIR AND libc_has_iconv) - SET(ICONV_FOUND TRUE) - SET(ICONV_LIBRARIES "") - IF(NOT ICONV_FIND_QUIETLY) - MESSAGE(STATUS "Found Iconv: provided by libc") - ENDIF(NOT ICONV_FIND_QUIETLY) -ELSEIF(ICONV_INCLUDE_DIR AND iconv_lib) - SET(ICONV_FOUND TRUE) - # split iconv into -L and -l linker options, so we can - # set them for pkg-config - GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH) - GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE) - STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name}) - SET(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}") - - IF(NOT ICONV_FIND_QUIETLY) - MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}") - ENDIF(NOT ICONV_FIND_QUIETLY) -ELSE() - IF(Iconv_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Iconv") - ENDIF(Iconv_FIND_REQUIRED) -ENDIF() - -MARK_AS_ADVANCED( - ICONV_INCLUDE_DIR - ICONV_LIBRARIES -) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindmbedTLS.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindmbedTLS.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindmbedTLS.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindmbedTLS.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -# - Try to find mbedTLS -# Once done this will define -# -# Read-Only variables -# MBEDTLS_FOUND - system has mbedTLS -# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory -# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory -# MBEDTLS_LIBRARIES - Link these to use mbedTLS -# MBEDTLS_LIBRARY - path to mbedTLS library -# MBEDX509_LIBRARY - path to mbedTLS X.509 library -# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library -# -# Hint -# MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation. - -SET(_MBEDTLS_ROOT_HINTS - ${MBEDTLS_ROOT_DIR} - ENV MBEDTLS_ROOT_DIR -) - -SET(_MBEDTLS_ROOT_HINTS_AND_PATHS - HINTS ${_MBEDTLS_ROOT_HINTS} - PATHS ${_MBEDTLS_ROOT_PATHS} -) - -FIND_PATH(MBEDTLS_INCLUDE_DIR - NAMES mbedtls/version.h - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES include -) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) - # Already in cache, be silent - SET(MBEDTLS_FIND_QUIETLY TRUE) -ENDIF() - -FIND_LIBRARY(MBEDTLS_LIBRARY - NAMES mbedtls libmbedtls - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) -FIND_LIBRARY(MBEDX509_LIBRARY - NAMES mbedx509 libmbedx509 - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) -FIND_LIBRARY(MBEDCRYPTO_LIBRARY - NAMES mbedcrypto libmbedcrypto - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) - SET(MBEDTLS_FOUND TRUE) -ENDIF() - -IF(MBEDTLS_FOUND) - # split mbedTLS into -L and -l linker options, so we can set them for pkg-config - GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH) - GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) - GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) - GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) - STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) - STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) - STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) - SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}") - - IF(NOT MBEDTLS_FIND_QUIETLY) - MESSAGE(STATUS "Found mbedTLS:") - FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) - STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) - IF (MBEDTLSMATCH) - STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) - MESSAGE(STATUS " version ${MBEDTLS_VERSION}") - ENDIF(MBEDTLSMATCH) - MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") - MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") - MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") - ENDIF(NOT MBEDTLS_FIND_QUIETLY) -ELSE(MBEDTLS_FOUND) - IF(MBEDTLS_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find mbedTLS") - ENDIF(MBEDTLS_FIND_REQUIRED) -ENDIF(MBEDTLS_FOUND) - -MARK_AS_ADVANCED( - MBEDTLS_INCLUDE_DIR - MBEDTLS_LIBRARY_DIR - MBEDTLS_LIBRARIES - MBEDTLS_LIBRARY - MBEDX509_LIBRARY - MBEDCRYPTO_LIBRARY -) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindPkgLibraries.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindPkgLibraries.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindPkgLibraries.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindPkgLibraries.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -INCLUDE(FindPkgConfig) - -# This function will find and set up a pkg-config based module. -# If a pc-file was found, it will resolve library paths to -# absolute paths. Furthermore, the function will automatically -# fall back to use static libraries in case no dynamic libraries -# were found. -FUNCTION(FIND_PKGLIBRARIES prefix package) - PKG_CHECK_MODULES(${prefix} ${package}) - IF(NOT ${prefix}_FOUND) - RETURN() - ENDIF() - - FOREACH(LIBRARY ${${prefix}_LIBRARIES}) - FIND_LIBRARY(${LIBRARY}_RESOLVED ${LIBRARY} PATHS ${${prefix}_LIBRARY_DIRS}) - IF(${${LIBRARY}_RESOLVED} STREQUAL "${LIBRARY}_RESOLVED-NOTFOUND") - MESSAGE(FATAL_ERROR "could not resolve ${LIBRARY}") - ENDIF() - LIST(APPEND RESOLVED_LIBRARIES ${${LIBRARY}_RESOLVED}) - ENDFOREACH(LIBRARY) - - SET(${prefix}_FOUND 1 PARENT_SCOPE) - SET(${prefix}_LIBRARIES ${RESOLVED_LIBRARIES} PARENT_SCOPE) - SET(${prefix}_INCLUDE_DIRS ${${prefix}_INCLUDE_DIRS} PARENT_SCOPE) - SET(${prefix}_LDFLAGS ${${prefix}_LDFLAGS} PARENT_SCOPE) - - MESSAGE(STATUS " Resolved libraries: ${RESOLVED_LIBRARIES}") -ENDFUNCTION() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindSecurity.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindSecurity.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindSecurity.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindSecurity.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -# Find Security.framework -# This will define : -# -# SECURITY_FOUND -# SECURITY_LIBRARIES -# SECURITY_LDFLAGS -# SECURITY_HAS_SSLCREATECONTEXT -# - -FIND_PATH(SECURITY_INCLUDE_DIR NAMES Security/Security.h) -FIND_LIBRARY(SECURITY_LIBRARIES NAMES Security) -IF (SECURITY_INCLUDE_DIR AND SECURITY_LIBRARIES) - IF (NOT Security_FIND_QUIETLY) - MESSAGE("-- Found Security ${SECURITY_LIBRARIES}") - ENDIF() - SET(SECURITY_FOUND TRUE) - SET(SECURITY_LDFLAGS "-framework Security") - CHECK_LIBRARY_EXISTS("${SECURITY_LIBRARIES}" SSLCreateContext "Security/SecureTransport.h" SECURITY_HAS_SSLCREATECONTEXT) -ENDIF () - -IF (Security_FIND_REQUIRED AND NOT SECURITY_FOUND) - MESSAGE(FATAL "-- Security not found") -ENDIF() - -MARK_AS_ADVANCED( - SECURITY_INCLUDE_DIR - SECURITY_LIBRARIES -) diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/FindStatNsec.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/FindStatNsec.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/FindStatNsec.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/FindStatNsec.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h" - HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C) -CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h" - HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C) -CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_nsec sys/stat.h - HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C) - -IF (HAVE_STRUCT_STAT_ST_MTIM) - CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h - HAVE_STRUCT_STAT_NSEC LANGUAGE C) -ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC) - CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h - HAVE_STRUCT_STAT_NSEC LANGUAGE C) -ELSE () - SET( HAVE_STRUCT_STAT_NSEC ON ) -ENDIF() - -IF (HAVE_STRUCT_STAT_NSEC OR WIN32) - OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) -ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/Modules/IdeSplitSources.cmake libgit2-1.1.0+dfsg.1/cmake/Modules/IdeSplitSources.cmake --- libgit2-0.28.5+dfsg.1/cmake/Modules/IdeSplitSources.cmake 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/Modules/IdeSplitSources.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -# This function splits the sources files up into their appropriate -# subdirectories. This is especially useful for IDEs like Xcode and -# Visual Studio, so that you can navigate into the libgit2_clar project, -# and see the folders within the tests folder (instead of just seeing all -# source and tests in a single folder.) -FUNCTION(IDE_SPLIT_SOURCES target) - IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode) - GET_TARGET_PROPERTY(sources ${target} SOURCES) - FOREACH(source ${sources}) - IF(source MATCHES ".*/") - STRING(REPLACE ${libgit2_SOURCE_DIR}/ "" rel ${source}) - IF(rel) - STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel}) - IF(rel) - STRING(REPLACE "/" "\\\\" rel ${rel}) - SOURCE_GROUP(${rel} FILES ${source}) - ENDIF() - ENDIF() - ENDIF() - ENDFOREACH() - ENDIF() -ENDFUNCTION() diff -Nru libgit2-0.28.5+dfsg.1/cmake/PkgBuildConfig.cmake libgit2-1.1.0+dfsg.1/cmake/PkgBuildConfig.cmake --- libgit2-0.28.5+dfsg.1/cmake/PkgBuildConfig.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/PkgBuildConfig.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,77 @@ +# pkg-config file generation +# + +function(pkg_build_config) + set(options) + set(oneValueArgs NAME DESCRIPTION VERSION FILENAME LIBS_SELF) + set(multiValueArgs LIBS PRIVATE_LIBS REQUIRES CFLAGS) + + cmake_parse_arguments(PKGCONFIG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT DEFINED PKGCONFIG_FILENAME AND DEFINED PKGCONFIG_NAME) + set(PKGCONFIG_FILENAME ${PKGCONFIG_NAME}) + endif() + if (NOT DEFINED PKGCONFIG_FILENAME) + message(FATAL_ERROR "Missing FILENAME argument") + endif() + set(PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${PKGCONFIG_FILENAME}.pc") + + if (NOT DEFINED PKGCONFIG_DESCRIPTION) + message(FATAL_ERROR "Missing DESCRIPTION argument") + endif() + + if (NOT DEFINED PKGCONFIG_VERSION) + message(FATAL_ERROR "Missing VERSION argument") + endif() + + # Write .pc "header" + file(WRITE "${PKGCONFIG_FILE}" + "prefix=\"${CMAKE_INSTALL_PREFIX}\"\n" + "libdir=\"${CMAKE_INSTALL_FULL_LIBDIR}\"\n" + "includedir=\"${CMAKE_INSTALL_FULL_INCLUDEDIR}\"\n" + "\n" + "Name: ${PKGCONFIG_NAME}\n" + "Description: ${PKGCONFIG_DESCRIPTION}\n" + "Version: ${PKGCONFIG_VERSION}\n" + ) + + # Prepare Libs + if(NOT DEFINED PKGCONFIG_LIBS_SELF) + set(PKGCONFIG_LIBS_SELF "${PKGCONFIG_FILE}") + endif() + + if(NOT DEFINED PKGCONFIG_LIBS) + set(PKGCONFIG_LIBS "-l${PKGCONFIG_LIBS_SELF}") + else() + list(INSERT PKGCONFIG_LIBS 0 "-l${PKGCONFIG_LIBS_SELF}") + endif() + + list(REMOVE_DUPLICATES PKGCONFIG_LIBS) + string(REPLACE ";" " " PKGCONFIG_LIBS "${PKGCONFIG_LIBS}") + file(APPEND "${PKGCONFIG_FILE}" "Libs: -L\${libdir} ${PKGCONFIG_LIBS}\n") + + # Prepare Libs.private + if(DEFINED PKGCONFIG_PRIVATE_LIBS) + list(REMOVE_DUPLICATES PKGCONFIG_PRIVATE_LIBS) + string(REPLACE ";" " " PKGCONFIG_PRIVATE_LIBS "${PKGCONFIG_PRIVATE_LIBS}") + file(APPEND "${PKGCONFIG_FILE}" "Libs.private: ${PKGCONFIG_PRIVATE_LIBS}\n") + endif() + + # Prepare Requires.private + if(DEFINED PKGCONFIG_REQUIRES) + list(REMOVE_DUPLICATES PKGCONFIG_REQUIRES) + string(REPLACE ";" " " PKGCONFIG_REQUIRES "${PKGCONFIG_REQUIRES}") + file(APPEND "${PKGCONFIG_FILE}" "Requires.private: ${PKGCONFIG_REQUIRES}\n") + endif() + + # Prepare Cflags + if(DEFINED PKGCONFIG_CFLAGS) + string(REPLACE ";" " " PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS}") + else() + set(PKGCONFIG_CFLAGS "") + endif() + file(APPEND "${PKGCONFIG_FILE}" "Cflags: -I\${includedir} ${PKGCONFIG_CFLAGS}\n") + + # Install .pc file + install(FILES "${PKGCONFIG_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endfunction() diff -Nru libgit2-0.28.5+dfsg.1/cmake/SanitizeBool.cmake libgit2-1.1.0+dfsg.1/cmake/SanitizeBool.cmake --- libgit2-0.28.5+dfsg.1/cmake/SanitizeBool.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/SanitizeBool.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,20 @@ +FUNCTION(SanitizeBool VAR) + STRING(TOLOWER "${${VAR}}" VALUE) + IF(VALUE STREQUAL "on") + SET(${VAR} "ON" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "yes") + SET(${VAR} "ON" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "true") + SET(${VAR} "ON" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "1") + SET(${VAR} "ON" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "off") + SET(${VAR} "OFF" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "no") + SET(${VAR} "OFF" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "false") + SET(${VAR} "OFF" PARENT_SCOPE) + ELSEIF(VALUE STREQUAL "0") + SET(${VAR} "OFF" PARENT_SCOPE) + ENDIF() +ENDFUNCTION() diff -Nru libgit2-0.28.5+dfsg.1/cmake/SelectGSSAPI.cmake libgit2-1.1.0+dfsg.1/cmake/SelectGSSAPI.cmake --- libgit2-0.28.5+dfsg.1/cmake/SelectGSSAPI.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/SelectGSSAPI.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,48 @@ +INCLUDE(SanitizeBool) + +# We try to find any packages our backends might use +FIND_PACKAGE(GSSAPI) +IF (CMAKE_SYSTEM_NAME MATCHES "Darwin") + INCLUDE(FindGSSFramework) +ENDIF() + +IF(USE_GSSAPI) + # Auto-select GSS backend + SanitizeBool(USE_GSSAPI) + IF (USE_GSSAPI STREQUAL ON) + IF (GSSFRAMEWORK_FOUND) + SET(USE_GSSAPI "GSS.framework") + ELSEIF(GSSAPI_FOUND) + SET(USE_GSSAPI "gssapi") + ELSE() + MESSAGE(FATAL_ERROR "Unable to autodetect a usable GSS backend." + "Please pass the backend name explicitly (-DUSE_GSS=backend)") + ENDIF() + ENDIF() + + # Check that we can find what's required for the selected backend + IF (USE_GSSAPI STREQUAL "GSS.framework") + IF (NOT GSSFRAMEWORK_FOUND) + MESSAGE(FATAL_ERROR "Asked for GSS.framework backend, but it wasn't found") + ENDIF() + + LIST(APPEND LIBGIT2_LIBS ${GSSFRAMEWORK_LIBRARIES}) + + SET(GIT_GSSFRAMEWORK 1) + ADD_FEATURE_INFO(SPNEGO GIT_GSSFRAMEWORK "SPNEGO authentication support (${USE_GSSAPI})") + ELSEIF (USE_GSSAPI STREQUAL "gssapi") + IF (NOT GSSAPI_FOUND) + MESSAGE(FATAL_ERROR "Asked for gssapi GSS backend, but it wasn't found") + ENDIF() + + LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES}) + + SET(GIT_GSSAPI 1) + ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support (${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") +ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/cmake/SelectHashes.cmake libgit2-1.1.0+dfsg.1/cmake/SelectHashes.cmake --- libgit2-0.28.5+dfsg.1/cmake/SelectHashes.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/SelectHashes.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,61 @@ +# Select a hash backend + +INCLUDE(SanitizeBool) + +# USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF + +SanitizeBool(USE_SHA1) +IF(USE_SHA1 STREQUAL ON) + SET(USE_SHA1 "CollisionDetection") +ELSEIF(USE_SHA1 STREQUAL "HTTPS") + IF(USE_HTTPS STREQUAL "SecureTransport") + SET(USE_SHA1 "CommonCrypto") + ELSEIF(USE_HTTPS STREQUAL "WinHTTP") + SET(USE_SHA1 "Win32") + ELSEIF(USE_HTTPS) + SET(USE_SHA1 ${USE_HTTPS}) + ELSE() + SET(USE_SHA1 "CollisionDetection") + ENDIF() +ENDIF() + +IF(USE_SHA1 STREQUAL "CollisionDetection") + SET(GIT_SHA1_COLLISIONDETECT 1) + ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1) + ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\") + ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\") + FILE(GLOB SRC_SHA1 hash/sha1/collisiondetect.* hash/sha1/sha1dc/*) +ELSEIF(USE_SHA1 STREQUAL "OpenSSL") + # OPENSSL_FOUND should already be set, we're checking USE_HTTPS + + SET(GIT_SHA1_OPENSSL 1) + IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + LIST(APPEND LIBGIT2_PC_LIBS "-lssl") + ELSE() + LIST(APPEND LIBGIT2_PC_REQUIRES "openssl") + ENDIF() + FILE(GLOB SRC_SHA1 hash/sha1/openssl.*) +ELSEIF(USE_SHA1 STREQUAL "CommonCrypto") + SET(GIT_SHA1_COMMON_CRYPTO 1) + FILE(GLOB SRC_SHA1 hash/sha1/common_crypto.*) +ELSEIF(USE_SHA1 STREQUAL "mbedTLS") + SET(GIT_SHA1_MBEDTLS 1) + FILE(GLOB SRC_SHA1 hash/sha1/mbedtls.*) + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR}) + LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES}) + # mbedTLS has no pkgconfig file, hence we can't require it + # https://github.com/ARMmbed/mbedtls/issues/228 + # For now, pass its link flags as our own + LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES}) +ELSEIF(USE_SHA1 STREQUAL "Win32") + SET(GIT_SHA1_WIN32 1) + FILE(GLOB SRC_SHA1 hash/sha1/win32.*) +ELSEIF(USE_SHA1 STREQUAL "Generic") + FILE(GLOB SRC_SHA1 hash/sha1/generic.*) +ELSE() + MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}") +ENDIF() + +list(SORT SRC_SHA1) + +ADD_FEATURE_INFO(SHA ON "using ${USE_SHA1}") diff -Nru libgit2-0.28.5+dfsg.1/cmake/SelectHTTPSBackend.cmake libgit2-1.1.0+dfsg.1/cmake/SelectHTTPSBackend.cmake --- libgit2-0.28.5+dfsg.1/cmake/SelectHTTPSBackend.cmake 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/cmake/SelectHTTPSBackend.cmake 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,120 @@ +INCLUDE(SanitizeBool) + +# We try to find any packages our backends might use +FIND_PACKAGE(OpenSSL) +FIND_PACKAGE(mbedTLS) +IF (CMAKE_SYSTEM_NAME MATCHES "Darwin") + FIND_PACKAGE(Security) + FIND_PACKAGE(CoreFoundation) +ENDIF() + +IF(USE_HTTPS) + # Auto-select TLS backend + SanitizeBool(USE_HTTPS) + IF (USE_HTTPS STREQUAL ON) + IF (SECURITY_FOUND) + IF (SECURITY_HAS_SSLCREATECONTEXT) + SET(USE_HTTPS "SecureTransport") + ELSE() + MESSAGE(STATUS "Security framework is too old, falling back to OpenSSL") + SET(USE_HTTPS "OpenSSL") + ENDIF() + ELSEIF (WINHTTP) + SET(USE_HTTPS "WinHTTP") + ELSEIF(OPENSSL_FOUND) + SET(USE_HTTPS "OpenSSL") + ELSEIF(MBEDTLS_FOUND) + SET(USE_HTTPS "mbedTLS") + ELSE() + MESSAGE(FATAL_ERROR "Unable to autodetect a usable HTTPS backend." + "Please pass the backend name explicitly (-DUSE_HTTPS=backend)") + ENDIF() + ENDIF() + + # Check that we can find what's required for the selected backend + IF (USE_HTTPS STREQUAL "SecureTransport") + IF (NOT COREFOUNDATION_FOUND) + MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, CoreFoundation.framework not found") + ENDIF() + IF (NOT SECURITY_FOUND) + MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, Security.framework not found") + ENDIF() + IF (NOT SECURITY_HAS_SSLCREATECONTEXT) + MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, SSLCreateContext not supported") + ENDIF() + + SET(GIT_SECURE_TRANSPORT 1) + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${SECURITY_INCLUDE_DIR}) + LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS}) + LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS}) + ELSEIF (USE_HTTPS STREQUAL "OpenSSL") + IF (NOT OPENSSL_FOUND) + MESSAGE(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found") + ENDIF() + + SET(GIT_OPENSSL 1) + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${OPENSSL_INCLUDE_DIR}) + LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS}) + LIST(APPEND LIBGIT2_PC_REQUIRES "openssl") + ELSEIF(USE_HTTPS STREQUAL "mbedTLS") + IF (NOT MBEDTLS_FOUND) + MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found") + ENDIF() + + IF(NOT CERT_LOCATION) + MESSAGE(STATUS "Auto-detecting default certificates location") + IF(CMAKE_SYSTEM_NAME MATCHES Darwin) + # Check for an Homebrew installation + SET(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl") + ELSE() + SET(OPENSSL_CMD "openssl") + ENDIF() + EXECUTE_PROCESS(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) + IF(OPENSSL_DIR) + STRING(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR}) + + SET(OPENSSL_CA_LOCATIONS + "ca-bundle.pem" # OpenSUSE Leap 42.1 + "cert.pem" # Ubuntu 14.04, FreeBSD + "certs/ca-certificates.crt" # Ubuntu 16.04 + "certs/ca.pem" # Debian 7 + ) + FOREACH(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS) + SET(LOC "${OPENSSL_DIR}${SUFFIX}") + IF(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}") + SET(CERT_LOCATION ${LOC}) + ENDIF() + ENDFOREACH() + ELSE() + MESSAGE(FATAL_ERROR "Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION") + ENDIF() + ENDIF() + + IF(CERT_LOCATION) + IF(NOT EXISTS ${CERT_LOCATION}) + MESSAGE(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist") + ENDIF() + ADD_FEATURE_INFO(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}") + ADD_DEFINITIONS(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}") + ENDIF() + + SET(GIT_MBEDTLS 1) + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR}) + LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES}) + # mbedTLS has no pkgconfig file, hence we can't require it + # https://github.com/ARMmbed/mbedtls/issues/228 + # For now, pass its link flags as our own + LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES}) + ELSEIF (USE_HTTPS STREQUAL "WinHTTP") + # WinHTTP setup was handled in the WinHTTP-specific block above + ELSE() + MESSAGE(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found") + ENDIF() + + SET(GIT_HTTPS 1) + ADD_FEATURE_INFO(HTTPS GIT_HTTPS "using ${USE_HTTPS}") +ELSE() + SET(GIT_HTTPS 0) + ADD_FEATURE_INFO(HTTPS NO "") +ENDIF() diff -Nru libgit2-0.28.5+dfsg.1/CMakeLists.txt libgit2-1.1.0+dfsg.1/CMakeLists.txt --- libgit2-0.28.5+dfsg.1/CMakeLists.txt 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/CMakeLists.txt 2020-10-12 18:53:06.000000000 +0000 @@ -11,21 +11,12 @@ # Install: # > cmake --build . --target install -PROJECT(libgit2 C) -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11) -CMAKE_POLICY(SET CMP0015 NEW) -IF(POLICY CMP0051) - CMAKE_POLICY(SET CMP0051 NEW) -ENDIF() -IF(POLICY CMP0042) - CMAKE_POLICY(SET CMP0042 NEW) -ENDIF() -IF(POLICY CMP0054) - CMAKE_POLICY(SET CMP0054 NEW) -ENDIF() +CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1) + +project(libgit2 VERSION "1.1.0" LANGUAGES C) # Add find modules to the path -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/Modules/") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/") INCLUDE(CheckLibraryExists) INCLUDE(CheckFunctionExists) @@ -36,6 +27,7 @@ INCLUDE(FindPkgLibraries) INCLUDE(FindThreads) INCLUDE(FindStatNsec) +INCLUDE(GNUInstallDirs) INCLUDE(IdeSplitSources) INCLUDE(FeatureSummary) INCLUDE(EnableWarnings) @@ -48,23 +40,28 @@ OPTION(BUILD_CLAR "Build Tests using the Clar suite" ON) OPTION(BUILD_EXAMPLES "Build library usage example apps" OFF) OPTION(BUILD_FUZZERS "Build the fuzz targets" OFF) -OPTION(TAGS "Generate tags" OFF) -OPTION(PROFILE "Generate profiling information" OFF) -OPTION(ENABLE_TRACE "Enables tracing support" OFF) +OPTION(ENABLE_TRACE "Enables tracing support" ON) OPTION(LIBGIT2_FILENAME "Name of the produced binary" OFF) - - SET(SHA1_BACKEND "CollisionDetection" CACHE STRING - "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, mbedTLS, CollisionDetection.") OPTION(USE_SSH "Link with libssh2 to enable SSH support" ON) OPTION(USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON) +OPTION(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS/Generic" ON) OPTION(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF) OPTION(USE_STANDALONE_FUZZERS "Enable standalone fuzzers (compatible with gcc)" OFF) -OPTION(VALGRIND "Configure build for valgrind" OFF) -OPTION(USE_EXT_HTTP_PARSER "Use system HTTP_Parser if available" ON) +OPTION(USE_LEAK_CHECKER "Run tests with leak checker" OFF) OPTION(DEBUG_POOL "Enable debug pool allocator" OFF) OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF) OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF) + SET(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.") OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF) + SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.") + +IF (UNIX) + IF (NOT USE_HTTPS) + OPTION(USE_NTLMCLIENT "Enable NTLM support on Unix." OFF ) + ELSE() + OPTION(USE_NTLMCLIENT "Enable NTLM support on Unix." ON ) + ENDIF() +ENDIF() IF (UNIX AND NOT APPLE) OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF) @@ -96,16 +93,6 @@ OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF) ENDIF() -FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$") - -STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}") -STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_MINOR "${GIT2_HEADER}") -STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}") -SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}") - -FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$") -STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}") - IF (DEPRECATE_HARD) ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD) ENDIF() @@ -129,6 +116,11 @@ # /Gd - explicitly set cdecl calling convention SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd") + IF (NOT (MSVC_VERSION LESS 1900)) + # /guard:cf - Enable Control Flow Guard + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /guard:cf") + ENDIF() + IF (STATIC_CRT) SET(CRT_FLAG_DEBUG "/MTd") SET(CRT_FLAG_RELEASE "/MT") @@ -173,7 +165,12 @@ # /NXCOMPAT - Data execution prevention (DEP) # /LARGEADDRESSAWARE - >2GB user address space on x86 # /VERSION - Embed version information in PE header - SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}") + SET(CMAKE_EXE_LINKER_FLAGS "/DYNAMICBASE /NXCOMPAT /LARGEADDRESSAWARE /VERSION:${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}") + + IF (NOT (MSVC_VERSION LESS 1900)) + # /GUARD:CF - Enable Control Flow Guard + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /GUARD:CF") + ENDIF() # /DEBUG - Create a PDB # /LTCG - Link time code generation (whole program optimization) @@ -224,23 +221,32 @@ ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1) ENDIF () - ENABLE_WARNINGS(documentation) - DISABLE_WARNINGS(missing-field-initializers) - ENABLE_WARNINGS(strict-aliasing) - ENABLE_WARNINGS(strict-prototypes) - ENABLE_WARNINGS(declaration-after-statement) - ENABLE_WARNINGS(shift-count-overflow) - ENABLE_WARNINGS(unused-const-variable) - ENABLE_WARNINGS(unused-function) - ENABLE_WARNINGS(format) - ENABLE_WARNINGS(format-security) - ENABLE_WARNINGS(int-conversion) - DISABLE_WARNINGS(documentation-deprecated-sync) - - IF (PROFILE) - SET(CMAKE_C_FLAGS "-pg ${CMAKE_C_FLAGS}") - SET(CMAKE_EXE_LINKER_FLAGS "-pg ${CMAKE_EXE_LINKER_FLAGS}") - ENDIF () + enable_warnings(documentation) + disable_warnings(documentation-deprecated-sync) + disable_warnings(missing-field-initializers) + enable_warnings(strict-aliasing) + enable_warnings(strict-prototypes) + enable_warnings(declaration-after-statement) + enable_warnings(shift-count-overflow) + enable_warnings(unused-const-variable) + enable_warnings(unused-function) + enable_warnings(int-conversion) + + # MinGW uses gcc, which expects POSIX formatting for printf, but + # uses the Windows C library, which uses its own format specifiers. + # Disable format specifier warnings. + if(MINGW) + disable_warnings(format) + disable_warnings(format-security) + else() + enable_warnings(format) + enable_warnings(format-security) + endif() +ENDIF() + +# Ensure that MinGW provides the correct header files. +IF (WIN32 AND NOT CYGWIN) + ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0600) ENDIF() IF( NOT CMAKE_CONFIGURATION_TYPES ) @@ -275,25 +281,6 @@ ADD_SUBDIRECTORY(tests) ENDIF () -IF (TAGS) - FIND_PROGRAM(CTAGS ctags) - IF (NOT CTAGS) - MESSAGE(FATAL_ERROR "Could not find ctags command") - ENDIF () - - FILE(GLOB_RECURSE SRC_ALL *.[ch]) - - ADD_CUSTOM_COMMAND( - OUTPUT tags - COMMAND ${CTAGS} -a ${SRC_ALL} - DEPENDS ${SRC_ALL} - ) - ADD_CUSTOM_TARGET( - do_tags ALL - DEPENDS tags - ) -ENDIF () - IF (BUILD_EXAMPLES) ADD_SUBDIRECTORY(examples) ENDIF () @@ -310,10 +297,5 @@ ADD_SUBDIRECTORY(fuzzers) ENDIF() -IF(CMAKE_VERSION VERSION_GREATER 3) - FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") - FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") -ELSE() - PRINT_ENABLED_FEATURES() - PRINT_DISABLED_FEATURES() -ENDIF() +FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") +FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") diff -Nru libgit2-0.28.5+dfsg.1/COPYING libgit2-1.1.0+dfsg.1/COPYING --- libgit2-0.28.5+dfsg.1/COPYING 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/COPYING 2020-10-12 18:53:06.000000000 +0000 @@ -991,3 +991,31 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +---------------------------------------------------------------------- + +The bundled wildmatch code is licensed under the BSD license: + +Copyright Rich Salz. +All rights reserved. + +Redistribution and use in any form are permitted provided that the +following restrictions are are met: + +1. Source distributions must retain this entire copyright notice + and comment. +2. Binary distributions must include the acknowledgement ``This + product includes software developed by Rich Salz'' in the + documentation or other materials provided with the + distribution. This must not be represented as an endorsement + or promotion without specific prior written permission. +3. The origin of this software must not be misrepresented, either + by explicit claim or by omission. Credits must appear in the + source and documentation. +4. Altered versions must be plainly marked as such in the source + and documentation and must not be misrepresented as being the + original software. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. diff -Nru libgit2-0.28.5+dfsg.1/debian/changelog libgit2-1.1.0+dfsg.1/debian/changelog --- libgit2-0.28.5+dfsg.1/debian/changelog 2020-04-10 17:33:48.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/changelog 2021-01-06 17:28:58.000000000 +0000 @@ -1,8 +1,100 @@ -libgit2 (0.28.5+dfsg.1-1) unstable; urgency=medium +libgit2 (1.1.0+dfsg.1-4) unstable; urgency=medium - * New upstream version 0.28.5+dfsg.1 + * Source-only upload for migration. - -- Utkarsh Gupta Fri, 10 Apr 2020 23:03:48 +0530 + -- Utkarsh Gupta Wed, 06 Jan 2021 22:58:58 +0530 + +libgit2 (1.1.0+dfsg.1-3) unstable; urgency=medium + + [ Cédric Boutillier ] + * Provide binary package for libgit2 fixtures (Closes: #972574) + * install as examples + + [ Utkarsh Gupta ] + * Wrap description wrt line length limitation + + -- Utkarsh Gupta Sun, 27 Dec 2020 10:06:10 +0530 + +libgit2 (1.1.0+dfsg.1-2) unstable; urgency=medium + + * Upload to unstable. + - Transition v1.x. (cf: #971571) + * Bump Standards-Version to 4.5.1 + + -- Utkarsh Gupta Wed, 09 Dec 2020 15:09:10 +0530 + +libgit2 (1.1.0+dfsg.1-1) experimental; urgency=medium + + * New upstream version 1.1.0+dfsg.1 + * Update branching information in d/gbp.conf + * Refresh d/patches + * Drop patch that has been merged upstream + * Library transition from 1.0 to 1.1 + * Update symbols file + * Drop Russell Sim from uploaders' field + - Thank you, Russell Sim, for all your work so far! + + -- Utkarsh Gupta Mon, 07 Dec 2020 14:21:42 +0530 + +libgit2 (1.0.1+dfsg.1-3) unstable; urgency=medium + + * Upload to unstable. + - Transition v1.x. (cf: #971571) + + -- Utkarsh Gupta Fri, 04 Dec 2020 23:34:22 +0530 + +libgit2 (1.0.1+dfsg.1-1) experimental; urgency=medium + + [ Utkarsh Gupta ] + * New upstream version 1.0.1+dfsg.1. + * Update symbols file to add git_worktree_prune_init_options@Base. + + [ Debian Janitor ] + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + * Drop transition for old debug package migration. + * Fix day-of-week for changelog entry 0.19.0-2. + + -- Utkarsh Gupta Fri, 09 Oct 2020 21:05:33 +0530 + +libgit2 (1.0.0+dfsg.1-2) experimental; urgency=medium + + [ Utkarsh Gupta ] + * Add Build-Depends-Package: libgit2-dev to libgit2-1.0.symbols + + [ Ximin Luo ] + * Add missing libgit2-dev: Depends: libpcre3-dev. (Closes: #961952) + + -- Ximin Luo Fri, 02 Oct 2020 03:30:36 +0100 + +libgit2 (1.0.0+dfsg.1-1) experimental; urgency=medium + + * New upstream version 1.0.0+dfsg.1 + * Library transition to 1.0.0 + * Drop patch as it is merged upstream + + -- Utkarsh Gupta Fri, 10 Apr 2020 02:21:10 +0530 + +libgit2 (0.99.0+dfsg.1-1) experimental; urgency=medium + + [ Utkarsh Gupta ] + * New upstream version 0.99.0+dfsg.1 + * Use pcre2 as REGEX_BACKEND + * Add patch to fix installation in wrong location + * Add BD on libpcre2-dev + * Add -DUSE_NTLMCLIENT and -DUSE_HTTP_PARSER flags to CMake + * Library transition from 28 to 99 + * Fix package-name-doesnt-match-sonames + * Fix d/copyright wrt the new release + * Add Rules-Requires-Root: no + + [ Sudip Mukherjee ] + * Revert "Use pcre2 as REGEX_BACKEND" + * Add dependency on ca-certificates and libpcre3-dev + * Add ci + * fix symbols file + + -- Utkarsh Gupta Thu, 26 Mar 2020 18:25:16 +0530 libgit2 (0.28.4+dfsg.1-4) unstable; urgency=medium @@ -379,7 +471,7 @@ * Multi-arch support. * Manually specified symbols instead of relying on regex. - -- Russell Sim Wed, 20 Aug 2013 22:33:20 +1000 + -- Russell Sim Tue, 20 Aug 2013 22:33:20 +1000 libgit2 (0.19.0-1) experimental; urgency=low diff -Nru libgit2-0.28.5+dfsg.1/debian/control libgit2-1.1.0+dfsg.1/debian/control --- libgit2-0.28.5+dfsg.1/debian/control 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/control 2020-12-27 04:35:32.000000000 +0000 @@ -2,8 +2,7 @@ Section: libs Priority: optional Maintainer: Utkarsh Gupta -Uploaders: Russell Sim , - Pirate Praveen +Uploaders: Pirate Praveen Build-Depends: debhelper-compat (= 12), python3-minimal:any, pkg-config, @@ -13,22 +12,25 @@ libmbedtls-dev, libssh2-1-dev, libhttp-parser-dev, - libkrb5-dev -Standards-Version: 4.5.0 + libpcre3-dev, + libkrb5-dev, + ca-certificates +Standards-Version: 4.5.1 Homepage: https://libgit2.github.com/ Vcs-Git: https://salsa.debian.org/debian/libgit2.git Vcs-Browser: https://salsa.debian.org/debian/libgit2 - +Rules-Requires-Root: no Package: libgit2-dev Architecture: any Section: libdevel Multi-Arch: same -Depends: libgit2-28 (= ${binary:Version}), +Depends: libgit2-1.1 (= ${binary:Version}), zlib1g-dev, libmbedtls-dev, libssh2-1-dev, libhttp-parser-dev, + libpcre3-dev, ${shlibs:Depends}, ${misc:Depends} Description: low-level Git library (development files) @@ -38,7 +40,7 @@ . This package contains the development files for libgit2. -Package: libgit2-28 +Package: libgit2-1.1 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} @@ -48,3 +50,17 @@ libgit2 is a portable, pure C implementation of the Git distributed version control system core methods provided as a re-entrant link-able library with a solid API. + +Package: libgit2-fixtures +Architecture: all +Pre-Depends: ${misc:Pre-Depends} +Depends: ${shlibs:Depends}, + ${misc:Depends} +Description: low-level Git library - test suite examples + libgit2 is a portable, pure C implementation of the Git + distributed version control system core methods provided as a + re-entrant link-able library with a solid API. + . + This package provides the test examples of the library, which + can be useful for other pieces of software relying on libgit2, + for testing purposes. diff -Nru libgit2-0.28.5+dfsg.1/debian/copyright libgit2-1.1.0+dfsg.1/debian/copyright --- libgit2-0.28.5+dfsg.1/debian/copyright 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/copyright 2020-12-06 22:35:33.000000000 +0000 @@ -20,7 +20,7 @@ Copyright: Public Domain License: CC0-1.0 -Files: include/git2/inttypes.h include/git2/stdint.h +Files: include/git2/stdint.h Copyright: 2006, Alexander Chemeris License: BSD-3-clause-modified @@ -33,7 +33,7 @@ 2011, Vicent Marti License: MIT -Files: src/path.c src/fnmatch.h +Files: src/path.c Copyright: 2008, The Android Open Source Project License: BSD-2-clause @@ -64,10 +64,6 @@ Copyright: 1999 - 2012, The PHP Group License: PHP-3.01 -Files: src/fnmatch.c -Copyright: 1989, 1993, 1994, The Regents of the University of California. -License: BSD-3-clause - Files: tests/clar/* Copyright: 2011, Vicent Marti License: MIT diff -Nru libgit2-0.28.5+dfsg.1/debian/gbp.conf libgit2-1.1.0+dfsg.1/debian/gbp.conf --- libgit2-0.28.5+dfsg.1/debian/gbp.conf 2020-04-10 17:32:52.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/gbp.conf 2020-12-06 22:35:58.000000000 +0000 @@ -1,2 +1,7 @@ [DEFAULT] -debian-branch = unstable +pristine-tar = True +debian-branch = debian/sid +upstream-branch = upstream/sid + +[pq] +patch-numbers = False diff -Nru libgit2-0.28.5+dfsg.1/debian/gitlab-ci.yml libgit2-1.1.0+dfsg.1/debian/gitlab-ci.yml --- libgit2-0.28.5+dfsg.1/debian/gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/gitlab-ci.yml 2020-12-06 22:35:33.000000000 +0000 @@ -0,0 +1,11 @@ +# For more information on what jobs are run see: +# https://salsa.debian.org/salsa-ci-team/pipeline +# +# To enable the jobs, go to your repository (at salsa.debian.org) +# and click over Settings > CI/CD > Expand (in General pipelines). +# In "Custom CI config path" write debian/salsa-ci.yml and click +# in "Save Changes". The CI tests will run after the next commit. +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml diff -Nru libgit2-0.28.5+dfsg.1/debian/libgit2-1.1.install libgit2-1.1.0+dfsg.1/debian/libgit2-1.1.install --- libgit2-0.28.5+dfsg.1/debian/libgit2-1.1.install 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/libgit2-1.1.install 2020-12-06 22:35:33.000000000 +0000 @@ -0,0 +1 @@ +/usr/lib/*/lib*so.* diff -Nru libgit2-0.28.5+dfsg.1/debian/libgit2-1.1.symbols libgit2-1.1.0+dfsg.1/debian/libgit2-1.1.symbols --- libgit2-0.28.5+dfsg.1/debian/libgit2-1.1.symbols 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/libgit2-1.1.symbols 2020-12-07 08:53:44.000000000 +0000 @@ -0,0 +1,891 @@ +libgit2.so.1.1 libgit2-1.1 #MINVER# + git_annotated_commit_free@Base 1.1.0 + git_annotated_commit_from_fetchhead@Base 1.1.0 + git_annotated_commit_from_ref@Base 1.1.0 + git_annotated_commit_from_revspec@Base 1.1.0 + git_annotated_commit_id@Base 1.1.0 + git_annotated_commit_lookup@Base 1.1.0 + git_annotated_commit_ref@Base 1.1.0 + git_apply@Base 1.1.0 + git_apply_options_init@Base 1.1.0 + git_apply_to_tree@Base 1.1.0 + git_attr_add_macro@Base 1.1.0 + git_attr_cache_flush@Base 1.1.0 + git_attr_foreach@Base 1.1.0 + git_attr_get@Base 1.1.0 + git_attr_get_many@Base 1.1.0 + git_attr_value@Base 1.1.0 + git_blame_buffer@Base 1.1.0 + git_blame_file@Base 1.1.0 + git_blame_free@Base 1.1.0 + git_blame_get_hunk_byindex@Base 1.1.0 + git_blame_get_hunk_byline@Base 1.1.0 + git_blame_get_hunk_count@Base 1.1.0 + git_blame_init_options@Base 1.1.0 + git_blame_options_init@Base 1.1.0 + git_blob_create_from_buffer@Base 1.1.0 + git_blob_create_from_disk@Base 1.1.0 + git_blob_create_from_stream@Base 1.1.0 + git_blob_create_from_stream_commit@Base 1.1.0 + git_blob_create_from_workdir@Base 1.1.0 + git_blob_create_frombuffer@Base 1.1.0 + git_blob_create_fromdisk@Base 1.1.0 + git_blob_create_fromstream@Base 1.1.0 + git_blob_create_fromstream_commit@Base 1.1.0 + git_blob_create_fromworkdir@Base 1.1.0 + git_blob_dup@Base 1.1.0 + git_blob_filter@Base 1.1.0 + git_blob_filtered_content@Base 1.1.0 + git_blob_free@Base 1.1.0 + git_blob_id@Base 1.1.0 + git_blob_is_binary@Base 1.1.0 + git_blob_lookup@Base 1.1.0 + git_blob_lookup_prefix@Base 1.1.0 + git_blob_owner@Base 1.1.0 + git_blob_rawcontent@Base 1.1.0 + git_blob_rawsize@Base 1.1.0 + git_branch_create@Base 1.1.0 + git_branch_create_from_annotated@Base 1.1.0 + git_branch_delete@Base 1.1.0 + git_branch_is_checked_out@Base 1.1.0 + git_branch_is_head@Base 1.1.0 + git_branch_iterator_free@Base 1.1.0 + git_branch_iterator_new@Base 1.1.0 + git_branch_lookup@Base 1.1.0 + git_branch_move@Base 1.1.0 + git_branch_name@Base 1.1.0 + git_branch_next@Base 1.1.0 + git_branch_remote_name@Base 1.1.0 + git_branch_set_upstream@Base 1.1.0 + git_branch_upstream@Base 1.1.0 + git_branch_upstream_name@Base 1.1.0 + git_branch_upstream_remote@Base 1.1.0 + git_buf_contains_nul@Base 1.1.0 + git_buf_dispose@Base 1.1.0 + git_buf_free@Base 1.1.0 + git_buf_grow@Base 1.1.0 + git_buf_is_binary@Base 1.1.0 + git_buf_set@Base 1.1.0 + git_checkout_head@Base 1.1.0 + git_checkout_index@Base 1.1.0 + git_checkout_init_options@Base 1.1.0 + git_checkout_options_init@Base 1.1.0 + git_checkout_tree@Base 1.1.0 + git_cherrypick@Base 1.1.0 + git_cherrypick_commit@Base 1.1.0 + git_cherrypick_init_options@Base 1.1.0 + git_cherrypick_options_init@Base 1.1.0 + git_clone@Base 1.1.0 + git_clone_init_options@Base 1.1.0 + git_clone_options_init@Base 1.1.0 + git_commit_amend@Base 1.1.0 + git_commit_author@Base 1.1.0 + git_commit_author_with_mailmap@Base 1.1.0 + git_commit_body@Base 1.1.0 + git_commit_committer@Base 1.1.0 + git_commit_committer_with_mailmap@Base 1.1.0 + git_commit_create@Base 1.1.0 + git_commit_create_buffer@Base 1.1.0 + git_commit_create_from_callback@Base 1.1.0 + git_commit_create_from_ids@Base 1.1.0 + git_commit_create_v@Base 1.1.0 + git_commit_create_with_signature@Base 1.1.0 + git_commit_dup@Base 1.1.0 + git_commit_extract_signature@Base 1.1.0 + git_commit_free@Base 1.1.0 + git_commit_header_field@Base 1.1.0 + git_commit_id@Base 1.1.0 + git_commit_lookup@Base 1.1.0 + git_commit_lookup_prefix@Base 1.1.0 + git_commit_message@Base 1.1.0 + git_commit_message_encoding@Base 1.1.0 + git_commit_message_raw@Base 1.1.0 + git_commit_nth_gen_ancestor@Base 1.1.0 + git_commit_owner@Base 1.1.0 + git_commit_parent@Base 1.1.0 + git_commit_parent_id@Base 1.1.0 + git_commit_parentcount@Base 1.1.0 + git_commit_raw_header@Base 1.1.0 + git_commit_summary@Base 1.1.0 + git_commit_time@Base 1.1.0 + git_commit_time_offset@Base 1.1.0 + git_commit_tree@Base 1.1.0 + git_commit_tree_id@Base 1.1.0 + git_config_add_backend@Base 1.1.0 + git_config_add_file_ondisk@Base 1.1.0 + git_config_backend_foreach_match@Base 1.1.0 + git_config_delete_entry@Base 1.1.0 + git_config_delete_multivar@Base 1.1.0 + git_config_entry_free@Base 1.1.0 + git_config_find_global@Base 1.1.0 + git_config_find_programdata@Base 1.1.0 + git_config_find_system@Base 1.1.0 + git_config_find_xdg@Base 1.1.0 + git_config_foreach@Base 1.1.0 + git_config_foreach_match@Base 1.1.0 + git_config_free@Base 1.1.0 + git_config_get_bool@Base 1.1.0 + git_config_get_entry@Base 1.1.0 + git_config_get_int32@Base 1.1.0 + git_config_get_int64@Base 1.1.0 + git_config_get_mapped@Base 1.1.0 + git_config_get_multivar_foreach@Base 1.1.0 + git_config_get_path@Base 1.1.0 + git_config_get_string@Base 1.1.0 + git_config_get_string_buf@Base 1.1.0 + git_config_init_backend@Base 1.1.0 + git_config_iterator_free@Base 1.1.0 + git_config_iterator_glob_new@Base 1.1.0 + git_config_iterator_new@Base 1.1.0 + git_config_lock@Base 1.1.0 + git_config_lookup_map_value@Base 1.1.0 + git_config_multivar_iterator_new@Base 1.1.0 + git_config_new@Base 1.1.0 + git_config_next@Base 1.1.0 + git_config_open_default@Base 1.1.0 + git_config_open_global@Base 1.1.0 + git_config_open_level@Base 1.1.0 + git_config_open_ondisk@Base 1.1.0 + git_config_parse_bool@Base 1.1.0 + git_config_parse_int32@Base 1.1.0 + git_config_parse_int64@Base 1.1.0 + git_config_parse_path@Base 1.1.0 + git_config_set_bool@Base 1.1.0 + git_config_set_int32@Base 1.1.0 + git_config_set_int64@Base 1.1.0 + git_config_set_multivar@Base 1.1.0 + git_config_set_string@Base 1.1.0 + git_config_snapshot@Base 1.1.0 + git_config_unlock@Base 1.1.0 + git_cred_default_new@Base 1.1.0 + git_cred_free@Base 1.1.0 + git_cred_get_username@Base 1.1.0 + git_cred_has_username@Base 1.1.0 + git_cred_ssh_custom_new@Base 1.1.0 + git_cred_ssh_interactive_new@Base 1.1.0 + git_cred_ssh_key_from_agent@Base 1.1.0 + git_cred_ssh_key_memory_new@Base 1.1.0 + git_cred_ssh_key_new@Base 1.1.0 + git_cred_username_new@Base 1.1.0 + git_cred_userpass@Base 1.1.0 + git_cred_userpass_plaintext_new@Base 1.1.0 + git_credential_default_new@Base 1.1.0 + git_credential_free@Base 1.1.0 + git_credential_get_username@Base 1.1.0 + git_credential_has_username@Base 1.1.0 + git_credential_ssh_custom_new@Base 1.1.0 + git_credential_ssh_interactive_new@Base 1.1.0 + git_credential_ssh_key_from_agent@Base 1.1.0 + git_credential_ssh_key_memory_new@Base 1.1.0 + git_credential_ssh_key_new@Base 1.1.0 + git_credential_username_new@Base 1.1.0 + git_credential_userpass@Base 1.1.0 + git_credential_userpass_plaintext_new@Base 1.1.0 + git_describe_commit@Base 1.1.0 + git_describe_format@Base 1.1.0 + git_describe_format_options_init@Base 1.1.0 + git_describe_init_format_options@Base 1.1.0 + git_describe_init_options@Base 1.1.0 + git_describe_options_init@Base 1.1.0 + git_describe_result_free@Base 1.1.0 + git_describe_workdir@Base 1.1.0 + git_diff_blob_to_buffer@Base 1.1.0 + git_diff_blobs@Base 1.1.0 + git_diff_buffers@Base 1.1.0 + git_diff_commit_as_email@Base 1.1.0 + git_diff_find_init_options@Base 1.1.0 + git_diff_find_options_init@Base 1.1.0 + git_diff_find_similar@Base 1.1.0 + git_diff_foreach@Base 1.1.0 + git_diff_format_email@Base 1.1.0 + git_diff_format_email_init_options@Base 1.1.0 + git_diff_format_email_options_init@Base 1.1.0 + git_diff_free@Base 1.1.0 + git_diff_from_buffer@Base 1.1.0 + git_diff_get_delta@Base 1.1.0 + git_diff_get_perfdata@Base 1.1.0 + git_diff_get_stats@Base 1.1.0 + git_diff_index_to_index@Base 1.1.0 + git_diff_index_to_workdir@Base 1.1.0 + git_diff_init_options@Base 1.1.0 + git_diff_is_sorted_icase@Base 1.1.0 + git_diff_merge@Base 1.1.0 + git_diff_num_deltas@Base 1.1.0 + git_diff_num_deltas_of_type@Base 1.1.0 + git_diff_options_init@Base 1.1.0 + git_diff_patchid@Base 1.1.0 + git_diff_patchid_options_init@Base 1.1.0 + git_diff_print@Base 1.1.0 + git_diff_print_callback__to_buf@Base 1.1.0 + git_diff_print_callback__to_file_handle@Base 1.1.0 + git_diff_stats_deletions@Base 1.1.0 + git_diff_stats_files_changed@Base 1.1.0 + git_diff_stats_free@Base 1.1.0 + git_diff_stats_insertions@Base 1.1.0 + git_diff_stats_to_buf@Base 1.1.0 + git_diff_status_char@Base 1.1.0 + git_diff_to_buf@Base 1.1.0 + git_diff_tree_to_index@Base 1.1.0 + git_diff_tree_to_tree@Base 1.1.0 + git_diff_tree_to_workdir@Base 1.1.0 + git_diff_tree_to_workdir_with_index@Base 1.1.0 + git_error_clear@Base 1.1.0 + git_error_last@Base 1.1.0 + git_error_set_oom@Base 1.1.0 + git_error_set_str@Base 1.1.0 + git_fetch_init_options@Base 1.1.0 + git_fetch_options_init@Base 1.1.0 + git_filter_init@Base 1.1.0 + git_filter_list_apply_to_blob@Base 1.1.0 + git_filter_list_apply_to_data@Base 1.1.0 + git_filter_list_apply_to_file@Base 1.1.0 + git_filter_list_contains@Base 1.1.0 + git_filter_list_free@Base 1.1.0 + git_filter_list_length@Base 1.1.0 + git_filter_list_load@Base 1.1.0 + git_filter_list_new@Base 1.1.0 + git_filter_list_push@Base 1.1.0 + git_filter_list_stream_blob@Base 1.1.0 + git_filter_list_stream_data@Base 1.1.0 + git_filter_list_stream_file@Base 1.1.0 + git_filter_lookup@Base 1.1.0 + git_filter_register@Base 1.1.0 + git_filter_source_filemode@Base 1.1.0 + git_filter_source_flags@Base 1.1.0 + git_filter_source_id@Base 1.1.0 + git_filter_source_mode@Base 1.1.0 + git_filter_source_path@Base 1.1.0 + git_filter_source_repo@Base 1.1.0 + git_filter_unregister@Base 1.1.0 + git_graph_ahead_behind@Base 1.1.0 + git_graph_descendant_of@Base 1.1.0 + git_hashsig_compare@Base 1.1.0 + git_hashsig_create@Base 1.1.0 + git_hashsig_create_fromfile@Base 1.1.0 + git_hashsig_free@Base 1.1.0 + git_ignore_add_rule@Base 1.1.0 + git_ignore_clear_internal_rules@Base 1.1.0 + git_ignore_path_is_ignored@Base 1.1.0 + git_index_add@Base 1.1.0 + git_index_add_all@Base 1.1.0 + git_index_add_bypath@Base 1.1.0 + git_index_add_from_buffer@Base 1.1.0 + git_index_add_frombuffer@Base 1.1.0 + git_index_caps@Base 1.1.0 + git_index_checksum@Base 1.1.0 + git_index_clear@Base 1.1.0 + git_index_conflict_add@Base 1.1.0 + git_index_conflict_cleanup@Base 1.1.0 + git_index_conflict_get@Base 1.1.0 + git_index_conflict_iterator_free@Base 1.1.0 + git_index_conflict_iterator_new@Base 1.1.0 + git_index_conflict_next@Base 1.1.0 + git_index_conflict_remove@Base 1.1.0 + git_index_entry_is_conflict@Base 1.1.0 + git_index_entry_stage@Base 1.1.0 + git_index_entrycount@Base 1.1.0 + git_index_find@Base 1.1.0 + git_index_find_prefix@Base 1.1.0 + git_index_free@Base 1.1.0 + git_index_get_byindex@Base 1.1.0 + git_index_get_bypath@Base 1.1.0 + git_index_has_conflicts@Base 1.1.0 + git_index_iterator_free@Base 1.1.0 + git_index_iterator_new@Base 1.1.0 + git_index_iterator_next@Base 1.1.0 + git_index_name_add@Base 1.1.0 + git_index_name_clear@Base 1.1.0 + git_index_name_entrycount@Base 1.1.0 + git_index_name_get_byindex@Base 1.1.0 + git_index_new@Base 1.1.0 + git_index_open@Base 1.1.0 + git_index_owner@Base 1.1.0 + git_index_path@Base 1.1.0 + git_index_read@Base 1.1.0 + git_index_read_tree@Base 1.1.0 + git_index_remove@Base 1.1.0 + git_index_remove_all@Base 1.1.0 + git_index_remove_bypath@Base 1.1.0 + git_index_remove_directory@Base 1.1.0 + git_index_reuc_add@Base 1.1.0 + git_index_reuc_clear@Base 1.1.0 + git_index_reuc_entrycount@Base 1.1.0 + git_index_reuc_find@Base 1.1.0 + git_index_reuc_get_byindex@Base 1.1.0 + git_index_reuc_get_bypath@Base 1.1.0 + git_index_reuc_remove@Base 1.1.0 + git_index_set_caps@Base 1.1.0 + git_index_set_version@Base 1.1.0 + git_index_update_all@Base 1.1.0 + git_index_version@Base 1.1.0 + git_index_write@Base 1.1.0 + git_index_write_tree@Base 1.1.0 + git_index_write_tree_to@Base 1.1.0 + git_indexer_append@Base 1.1.0 + git_indexer_commit@Base 1.1.0 + git_indexer_free@Base 1.1.0 + git_indexer_hash@Base 1.1.0 + git_indexer_init_options@Base 1.1.0 + git_indexer_new@Base 1.1.0 + git_indexer_options_init@Base 1.1.0 + git_libgit2_features@Base 1.1.0 + git_libgit2_init@Base 1.1.0 + git_libgit2_opts@Base 1.1.0 + git_libgit2_shutdown@Base 1.1.0 + git_libgit2_version@Base 1.1.0 + git_mailmap_add_entry@Base 1.1.0 + git_mailmap_free@Base 1.1.0 + git_mailmap_from_buffer@Base 1.1.0 + git_mailmap_from_repository@Base 1.1.0 + git_mailmap_new@Base 1.1.0 + git_mailmap_resolve@Base 1.1.0 + git_mailmap_resolve_signature@Base 1.1.0 + git_mempack_dump@Base 1.1.0 + git_mempack_new@Base 1.1.0 + git_mempack_reset@Base 1.1.0 + git_merge@Base 1.1.0 + git_merge_analysis@Base 1.1.0 + git_merge_analysis_for_ref@Base 1.1.0 + git_merge_base@Base 1.1.0 + git_merge_base_many@Base 1.1.0 + git_merge_base_octopus@Base 1.1.0 + git_merge_bases@Base 1.1.0 + git_merge_bases_many@Base 1.1.0 + git_merge_commits@Base 1.1.0 + git_merge_driver_lookup@Base 1.1.0 + git_merge_driver_register@Base 1.1.0 + git_merge_driver_source_ancestor@Base 1.1.0 + git_merge_driver_source_file_options@Base 1.1.0 + git_merge_driver_source_ours@Base 1.1.0 + git_merge_driver_source_repo@Base 1.1.0 + git_merge_driver_source_theirs@Base 1.1.0 + git_merge_driver_unregister@Base 1.1.0 + git_merge_file@Base 1.1.0 + git_merge_file_from_index@Base 1.1.0 + git_merge_file_init_input@Base 1.1.0 + git_merge_file_init_options@Base 1.1.0 + git_merge_file_input_init@Base 1.1.0 + git_merge_file_options_init@Base 1.1.0 + git_merge_file_result_free@Base 1.1.0 + git_merge_init_options@Base 1.1.0 + git_merge_options_init@Base 1.1.0 + git_merge_trees@Base 1.1.0 + git_message_prettify@Base 1.1.0 + git_message_trailer_array_free@Base 1.1.0 + git_message_trailers@Base 1.1.0 + git_note_author@Base 1.1.0 + git_note_commit_create@Base 1.1.0 + git_note_commit_iterator_new@Base 1.1.0 + git_note_commit_read@Base 1.1.0 + git_note_commit_remove@Base 1.1.0 + git_note_committer@Base 1.1.0 + git_note_create@Base 1.1.0 + git_note_default_ref@Base 1.1.0 + git_note_foreach@Base 1.1.0 + git_note_free@Base 1.1.0 + git_note_id@Base 1.1.0 + git_note_iterator_free@Base 1.1.0 + git_note_iterator_new@Base 1.1.0 + git_note_message@Base 1.1.0 + git_note_next@Base 1.1.0 + git_note_read@Base 1.1.0 + git_note_remove@Base 1.1.0 + git_object__size@Base 1.1.0 + git_object_dup@Base 1.1.0 + git_object_free@Base 1.1.0 + git_object_id@Base 1.1.0 + git_object_lookup@Base 1.1.0 + git_object_lookup_bypath@Base 1.1.0 + git_object_lookup_prefix@Base 1.1.0 + git_object_owner@Base 1.1.0 + git_object_peel@Base 1.1.0 + git_object_short_id@Base 1.1.0 + git_object_string2type@Base 1.1.0 + git_object_type2string@Base 1.1.0 + git_object_type@Base 1.1.0 + git_object_typeisloose@Base 1.1.0 + git_odb_add_alternate@Base 1.1.0 + git_odb_add_backend@Base 1.1.0 + git_odb_add_disk_alternate@Base 1.1.0 + git_odb_backend_data_alloc@Base 1.1.0 + git_odb_backend_data_free@Base 1.1.0 + git_odb_backend_loose@Base 1.1.0 + git_odb_backend_malloc@Base 1.1.0 + git_odb_backend_one_pack@Base 1.1.0 + git_odb_backend_pack@Base 1.1.0 + git_odb_exists@Base 1.1.0 + git_odb_exists_prefix@Base 1.1.0 + git_odb_expand_ids@Base 1.1.0 + git_odb_foreach@Base 1.1.0 + git_odb_free@Base 1.1.0 + git_odb_get_backend@Base 1.1.0 + git_odb_hash@Base 1.1.0 + git_odb_hashfile@Base 1.1.0 + git_odb_init_backend@Base 1.1.0 + git_odb_new@Base 1.1.0 + git_odb_num_backends@Base 1.1.0 + git_odb_object_data@Base 1.1.0 + git_odb_object_dup@Base 1.1.0 + git_odb_object_free@Base 1.1.0 + git_odb_object_id@Base 1.1.0 + git_odb_object_size@Base 1.1.0 + git_odb_object_type@Base 1.1.0 + git_odb_open@Base 1.1.0 + git_odb_open_rstream@Base 1.1.0 + git_odb_open_wstream@Base 1.1.0 + git_odb_read@Base 1.1.0 + git_odb_read_header@Base 1.1.0 + git_odb_read_prefix@Base 1.1.0 + git_odb_refresh@Base 1.1.0 + git_odb_stream_finalize_write@Base 1.1.0 + git_odb_stream_free@Base 1.1.0 + git_odb_stream_read@Base 1.1.0 + git_odb_stream_write@Base 1.1.0 + git_odb_write@Base 1.1.0 + git_odb_write_pack@Base 1.1.0 + git_oid_cmp@Base 1.1.0 + git_oid_cpy@Base 1.1.0 + git_oid_equal@Base 1.1.0 + git_oid_fmt@Base 1.1.0 + git_oid_fromraw@Base 1.1.0 + git_oid_fromstr@Base 1.1.0 + git_oid_fromstrn@Base 1.1.0 + git_oid_fromstrp@Base 1.1.0 + git_oid_is_zero@Base 1.1.0 + git_oid_iszero@Base 1.1.0 + git_oid_ncmp@Base 1.1.0 + git_oid_nfmt@Base 1.1.0 + git_oid_pathfmt@Base 1.1.0 + git_oid_shorten_add@Base 1.1.0 + git_oid_shorten_free@Base 1.1.0 + git_oid_shorten_new@Base 1.1.0 + git_oid_strcmp@Base 1.1.0 + git_oid_streq@Base 1.1.0 + git_oid_tostr@Base 1.1.0 + git_oid_tostr_s@Base 1.1.0 + git_oidarray_free@Base 1.1.0 + git_openssl_set_locking@Base 1.1.0 + git_packbuilder_foreach@Base 1.1.0 + git_packbuilder_free@Base 1.1.0 + git_packbuilder_hash@Base 1.1.0 + git_packbuilder_insert@Base 1.1.0 + git_packbuilder_insert_commit@Base 1.1.0 + git_packbuilder_insert_recur@Base 1.1.0 + git_packbuilder_insert_tree@Base 1.1.0 + git_packbuilder_insert_walk@Base 1.1.0 + git_packbuilder_new@Base 1.1.0 + git_packbuilder_object_count@Base 1.1.0 + git_packbuilder_set_callbacks@Base 1.1.0 + git_packbuilder_set_threads@Base 1.1.0 + git_packbuilder_write@Base 1.1.0 + git_packbuilder_write_buf@Base 1.1.0 + git_packbuilder_written@Base 1.1.0 + git_patch_free@Base 1.1.0 + git_patch_from_blob_and_buffer@Base 1.1.0 + git_patch_from_blobs@Base 1.1.0 + git_patch_from_buffers@Base 1.1.0 + git_patch_from_diff@Base 1.1.0 + git_patch_get_delta@Base 1.1.0 + git_patch_get_hunk@Base 1.1.0 + git_patch_get_line_in_hunk@Base 1.1.0 + git_patch_line_stats@Base 1.1.0 + git_patch_num_hunks@Base 1.1.0 + git_patch_num_lines_in_hunk@Base 1.1.0 + git_patch_print@Base 1.1.0 + git_patch_size@Base 1.1.0 + git_patch_to_buf@Base 1.1.0 + git_path_is_gitfile@Base 1.1.0 + git_pathspec_free@Base 1.1.0 + git_pathspec_match_diff@Base 1.1.0 + git_pathspec_match_index@Base 1.1.0 + git_pathspec_match_list_diff_entry@Base 1.1.0 + git_pathspec_match_list_entry@Base 1.1.0 + git_pathspec_match_list_entrycount@Base 1.1.0 + git_pathspec_match_list_failed_entry@Base 1.1.0 + git_pathspec_match_list_failed_entrycount@Base 1.1.0 + git_pathspec_match_list_free@Base 1.1.0 + git_pathspec_match_tree@Base 1.1.0 + git_pathspec_match_workdir@Base 1.1.0 + git_pathspec_matches_path@Base 1.1.0 + git_pathspec_new@Base 1.1.0 + git_proxy_init_options@Base 1.1.0 + git_proxy_options_init@Base 1.1.0 + git_push_init_options@Base 1.1.0 + git_push_options_init@Base 1.1.0 + git_rebase_abort@Base 1.1.0 + git_rebase_commit@Base 1.1.0 + git_rebase_finish@Base 1.1.0 + git_rebase_free@Base 1.1.0 + git_rebase_init@Base 1.1.0 + git_rebase_init_options@Base 1.1.0 + git_rebase_inmemory_index@Base 1.1.0 + git_rebase_next@Base 1.1.0 + git_rebase_onto_id@Base 1.1.0 + git_rebase_onto_name@Base 1.1.0 + git_rebase_open@Base 1.1.0 + git_rebase_operation_byindex@Base 1.1.0 + git_rebase_operation_current@Base 1.1.0 + git_rebase_operation_entrycount@Base 1.1.0 + git_rebase_options_init@Base 1.1.0 + git_rebase_orig_head_id@Base 1.1.0 + git_rebase_orig_head_name@Base 1.1.0 + git_refdb_backend_fs@Base 1.1.0 + git_refdb_compress@Base 1.1.0 + git_refdb_free@Base 1.1.0 + git_refdb_init_backend@Base 1.1.0 + git_refdb_new@Base 1.1.0 + git_refdb_open@Base 1.1.0 + git_refdb_set_backend@Base 1.1.0 + git_reference__alloc@Base 1.1.0 + git_reference__alloc_symbolic@Base 1.1.0 + git_reference_cmp@Base 1.1.0 + git_reference_create@Base 1.1.0 + git_reference_create_matching@Base 1.1.0 + git_reference_delete@Base 1.1.0 + git_reference_dup@Base 1.1.0 + git_reference_dwim@Base 1.1.0 + git_reference_ensure_log@Base 1.1.0 + git_reference_foreach@Base 1.1.0 + git_reference_foreach_glob@Base 1.1.0 + git_reference_foreach_name@Base 1.1.0 + git_reference_free@Base 1.1.0 + git_reference_has_log@Base 1.1.0 + git_reference_is_branch@Base 1.1.0 + git_reference_is_note@Base 1.1.0 + git_reference_is_remote@Base 1.1.0 + git_reference_is_tag@Base 1.1.0 + git_reference_is_valid_name@Base 1.1.0 + git_reference_iterator_free@Base 1.1.0 + git_reference_iterator_glob_new@Base 1.1.0 + git_reference_iterator_new@Base 1.1.0 + git_reference_list@Base 1.1.0 + git_reference_lookup@Base 1.1.0 + git_reference_name@Base 1.1.0 + git_reference_name_to_id@Base 1.1.0 + git_reference_next@Base 1.1.0 + git_reference_next_name@Base 1.1.0 + git_reference_normalize_name@Base 1.1.0 + git_reference_owner@Base 1.1.0 + git_reference_peel@Base 1.1.0 + git_reference_remove@Base 1.1.0 + git_reference_rename@Base 1.1.0 + git_reference_resolve@Base 1.1.0 + git_reference_set_target@Base 1.1.0 + git_reference_shorthand@Base 1.1.0 + git_reference_symbolic_create@Base 1.1.0 + git_reference_symbolic_create_matching@Base 1.1.0 + git_reference_symbolic_set_target@Base 1.1.0 + git_reference_symbolic_target@Base 1.1.0 + git_reference_target@Base 1.1.0 + git_reference_target_peel@Base 1.1.0 + git_reference_type@Base 1.1.0 + git_reflog_append@Base 1.1.0 + git_reflog_delete@Base 1.1.0 + git_reflog_drop@Base 1.1.0 + git_reflog_entry__free@Base 1.1.0 + git_reflog_entry_byindex@Base 1.1.0 + git_reflog_entry_committer@Base 1.1.0 + git_reflog_entry_id_new@Base 1.1.0 + git_reflog_entry_id_old@Base 1.1.0 + git_reflog_entry_message@Base 1.1.0 + git_reflog_entrycount@Base 1.1.0 + git_reflog_free@Base 1.1.0 + git_reflog_read@Base 1.1.0 + git_reflog_rename@Base 1.1.0 + git_reflog_write@Base 1.1.0 + git_refspec_direction@Base 1.1.0 + git_refspec_dst@Base 1.1.0 + git_refspec_dst_matches@Base 1.1.0 + git_refspec_force@Base 1.1.0 + git_refspec_free@Base 1.1.0 + git_refspec_parse@Base 1.1.0 + git_refspec_rtransform@Base 1.1.0 + git_refspec_src@Base 1.1.0 + git_refspec_src_matches@Base 1.1.0 + git_refspec_string@Base 1.1.0 + git_refspec_transform@Base 1.1.0 + git_remote_add_fetch@Base 1.1.0 + git_remote_add_push@Base 1.1.0 + git_remote_autotag@Base 1.1.0 + git_remote_connect@Base 1.1.0 + git_remote_connected@Base 1.1.0 + git_remote_create@Base 1.1.0 + git_remote_create_anonymous@Base 1.1.0 + git_remote_create_detached@Base 1.1.0 + git_remote_create_init_options@Base 1.1.0 + git_remote_create_options_init@Base 1.1.0 + git_remote_create_with_fetchspec@Base 1.1.0 + git_remote_create_with_opts@Base 1.1.0 + git_remote_default_branch@Base 1.1.0 + git_remote_delete@Base 1.1.0 + git_remote_disconnect@Base 1.1.0 + git_remote_download@Base 1.1.0 + git_remote_dup@Base 1.1.0 + git_remote_fetch@Base 1.1.0 + git_remote_free@Base 1.1.0 + git_remote_get_fetch_refspecs@Base 1.1.0 + git_remote_get_push_refspecs@Base 1.1.0 + git_remote_get_refspec@Base 1.1.0 + git_remote_init_callbacks@Base 1.1.0 + git_remote_is_valid_name@Base 1.1.0 + git_remote_list@Base 1.1.0 + git_remote_lookup@Base 1.1.0 + git_remote_ls@Base 1.1.0 + git_remote_name@Base 1.1.0 + git_remote_owner@Base 1.1.0 + git_remote_prune@Base 1.1.0 + git_remote_prune_refs@Base 1.1.0 + git_remote_push@Base 1.1.0 + git_remote_pushurl@Base 1.1.0 + git_remote_refspec_count@Base 1.1.0 + git_remote_rename@Base 1.1.0 + git_remote_set_autotag@Base 1.1.0 + git_remote_set_pushurl@Base 1.1.0 + git_remote_set_url@Base 1.1.0 + git_remote_stats@Base 1.1.0 + git_remote_stop@Base 1.1.0 + git_remote_update_tips@Base 1.1.0 + git_remote_upload@Base 1.1.0 + git_remote_url@Base 1.1.0 + git_repository__cleanup@Base 1.1.0 + git_repository_commondir@Base 1.1.0 + git_repository_config@Base 1.1.0 + git_repository_config_snapshot@Base 1.1.0 + git_repository_detach_head@Base 1.1.0 + git_repository_discover@Base 1.1.0 + git_repository_fetchhead_foreach@Base 1.1.0 + git_repository_free@Base 1.1.0 + git_repository_get_namespace@Base 1.1.0 + git_repository_hashfile@Base 1.1.0 + git_repository_head@Base 1.1.0 + git_repository_head_detached@Base 1.1.0 + git_repository_head_detached_for_worktree@Base 1.1.0 + git_repository_head_for_worktree@Base 1.1.0 + git_repository_head_unborn@Base 1.1.0 + git_repository_ident@Base 1.1.0 + git_repository_index@Base 1.1.0 + git_repository_init@Base 1.1.0 + git_repository_init_ext@Base 1.1.0 + git_repository_init_init_options@Base 1.1.0 + git_repository_init_options_init@Base 1.1.0 + git_repository_is_bare@Base 1.1.0 + git_repository_is_empty@Base 1.1.0 + git_repository_is_shallow@Base 1.1.0 + git_repository_is_worktree@Base 1.1.0 + git_repository_item_path@Base 1.1.0 + git_repository_mergehead_foreach@Base 1.1.0 + git_repository_message@Base 1.1.0 + git_repository_message_remove@Base 1.1.0 + git_repository_new@Base 1.1.0 + git_repository_odb@Base 1.1.0 + git_repository_open@Base 1.1.0 + git_repository_open_bare@Base 1.1.0 + git_repository_open_ext@Base 1.1.0 + git_repository_open_from_worktree@Base 1.1.0 + git_repository_path@Base 1.1.0 + git_repository_refdb@Base 1.1.0 + git_repository_reinit_filesystem@Base 1.1.0 + git_repository_set_bare@Base 1.1.0 + git_repository_set_config@Base 1.1.0 + git_repository_set_head@Base 1.1.0 + git_repository_set_head_detached@Base 1.1.0 + git_repository_set_head_detached_from_annotated@Base 1.1.0 + git_repository_set_ident@Base 1.1.0 + git_repository_set_index@Base 1.1.0 + git_repository_set_namespace@Base 1.1.0 + git_repository_set_odb@Base 1.1.0 + git_repository_set_refdb@Base 1.1.0 + git_repository_set_workdir@Base 1.1.0 + git_repository_state@Base 1.1.0 + git_repository_state_cleanup@Base 1.1.0 + git_repository_submodule_cache_all@Base 1.1.0 + git_repository_submodule_cache_clear@Base 1.1.0 + git_repository_workdir@Base 1.1.0 + git_repository_wrap_odb@Base 1.1.0 + git_reset@Base 1.1.0 + git_reset_default@Base 1.1.0 + git_reset_from_annotated@Base 1.1.0 + git_revert@Base 1.1.0 + git_revert_commit@Base 1.1.0 + git_revert_init_options@Base 1.1.0 + git_revert_options_init@Base 1.1.0 + git_revparse@Base 1.1.0 + git_revparse_ext@Base 1.1.0 + git_revparse_single@Base 1.1.0 + git_revwalk_add_hide_cb@Base 1.1.0 + git_revwalk_free@Base 1.1.0 + git_revwalk_hide@Base 1.1.0 + git_revwalk_hide_glob@Base 1.1.0 + git_revwalk_hide_head@Base 1.1.0 + git_revwalk_hide_ref@Base 1.1.0 + git_revwalk_new@Base 1.1.0 + git_revwalk_next@Base 1.1.0 + git_revwalk_push@Base 1.1.0 + git_revwalk_push_glob@Base 1.1.0 + git_revwalk_push_head@Base 1.1.0 + git_revwalk_push_range@Base 1.1.0 + git_revwalk_push_ref@Base 1.1.0 + git_revwalk_repository@Base 1.1.0 + git_revwalk_reset@Base 1.1.0 + git_revwalk_simplify_first_parent@Base 1.1.0 + git_revwalk_sorting@Base 1.1.0 + git_signature_default@Base 1.1.0 + git_signature_dup@Base 1.1.0 + git_signature_free@Base 1.1.0 + git_signature_from_buffer@Base 1.1.0 + git_signature_new@Base 1.1.0 + git_signature_now@Base 1.1.0 + git_smart_subtransport_git@Base 1.1.0 + git_smart_subtransport_http@Base 1.1.0 + git_smart_subtransport_ssh@Base 1.1.0 + git_stash_apply@Base 1.1.0 + git_stash_apply_init_options@Base 1.1.0 + git_stash_apply_options_init@Base 1.1.0 + git_stash_drop@Base 1.1.0 + git_stash_foreach@Base 1.1.0 + git_stash_pop@Base 1.1.0 + git_stash_save@Base 1.1.0 + git_status_byindex@Base 1.1.0 + git_status_file@Base 1.1.0 + git_status_foreach@Base 1.1.0 + git_status_foreach_ext@Base 1.1.0 + git_status_init_options@Base 1.1.0 + git_status_list_entrycount@Base 1.1.0 + git_status_list_free@Base 1.1.0 + git_status_list_get_perfdata@Base 1.1.0 + git_status_list_new@Base 1.1.0 + git_status_options_init@Base 1.1.0 + git_status_should_ignore@Base 1.1.0 + git_strarray_copy@Base 1.1.0 + git_strarray_dispose@Base 1.1.0 + git_strarray_free@Base 1.1.0 + git_stream_register@Base 1.1.0 + git_stream_register_tls@Base 1.1.0 + git_submodule_add_finalize@Base 1.1.0 + git_submodule_add_setup@Base 1.1.0 + git_submodule_add_to_index@Base 1.1.0 + git_submodule_branch@Base 1.1.0 + git_submodule_clone@Base 1.1.0 + git_submodule_fetch_recurse_submodules@Base 1.1.0 + git_submodule_foreach@Base 1.1.0 + git_submodule_free@Base 1.1.0 + git_submodule_head_id@Base 1.1.0 + git_submodule_ignore@Base 1.1.0 + git_submodule_index_id@Base 1.1.0 + git_submodule_init@Base 1.1.0 + git_submodule_location@Base 1.1.0 + git_submodule_lookup@Base 1.1.0 + git_submodule_name@Base 1.1.0 + git_submodule_open@Base 1.1.0 + git_submodule_owner@Base 1.1.0 + git_submodule_path@Base 1.1.0 + git_submodule_reload@Base 1.1.0 + git_submodule_repo_init@Base 1.1.0 + git_submodule_resolve_url@Base 1.1.0 + git_submodule_set_branch@Base 1.1.0 + git_submodule_set_fetch_recurse_submodules@Base 1.1.0 + git_submodule_set_ignore@Base 1.1.0 + git_submodule_set_update@Base 1.1.0 + git_submodule_set_url@Base 1.1.0 + git_submodule_status@Base 1.1.0 + git_submodule_sync@Base 1.1.0 + git_submodule_update@Base 1.1.0 + git_submodule_update_init_options@Base 1.1.0 + git_submodule_update_options_init@Base 1.1.0 + git_submodule_update_strategy@Base 1.1.0 + git_submodule_url@Base 1.1.0 + git_submodule_wd_id@Base 1.1.0 + git_tag_annotation_create@Base 1.1.0 + git_tag_create@Base 1.1.0 + git_tag_create_from_buffer@Base 1.1.0 + git_tag_create_frombuffer@Base 1.1.0 + git_tag_create_lightweight@Base 1.1.0 + git_tag_delete@Base 1.1.0 + git_tag_dup@Base 1.1.0 + git_tag_foreach@Base 1.1.0 + git_tag_free@Base 1.1.0 + git_tag_id@Base 1.1.0 + git_tag_list@Base 1.1.0 + git_tag_list_match@Base 1.1.0 + git_tag_lookup@Base 1.1.0 + git_tag_lookup_prefix@Base 1.1.0 + git_tag_message@Base 1.1.0 + git_tag_name@Base 1.1.0 + git_tag_owner@Base 1.1.0 + git_tag_peel@Base 1.1.0 + git_tag_tagger@Base 1.1.0 + git_tag_target@Base 1.1.0 + git_tag_target_id@Base 1.1.0 + git_tag_target_type@Base 1.1.0 + git_trace_set@Base 1.1.0 + git_transaction_commit@Base 1.1.0 + git_transaction_free@Base 1.1.0 + git_transaction_lock_ref@Base 1.1.0 + git_transaction_new@Base 1.1.0 + git_transaction_remove@Base 1.1.0 + git_transaction_set_reflog@Base 1.1.0 + git_transaction_set_symbolic_target@Base 1.1.0 + git_transaction_set_target@Base 1.1.0 + git_transport_init@Base 1.1.0 + git_transport_local@Base 1.1.0 + git_transport_new@Base 1.1.0 + git_transport_register@Base 1.1.0 + git_transport_smart@Base 1.1.0 + git_transport_smart_certificate_check@Base 1.1.0 + git_transport_smart_credentials@Base 1.1.0 + git_transport_smart_proxy_options@Base 1.1.0 + git_transport_ssh_with_paths@Base 1.1.0 + git_transport_unregister@Base 1.1.0 + git_tree_create_updated@Base 1.1.0 + git_tree_dup@Base 1.1.0 + git_tree_entry_byid@Base 1.1.0 + git_tree_entry_byindex@Base 1.1.0 + git_tree_entry_byname@Base 1.1.0 + git_tree_entry_bypath@Base 1.1.0 + git_tree_entry_cmp@Base 1.1.0 + git_tree_entry_dup@Base 1.1.0 + git_tree_entry_filemode@Base 1.1.0 + git_tree_entry_filemode_raw@Base 1.1.0 + git_tree_entry_free@Base 1.1.0 + git_tree_entry_id@Base 1.1.0 + git_tree_entry_name@Base 1.1.0 + git_tree_entry_to_object@Base 1.1.0 + git_tree_entry_type@Base 1.1.0 + git_tree_entrycount@Base 1.1.0 + git_tree_free@Base 1.1.0 + git_tree_id@Base 1.1.0 + git_tree_lookup@Base 1.1.0 + git_tree_lookup_prefix@Base 1.1.0 + git_tree_owner@Base 1.1.0 + git_tree_walk@Base 1.1.0 + git_treebuilder_clear@Base 1.1.0 + git_treebuilder_entrycount@Base 1.1.0 + git_treebuilder_filter@Base 1.1.0 + git_treebuilder_free@Base 1.1.0 + git_treebuilder_get@Base 1.1.0 + git_treebuilder_insert@Base 1.1.0 + git_treebuilder_new@Base 1.1.0 + git_treebuilder_remove@Base 1.1.0 + git_treebuilder_write@Base 1.1.0 + git_treebuilder_write_with_buffer@Base 1.1.0 + git_worktree_add@Base 1.1.0 + git_worktree_add_init_options@Base 1.1.0 + git_worktree_add_options_init@Base 1.1.0 + git_worktree_free@Base 1.1.0 + git_worktree_is_locked@Base 1.1.0 + git_worktree_is_prunable@Base 1.1.0 + git_worktree_list@Base 1.1.0 + git_worktree_lock@Base 1.1.0 + git_worktree_lookup@Base 1.1.0 + git_worktree_name@Base 1.1.0 + git_worktree_open_from_repository@Base 1.1.0 + git_worktree_path@Base 1.1.0 + git_worktree_prune@Base 1.1.0 + git_worktree_prune_init_options@Base 1.1.0 + git_worktree_prune_options_init@Base 1.1.0 + git_worktree_unlock@Base 1.1.0 + git_worktree_validate@Base 1.1.0 + giterr_clear@Base 1.1.0 + giterr_last@Base 1.1.0 + giterr_set_oom@Base 1.1.0 + giterr_set_str@Base 1.1.0 diff -Nru libgit2-0.28.5+dfsg.1/debian/libgit2-28.install libgit2-1.1.0+dfsg.1/debian/libgit2-28.install --- libgit2-0.28.5+dfsg.1/debian/libgit2-28.install 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/libgit2-28.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -/usr/lib/*/lib*so.* diff -Nru libgit2-0.28.5+dfsg.1/debian/libgit2-28.symbols libgit2-1.1.0+dfsg.1/debian/libgit2-28.symbols --- libgit2-0.28.5+dfsg.1/debian/libgit2-28.symbols 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/libgit2-28.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,834 +0,0 @@ -libgit2.so.28 libgit2-28 #MINVER# - git_annotated_commit_free@Base 0.26.0 - git_annotated_commit_from_fetchhead@Base 0.26.0 - git_annotated_commit_from_ref@Base 0.26.0 - git_annotated_commit_from_revspec@Base 0.26.0 - git_annotated_commit_id@Base 0.26.0 - git_annotated_commit_lookup@Base 0.26.0 - git_annotated_commit_ref@Base 0.28.1 - git_apply@Base 0.28.1 - git_apply_to_tree@Base 0.28.1 - git_attr_add_macro@Base 0.26.0 - git_attr_cache_flush@Base 0.26.0 - git_attr_foreach@Base 0.26.0 - git_attr_get@Base 0.26.0 - git_attr_get_many@Base 0.26.0 - git_attr_value@Base 0.26.0 - git_blame_buffer@Base 0.26.0 - git_blame_file@Base 0.26.0 - git_blame_free@Base 0.26.0 - git_blame_get_hunk_byindex@Base 0.26.0 - git_blame_get_hunk_byline@Base 0.26.0 - git_blame_get_hunk_count@Base 0.26.0 - git_blame_init_options@Base 0.26.0 - git_blob_create_frombuffer@Base 0.26.0 - git_blob_create_fromdisk@Base 0.26.0 - git_blob_create_fromstream@Base 0.26.0 - git_blob_create_fromstream_commit@Base 0.26.0 - git_blob_create_fromworkdir@Base 0.26.0 - git_blob_dup@Base 0.26.0 - git_blob_filtered_content@Base 0.26.0 - git_blob_free@Base 0.26.0 - git_blob_id@Base 0.26.0 - git_blob_is_binary@Base 0.26.0 - git_blob_lookup@Base 0.26.0 - git_blob_lookup_prefix@Base 0.26.0 - git_blob_owner@Base 0.26.0 - git_blob_rawcontent@Base 0.26.0 - git_blob_rawsize@Base 0.26.0 - git_branch_create@Base 0.26.0 - git_branch_create_from_annotated@Base 0.26.0 - git_branch_delete@Base 0.26.0 - git_branch_is_checked_out@Base 0.26.0 - git_branch_is_head@Base 0.26.0 - git_branch_iterator_free@Base 0.26.0 - git_branch_iterator_new@Base 0.26.0 - git_branch_lookup@Base 0.26.0 - git_branch_move@Base 0.26.0 - git_branch_name@Base 0.26.0 - git_branch_next@Base 0.26.0 - git_branch_remote_name@Base 0.26.0 - git_branch_set_upstream@Base 0.26.0 - git_branch_upstream@Base 0.26.0 - git_branch_upstream_name@Base 0.26.0 - git_branch_upstream_remote@Base 0.26.0 - git_buf_contains_nul@Base 0.26.0 - git_buf_dispose@Base 0.28.1 - git_buf_free@Base 0.26.0 - git_buf_grow@Base 0.26.0 - git_buf_is_binary@Base 0.26.0 - git_buf_set@Base 0.26.0 - git_checkout_head@Base 0.26.0 - git_checkout_index@Base 0.26.0 - git_checkout_init_options@Base 0.26.0 - git_checkout_tree@Base 0.26.0 - git_cherrypick@Base 0.26.0 - git_cherrypick_commit@Base 0.26.0 - git_cherrypick_init_options@Base 0.26.0 - git_clone@Base 0.26.0 - git_clone_init_options@Base 0.26.0 - git_commit_amend@Base 0.26.0 - git_commit_author@Base 0.26.0 - git_commit_author_with_mailmap@Base 0.28.1 - git_commit_body@Base 0.26.0 - git_commit_committer@Base 0.26.0 - git_commit_committer_with_mailmap@Base 0.28.1 - git_commit_create@Base 0.26.0 - git_commit_create_buffer@Base 0.26.0 - git_commit_create_from_callback@Base 0.26.0 - git_commit_create_from_ids@Base 0.26.0 - git_commit_create_v@Base 0.26.0 - git_commit_create_with_signature@Base 0.26.0 - git_commit_dup@Base 0.26.0 - git_commit_extract_signature@Base 0.26.0 - git_commit_free@Base 0.26.0 - git_commit_header_field@Base 0.26.0 - git_commit_id@Base 0.26.0 - git_commit_lookup@Base 0.26.0 - git_commit_lookup_prefix@Base 0.26.0 - git_commit_message@Base 0.26.0 - git_commit_message_encoding@Base 0.26.0 - git_commit_message_raw@Base 0.26.0 - git_commit_nth_gen_ancestor@Base 0.26.0 - git_commit_owner@Base 0.26.0 - git_commit_parent@Base 0.26.0 - git_commit_parent_id@Base 0.26.0 - git_commit_parentcount@Base 0.26.0 - git_commit_raw_header@Base 0.26.0 - git_commit_summary@Base 0.26.0 - git_commit_time@Base 0.26.0 - git_commit_time_offset@Base 0.26.0 - git_commit_tree@Base 0.26.0 - git_commit_tree_id@Base 0.26.0 - git_config_add_backend@Base 0.26.0 - git_config_add_file_ondisk@Base 0.26.0 - git_config_backend_foreach_match@Base 0.26.0 - git_config_delete_entry@Base 0.26.0 - git_config_delete_multivar@Base 0.26.0 - git_config_entry_free@Base 0.26.0 - git_config_find_global@Base 0.26.0 - git_config_find_programdata@Base 0.26.0 - git_config_find_system@Base 0.26.0 - git_config_find_xdg@Base 0.26.0 - git_config_foreach@Base 0.26.0 - git_config_foreach_match@Base 0.26.0 - git_config_free@Base 0.26.0 - git_config_get_bool@Base 0.26.0 - git_config_get_entry@Base 0.26.0 - git_config_get_int32@Base 0.26.0 - git_config_get_int64@Base 0.26.0 - git_config_get_mapped@Base 0.26.0 - git_config_get_multivar_foreach@Base 0.26.0 - git_config_get_path@Base 0.26.0 - git_config_get_string@Base 0.26.0 - git_config_get_string_buf@Base 0.26.0 - git_config_init_backend@Base 0.26.0 - git_config_iterator_free@Base 0.26.0 - git_config_iterator_glob_new@Base 0.26.0 - git_config_iterator_new@Base 0.26.0 - git_config_lock@Base 0.26.0 - git_config_lookup_map_value@Base 0.26.0 - git_config_multivar_iterator_new@Base 0.26.0 - git_config_new@Base 0.26.0 - git_config_next@Base 0.26.0 - git_config_open_default@Base 0.26.0 - git_config_open_global@Base 0.26.0 - git_config_open_level@Base 0.26.0 - git_config_open_ondisk@Base 0.26.0 - git_config_parse_bool@Base 0.26.0 - git_config_parse_int32@Base 0.26.0 - git_config_parse_int64@Base 0.26.0 - git_config_parse_path@Base 0.26.0 - git_config_set_bool@Base 0.26.0 - git_config_set_int32@Base 0.26.0 - git_config_set_int64@Base 0.26.0 - git_config_set_multivar@Base 0.26.0 - git_config_set_string@Base 0.26.0 - git_config_snapshot@Base 0.26.0 - git_config_unlock@Base 0.26.0 - git_cred_default_new@Base 0.26.0 - git_cred_free@Base 0.26.0 - git_cred_has_username@Base 0.26.0 - git_cred_ssh_custom_new@Base 0.26.0 - git_cred_ssh_interactive_new@Base 0.26.0 - git_cred_ssh_key_from_agent@Base 0.26.0 - git_cred_ssh_key_memory_new@Base 0.26.0 - git_cred_ssh_key_new@Base 0.26.0 - git_cred_username_new@Base 0.26.0 - git_cred_userpass@Base 0.26.0 - git_cred_userpass_plaintext_new@Base 0.26.0 - git_describe_commit@Base 0.26.0 - git_describe_format@Base 0.26.0 - git_describe_init_format_options@Base 0.26.0 - git_describe_init_options@Base 0.26.0 - git_describe_result_free@Base 0.26.0 - git_describe_workdir@Base 0.26.0 - git_diff_blob_to_buffer@Base 0.26.0 - git_diff_blobs@Base 0.26.0 - git_diff_buffers@Base 0.26.0 - git_diff_commit_as_email@Base 0.26.0 - git_diff_find_init_options@Base 0.26.0 - git_diff_find_similar@Base 0.26.0 - git_diff_foreach@Base 0.26.0 - git_diff_format_email@Base 0.26.0 - git_diff_format_email_init_options@Base 0.26.0 - git_diff_free@Base 0.26.0 - git_diff_from_buffer@Base 0.26.0 - git_diff_get_delta@Base 0.26.0 - git_diff_get_perfdata@Base 0.26.0 - git_diff_get_stats@Base 0.26.0 - git_diff_index_to_index@Base 0.26.0 - git_diff_index_to_workdir@Base 0.26.0 - git_diff_init_options@Base 0.26.0 - git_diff_is_sorted_icase@Base 0.26.0 - git_diff_merge@Base 0.26.0 - git_diff_num_deltas@Base 0.26.0 - git_diff_num_deltas_of_type@Base 0.26.0 - git_diff_patchid@Base 0.27.0 - git_diff_patchid_init_options@Base 0.27.0 - git_diff_print@Base 0.26.0 - git_diff_print_callback__to_buf@Base 0.26.0 - git_diff_print_callback__to_file_handle@Base 0.26.0 - git_diff_stats_deletions@Base 0.26.0 - git_diff_stats_files_changed@Base 0.26.0 - git_diff_stats_free@Base 0.26.0 - git_diff_stats_insertions@Base 0.26.0 - git_diff_stats_to_buf@Base 0.26.0 - git_diff_status_char@Base 0.26.0 - git_diff_to_buf@Base 0.26.0 - git_diff_tree_to_index@Base 0.26.0 - git_diff_tree_to_tree@Base 0.26.0 - git_diff_tree_to_workdir@Base 0.26.0 - git_diff_tree_to_workdir_with_index@Base 0.26.0 - git_error_clear@Base 0.28.1 - git_error_last@Base 0.28.1 - git_error_set_oom@Base 0.28.1 - git_error_set_str@Base 0.28.1 - git_fetch_init_options@Base 0.26.0 - git_filter_init@Base 0.26.0 - git_filter_list_apply_to_blob@Base 0.26.0 - git_filter_list_apply_to_data@Base 0.26.0 - git_filter_list_apply_to_file@Base 0.26.0 - git_filter_list_contains@Base 0.26.0 - git_filter_list_free@Base 0.26.0 - git_filter_list_length@Base 0.26.0 - git_filter_list_load@Base 0.26.0 - git_filter_list_new@Base 0.26.0 - git_filter_list_push@Base 0.26.0 - git_filter_list_stream_blob@Base 0.26.0 - git_filter_list_stream_data@Base 0.26.0 - git_filter_list_stream_file@Base 0.26.0 - git_filter_lookup@Base 0.26.0 - git_filter_register@Base 0.26.0 - git_filter_source_filemode@Base 0.26.0 - git_filter_source_flags@Base 0.26.0 - git_filter_source_id@Base 0.26.0 - git_filter_source_mode@Base 0.26.0 - git_filter_source_path@Base 0.26.0 - git_filter_source_repo@Base 0.26.0 - git_filter_unregister@Base 0.26.0 - git_graph_ahead_behind@Base 0.26.0 - git_graph_descendant_of@Base 0.26.0 - git_hashsig_compare@Base 0.26.0 - git_hashsig_create@Base 0.26.0 - git_hashsig_create_fromfile@Base 0.26.0 - git_hashsig_free@Base 0.26.0 - git_ignore_add_rule@Base 0.26.0 - git_ignore_clear_internal_rules@Base 0.26.0 - git_ignore_path_is_ignored@Base 0.26.0 - git_index_add@Base 0.26.0 - git_index_add_all@Base 0.26.0 - git_index_add_bypath@Base 0.26.0 - git_index_add_frombuffer@Base 0.26.0 - git_index_caps@Base 0.26.0 - git_index_checksum@Base 0.26.0 - git_index_clear@Base 0.26.0 - git_index_conflict_add@Base 0.26.0 - git_index_conflict_cleanup@Base 0.26.0 - git_index_conflict_get@Base 0.26.0 - git_index_conflict_iterator_free@Base 0.26.0 - git_index_conflict_iterator_new@Base 0.26.0 - git_index_conflict_next@Base 0.26.0 - git_index_conflict_remove@Base 0.26.0 - git_index_entry_is_conflict@Base 0.26.0 - git_index_entry_stage@Base 0.26.0 - git_index_entrycount@Base 0.26.0 - git_index_find@Base 0.26.0 - git_index_find_prefix@Base 0.26.0 - git_index_free@Base 0.26.0 - git_index_get_byindex@Base 0.26.0 - git_index_get_bypath@Base 0.26.0 - git_index_has_conflicts@Base 0.26.0 - git_index_iterator_free@Base 0.28.1 - git_index_iterator_new@Base 0.28.1 - git_index_iterator_next@Base 0.28.1 - git_index_name_add@Base 0.26.0 - git_index_name_clear@Base 0.26.0 - git_index_name_entrycount@Base 0.26.0 - git_index_name_get_byindex@Base 0.26.0 - git_index_new@Base 0.26.0 - git_index_open@Base 0.26.0 - git_index_owner@Base 0.26.0 - git_index_path@Base 0.26.0 - git_index_read@Base 0.26.0 - git_index_read_tree@Base 0.26.0 - git_index_remove@Base 0.26.0 - git_index_remove_all@Base 0.26.0 - git_index_remove_bypath@Base 0.26.0 - git_index_remove_directory@Base 0.26.0 - git_index_reuc_add@Base 0.26.0 - git_index_reuc_clear@Base 0.26.0 - git_index_reuc_entrycount@Base 0.26.0 - git_index_reuc_find@Base 0.26.0 - git_index_reuc_get_byindex@Base 0.26.0 - git_index_reuc_get_bypath@Base 0.26.0 - git_index_reuc_remove@Base 0.26.0 - git_index_set_caps@Base 0.26.0 - git_index_set_version@Base 0.26.0 - git_index_update_all@Base 0.26.0 - git_index_version@Base 0.26.0 - git_index_write@Base 0.26.0 - git_index_write_tree@Base 0.26.0 - git_index_write_tree_to@Base 0.26.0 - git_indexer_append@Base 0.26.0 - git_indexer_commit@Base 0.26.0 - git_indexer_free@Base 0.26.0 - git_indexer_hash@Base 0.26.0 - git_indexer_init_options@Base 0.28.1 - git_indexer_new@Base 0.26.0 - git_libgit2_features@Base 0.26.0 - git_libgit2_init@Base 0.26.0 - git_libgit2_opts@Base 0.26.0 - git_libgit2_shutdown@Base 0.26.0 - git_libgit2_version@Base 0.26.0 - git_mailmap_add_entry@Base 0.28.1 - git_mailmap_free@Base 0.28.1 - git_mailmap_from_buffer@Base 0.28.1 - git_mailmap_from_repository@Base 0.28.1 - git_mailmap_new@Base 0.28.1 - git_mailmap_resolve@Base 0.28.1 - git_mailmap_resolve_signature@Base 0.28.1 - git_mempack_dump@Base 0.27.0 - git_mempack_new@Base 0.27.0 - git_mempack_reset@Base 0.27.0 - git_merge@Base 0.26.0 - git_merge_analysis@Base 0.26.0 - git_merge_analysis_for_ref@Base 0.28.1 - git_merge_base@Base 0.26.0 - git_merge_base_many@Base 0.26.0 - git_merge_base_octopus@Base 0.26.0 - git_merge_bases@Base 0.26.0 - git_merge_bases_many@Base 0.26.0 - git_merge_commits@Base 0.26.0 - git_merge_driver_lookup@Base 0.26.0 - git_merge_driver_register@Base 0.26.0 - git_merge_driver_source_ancestor@Base 0.26.0 - git_merge_driver_source_file_options@Base 0.26.0 - git_merge_driver_source_ours@Base 0.26.0 - git_merge_driver_source_repo@Base 0.26.0 - git_merge_driver_source_theirs@Base 0.26.0 - git_merge_driver_unregister@Base 0.26.0 - git_merge_file@Base 0.26.0 - git_merge_file_from_index@Base 0.26.0 - git_merge_file_init_input@Base 0.26.0 - git_merge_file_init_options@Base 0.26.0 - git_merge_file_result_free@Base 0.26.0 - git_merge_init_options@Base 0.26.0 - git_merge_trees@Base 0.26.0 - git_message_prettify@Base 0.26.0 - git_message_trailer_array_free@Base 0.27.0 - git_message_trailers@Base 0.27.0 - git_note_author@Base 0.26.0 - git_note_commit_create@Base 0.27.0 - git_note_commit_iterator_new@Base 0.27.0 - git_note_commit_read@Base 0.27.0 - git_note_commit_remove@Base 0.27.0 - git_note_committer@Base 0.26.0 - git_note_create@Base 0.26.0 - git_note_default_ref@Base 0.26.0 - git_note_foreach@Base 0.26.0 - git_note_free@Base 0.26.0 - git_note_id@Base 0.26.0 - git_note_iterator_free@Base 0.26.0 - git_note_iterator_new@Base 0.26.0 - git_note_message@Base 0.26.0 - git_note_next@Base 0.26.0 - git_note_read@Base 0.26.0 - git_note_remove@Base 0.26.0 - git_object__size@Base 0.26.0 - git_object_dup@Base 0.26.0 - git_object_free@Base 0.26.0 - git_object_id@Base 0.26.0 - git_object_lookup@Base 0.26.0 - git_object_lookup_bypath@Base 0.26.0 - git_object_lookup_prefix@Base 0.26.0 - git_object_owner@Base 0.26.0 - git_object_peel@Base 0.26.0 - git_object_short_id@Base 0.26.0 - git_object_string2type@Base 0.26.0 - git_object_type2string@Base 0.26.0 - git_object_type@Base 0.26.0 - git_object_typeisloose@Base 0.26.0 - git_odb_add_alternate@Base 0.26.0 - git_odb_add_backend@Base 0.26.0 - git_odb_add_disk_alternate@Base 0.26.0 - git_odb_backend_loose@Base 0.26.0 - git_odb_backend_malloc@Base 0.26.0 - git_odb_backend_one_pack@Base 0.26.0 - git_odb_backend_pack@Base 0.26.0 - git_odb_exists@Base 0.26.0 - git_odb_exists_prefix@Base 0.26.0 - git_odb_expand_ids@Base 0.26.0 - git_odb_foreach@Base 0.26.0 - git_odb_free@Base 0.26.0 - git_odb_get_backend@Base 0.26.0 - git_odb_hash@Base 0.26.0 - git_odb_hashfile@Base 0.26.0 - git_odb_init_backend@Base 0.26.0 - git_odb_new@Base 0.26.0 - git_odb_num_backends@Base 0.26.0 - git_odb_object_data@Base 0.26.0 - git_odb_object_dup@Base 0.26.0 - git_odb_object_free@Base 0.26.0 - git_odb_object_id@Base 0.26.0 - git_odb_object_size@Base 0.26.0 - git_odb_object_type@Base 0.26.0 - git_odb_open@Base 0.26.0 - git_odb_open_rstream@Base 0.26.0 - git_odb_open_wstream@Base 0.26.0 - git_odb_read@Base 0.26.0 - git_odb_read_header@Base 0.26.0 - git_odb_read_prefix@Base 0.26.0 - git_odb_refresh@Base 0.26.0 - git_odb_stream_finalize_write@Base 0.26.0 - git_odb_stream_free@Base 0.26.0 - git_odb_stream_read@Base 0.26.0 - git_odb_stream_write@Base 0.26.0 - git_odb_write@Base 0.26.0 - git_odb_write_pack@Base 0.26.0 - git_oid_cmp@Base 0.26.0 - git_oid_cpy@Base 0.26.0 - git_oid_equal@Base 0.26.0 - git_oid_fmt@Base 0.26.0 - git_oid_fromraw@Base 0.26.0 - git_oid_fromstr@Base 0.26.0 - git_oid_fromstrn@Base 0.26.0 - git_oid_fromstrp@Base 0.26.0 - git_oid_iszero@Base 0.26.0 - git_oid_ncmp@Base 0.26.0 - git_oid_nfmt@Base 0.26.0 - git_oid_pathfmt@Base 0.26.0 - git_oid_shorten_add@Base 0.26.0 - git_oid_shorten_free@Base 0.26.0 - git_oid_shorten_new@Base 0.26.0 - git_oid_strcmp@Base 0.26.0 - git_oid_streq@Base 0.26.0 - git_oid_tostr@Base 0.26.0 - git_oid_tostr_s@Base 0.26.0 - git_oidarray_free@Base 0.26.0 - git_openssl_set_locking@Base 0.26.0 - git_packbuilder_foreach@Base 0.26.0 - git_packbuilder_free@Base 0.26.0 - git_packbuilder_hash@Base 0.26.0 - git_packbuilder_insert@Base 0.26.0 - git_packbuilder_insert_commit@Base 0.26.0 - git_packbuilder_insert_recur@Base 0.26.0 - git_packbuilder_insert_tree@Base 0.26.0 - git_packbuilder_insert_walk@Base 0.26.0 - git_packbuilder_new@Base 0.26.0 - git_packbuilder_object_count@Base 0.26.0 - git_packbuilder_set_callbacks@Base 0.26.0 - git_packbuilder_set_threads@Base 0.26.0 - git_packbuilder_write@Base 0.26.0 - git_packbuilder_write_buf@Base 0.26.0 - git_packbuilder_written@Base 0.26.0 - git_patch_free@Base 0.26.0 - git_patch_from_blob_and_buffer@Base 0.26.0 - git_patch_from_blobs@Base 0.26.0 - git_patch_from_buffers@Base 0.26.0 - git_patch_from_diff@Base 0.26.0 - git_patch_get_delta@Base 0.26.0 - git_patch_get_hunk@Base 0.26.0 - git_patch_get_line_in_hunk@Base 0.26.0 - git_patch_line_stats@Base 0.26.0 - git_patch_num_hunks@Base 0.26.0 - git_patch_num_lines_in_hunk@Base 0.26.0 - git_patch_print@Base 0.26.0 - git_patch_size@Base 0.26.0 - git_patch_to_buf@Base 0.26.0 - git_path_is_gitfile@Base 0.28.1 - git_pathspec_free@Base 0.26.0 - git_pathspec_match_diff@Base 0.26.0 - git_pathspec_match_index@Base 0.26.0 - git_pathspec_match_list_diff_entry@Base 0.26.0 - git_pathspec_match_list_entry@Base 0.26.0 - git_pathspec_match_list_entrycount@Base 0.26.0 - git_pathspec_match_list_failed_entry@Base 0.26.0 - git_pathspec_match_list_failed_entrycount@Base 0.26.0 - git_pathspec_match_list_free@Base 0.26.0 - git_pathspec_match_tree@Base 0.26.0 - git_pathspec_match_workdir@Base 0.26.0 - git_pathspec_matches_path@Base 0.26.0 - git_pathspec_new@Base 0.26.0 - git_proxy_init_options@Base 0.26.0 - git_push_init_options@Base 0.26.0 - git_rebase_abort@Base 0.26.0 - git_rebase_commit@Base 0.26.0 - git_rebase_finish@Base 0.26.0 - git_rebase_free@Base 0.26.0 - git_rebase_init@Base 0.26.0 - git_rebase_init_options@Base 0.26.0 - git_rebase_inmemory_index@Base 0.26.0 - git_rebase_next@Base 0.26.0 - git_rebase_open@Base 0.26.0 - git_rebase_operation_byindex@Base 0.26.0 - git_rebase_operation_current@Base 0.26.0 - git_rebase_operation_entrycount@Base 0.26.0 - git_refdb_backend_fs@Base 0.26.0 - git_refdb_compress@Base 0.26.0 - git_refdb_free@Base 0.26.0 - git_refdb_init_backend@Base 0.26.0 - git_refdb_new@Base 0.26.0 - git_refdb_open@Base 0.26.0 - git_refdb_set_backend@Base 0.26.0 - git_reference__alloc@Base 0.26.0 - git_reference__alloc_symbolic@Base 0.26.0 - git_reference_cmp@Base 0.26.0 - git_reference_create@Base 0.26.0 - git_reference_create_matching@Base 0.26.0 - git_reference_delete@Base 0.26.0 - git_reference_dup@Base 0.26.0 - git_reference_dwim@Base 0.26.0 - git_reference_ensure_log@Base 0.26.0 - git_reference_foreach@Base 0.26.0 - git_reference_foreach_glob@Base 0.26.0 - git_reference_foreach_name@Base 0.26.0 - git_reference_free@Base 0.26.0 - git_reference_has_log@Base 0.26.0 - git_reference_is_branch@Base 0.26.0 - git_reference_is_note@Base 0.26.0 - git_reference_is_remote@Base 0.26.0 - git_reference_is_tag@Base 0.26.0 - git_reference_is_valid_name@Base 0.26.0 - git_reference_iterator_free@Base 0.26.0 - git_reference_iterator_glob_new@Base 0.26.0 - git_reference_iterator_new@Base 0.26.0 - git_reference_list@Base 0.26.0 - git_reference_lookup@Base 0.26.0 - git_reference_name@Base 0.26.0 - git_reference_name_to_id@Base 0.26.0 - git_reference_next@Base 0.26.0 - git_reference_next_name@Base 0.26.0 - git_reference_normalize_name@Base 0.26.0 - git_reference_owner@Base 0.26.0 - git_reference_peel@Base 0.26.0 - git_reference_remove@Base 0.26.0 - git_reference_rename@Base 0.26.0 - git_reference_resolve@Base 0.26.0 - git_reference_set_target@Base 0.26.0 - git_reference_shorthand@Base 0.26.0 - git_reference_symbolic_create@Base 0.26.0 - git_reference_symbolic_create_matching@Base 0.26.0 - git_reference_symbolic_set_target@Base 0.26.0 - git_reference_symbolic_target@Base 0.26.0 - git_reference_target@Base 0.26.0 - git_reference_target_peel@Base 0.26.0 - git_reference_type@Base 0.26.0 - git_reflog_append@Base 0.26.0 - git_reflog_delete@Base 0.26.0 - git_reflog_drop@Base 0.26.0 - git_reflog_entry_byindex@Base 0.26.0 - git_reflog_entry_committer@Base 0.26.0 - git_reflog_entry_id_new@Base 0.26.0 - git_reflog_entry_id_old@Base 0.26.0 - git_reflog_entry_message@Base 0.26.0 - git_reflog_entrycount@Base 0.26.0 - git_reflog_free@Base 0.26.0 - git_reflog_read@Base 0.26.0 - git_reflog_rename@Base 0.26.0 - git_reflog_write@Base 0.26.0 - git_refspec_direction@Base 0.26.0 - git_refspec_dst@Base 0.26.0 - git_refspec_dst_matches@Base 0.26.0 - git_refspec_force@Base 0.26.0 - git_refspec_free@Base 0.28.1 - git_refspec_parse@Base 0.28.1 - git_refspec_rtransform@Base 0.26.0 - git_refspec_src@Base 0.26.0 - git_refspec_src_matches@Base 0.26.0 - git_refspec_string@Base 0.26.0 - git_refspec_transform@Base 0.26.0 - git_remote_add_fetch@Base 0.26.0 - git_remote_add_push@Base 0.26.0 - git_remote_autotag@Base 0.26.0 - git_remote_connect@Base 0.26.0 - git_remote_connected@Base 0.26.0 - git_remote_create@Base 0.26.0 - git_remote_create_anonymous@Base 0.26.0 - git_remote_create_detached@Base 0.27.0 - git_remote_create_init_options@Base 0.28.1 - git_remote_create_with_fetchspec@Base 0.26.0 - git_remote_create_with_opts@Base 0.28.1 - git_remote_default_branch@Base 0.26.0 - git_remote_delete@Base 0.26.0 - git_remote_disconnect@Base 0.26.0 - git_remote_download@Base 0.26.0 - git_remote_dup@Base 0.26.0 - git_remote_fetch@Base 0.26.0 - git_remote_free@Base 0.26.0 - git_remote_get_fetch_refspecs@Base 0.26.0 - git_remote_get_push_refspecs@Base 0.26.0 - git_remote_get_refspec@Base 0.26.0 - git_remote_init_callbacks@Base 0.26.0 - git_remote_is_valid_name@Base 0.26.0 - git_remote_list@Base 0.26.0 - git_remote_lookup@Base 0.26.0 - git_remote_ls@Base 0.26.0 - git_remote_name@Base 0.26.0 - git_remote_owner@Base 0.26.0 - git_remote_prune@Base 0.26.0 - git_remote_prune_refs@Base 0.26.0 - git_remote_push@Base 0.26.0 - git_remote_pushurl@Base 0.26.0 - git_remote_refspec_count@Base 0.26.0 - git_remote_rename@Base 0.26.0 - git_remote_set_autotag@Base 0.26.0 - git_remote_set_pushurl@Base 0.26.0 - git_remote_set_url@Base 0.26.0 - git_remote_stats@Base 0.26.0 - git_remote_stop@Base 0.26.0 - git_remote_update_tips@Base 0.26.0 - git_remote_upload@Base 0.26.0 - git_remote_url@Base 0.26.0 - git_repository__cleanup@Base 0.26.0 - git_repository_commondir@Base 0.26.0 - git_repository_config@Base 0.26.0 - git_repository_config_snapshot@Base 0.26.0 - git_repository_detach_head@Base 0.26.0 - git_repository_discover@Base 0.26.0 - git_repository_fetchhead_foreach@Base 0.26.0 - git_repository_free@Base 0.26.0 - git_repository_get_namespace@Base 0.26.0 - git_repository_hashfile@Base 0.26.0 - git_repository_head@Base 0.26.0 - git_repository_head_detached@Base 0.26.0 - git_repository_head_detached_for_worktree@Base 0.26.0 - git_repository_head_for_worktree@Base 0.26.0 - git_repository_head_unborn@Base 0.26.0 - git_repository_ident@Base 0.26.0 - git_repository_index@Base 0.26.0 - git_repository_init@Base 0.26.0 - git_repository_init_ext@Base 0.26.0 - git_repository_init_init_options@Base 0.26.0 - git_repository_is_bare@Base 0.26.0 - git_repository_is_empty@Base 0.26.0 - git_repository_is_shallow@Base 0.26.0 - git_repository_is_worktree@Base 0.26.0 - git_repository_item_path@Base 0.26.0 - git_repository_mergehead_foreach@Base 0.26.0 - git_repository_message@Base 0.26.0 - git_repository_message_remove@Base 0.26.0 - git_repository_new@Base 0.26.0 - git_repository_odb@Base 0.26.0 - git_repository_open@Base 0.26.0 - git_repository_open_bare@Base 0.26.0 - git_repository_open_ext@Base 0.26.0 - git_repository_open_from_worktree@Base 0.26.0 - git_repository_path@Base 0.26.0 - git_repository_refdb@Base 0.26.0 - git_repository_reinit_filesystem@Base 0.26.0 - git_repository_set_bare@Base 0.26.0 - git_repository_set_config@Base 0.26.0 - git_repository_set_head@Base 0.26.0 - git_repository_set_head_detached@Base 0.26.0 - git_repository_set_head_detached_from_annotated@Base 0.26.0 - git_repository_set_ident@Base 0.26.0 - git_repository_set_index@Base 0.26.0 - git_repository_set_namespace@Base 0.26.0 - git_repository_set_odb@Base 0.26.0 - git_repository_set_refdb@Base 0.26.0 - git_repository_set_workdir@Base 0.26.0 - git_repository_state@Base 0.26.0 - git_repository_state_cleanup@Base 0.26.0 - git_repository_submodule_cache_all@Base 0.26.0 - git_repository_submodule_cache_clear@Base 0.26.0 - git_repository_workdir@Base 0.26.0 - git_repository_wrap_odb@Base 0.26.0 - git_reset@Base 0.26.0 - git_reset_default@Base 0.26.0 - git_reset_from_annotated@Base 0.26.0 - git_revert@Base 0.26.0 - git_revert_commit@Base 0.26.0 - git_revert_init_options@Base 0.26.0 - git_revparse@Base 0.26.0 - git_revparse_ext@Base 0.26.0 - git_revparse_single@Base 0.26.0 - git_revwalk_add_hide_cb@Base 0.26.0 - git_revwalk_free@Base 0.26.0 - git_revwalk_hide@Base 0.26.0 - git_revwalk_hide_glob@Base 0.26.0 - git_revwalk_hide_head@Base 0.26.0 - git_revwalk_hide_ref@Base 0.26.0 - git_revwalk_new@Base 0.26.0 - git_revwalk_next@Base 0.26.0 - git_revwalk_push@Base 0.26.0 - git_revwalk_push_glob@Base 0.26.0 - git_revwalk_push_head@Base 0.26.0 - git_revwalk_push_range@Base 0.26.0 - git_revwalk_push_ref@Base 0.26.0 - git_revwalk_repository@Base 0.26.0 - git_revwalk_reset@Base 0.26.0 - git_revwalk_simplify_first_parent@Base 0.26.0 - git_revwalk_sorting@Base 0.26.0 - git_signature_default@Base 0.26.0 - git_signature_dup@Base 0.26.0 - git_signature_free@Base 0.26.0 - git_signature_from_buffer@Base 0.26.0 - git_signature_new@Base 0.26.0 - git_signature_now@Base 0.26.0 - git_smart_subtransport_git@Base 0.26.0 - git_smart_subtransport_http@Base 0.26.0 - git_smart_subtransport_ssh@Base 0.26.0 - git_stash_apply@Base 0.26.0 - git_stash_apply_init_options@Base 0.26.0 - git_stash_drop@Base 0.26.0 - git_stash_foreach@Base 0.26.0 - git_stash_pop@Base 0.26.0 - git_stash_save@Base 0.26.0 - git_status_byindex@Base 0.26.0 - git_status_file@Base 0.26.0 - git_status_foreach@Base 0.26.0 - git_status_foreach_ext@Base 0.26.0 - git_status_init_options@Base 0.26.0 - git_status_list_entrycount@Base 0.26.0 - git_status_list_free@Base 0.26.0 - git_status_list_get_perfdata@Base 0.26.0 - git_status_list_new@Base 0.26.0 - git_status_should_ignore@Base 0.26.0 - git_strarray_copy@Base 0.26.0 - git_strarray_free@Base 0.26.0 - git_stream_register@Base 0.28.1 - git_stream_register_tls@Base 0.26.0 - git_submodule_add_finalize@Base 0.26.0 - git_submodule_add_setup@Base 0.26.0 - git_submodule_add_to_index@Base 0.26.0 - git_submodule_branch@Base 0.26.0 - git_submodule_fetch_recurse_submodules@Base 0.26.0 - git_submodule_foreach@Base 0.26.0 - git_submodule_free@Base 0.26.0 - git_submodule_head_id@Base 0.26.0 - git_submodule_ignore@Base 0.26.0 - git_submodule_index_id@Base 0.26.0 - git_submodule_init@Base 0.26.0 - git_submodule_location@Base 0.26.0 - git_submodule_lookup@Base 0.26.0 - git_submodule_name@Base 0.26.0 - git_submodule_open@Base 0.26.0 - git_submodule_owner@Base 0.26.0 - git_submodule_path@Base 0.26.0 - git_submodule_reload@Base 0.26.0 - git_submodule_repo_init@Base 0.26.0 - git_submodule_resolve_url@Base 0.26.0 - git_submodule_set_branch@Base 0.26.0 - git_submodule_set_fetch_recurse_submodules@Base 0.26.0 - git_submodule_set_ignore@Base 0.26.0 - git_submodule_set_update@Base 0.26.0 - git_submodule_set_url@Base 0.26.0 - git_submodule_status@Base 0.26.0 - git_submodule_sync@Base 0.26.0 - git_submodule_update@Base 0.26.0 - git_submodule_update_init_options@Base 0.26.0 - git_submodule_update_strategy@Base 0.26.0 - git_submodule_url@Base 0.26.0 - git_submodule_wd_id@Base 0.26.0 - git_tag_annotation_create@Base 0.26.0 - git_tag_create@Base 0.26.0 - git_tag_create_frombuffer@Base 0.26.0 - git_tag_create_lightweight@Base 0.26.0 - git_tag_delete@Base 0.26.0 - git_tag_dup@Base 0.26.0 - git_tag_foreach@Base 0.26.0 - git_tag_free@Base 0.26.0 - git_tag_id@Base 0.26.0 - git_tag_list@Base 0.26.0 - git_tag_list_match@Base 0.26.0 - git_tag_lookup@Base 0.26.0 - git_tag_lookup_prefix@Base 0.26.0 - git_tag_message@Base 0.26.0 - git_tag_name@Base 0.26.0 - git_tag_owner@Base 0.26.0 - git_tag_peel@Base 0.26.0 - git_tag_tagger@Base 0.26.0 - git_tag_target@Base 0.26.0 - git_tag_target_id@Base 0.26.0 - git_tag_target_type@Base 0.26.0 - git_trace_set@Base 0.26.0 - git_transaction_commit@Base 0.26.0 - git_transaction_free@Base 0.26.0 - git_transaction_lock_ref@Base 0.26.0 - git_transaction_new@Base 0.26.0 - git_transaction_remove@Base 0.26.0 - git_transaction_set_reflog@Base 0.26.0 - git_transaction_set_symbolic_target@Base 0.26.0 - git_transaction_set_target@Base 0.26.0 - git_transport_init@Base 0.26.0 - git_transport_local@Base 0.26.0 - git_transport_new@Base 0.26.0 - git_transport_register@Base 0.26.0 - git_transport_smart@Base 0.26.0 - git_transport_smart_certificate_check@Base 0.26.0 - git_transport_smart_credentials@Base 0.26.0 - git_transport_smart_proxy_options@Base 0.26.0 - git_transport_ssh_with_paths@Base 0.26.0 - git_transport_unregister@Base 0.26.0 - git_tree_create_updated@Base 0.26.0 - git_tree_dup@Base 0.26.0 - git_tree_entry_byid@Base 0.26.0 - git_tree_entry_byindex@Base 0.26.0 - git_tree_entry_byname@Base 0.26.0 - git_tree_entry_bypath@Base 0.26.0 - git_tree_entry_cmp@Base 0.26.0 - git_tree_entry_dup@Base 0.26.0 - git_tree_entry_filemode@Base 0.26.0 - git_tree_entry_filemode_raw@Base 0.26.0 - git_tree_entry_free@Base 0.26.0 - git_tree_entry_id@Base 0.26.0 - git_tree_entry_name@Base 0.26.0 - git_tree_entry_to_object@Base 0.26.0 - git_tree_entry_type@Base 0.26.0 - git_tree_entrycount@Base 0.26.0 - git_tree_free@Base 0.26.0 - git_tree_id@Base 0.26.0 - git_tree_lookup@Base 0.26.0 - git_tree_lookup_prefix@Base 0.26.0 - git_tree_owner@Base 0.26.0 - git_tree_walk@Base 0.26.0 - git_treebuilder_clear@Base 0.26.0 - git_treebuilder_entrycount@Base 0.26.0 - git_treebuilder_filter@Base 0.26.0 - git_treebuilder_free@Base 0.26.0 - git_treebuilder_get@Base 0.26.0 - git_treebuilder_insert@Base 0.26.0 - git_treebuilder_new@Base 0.26.0 - git_treebuilder_remove@Base 0.26.0 - git_treebuilder_write@Base 0.26.0 - git_treebuilder_write_with_buffer@Base 0.26.0 - git_worktree_add@Base 0.26.0 - git_worktree_add_init_options@Base 0.28.1 - git_worktree_free@Base 0.26.0 - git_worktree_is_locked@Base 0.26.0 - git_worktree_is_prunable@Base 0.26.0 - git_worktree_list@Base 0.26.0 - git_worktree_lock@Base 0.26.0 - git_worktree_lookup@Base 0.26.0 - git_worktree_name@Base 0.28.1 - git_worktree_open_from_repository@Base 0.26.0 - git_worktree_path@Base 0.28.1 - git_worktree_prune@Base 0.26.0 - git_worktree_prune_init_options@Base 0.26.0 - git_worktree_unlock@Base 0.26.0 - git_worktree_validate@Base 0.26.0 - giterr_clear@Base 0.26.0 - giterr_last@Base 0.26.0 - giterr_set_oom@Base 0.26.0 - giterr_set_str@Base 0.26.0 diff -Nru libgit2-0.28.5+dfsg.1/debian/libgit2-fixtures.examples libgit2-1.1.0+dfsg.1/debian/libgit2-fixtures.examples --- libgit2-0.28.5+dfsg.1/debian/libgit2-fixtures.examples 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/libgit2-fixtures.examples 2020-12-27 04:34:39.000000000 +0000 @@ -0,0 +1 @@ +tests/resources/* diff -Nru libgit2-0.28.5+dfsg.1/debian/patches/disable-online-tests.patch libgit2-1.1.0+dfsg.1/debian/patches/disable-online-tests.patch --- libgit2-0.28.5+dfsg.1/debian/patches/disable-online-tests.patch 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/patches/disable-online-tests.patch 2020-12-06 22:35:33.000000000 +0000 @@ -2,13 +2,15 @@ --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt -@@ -57,9 +57,4 @@ IF (MSVC_IDE) - SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h") - ENDIF () +@@ -60,11 +60,4 @@ + ENDIF() + ENDFUNCTION(ADD_CLAR_TEST) --ADD_TEST(offline "${libgit2_BINARY_DIR}/libgit2_clar" -v -xonline) - ADD_TEST(invasive "${libgit2_BINARY_DIR}/libgit2_clar" -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root) --ADD_TEST(online "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline) --ADD_TEST(gitdaemon "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push) --ADD_TEST(ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths) --ADD_TEST(proxy "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request) +-ADD_CLAR_TEST(offline -v -xonline) + ADD_CLAR_TEST(invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root) +-ADD_CLAR_TEST(online -v -sonline) +-ADD_CLAR_TEST(gitdaemon -v -sonline::push) +-ADD_CLAR_TEST(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh) +-ADD_CLAR_TEST(proxy -v -sonline::clone::proxy) +-ADD_CLAR_TEST(auth_clone -v -sonline::clone::cred) +-ADD_CLAR_TEST(auth_clone_and_push -v -sonline::clone::push -sonline::push) diff -Nru libgit2-0.28.5+dfsg.1/debian/patches/enable-repro-builds.patch libgit2-1.1.0+dfsg.1/debian/patches/enable-repro-builds.patch --- libgit2-0.28.5+dfsg.1/debian/patches/enable-repro-builds.patch 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/patches/enable-repro-builds.patch 2020-12-06 22:39:10.000000000 +0000 @@ -0,0 +1,19 @@ +Description: Enable reproducible builds by default. +Author: Utkarsh Gupta + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -188,6 +188,13 @@ + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") + SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}") + SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}") ++ ++ # Enable reproducible builds by default ++ SET(CMAKE_C_FLAGS "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=. ${CMAKE_C_FLAGS}") ++ SET(CMAKE_C_ARCHIVE_CREATE " Dqc ") ++ SET(CMAKE_C_ARCHIVE_APPEND " Dq ") ++ SET(CMAKE_C_ARCHIVE_FINISH " -D ") ++ + ELSE () + IF (ENABLE_REPRODUCIBLE_BUILDS) + SET(CMAKE_C_ARCHIVE_CREATE " Dqc ") diff -Nru libgit2-0.28.5+dfsg.1/debian/patches/series libgit2-1.1.0+dfsg.1/debian/patches/series --- libgit2-0.28.5+dfsg.1/debian/patches/series 2020-04-10 17:30:59.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/patches/series 2020-12-06 22:46:54.000000000 +0000 @@ -1 +1,2 @@ disable-online-tests.patch +enable-repro-builds.patch diff -Nru libgit2-0.28.5+dfsg.1/debian/rules libgit2-1.1.0+dfsg.1/debian/rules --- libgit2-0.28.5+dfsg.1/debian/rules 2020-04-10 17:31:08.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/rules 2020-12-06 22:35:33.000000000 +0000 @@ -24,6 +24,9 @@ -DUSE_GSSAPI:BOOL=ON \ -DTHREADSAFE:BOOL=ON \ -DBUILD_CLAR:BOOL=ON \ + -DUSE_NTLMCLIENT=OFF \ + -DENABLE_REPRODUCIBLE_BUILDS=ON \ + -DUSE_HTTP_PARSER=system \ -DLIB_INSTALL_DIR:STRING=lib/$(DEB_HOST_MULTIARCH) dh_auto_configure --builddirectory=build-debian-devel -- \ @@ -35,6 +38,9 @@ -DUSE_GSSAPI:BOOL=ON \ -DBUILD_CLAR:BOOL=OFF \ -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DUSE_NTLMCLIENT=OFF \ + -DENABLE_REPRODUCIBLE_BUILDS=ON \ + -DUSE_HTTP_PARSER=system \ -DLIB_INSTALL_DIR:STRING=lib/$(DEB_HOST_MULTIARCH) @@ -55,9 +61,6 @@ mkdir -p build-debian-devel/tmp dh_auto_test --builddirectory=build-debian-devel -override_dh_strip: - dh_strip --dbgsym-migration='libgit2-dbg (<< 0.26.0+dfsg.1-1~)' - override_dh_installexamples: dh_installexamples --exclude .gitignore diff -Nru libgit2-0.28.5+dfsg.1/debian/upstream/metadata libgit2-1.1.0+dfsg.1/debian/upstream/metadata --- libgit2-0.28.5+dfsg.1/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/debian/upstream/metadata 2020-12-06 22:35:33.000000000 +0000 @@ -0,0 +1,5 @@ +--- +Bug-Database: https://github.com/libgit2/libgit2/issues +Bug-Submit: https://github.com/libgit2/libgit2/issues/new +Repository: https://github.com/libgit2/libgit2.git +Repository-Browse: https://github.com/libgit2/libgit2 diff -Nru libgit2-0.28.5+dfsg.1/docs/changelog.md libgit2-1.1.0+dfsg.1/docs/changelog.md --- libgit2-0.28.5+dfsg.1/docs/changelog.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/docs/changelog.md 2020-10-12 18:53:06.000000000 +0000 @@ -1,57 +1,431 @@ -v0.28.5 -------- +v1.1 +---- + +This is release v1.1, "Fernweh". + +### Changes or improvements + +* Our bundled PCRE dependency has been updated to 8.44. + +* The `refs/remotes/origin/HEAD` file will be created at clone time to + point to the origin's default branch. + +* libgit2 now uses the `__atomic_` intrinsics instead of `__sync_` + intrinsics on supported gcc and clang versions. + +* The `init.defaultBranch` setting is now respected and `master` is + no longer the hardcoded as the default branch name. + +* Patch files that do not contain an `index` line can now be parsed. + +* Configuration files with multi-line values can now contain quotes + split across multiple lines. + +* Windows clients now attempt to use TLS1.3 when available. + +* Servers that request an upgrade to a newer HTTP version are + silently ignored instead of erroneously failing. + +* Users can pass `NULL` to the options argument to + `git_describe_commit`. + +* Clones and fetches of very large packfiles now succeeds on 32-bit + platforms. + +* Custom reference database backends can now handle the repository's + `HEAD` correctly. + +* Repositories with a large number of packfiles no longer exhaust the + number of file descriptors. + +* The test framework now supports TAP output when the `-t` flag is + specified. + +* The test framework can now specify an exact match to a test + function using a trailing `$`. + +* All checkout types support `GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH`. + +* `git_blame` now can ignore whitespace changes using the option + `GIT_BLAME_IGNORE_WHITESPACE`. + +* Several new examples have been created, including an examples for + commit, add and push. + +* Mode changes during rename are now supported in patch application. + +* `git_checkout_head` now correctly removes untracked files in a + subdirectory when the `FORCE | REMOVE_UNTRACKED` options are specified. + +v1.0.1 +------ This is a bugfix release with the following changes: -- Fix an out-of-bounds read when applying patches that do not end - with a newline. +- Calculating information about renamed files during merges is more + efficient because dissimilarity about files is now being cached and + no longer needs to be recomputed. + +- The `git_worktree_prune_init_options` has been correctly restored for + backward compatibility. In v1.0 it was incorrectly deprecated with a + typo. + +- The optional ntlmclient dependency now supports NetBSD. + +- A bug where attempting to stash on a bare repository may have failed + has been fixed. + +- Configuration files that are unreadable due to permissions are now + silently ignored, and treated as if they do not exist. This matches + git's behavior; previously this case would have been an error. + +- v4 index files are now correctly written; previously we would read + them correctly but would not write the prefix-compression accurately, + causing corruption. -- Fix an out-of-bounds read when decoding specially crafted - binary patches. +- A bug where the smart HTTP transport could not read large data packets + has been fixed. Previously, fetching from servers like Gerrit, that + sent large data packets, would error. -- Fix an out-of-bounds read when receiving a specially crafted - "OK" packet via the smarthttp transport. +v1.0 +---- -- Fix lifetime for parsed patches depending on the lifetime of - the parsed buffe. +This is release v1.0 "Luftschloss", which is the first stabe release of +libgit2. The API will stay compatible across all releases of the same major +version. This release includes bugfixes only and supersedes v0.99, which will +stop being maintained. Both v0.27 and v0.28 stay supported in accordance with +our release policy. -- Several fixes when parsing and applying patches. +### Changes or improvements -- Fix computed patch IDs for patches that have no newline at end - of file. +- CMake was converted to make use of the GNUInstallDirs module for both our + pkgconfig and install targets in favor of our custom build options + `BIN_INSTALL_DIR`, `LIB_INSTALL_DIR` and `INCLUDE_INSTALL_DIR`. Instead, you + can now use CMakes standard variables `CMAKE_INSTALL_BINDIR`, + `CMAKE_INSTALL_LIBDIR` and `CMAKE_INSTALL_INCLUDEDIR`. -- Fix applying patches to trees that add new files. +- Some CMake build options accepted either a specific value or a boolean value + to disable the option altogether or use automatic detection. We only accepted + "ON" or "OFF", but none of the other values CMake recognizes as boolean. This + was aligned with CMake's understanding of booleans. -- Do not read configuration from a user's home directory if - running in a sandboxed environment. +- The installed pkgconfig file contained incorrect values for both `libdir` and + `includedir` variables. -- Fix handling of nested ignore rules overriding wildcard - unignores in parent directories. +- If using pcre2 for regular expressions, then we incorrectly added "pcre2" + instead of "pcre2-8" to our pkgconfig dependencies, which was corrected. -- Fix reference locks not being correctly honored on Unix - systems. +- Fixed building the bundled ntlmclient dependency on FreeBSD, OpenBSD and + SunOS. -- Follow 308 redirects when fetching or pushing from remote - repositories on Windows. +- When writing symlinks on Windows, we incorrectly handled relative symlink + targets, which was corrected. -- Fix a race when detaching the libgit2 library on Windows. +- When using the HTTP protocol via macOS' SecureTransport implementation, reads + could stall at the end of the session and only continue after a timeout of 60 + seconds was reached. -- Update the "binary" gitattribute macro to match git's change - to "-diff -merge -text -crlf". +- The filesystem-based reference callback didn't corectly initialize the backend + version. -- Refuse to delete the HEAD reference. +- A segmentation fault was fixed when calling `git_blame_buffer()` for files + that were modified and added to the index. -- Fixes for several memory leaks. +- A backwards-incompatible change was introduced when we moved some structures + from "git2/credentials.h" into "git2/sys/credentials.h". This was fixed in the + case where you do not use hard deprecation. -- When fetching from an anonymous remote using a URL with authentication +- Improved error handling in various places. + + +v0.99 +----- + +This is v0.99 "Torschlusspanik". This will be the last minor release +before libgit2 v1.0. We expect to only respond to bugs in this release, +to stabilize it for next major release. + +It contains significant refactorings, but is expected to be API-compatible +with v0.28.0. + +### Changes or improvements + +* When fetching from an anonymous remote using a URL with authentication information provided in the URL (eg `https://foo:bar@example.com/repo`), we would erroneously include the literal URL in the FETCH_HEAD file. We now remove that to match git's behavior. -v0.28.4 --------- +* Some credential structures, enums and values have been renamed: + `git_cred` is now `git_credential`. `git_credtype_t` is now + `git_credential_t`. Functions and types beginning with + `git_cred_` now begin with `git_credential`, and constants beginning + with `GIT_CREDTYPE` now begin with `GIT_CREDENTIAL`. The former names + are deprecated. + +* Several function signatures have been changed to return an `int` to + indicate error conditions. We encourage you to check them for errors + in the standard way. + + * `git_attr_cache_flush` + * `git_error_set_str` + * `git_index_name_clear` + * `git_index_reuc_clear` + * `git_libgit2_version` + * `git_mempack_reset` + * `git_oid_cpy` + * `git_oid_fmt` + * `git_oid_fromraw` + * `git_oid_nfmt` + * `git_oid_pathfmt` + * `git_remote_stop` + * `git_remote_disconnect` + * `git_repository__cleanup` + * `git_repository_set_config` + * `git_repository_set_index` + * `git_repository_set_odb` + * `git_repository_set_refdb` + * `git_revwalk_reset` + * `git_revwalk_simplify_first_parent` + * `git_revwalk_sorting` + * `git_treebuilder_clear` + * `git_treebuilder_filter` + +* The NTLM and Negotiate authentication mechanisms are now supported when + talking to git implementations hosted on Apache or nginx servers. + +* The `HEAD` symbolic reference can no longer be deleted. + +* `git_merge_driver_source_repo` no longer returns a `const git_repository *`, + it now returns a non-`const` `git_repository *`. + +* Relative symbolic links are now supported on Windows when `core.symlinks` + is enabled. + +* Servers that provide query parameters with a redirect are now supported. + +* `git_submodule_sync` will now resolve relative URLs. + +* When creating git endpoint URLs, double-slashes are no longer used when + the given git URL has a trailing slash. + +* On Windows, a `DllMain` function is no longer included and thread-local + storage has moved to fiber-local storage in order to prevent race + conditions during shutdown. + +* The tracing mechanism (`GIT_TRACE`) is now enabled by default and does + not need to be explicitly enabled in CMake. + +* The size of Git objects is now represented by `git_object_size_t` + instead of `off_t`. + +* Binary patches without data can now be parsed. + +* A configuration snapshot can now be created from another configuration + snapshot, not just a "true" configuration object. + +* The `git_commit_with_signature` API will now ensure that referenced + objects exist in the object database. + +* Stash messages containing newlines will now be replaced with spaces; + they will no longer be (erroneously) written to the repository. + +* `git_commit_create_with_signature` now verifies the commit information + to ensure that it points to a valid tree and valid parents. + +* `git_apply` has an option `GIT_APPLY_CHECK` that will only do a dry-run. + The index and working directory will remain unmodified, and application + will report if it would have worked. + +* Patches produced by Mercurial (those that lack some git extended headers) + can now be parsed and applied. + +* Reference locks are obeyed correctly on POSIX platforms, instead of + being removed. + +* Patches with empty new files can now be read and applied. + +* `git_apply_to_tree` can now correctly apply patches that add new files. + +* The program data configuration on Windows (`C:\ProgramData\Git\config`) + must be owned by an administrator, a system account or the current user + to be read. + +* `git_blob_filtered_content` is now deprecated in favor of `git_blob_filter`. + +* Configuration files can now be included conditionally using the + `onbranch` conditional. + +* Checkout can now properly create and remove symbolic links to directories + on Windows. + +* Stash no longer recomputes trees when committing a worktree, for + improved performance. + +* Repository templates can now include a `HEAD` file to default the + initial default branch. + +* Some configuration structures, enums and values have been renamed: + `git_cvar_map` is now `git_configmap`, `git_cvar_t` is now + `git_configmap_t`, `GIT_CVAR_FALSE` is now `GIT_CONFIGMAP_FALSE`, + `GIT_CVAR_TRUE` is now `GIT_CONFIGMAP_TRUE`, `GIT_CVAR_INT32` is now + `GIT_CONFIGMAP_INT32`, and `GIT_CVAR_STRING` is now `GIT_CONFIGMAP_STRING`. + The former names are deprecated. + +* Repositories can now be created at the root of a Windows drive. + +* Configuration lookups are now more efficiently cached. + +* `git_commit_create_with_signature` now supports a `NULL` signature, + which will create a commit without adding a signature. + +* When a repository lacks an `info` "common directory", we will no + longer erroneously return `GIT_ENOTFOUND` for all attribute lookups. + +* Several attribute macros have been renamed: `GIT_ATTR_TRUE` is now + `GIT_ATTR_IS_TRUE`, `GIT_ATTR_FALSE` is now `GIT_ATTR_IS_FALSE`, + `GIT_ATTR_UNSPECIFIED` is now `GIT_ATTR_IS_UNSPECIFIED`. The + attribute enum `git_attr_t` is now `git_attr_value_t` and its + values have been renamed: `GIT_ATTR_UNSPECIFIED_T` is now + `GIT_ATTR_VALUE_UNSPECIFIED`, `GIT_ATTR_TRUE_T` is now + `GIT_ATTR_VALUE_TRUE`, `GIT_ATTR_FALSE_T` is now `GIT_ATTR_VALUE_FALSE`, + and `GIT_ATTR_VALUE_T` is now `GIT_ATTR_VALUE_STRING`. The + former names are deprecated. + +* `git_object__size` is now `git_object_size`. The former name is + deprecated. -This is a security release fixing the following issues: +* `git_tag_create_frombuffer` is now `git_tag_create_from_buffer`. The + former name is deprecated. + +* Several blob creation functions have been renamed: + `git_blob_create_frombuffer` is now named `git_blob_create_from_buffer`, + `git_blob_create_fromdisk` is now named `git_blob_create_from_disk`, + `git_blob_create_fromworkdir` is now named `git_blob_create_from_workdir`, + `git_blob_create_fromstream` is now named `git_blob_create_from_stream`, + and `git_blob_create_fromstream_commit` is now named + `git_blob_create_from_stream_commit`. The former names are deprecated. + +* The function `git_oid_iszero` is now named `git_oid_is_zero`. The + former name is deprecated. + +* Pattern matching is now done using `wildmatch` instead of `fnmatch` + for compatibility with git. + +* The option initialization functions suffixed by `init_options` are now + suffixed with `options_init`. (For example, `git_checkout_init_options` + is now `git_checkout_options_init`.) The former names are deprecated. + +* NTLM2 authentication is now supported on non-Windows platforms. + +* The `git_cred_sign_callback` callback is now named `git_cred_sign_cb`. + The `git_cred_ssh_interactive_callback` callback is now named + `git_cred_ssh_interactive_cb`. + +* Ignore files now: + + * honor escaped trailing whitespace. + * do not incorrectly negate sibling paths of a negated pattern. + * honor rules that stop ignoring files after a wildcard + +* Attribute files now: + + * honor leading and trailing whitespace. + * treat paths beginning with `\` as absolute only on Windows. + * properly handle escaped characters. + * stop reading macros defined in subdirectories + +* The C locale is now correctly used when parsing regular expressions. + +* The system PCRE2 or PCRE regular expression libraries are now used + when `regcomp_l` is not available on the system. If none of these + are available on the system, an included version of PCRE is used. + +* Wildcards in reference specifications are now supported beyond simply + a bare wildcard (`*`) for compatibility with git. + +* When `git_ignore_path_is_ignored` is provided a path with a trailing + slash (eg, `dir/`), it will now treat it as a directory for the + purposes of ignore matching. + +* Patches that add or remove a file with a space in the path can now + be correctly parsed. + +* The `git_remote_completion_type` type is now `git_remote_completion_t`. + The former name is deprecated. + +* The `git_odb_backend_malloc` is now `git_odb_backend_data_alloc`. The + former name is deprecated. + +* The `git_transfer_progress_cb` callback is now `git_indexer_progress_cb` + and the `git_transfer_progress` structure is now `git_indexer_progress`. + The former names are deprecated. + +* The example projects are now contained in a single `lg2` executable + for ease of use. + +* libgit2 now correctly handles more URLs, such as + `http://example.com:/repo.git` (colon but no port), + `http://example.com` (no path), + and `http://example.com:8080/` (path is /, nonstandard port). + +* A carefully constructed commit object with a very large number + of parents may lead to potential out-of-bounds writes or + potential denial of service. + +* The ProgramData configuration file is always read for compatibility + with Git for Windows and Portable Git installations. The ProgramData + location is not necessarily writable only by administrators, so we + now ensure that the configuration file is owned by the administrator + or the current user. + +### API additions + +* The SSH host key now supports SHA-256 when `GIT_CERT_SSH_SHA256` is set. + +* The diff format option `GIT_DIFF_FORMAT_PATCH_ID` can now be used to + emit an output like `git patch-id`. + +* The `git_apply_options_init` function will initialize a + `git_apply_options` structure. + +* The remote callbacks structure adds a `git_url_resolve_cb` callback + that is invoked when connecting to a server, so that applications + may edit or replace the URL before connection. + +* The information about the original `HEAD` in a rebase operation is + available with `git_rebase_orig_head_name`. Its ID is available with + `git_rebase_orig_head_id`. The `onto` reference name is available with + `git_rebase_onto_name` and its ID is available with `git_rebase_onto_id`. + +* ODB backends can now free backend data when an error occurs during its + backend data creation using `git_odb_backend_data_free`. + +* Options may be specified to `git_repository_foreach_head` to control + its behavior: `GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO` will not skip + the main repository's HEAD reference, while + `GIT_REPOSITORY_FOREACH_HEAD_SKIP_WORKTREES` will now skip the + worktree HEAD references. + +* The `GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS` option can be specified to + `git_libgit2_opts()` to avoid looking for `.keep` files that correspond + to packfiles. This setting can improve performance when packfiles are + stored on high-latency filesystems like network filesystems. + +* Blobs can now be filtered with `git_blob_filter`, which allows for + options to be set with `git_blob_filter_options`, including + `GIT_FILTER_NO_SYSTEM_ATTRIBUTES` to disable filtering with system-level + attributes in `/etc/gitattributes` and `GIT_ATTR_CHECK_INCLUDE_HEAD` to + enable filtering with `.gitattributes` files in the HEAD revision. + +### API removals + +* The unused `git_headlist_cb` function declaration was removed. + +* The unused `git_time_monotonic` API is removed. + +* The erroneously exported `inttypes.h` header was removed. + +# Security Fixes - CVE-2019-1348: the fast-import stream command "feature export-marks=path" allows writing to arbitrary file paths. As @@ -108,54 +482,86 @@ recursive submodule clones manually are encouraged to review their implementation for this vulnerability. -v0.28.3 -------- - -This is a security release fixing the following issues: - -* A carefully constructed commit object with a very large number - of parents may lead to potential out-of-bounds writes or - potential denial of service. - -* The ProgramData configuration file is always read for compatibility - with Git for Windows and Portable Git installations. The ProgramData - location is not necessarily writable only by administrators, so we - now ensure that the configuration file is owned by the administrator - or the current user. - -v0.28.2 -------- - -This is a bugfix release with the following changes: - -* Fix include directory ordering when using bundled dependencies. - -* Fix infinite loop when searching for a non-existing repository with - Windows-style paths including drive prefixes. - -* Fix paths with a trailing "/" not always being treated as - directories when computing ignores. - -* Fix false negatives when computing ignores where ignore rules - that are a prefix to a negative ignore rule exist. - -* Fix patches with CRLF line endings not being parsed correctly. - -* Fix segfault when parsing patches with file addition (deletion) - where the added (deleted) file name contains a space. - -* Fix assertion failure when trying to write to a non-existent - locked configuration file. - -v0.28.1 -------- - -This is a bugfix release with the following change: +### Breaking API changes -* The deprecated functions (`git_buf_free` and the `giterr_` family of - functions) are now exported properly. In the v0.28 release, they were - not given the correct external attributes and they did not have the - correct linkage visibility in the v0.28 library. +* The "private" implementation details of the `git_cred` structure have been + moved to a dedicated `git2/sys/cred.h` header, to clarify that the underlying + structures are only provided for custom transport implementers. + The breaking change is that the `username` member of the underlying struct + is now hidden, and a new `git_cred_get_username` function has been provided. + +### Breaking CMake configuration changes + +* The CMake option to use a system http-parser library, instead of the + bundled dependency, has changed. This is due to a deficiency in + http-parser that we have fixed in our implementation. The bundled + library is now the default, but if you wish to force the use of the + system http-parser implementation despite incompatibilities, you can + specify `-DUSE_HTTP_PARSER=system` to CMake. + +* The interactions between `USE_HTTPS` and `SHA1_BACKEND` have been + streamlined. The detection was moved to a new `USE_SHA1`, modeled after + `USE_HTTPS`, which takes the values "CollisionDetection/Backend/Generic", to + better match how the "hashing backend" is selected, the default (ON) being + "CollisionDetection". If you were using `SHA1_BACKEND` previously, you'll + need to check the value you've used, or switch to the autodetection. + +### Authors + +The following individuals provided changes that were included in this +release: + +* Aaron Patterson +* Alberto Fanjul +* Anders Borum +* Augie Fackler +* Augustin Fabre +* Ayush Shridhar +* brian m. carlson +* buddyspike +* Carlos Martín Nieto +* cheese1 +* Dan Skorupski +* Daniel Cohen Gindi +* Dave Lee +* David Brooks +* David Turner +* Denis Laxalde +* Dhruva Krishnamurthy +* Dominik Ritter +* Drew DeVault +* Edward Thomson +* Eric Huss +* Erik Aigner +* Etienne Samson +* Gregory Herrero +* Heiko Voigt +* Ian Hattendorf +* Jacques Germishuys +* Janardhan Pulivarthi +* Jason Haslam +* Johannes Schindelin +* Jordan Wallet +* Josh Bleecher Snyder +* kas +* kdj0c +* Laurence McGlashan +* lhchavez +* Lukas Berk +* Max Kostyukevich +* Patrick Steinhardt +* pcpthm +* Remy Suen +* Robert Coup +* romkatv +* Scott Furry +* Sebastian Henke +* Stefan Widgren +* Steve King Jr +* Sven Strickroth +* Tobias Nießen +* Tyler Ang-Wanek +* Tyler Wanek v0.28 ----- diff -Nru libgit2-0.28.5+dfsg.1/docs/coding-style.md libgit2-1.1.0+dfsg.1/docs/coding-style.md --- libgit2-0.28.5+dfsg.1/docs/coding-style.md 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/docs/coding-style.md 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,364 @@ +# libgit2 Coding Style + +This documentation describes the preferred coding style for the libgit2 project. +While not all parts of our code base conform to this coding style, the outlined +rules are what we aim for. + +Note that in no case do we accept changes that convert huge parts of the code +base to use our coding style. Instead, it is encouraged to modernize small parts +of code you're going to modify anyway for a given change you want to introduce. +A good rule to follow is the Boy Scout Rule: "Leave the campground cleaner than +you found it." + +## C Coding Style + +The following sections define the coding style for all code files and headers. + +### Indentation and Alignment + +Code is indented by tabs, where a tab is 8 spaces. Each opening scope increases +the indentation level. + +```c +int foobar(int void) +{ + if (condition) + doit(); + /* Body */ +} +``` + +Switch statements have their `case`s aligned with the `switch` keyword. Case +bodies are indented by an additional level. Case bodies should not open their +own scope to declare variables. + +```c +switch (c) { +case 'a': +case 'b': + return 0; +default: + return -1; +} +``` + +Multi-line conditions should be aligned with the opening brace of the current +statement: + +```c +if (one_very_long_condition(c) && + another_very_long_condition(c)) + doit(); +``` + +### Spaces + +There must be no space between the function and its arguments, arguments must be +separated by a space: + +```c +int doit(int first_arg, int second_arg); +doit(1, 2); +``` + +For any binary or ternary operators, the arguments and separator must be +separated by a space: + +```c +1 + 2; +x ? x : NULL; +``` + +Unary operators do not have a space between them and the argument they refer to: + +```c +*c +&c +``` + +The `sizeof` operator always must not have a space and must use braces around +the type: + +``` +sizeof(int) +``` + +There must be a space after the keywords `if`, `switch`, `case`, `do` and +`while`. + +### Braces + +Functions must have their opening brace on the following line: + +```c +void foobar(void) +{ + doit(); +} +``` + +For conditions, braces should be placed on the same line as the condition: + +```c +if (condition(c)) { + doit(); + dothat(); +} + +while (true) { + doit(); +} +``` + +In case a condition's body has a single line, only, it's allowed to omit braces, +except if any of its `else if` or `else` branches has more than one line: + +```c +if (condition(c)) + doit(); + +if (condition(c)) + doit(); +else if (other_condition(c)) + doit(); + +/* This example must use braces as the `else if` requires them. */ +if (condition(c)) { + doit(); +} else if (other_condition(c)) { + doit(); + dothat(); +} else { + abort(); +} +``` + +### Comments + +Comments must use C-style `/* */` comments. C++-style `// `comments are not +allowed in our codebase. This is a strict requirement as libgit2 tries to be +compliant with the ISO C90 standard, which only allows C-style comments. + +Single-line comments may have their opening and closing tag on the same line: + +```c +/* This is a short comment. */ +``` + +For multi-line comments, the opening and closing tag should be empty: + +```c +/* + * This is a rather long and potentially really unwiedly but informative + * multiline comment that helps quite a lot. + */ +``` + +Public functions must have documentation that explain their usage, internal +functions should have a comment. We use Docurium to generate documentation +derived from these comments, which uses syntax similar to Doxygen. The first +line should be a short summary of what the function does. More in-depth +explanation should be separated from that first line by an empty line. +Parameters and return values should be documented via `@return` and `@param` +tags: + +```c +/* + * Froznicate the string. + * + * Froznicate the string by foobaring its internal structure into a more obvious + * translation. Note that the returned string is a newly allocated string that + * shall be `free`d by the caller. + * + * @param s String to froznicate + * @return A newly allocated string or `NULL` in case an error occurred. + * / +char *froznicate(const char *s); +``` + +### Variables + +Variables must be declared at the beginning of their scope. This is a strict +requirement as libgit2 tries to be compliant with the ISO C90 standard, which +forbids mixed declarations and code: + +```c +void foobar(void) +{ + char *c = NULL; + int a, b; + + a = 0; + b = 1; + + return c; +} +``` + +### Naming + +Variables must have all-lowercase names. In case a variable name has multiple +words, words should be separated by an underscore `_` character. While +recommended to use descriptive naming, common variable names like `i` for +indices are allowed. + +All public functions must have a `git` prefix as well as a prefix indicating +their respective subsystem. E.g. a function that opens a repository should be +called `git_repository_open()`. Functions that are not public but declared in +an internal header file for use by other subsystems should follow the same +naming pattern. File-local static functions must not have a `git` prefix, but +should have a prefix indicating their respective subsystem. + +All structures declared in the libgit2 project must have a `typedef`, we do not +use `struct type` variables. Type names follow the same schema as functions. + +### Error Handling + +The libgit2 project mostly uses error codes to indicate errors. Error codes are +always of type `int`, where `0` indicates success and a negative error code +indicates an error case. In some cases, positive error codes may be used to +indicate special cases. Returned values that are not an error code should be +returned via an out parameter. Out parameters must always come first in the list +of arguments. + +```c +int doit(const char **out, int arg) +{ + if (!arg) + return -1; + *out = "Got an argument"; + return 0; +} +``` + +To avoid repetitive and fragile error handling in case a function has resources +that need to be free'd, we use `goto out`s: + +```c +int doit(char **out, int arg) +{ + int error = 0; + char *c; + + c = malloc(strlen("Got an argument") + 1); + if (!c) { + error = -1; + goto out; + } + + if (!arg) { + error = -1; + goto out; + } + + strcpy(c, "Got an argument") + *out = c; + +out: + if (error) + free(c); + return error; +} +``` + +When calling functions that return an error code, you should assign the error +code to an `error` variable and, in case an error case is indicated and no +custom error handling is required, return that error code: + +```c +int foobar(void) +{ + int error; + + if ((error = doit()) < 0) + return error; + + return 0; +} +``` + +When doing multiple function calls where all of the functions return an error +code, it's common practice to chain these calls together: + +```c +int doit(void) +{ + int error; + + if ((error = dothis()) < 0 || + (error = dothat()) < 0) + return error; + + return 0; +} +``` + +## CMake Coding Style + +The following section defines the coding style for our CMake build system. + +### Indentation + +Code is indented by tabs, where a tab is 8 spaces. Each opening scope increases +the indentation level. + +```cmake +if(CONDITION) + doit() +endif() +``` + +### Spaces + +There must be no space between keywords and their opening brace. While this is +the same as in our C codebase for function calls, this also applies to +conditional keywords. This is done to avoid the awkward-looking `else ()` +statement. + +```cmake +if(CONDITION) + doit() +else() + dothat() +endif() +``` + +### Case + +While CMake is completely case-insensitive when it comes to function calls, we +want to agree on a common coding style for this. To reduce the danger of +repetitive strain injuries, all function calls should be lower-case (NB: this is +not currently the case yet, but introduced as a new coding style by this +document). + +Variables are written all-uppercase. In contrast to functions, variables are +case-sensitive in CMake. As CMake itself uses upper-case variables in all +places, we should follow suit and do the same. + +Control flow keywords must be all lowercase. In contrast to that, test keywords +must be all uppercase: + +```cmake +if(NOT CONDITION) + doit() +elseif(FOO AND BAR) + dothat() +endif() +``` + +### Targets + +CMake code should not use functions that modify the global scope but prefer +their targeted equivalents, instead. E.g. instead of using +`include_directories()`, you must use `target_include_directories()`. An +exception to this rule is setting up global compiler flags like warnings or +flags required to set up the build type. + +### Dependencies + +Dependencies should not be discovered or set up in the main "CMakeLists.txt" +module. Instead, they should either have their own module in our top-level +"cmake/" directory or have a "CMakeLists.txt" in their respective "deps/" +directory in case it is a vendored library. All dependencies should expose +interface library targets that can be linked against with +`target_link_libraries()`. diff -Nru libgit2-0.28.5+dfsg.1/docs/fuzzing.md libgit2-1.1.0+dfsg.1/docs/fuzzing.md --- libgit2-0.28.5+dfsg.1/docs/fuzzing.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/docs/fuzzing.md 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ libgit2 is currently using [libFuzzer](https://libfuzzer.info) to perform automated fuzz testing. libFuzzer only works with clang. -## Prerequisites** for building fuzz targets: +## Prerequisites for building fuzz targets: 1. All the prerequisites for [building libgit2](https://github.com/libgit2/libgit2). 2. A recent version of clang. 6.0 is preferred. [pre-build Debian/Ubuntu @@ -27,14 +27,15 @@ ## Run the fuzz targets -1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize-6.0 +1. `ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolize LSAN_OPTIONS=allocator_may_return_null=1 - ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzz/fuzz_packfile_raw - fuzz/corpora/fuzz_packfile_raw/` + ASAN_OPTIONS=allocator_may_return_null=1 ./build/fuzzers/packfile_fuzzer + fuzzers/corpora/packfile/` The `LSAN_OPTIONS` and `ASAN_OPTIONS` are there to allow `malloc(3)` to return -`NULL`. The `LLVM_PROFILE_FILE` is there to override the path where libFuzzer -will write the coverage report. +`NULL`, which is expected if a huge chunk of memory is allocated. The +`LLVM_PROFILE_FILE` environment string can also be added to override the path +where libFuzzer will write the coverage report. ## Get coverage diff -Nru libgit2-0.28.5+dfsg.1/docs/release.md libgit2-1.1.0+dfsg.1/docs/release.md --- libgit2-0.28.5+dfsg.1/docs/release.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/docs/release.md 2020-10-12 18:53:06.000000000 +0000 @@ -68,7 +68,7 @@ This is the same as a maintenance release, except that the fix itself will most likely be developed in a private repository and will only be visible to a select group of people until the release. -Everything else remains the same. Occasionally we might opt to backport a security fix to the previous series, based on how recently we started the new series and how serious the issue is. +We have committed to providing security fixes for the latest two released versions. E.g. if the latest version is v0.28.x, then we will provide security fixes for both v0.28.x and v0.27.y. ## Updating documentation diff -Nru libgit2-0.28.5+dfsg.1/docs/threading.md libgit2-1.1.0+dfsg.1/docs/threading.md --- libgit2-0.28.5+dfsg.1/docs/threading.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/docs/threading.md 2020-10-12 18:53:06.000000000 +0000 @@ -1,8 +1,10 @@ -Threads in libgit2 +Threading in libgit2 ================== -You may safely use any libgit2 object from any thread, though there -may be issues depending on the cryptographic libraries libgit2 or its +Unless otherwise specified, libgit2 objects cannot be safely accessed by +multiple threads simultaneously. + +There are also caveats on the cryptographic libraries libgit2 or its dependencies link to (more on this later). For libgit2 itself, provided you take the following into consideration you won't run into issues: @@ -26,11 +28,11 @@ happen on the same thread as the error in order to get the message. Often this will be the case regardless, but if you use something like the [GCD](http://en.wikipedia.org/wiki/Grand_Central_Dispatch) -on Mac OS X (where code is executed on an arbitrary thread), the code +on macOS (where code is executed on an arbitrary thread), the code must make sure to retrieve the error code on the thread where the error happened. -Threads and cryptographic libraries +Threading and cryptographic libraries ======================================= On Windows @@ -44,17 +46,11 @@ libssh2 uses OpenSSL or libgcrypt, then the general case affects you. -On Mac OS X +On macOS ----------- -By default we use libcurl to perform the encryption. The -system-provided libcurl uses SecureTransport, so no special steps are -necessary. If you link against another libcurl (e.g. from homebrew) -refer to the general case. - -If the option to use libcurl was deactivated, the library makes use of -CommonCrypto and SecureTransport for cryptographic support. These are -thread-safe and you do not need to do anything special. +By default we make use of CommonCrypto and SecureTransport for cryptographic +support. These are thread-safe and you do not need to do anything special. Note that libssh2 may still use OpenSSL itself. In that case, the general case still affects you if you use ssh. @@ -62,15 +58,11 @@ General Case ------------ -If it's available, by default we use libcurl to provide HTTP tunneling support, -which may be linked against a number of cryptographic libraries and has its -own -[recommendations for thread safety](https://curl.haxx.se/libcurl/c/threadsafe.html). - -If there are no alternative TLS implementations (currently only -SecureTransport), libgit2 uses OpenSSL in order to use HTTPS as a transport. -OpenSSL is thread-safe starting at version 1.1.0. If your copy of libgit2 is -linked against that version, you do not need to take any further steps. +libgit2 will default to OpenSSL for HTTPS transport (except on Windows and +macOS, as mentioned above). On any system, mbedTLS _may_ be optionally +enabled as the security provider. OpenSSL is thread-safe starting at +version 1.1.0. If your copy of libgit2 is linked against that version, +you do not need to take any further steps. Older versions of OpenSSL are made to be thread-implementation agnostic, and the users of the library must set which locking function it should use. libgit2 @@ -78,10 +70,10 @@ the locking settings must then live outside the lifetime of libgit2. Even if libgit2 doesn't use OpenSSL directly, OpenSSL can still be used by -libssh2 or libcurl depending on the configuration. If OpenSSL is used by +libssh2 depending on the configuration. If OpenSSL is used by more than one library, you only need to set up threading for OpenSSL once. -If libgit2 is linked against OpenSSL, it provides a last-resort convenience function +If libgit2 is linked against OpenSSL < 1.1.0, it provides a last-resort convenience function `git_openssl_set_locking()` (available in `sys/openssl.h`) to use the platform-native mutex mechanisms to perform the locking, which you can use if you do not want to use OpenSSL outside of libgit2, or you @@ -89,7 +81,7 @@ safe to use OpenSSL multi-threaded after libgit2's shutdown function has been called. Note `git_openssl_set_locking()` only works if libgit2 uses OpenSSL directly - if OpenSSL is only used as a dependency -of libssh2 or libcurl as described above, `git_openssl_set_locking()` is a no-op. +of libssh2 as described above, `git_openssl_set_locking()` is a no-op. If your programming language offers a package/bindings for OpenSSL, you should very strongly prefer to use that in order to set up diff -Nru libgit2-0.28.5+dfsg.1/.editorconfig libgit2-1.1.0+dfsg.1/.editorconfig --- libgit2-0.28.5+dfsg.1/.editorconfig 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/.editorconfig 2020-10-12 18:53:06.000000000 +0000 @@ -1,15 +1,21 @@ ; Check http://editorconfig.org/ for more informations -; Top-most EditorConfig file root = true -; tab indentation [*] indent_style = tab +tab_width = 8 trim_trailing_whitespace = true insert_final_newline = true -; 4-column space indentation +[*.yml] +indent_style = space +indent_size = 2 + [*.md] indent_style = space indent_size = 4 trim_trailing_whitespace = false + +[*.py] +indent_style = space +indent_size = 4 diff -Nru libgit2-0.28.5+dfsg.1/examples/add.c libgit2-1.1.0+dfsg.1/examples/add.c --- libgit2-0.28.5+dfsg.1/examples/add.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/add.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,85 +13,99 @@ */ #include "common.h" -#include -enum print_options { - SKIP = 1, - VERBOSE = 2, - UPDATE = 4, +/** + * The following example demonstrates how to add files with libgit2. + * + * It will use the repository in the current working directory, and act + * on files passed as its parameters. + * + * Recognized options are: + * -v/--verbose: show the file's status after acting on it. + * -n/--dry-run: do not actually change the index. + * -u/--update: update the index instead of adding to it. + */ + +enum index_mode { + INDEX_NONE, + INDEX_ADD, }; -struct print_payload { - enum print_options options; +struct index_options { + int dry_run; + int verbose; git_repository *repo; + enum index_mode mode; + int add_update; }; /* Forward declarations for helpers */ -static void parse_opts(int *options, int *count, int argc, char *argv[]); -void init_array(git_strarray *array, int argc, char **argv); +static void parse_opts(const char **repo_path, struct index_options *opts, struct args_info *args); int print_matched_cb(const char *path, const char *matched_pathspec, void *payload); -int main (int argc, char** argv) +int lg2_add(git_repository *repo, int argc, char **argv) { git_index_matched_path_cb matched_cb = NULL; - git_repository *repo = NULL; git_index *index; git_strarray array = {0}; - int options = 0, count = 0; - struct print_payload payload = {0}; - - git_libgit2_init(); + struct index_options options = {0}; + struct args_info args = ARGS_INFO_INIT; - parse_opts(&options, &count, argc, argv); + options.mode = INDEX_ADD; - init_array(&array, argc-count, argv+count); + /* Parse the options & arguments. */ + parse_opts(NULL, &options, &args); + strarray_from_args(&array, &args); - check_lg2(git_repository_open(&repo, "."), "No git repository", NULL); + /* Grab the repository's index. */ check_lg2(git_repository_index(&index, repo), "Could not open repository index", NULL); - if (options&VERBOSE || options&SKIP) { + /* Setup a callback if the requested options need it */ + if (options.verbose || options.dry_run) { matched_cb = &print_matched_cb; } - payload.options = options; - payload.repo = repo; + options.repo = repo; - if (options&UPDATE) { - git_index_update_all(index, &array, matched_cb, &payload); + /* Perform the requested action with the index and files */ + if (options.add_update) { + git_index_update_all(index, &array, matched_cb, &options); } else { - git_index_add_all(index, &array, 0, matched_cb, &payload); + git_index_add_all(index, &array, 0, matched_cb, &options); } + /* Cleanup memory */ git_index_write(index); git_index_free(index); - git_repository_free(repo); - - git_libgit2_shutdown(); return 0; } +/* + * This callback is called for each file under consideration by + * git_index_(update|add)_all above. + * It makes uses of the callback's ability to abort the action. + */ int print_matched_cb(const char *path, const char *matched_pathspec, void *payload) { - struct print_payload p = *(struct print_payload*)(payload); + struct index_options *opts = (struct index_options *)(payload); int ret; unsigned status; (void)matched_pathspec; - if (git_status_file(&status, p.repo, path)) { + /* Get the file status */ + if (git_status_file(&status, opts->repo, path) < 0) return -1; - } - if (status & GIT_STATUS_WT_MODIFIED || status & GIT_STATUS_WT_NEW) { + if ((status & GIT_STATUS_WT_MODIFIED) || (status & GIT_STATUS_WT_NEW)) { printf("add '%s'\n", path); ret = 0; } else { ret = 1; } - if(p.options & SKIP) { + if (opts->dry_run) ret = 1; - } return ret; } @@ -101,11 +115,11 @@ unsigned int i; array->count = argc; - array->strings = malloc(sizeof(char*) * array->count); - assert(array->strings!=NULL); + array->strings = calloc(array->count, sizeof(char *)); + assert(array->strings != NULL); - for(i=0; icount; i++) { - array->strings[i]=argv[i]; + for (i = 0; i < array->count; i++) { + array->strings[i] = argv[i]; } return; @@ -120,39 +134,39 @@ exit(1); } -static void parse_opts(int *options, int *count, int argc, char *argv[]) +static void parse_opts(const char **repo_path, struct index_options *opts, struct args_info *args) { - int i; + if (args->argc <= 1) + print_usage(); - for (i = 1; i < argc; ++i) { - if (argv[i][0] != '-') { - break; - } - else if(!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) { - *options |= VERBOSE; - } - else if(!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) { - *options |= SKIP; - } - else if(!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) { - *options |= UPDATE; - } - else if(!strcmp(argv[i], "-h")) { + for (args->pos = 1; args->pos < args->argc; ++args->pos) { + const char *curr = args->argv[args->pos]; + + if (curr[0] != '-') { + if (!strcmp("add", curr)) { + opts->mode = INDEX_ADD; + continue; + } else if (opts->mode == INDEX_NONE) { + fprintf(stderr, "missing command: %s", curr); + print_usage(); + break; + } else { + /* We might be looking at a filename */ + break; + } + } else if (match_bool_arg(&opts->verbose, args, "--verbose") || + match_bool_arg(&opts->dry_run, args, "--dry-run") || + match_str_arg(repo_path, args, "--git-dir") || + (opts->mode == INDEX_ADD && match_bool_arg(&opts->add_update, args, "--update"))) { + continue; + } else if (match_bool_arg(NULL, args, "--help")) { print_usage(); break; - } - else if(!strcmp(argv[i], "--")) { - i++; + } else if (match_arg_separator(args)) { break; - } - else { - fprintf(stderr, "Unsupported option %s.\n", argv[i]); + } else { + fprintf(stderr, "Unsupported option %s.\n", curr); print_usage(); } } - - if (argc<=i) - print_usage(); - - *count = i; } diff -Nru libgit2-0.28.5+dfsg.1/examples/args.c libgit2-1.1.0+dfsg.1/examples/args.c --- libgit2-0.28.5+dfsg.1/examples/args.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/args.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,197 @@ +#include "common.h" +#include "args.h" + +size_t is_prefixed(const char *str, const char *pfx) +{ + size_t len = strlen(pfx); + return strncmp(str, pfx, len) ? 0 : len; +} + +int optional_str_arg( + const char **out, struct args_info *args, const char *opt, const char *def) +{ + const char *found = args->argv[args->pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return 0; + + if (!found[len]) { + if (args->pos + 1 == args->argc) { + *out = def; + return 1; + } + args->pos += 1; + *out = args->argv[args->pos]; + return 1; + } + + if (found[len] == '=') { + *out = found + len + 1; + return 1; + } + + return 0; +} + +int match_str_arg( + const char **out, struct args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return 0; + + if (!found[len]) { + if (args->pos + 1 == args->argc) + fatal("expected value following argument", opt); + args->pos += 1; + *out = args->argv[args->pos]; + return 1; + } + + if (found[len] == '=') { + *out = found + len + 1; + return 1; + } + + return 0; +} + +static const char *match_numeric_arg(struct args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return NULL; + + if (!found[len]) { + if (args->pos + 1 == args->argc) + fatal("expected numeric value following argument", opt); + args->pos += 1; + found = args->argv[args->pos]; + } else { + found = found + len; + if (*found == '=') + found++; + } + + return found; +} + +int match_uint16_arg( + uint16_t *out, struct args_info *args, const char *opt) +{ + const char *found = match_numeric_arg(args, opt); + uint16_t val; + char *endptr = NULL; + + if (!found) + return 0; + + val = (uint16_t)strtoul(found, &endptr, 0); + if (!endptr || *endptr != '\0') + fatal("expected number after argument", opt); + + if (out) + *out = val; + return 1; +} + +int match_uint32_arg( + uint32_t *out, struct args_info *args, const char *opt) +{ + const char *found = match_numeric_arg(args, opt); + uint16_t val; + char *endptr = NULL; + + if (!found) + return 0; + + val = (uint32_t)strtoul(found, &endptr, 0); + if (!endptr || *endptr != '\0') + fatal("expected number after argument", opt); + + if (out) + *out = val; + return 1; +} + +static int match_int_internal( + int *out, const char *str, int allow_negative, const char *opt) +{ + char *endptr = NULL; + int val = (int)strtol(str, &endptr, 10); + + if (!endptr || *endptr != '\0') + fatal("expected number", opt); + else if (val < 0 && !allow_negative) + fatal("negative values are not allowed", opt); + + if (out) + *out = val; + + return 1; +} + +int match_bool_arg(int *out, struct args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + + if (!strcmp(found, opt)) { + *out = 1; + return 1; + } + + if (!strncmp(found, "--no-", strlen("--no-")) && + !strcmp(found + strlen("--no-"), opt + 2)) { + *out = 0; + return 1; + } + + *out = -1; + return 0; +} + +int is_integer(int *out, const char *str, int allow_negative) +{ + return match_int_internal(out, str, allow_negative, NULL); +} + +int match_int_arg( + int *out, struct args_info *args, const char *opt, int allow_negative) +{ + const char *found = match_numeric_arg(args, opt); + if (!found) + return 0; + return match_int_internal(out, found, allow_negative, opt); +} + +int match_arg_separator(struct args_info *args) +{ + if (args->opts_done) + return 1; + + if (strcmp(args->argv[args->pos], "--") != 0) + return 0; + + args->opts_done = 1; + args->pos++; + return 1; +} + +void strarray_from_args(git_strarray *array, struct args_info *args) +{ + size_t i; + + array->count = args->argc - args->pos; + array->strings = calloc(array->count, sizeof(char *)); + assert(array->strings != NULL); + + for (i = 0; args->pos < args->argc; ++args->pos) { + array->strings[i++] = args->argv[args->pos]; + } + args->pos = args->argc; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/args.h libgit2-1.1.0+dfsg.1/examples/args.h --- libgit2-0.28.5+dfsg.1/examples/args.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/args.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,90 @@ +#ifndef INCLUDE_examples_args_h__ +#define INCLUDE_examples_args_h__ + +/** + * Argument-processing helper structure + */ +struct args_info { + int argc; + char **argv; + int pos; + int opts_done : 1; /**< Did we see a -- separator */ +}; +#define ARGS_INFO_INIT { argc, argv, 0, 0 } +#define ARGS_CURRENT(args) args->argv[args->pos] + +/** + * Check if a string has the given prefix. Returns 0 if not prefixed + * or the length of the prefix if it is. + */ +extern size_t is_prefixed(const char *str, const char *pfx); + +/** + * Match an integer string, returning 1 if matched, 0 if not. + */ +extern int is_integer(int *out, const char *str, int allow_negative); + +/** + * Check current `args` entry against `opt` string. If it matches + * exactly, take the next arg as a string; if it matches as a prefix with + * an equal sign, take the remainder as a string; if value not supplied, + * default value `def` will be given. otherwise return 0. + */ +extern int optional_str_arg( + const char **out, struct args_info *args, const char *opt, const char *def); + +/** + * Check current `args` entry against `opt` string. If it matches + * exactly, take the next arg as a string; if it matches as a prefix with + * an equal sign, take the remainder as a string; otherwise return 0. + */ +extern int match_str_arg( + const char **out, struct args_info *args, const char *opt); + +/** + * Check current `args` entry against `opt` string parsing as uint16. If + * `opt` matches exactly, take the next arg as a uint16_t value; if `opt` + * is a prefix (equal sign optional), take the remainder of the arg as a + * uint16_t value; otherwise return 0. + */ +extern int match_uint16_arg( + uint16_t *out, struct args_info *args, const char *opt); + +/** + * Check current `args` entry against `opt` string parsing as uint32. If + * `opt` matches exactly, take the next arg as a uint16_t value; if `opt` + * is a prefix (equal sign optional), take the remainder of the arg as a + * uint32_t value; otherwise return 0. + */ +extern int match_uint32_arg( + uint32_t *out, struct args_info *args, const char *opt); + +/** + * Check current `args` entry against `opt` string parsing as int. If + * `opt` matches exactly, take the next arg as an int value; if it matches + * as a prefix (equal sign optional), take the remainder of the arg as a + * int value; otherwise return 0. + */ +extern int match_int_arg( + int *out, struct args_info *args, const char *opt, int allow_negative); + +/** + * Check current `args` entry against a "bool" `opt` (ie. --[no-]progress). + * If `opt` matches positively, out will be set to 1, or if `opt` matches + * negatively, out will be set to 0, and in both cases 1 will be returned. + * If neither the positive or the negative form of opt matched, out will be -1, + * and 0 will be returned. + */ +extern int match_bool_arg(int *out, struct args_info *args, const char *opt); + +/** + * Check if we're processing past the single -- separator + */ +extern int match_arg_separator(struct args_info *args); + +/** + * Consume all remaining arguments in a git_strarray + */ +extern void strarray_from_args(git_strarray *array, struct args_info *args); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/examples/blame.c libgit2-1.1.0+dfsg.1/examples/blame.c --- libgit2-0.28.5+dfsg.1/examples/blame.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/blame.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,17 +14,12 @@ #include "common.h" -#ifdef _MSC_VER -#define snprintf sprintf_s -#define strcasecmp strcmpi -#endif - /** * This example demonstrates how to invoke the libgit2 blame API to roughly * simulate the output of `git blame` and a few of its command line arguments. */ -struct opts { +struct blame_opts { char *path; char *commitspec; int C; @@ -33,32 +28,26 @@ int end_line; int F; }; -static void parse_opts(struct opts *o, int argc, char *argv[]); +static void parse_opts(struct blame_opts *o, int argc, char *argv[]); -int main(int argc, char *argv[]) +int lg2_blame(git_repository *repo, int argc, char *argv[]) { int line, break_on_null_hunk; - size_t i, rawsize; + git_object_size_t i, rawsize; char spec[1024] = {0}; - struct opts o = {0}; + struct blame_opts o = {0}; const char *rawdata; - git_repository *repo = NULL; git_revspec revspec = {0}; git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; git_blame *blame = NULL; git_blob *blob; git_object *obj; - git_libgit2_init(); - parse_opts(&o, argc, argv); if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT; - /** Open the repository. */ - check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL); - /** * The commit range comes in "commitish" form. Use the rev-parse API to * nail down the end points. @@ -83,7 +72,7 @@ * Get the raw data inside the blob for output. We use the * `commitish:path/to/file.txt` format to find it. */ - if (git_oid_iszero(&blameopts.newest_commit)) + if (git_oid_is_zero(&blameopts.newest_commit)) strcpy(spec, "HEAD"); else git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); @@ -102,7 +91,7 @@ i = 0; break_on_null_hunk = 0; while (i < rawsize) { - const char *eol = memchr(rawdata + i, '\n', rawsize - i); + const char *eol = memchr(rawdata + i, '\n', (size_t)(rawsize - i)); char oid[10] = {0}; const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); @@ -112,7 +101,7 @@ if (hunk) { char sig[128] = {0}; break_on_null_hunk = 1; - + git_oid_tostr(oid, 10, &hunk->final_commit_id); snprintf(sig, 30, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); @@ -131,9 +120,6 @@ /** Cleanup. */ git_blob_free(blob); git_blame_free(blame); - git_repository_free(repo); - - git_libgit2_shutdown(); return 0; } @@ -157,7 +143,7 @@ } /** Parse the arguments. */ -static void parse_opts(struct opts *o, int argc, char *argv[]) +static void parse_opts(struct blame_opts *o, int argc, char *argv[]) { int i; char *bare_args[3] = {0}; diff -Nru libgit2-0.28.5+dfsg.1/examples/cat-file.c libgit2-1.1.0+dfsg.1/examples/cat-file.c --- libgit2-0.28.5+dfsg.1/examples/cat-file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/cat-file.c 2020-10-12 18:53:06.000000000 +0000 @@ -102,37 +102,33 @@ printf("\n%s\n", git_tag_message(tag)); } -enum { +typedef enum { SHOW_TYPE = 1, SHOW_SIZE = 2, SHOW_NONE = 3, SHOW_PRETTY = 4 -}; +} catfile_mode; /* Forward declarations for option-parsing helper */ -struct opts { +struct catfile_options { const char *dir; const char *rev; - int action; + catfile_mode action; int verbose; }; -static void parse_opts(struct opts *o, int argc, char *argv[]); + +static void parse_opts(struct catfile_options *o, int argc, char *argv[]); /** Entry point for this command */ -int main(int argc, char *argv[]) +int lg2_cat_file(git_repository *repo, int argc, char *argv[]) { - git_repository *repo; - struct opts o = { ".", NULL, 0, 0 }; + struct catfile_options o = { ".", NULL, 0, 0 }; git_object *obj = NULL; char oidstr[GIT_OID_HEXSZ + 1]; - git_libgit2_init(); - parse_opts(&o, argc, argv); - check_lg2(git_repository_open_ext(&repo, o.dir, 0, NULL), - "Could not open repository", NULL); check_lg2(git_revparse_single(&obj, repo, o.rev), "Could not resolve", o.rev); @@ -188,9 +184,6 @@ } git_object_free(obj); - git_repository_free(repo); - - git_libgit2_shutdown(); return 0; } @@ -209,7 +202,7 @@ } /** Parse the command-line options taken from git */ -static void parse_opts(struct opts *o, int argc, char *argv[]) +static void parse_opts(struct catfile_options *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; diff -Nru libgit2-0.28.5+dfsg.1/examples/checkout.c libgit2-1.1.0+dfsg.1/examples/checkout.c --- libgit2-0.28.5+dfsg.1/examples/checkout.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/checkout.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,7 +13,6 @@ */ #include "common.h" -#include /* Define the printf format specifer to use for size_t output */ #if defined(_MSC_VER) || defined(__MINGW32__) @@ -66,7 +65,7 @@ const char *curr = args->argv[args->pos]; int bool_arg; - if (strcmp(curr, "--") == 0) { + if (match_arg_separator(args)) { break; } else if (!strcmp(curr, "--force")) { opts->force = 1; @@ -112,9 +111,10 @@ * This is the main "checkout " function, responsible for performing * a branch-based checkout. */ -static int perform_checkout_ref(git_repository *repo, git_annotated_commit *target, checkout_options *opts) +static int perform_checkout_ref(git_repository *repo, git_annotated_commit *target, const char *target_ref, checkout_options *opts) { git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_reference *ref = NULL, *branch = NULL; git_commit *target_commit = NULL; int err; @@ -156,10 +156,25 @@ * we might need to detach HEAD. */ if (git_annotated_commit_ref(target)) { - err = git_repository_set_head(repo, git_annotated_commit_ref(target)); + const char *target_head; + + if ((err = git_reference_lookup(&ref, repo, git_annotated_commit_ref(target))) < 0) + goto error; + + if (git_reference_is_remote(ref)) { + if ((err = git_branch_create_from_annotated(&branch, repo, target_ref, target, 0)) < 0) + goto error; + target_head = git_reference_name(branch); + } else { + target_head = git_annotated_commit_ref(target); + } + + err = git_repository_set_head(repo, target_head); } else { err = git_repository_set_head_detached_from_annotated(repo, target); } + +error: if (err != 0) { fprintf(stderr, "failed to update HEAD reference: %s\n", git_error_last()->message); goto cleanup; @@ -167,14 +182,70 @@ cleanup: git_commit_free(target_commit); + git_reference_free(branch); + git_reference_free(ref); return err; } +/** + * This corresponds to `git switch --guess`: if a given ref does + * not exist, git will by default try to guess the reference by + * seeing whether any remote has a branch called . If there + * is a single remote only that has it, then it is assumed to be + * the desired reference and a local branch is created for it. + * + * The following is a simplified implementation. It will not try + * to check whether the ref is unique across all remotes. + */ +static int guess_refish(git_annotated_commit **out, git_repository *repo, const char *ref) +{ + git_strarray remotes = { NULL, 0 }; + git_reference *remote_ref = NULL; + int error; + size_t i; + + if ((error = git_remote_list(&remotes, repo)) < 0) + goto out; + + for (i = 0; i < remotes.count; i++) { + char *refname = NULL; + size_t reflen; + + reflen = snprintf(refname, 0, "refs/remotes/%s/%s", remotes.strings[i], ref); + if ((refname = malloc(reflen + 1)) == NULL) { + error = -1; + goto next; + } + snprintf(refname, reflen + 1, "refs/remotes/%s/%s", remotes.strings[i], ref); + + if ((error = git_reference_lookup(&remote_ref, repo, refname)) < 0) + goto next; + + break; +next: + free(refname); + if (error < 0 && error != GIT_ENOTFOUND) + break; + } + + if (!remote_ref) { + error = GIT_ENOTFOUND; + goto out; + } + + if ((error = git_annotated_commit_from_ref(out, repo, remote_ref)) < 0) + goto out; + +out: + git_reference_free(remote_ref); + git_strarray_dispose(&remotes); + return error; +} + /** That example's entry point */ -int main(int argc, char **argv) +int lg2_checkout(git_repository *repo, int argc, char **argv) { - git_repository *repo = NULL; struct args_info args = ARGS_INFO_INIT; checkout_options opts; git_repository_state_t state; @@ -185,15 +256,6 @@ /** Parse our command line options */ parse_options(&path, &opts, &args); - /** Initialize the library */ - err = git_libgit2_init(); - if (!err) - check_lg2(err, "Failed to initialize libgit2", NULL); - - /** Open the repository corresponding to the options */ - check_lg2(git_repository_open_ext(&repo, path, 0, NULL), - "Could not open repository", NULL); - /** Make sure we're not about to checkout while something else is going on */ state = git_repository_state(repo); if (state != GIT_REPOSITORY_STATE_NONE) { @@ -201,11 +263,7 @@ goto cleanup; } - if (args.pos >= args.argc) { - fprintf(stderr, "unhandled\n"); - err = -1; - goto cleanup; - } else if (strcmp("--", args.argv[args.pos])) { + if (match_arg_separator(&args)) { /** * Try to checkout the given path */ @@ -217,19 +275,16 @@ /** * Try to resolve a "refish" argument to a target libgit2 can use */ - err = resolve_refish(&checkout_target, repo, args.argv[args.pos]); - if (err != 0) { + if ((err = resolve_refish(&checkout_target, repo, args.argv[args.pos])) < 0 && + (err = guess_refish(&checkout_target, repo, args.argv[args.pos])) < 0) { fprintf(stderr, "failed to resolve %s: %s\n", args.argv[args.pos], git_error_last()->message); goto cleanup; } - err = perform_checkout_ref(repo, checkout_target, &opts); + err = perform_checkout_ref(repo, checkout_target, args.argv[args.pos], &opts); } cleanup: git_annotated_commit_free(checkout_target); - git_repository_free(repo); - git_libgit2_shutdown(); - return err; } diff -Nru libgit2-0.28.5+dfsg.1/examples/clone.c libgit2-1.1.0+dfsg.1/examples/clone.c --- libgit2-0.28.5+dfsg.1/examples/clone.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/clone.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,104 @@ +#include "common.h" + +typedef struct progress_data { + git_indexer_progress fetch_progress; + size_t completed_steps; + size_t total_steps; + const char *path; +} progress_data; + +static void print_progress(const progress_data *pd) +{ + int network_percent = pd->fetch_progress.total_objects > 0 ? + (100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects : + 0; + int index_percent = pd->fetch_progress.total_objects > 0 ? + (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects : + 0; + + int checkout_percent = pd->total_steps > 0 + ? (int)((100 * pd->completed_steps) / pd->total_steps) + : 0; + size_t kbytes = pd->fetch_progress.received_bytes / 1024; + + if (pd->fetch_progress.total_objects && + pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) { + printf("Resolving deltas %u/%u\r", + pd->fetch_progress.indexed_deltas, + pd->fetch_progress.total_deltas); + } else { + printf("net %3d%% (%4" PRIuZ " kb, %5u/%5u) / idx %3d%% (%5u/%5u) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ")%s\n", + network_percent, kbytes, + pd->fetch_progress.received_objects, pd->fetch_progress.total_objects, + index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects, + checkout_percent, + pd->completed_steps, pd->total_steps, + pd->path); + } +} + +static int sideband_progress(const char *str, int len, void *payload) +{ + (void)payload; /* unused */ + + printf("remote: %.*s", len, str); + fflush(stdout); + return 0; +} + +static int fetch_progress(const git_indexer_progress *stats, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->fetch_progress = *stats; + print_progress(pd); + return 0; +} +static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->completed_steps = cur; + pd->total_steps = tot; + pd->path = path; + print_progress(pd); +} + + +int lg2_clone(git_repository *repo, int argc, char **argv) +{ + progress_data pd = {{0}}; + git_repository *cloned_repo = NULL; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + const char *url = argv[1]; + const char *path = argv[2]; + int error; + + (void)repo; /* unused */ + + /* Validate args */ + if (argc < 3) { + printf ("USAGE: %s \n", argv[0]); + return -1; + } + + /* Set up options */ + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + checkout_opts.progress_cb = checkout_progress; + checkout_opts.progress_payload = &pd; + clone_opts.checkout_opts = checkout_opts; + clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress; + clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; + clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb; + clone_opts.fetch_opts.callbacks.payload = &pd; + + /* Do the clone */ + error = git_clone(&cloned_repo, url, path, &clone_opts); + printf("\n"); + if (error != 0) { + const git_error *err = git_error_last(); + if (err) printf("ERROR %d: %s\n", err->klass, err->message); + else printf("ERROR %d: no detailed info\n", error); + } + else if (cloned_repo) git_repository_free(cloned_repo); + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/CMakeLists.txt libgit2-1.1.0+dfsg.1/examples/CMakeLists.txt --- libgit2-0.28.5+dfsg.1/examples/CMakeLists.txt 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/CMakeLists.txt 2020-10-12 18:53:06.000000000 +0000 @@ -1,25 +1,15 @@ INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES}) INCLUDE_DIRECTORIES(SYSTEM ${LIBGIT2_SYSTEM_INCLUDES}) -FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h common.?) -ADD_EXECUTABLE(cgit2 ${SRC_EXAMPLE_GIT2}) -SET_TARGET_PROPERTIES(cgit2 PROPERTIES C_STANDARD 90) +FILE(GLOB LG2_SOURCES *.c *.h) +ADD_EXECUTABLE(lg2 ${LG2_SOURCES}) +SET_TARGET_PROPERTIES(lg2 PROPERTIES C_STANDARD 90) # Ensure that we do not use deprecated functions internally ADD_DEFINITIONS(-DGIT_DEPRECATE_HARD) IF(WIN32 OR ANDROID) - TARGET_LINK_LIBRARIES(cgit2 git2) + TARGET_LINK_LIBRARIES(lg2 git2) ELSE() - TARGET_LINK_LIBRARIES(cgit2 git2 pthread) + TARGET_LINK_LIBRARIES(lg2 git2 pthread) ENDIF() - -FILE(GLOB SRC_EXAMPLE_APPS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c) -FOREACH(src_app ${SRC_EXAMPLE_APPS}) - STRING(REPLACE ".c" "" app_name ${src_app}) - IF(NOT ${app_name} STREQUAL "common") - ADD_EXECUTABLE(${app_name} ${src_app} "common.c") - TARGET_LINK_LIBRARIES(${app_name} git2) - SET_TARGET_PROPERTIES(${app_name} PROPERTIES C_STANDARD 90) - ENDIF() -ENDFOREACH() diff -Nru libgit2-0.28.5+dfsg.1/examples/commit.c libgit2-1.1.0+dfsg.1/examples/commit.c --- libgit2-0.28.5+dfsg.1/examples/commit.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/commit.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * libgit2 "commit" example - shows how to create a git commit + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include "common.h" + +/** + * This example demonstrates the libgit2 commit APIs to roughly + * simulate `git commit` with the commit message argument. + * + * This does not have: + * + * - Robust error handling + * - Most of the `git commit` options + * + * This does have: + * + * - Example of performing a git commit with a comment + * + */ +int lg2_commit(git_repository *repo, int argc, char **argv) +{ + const char *opt = argv[1]; + const char *comment = argv[2]; + int error; + + git_oid commit_oid,tree_oid; + git_tree *tree; + git_index *index; + git_object *parent = NULL; + git_reference *ref = NULL; + git_signature *signature; + + /* Validate args */ + if (argc < 3 || strcmp(opt, "-m") != 0) { + printf ("USAGE: %s -m \n", argv[0]); + return -1; + } + + error = git_revparse_ext(&parent, &ref, repo, "HEAD"); + if (error == GIT_ENOTFOUND) { + printf("HEAD not found. Creating first commit\n"); + error = 0; + } else if (error != 0) { + const git_error *err = git_error_last(); + if (err) printf("ERROR %d: %s\n", err->klass, err->message); + else printf("ERROR %d: no detailed info\n", error); + } + + check_lg2(git_repository_index(&index, repo), "Could not open repository index", NULL); + check_lg2(git_index_write_tree(&tree_oid, index), "Could not write tree", NULL);; + check_lg2(git_index_write(index), "Could not write index", NULL);; + + check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL); + + check_lg2(git_signature_default(&signature, repo), "Error creating signature", NULL); + + check_lg2(git_commit_create_v( + &commit_oid, + repo, + "HEAD", + signature, + signature, + NULL, + comment, + tree, + parent ? 1 : 0, parent), "Error creating commit", NULL); + + git_index_free(index); + git_signature_free(signature); + git_tree_free(tree); + + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/common.c libgit2-1.1.0+dfsg.1/examples/common.c --- libgit2-0.28.5+dfsg.1/examples/common.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/common.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,10 +12,14 @@ * . */ -#include #include "common.h" +#ifndef _WIN32 +# include +#endif +#include + void check_lg2(int error, const char *message, const char *extra) { const git_error *lg2err; @@ -49,174 +53,6 @@ exit(1); } -size_t is_prefixed(const char *str, const char *pfx) -{ - size_t len = strlen(pfx); - return strncmp(str, pfx, len) ? 0 : len; -} - -int optional_str_arg( - const char **out, struct args_info *args, const char *opt, const char *def) -{ - const char *found = args->argv[args->pos]; - size_t len = is_prefixed(found, opt); - - if (!len) - return 0; - - if (!found[len]) { - if (args->pos + 1 == args->argc) { - *out = def; - return 1; - } - args->pos += 1; - *out = args->argv[args->pos]; - return 1; - } - - if (found[len] == '=') { - *out = found + len + 1; - return 1; - } - - return 0; -} - -int match_str_arg( - const char **out, struct args_info *args, const char *opt) -{ - const char *found = args->argv[args->pos]; - size_t len = is_prefixed(found, opt); - - if (!len) - return 0; - - if (!found[len]) { - if (args->pos + 1 == args->argc) - fatal("expected value following argument", opt); - args->pos += 1; - *out = args->argv[args->pos]; - return 1; - } - - if (found[len] == '=') { - *out = found + len + 1; - return 1; - } - - return 0; -} - -static const char *match_numeric_arg(struct args_info *args, const char *opt) -{ - const char *found = args->argv[args->pos]; - size_t len = is_prefixed(found, opt); - - if (!len) - return NULL; - - if (!found[len]) { - if (args->pos + 1 == args->argc) - fatal("expected numeric value following argument", opt); - args->pos += 1; - found = args->argv[args->pos]; - } else { - found = found + len; - if (*found == '=') - found++; - } - - return found; -} - -int match_uint16_arg( - uint16_t *out, struct args_info *args, const char *opt) -{ - const char *found = match_numeric_arg(args, opt); - uint16_t val; - char *endptr = NULL; - - if (!found) - return 0; - - val = (uint16_t)strtoul(found, &endptr, 0); - if (!endptr || *endptr != '\0') - fatal("expected number after argument", opt); - - if (out) - *out = val; - return 1; -} - -int match_uint32_arg( - uint32_t *out, struct args_info *args, const char *opt) -{ - const char *found = match_numeric_arg(args, opt); - uint16_t val; - char *endptr = NULL; - - if (!found) - return 0; - - val = (uint32_t)strtoul(found, &endptr, 0); - if (!endptr || *endptr != '\0') - fatal("expected number after argument", opt); - - if (out) - *out = val; - return 1; -} - -static int match_int_internal( - int *out, const char *str, int allow_negative, const char *opt) -{ - char *endptr = NULL; - int val = (int)strtol(str, &endptr, 10); - - if (!endptr || *endptr != '\0') - fatal("expected number", opt); - else if (val < 0 && !allow_negative) - fatal("negative values are not allowed", opt); - - if (out) - *out = val; - - return 1; -} - -int match_bool_arg(int *out, struct args_info *args, const char *opt) -{ - const char *found = args->argv[args->pos]; - - if (!strcmp(found, opt)) { - *out = 1; - return 1; - } - - if (!strncmp(found, "--no-", strlen("--no-")) && - !strcmp(found + strlen("--no-"), opt + 2)) { - *out = 0; - return 1; - } - - *out = -1; - return 0; -} - -int is_integer(int *out, const char *str, int allow_negative) -{ - return match_int_internal(out, str, allow_negative, NULL); -} - -int match_int_arg( - int *out, struct args_info *args, const char *opt, int allow_negative) -{ - const char *found = match_numeric_arg(args, opt); - if (!found) - return 0; - return match_int_internal(out, found, allow_negative, opt); -} - int diff_output( const git_diff_delta *d, const git_diff_hunk *h, @@ -289,3 +125,136 @@ return err; } + +static int readline(char **out) +{ + int c, error = 0, length = 0, allocated = 0; + char *line = NULL; + + errno = 0; + + while ((c = getchar()) != EOF) { + if (length == allocated) { + allocated += 16; + + if ((line = realloc(line, allocated)) == NULL) { + error = -1; + goto error; + } + } + + if (c == '\n') + break; + + line[length++] = c; + } + + if (errno != 0) { + error = -1; + goto error; + } + + line[length] = '\0'; + *out = line; + line = NULL; + error = length; +error: + free(line); + return error; +} + +static int ask(char **out, const char *prompt, char optional) +{ + printf("%s ", prompt); + fflush(stdout); + + if (!readline(out) && !optional) { + fprintf(stderr, "Could not read response: %s", strerror(errno)); + return -1; + } + + return 0; +} + +int cred_acquire_cb(git_credential **out, + const char *url, + const char *username_from_url, + unsigned int allowed_types, + void *payload) +{ + char *username = NULL, *password = NULL, *privkey = NULL, *pubkey = NULL; + int error = 1; + + UNUSED(url); + UNUSED(payload); + + if (username_from_url) { + if ((username = strdup(username_from_url)) == NULL) + goto out; + } else if ((error = ask(&username, "Username:", 0)) < 0) { + goto out; + } + + if (allowed_types & GIT_CREDENTIAL_SSH_KEY) { + int n; + + if ((error = ask(&privkey, "SSH Key:", 0)) < 0 || + (error = ask(&password, "Password:", 1)) < 0) + goto out; + + if ((n = snprintf(NULL, 0, "%s.pub", privkey)) < 0 || + (pubkey = malloc(n + 1)) == NULL || + (n = snprintf(pubkey, n + 1, "%s.pub", privkey)) < 0) + goto out; + + error = git_credential_ssh_key_new(out, username, pubkey, privkey, password); + } else if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) { + if ((error = ask(&password, "Password:", 1)) < 0) + goto out; + + error = git_credential_userpass_plaintext_new(out, username, password); + } else if (allowed_types & GIT_CREDENTIAL_USERNAME) { + error = git_credential_username_new(out, username); + } + +out: + free(username); + free(password); + free(privkey); + free(pubkey); + return error; +} + +char *read_file(const char *path) +{ + ssize_t total = 0; + char *buf = NULL; + struct stat st; + int fd = -1; + + if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, &st) < 0) + goto out; + + if ((buf = malloc(st.st_size + 1)) == NULL) + goto out; + + while (total < st.st_size) { + ssize_t bytes = read(fd, buf + total, st.st_size - total); + if (bytes <= 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + free(buf); + buf = NULL; + goto out; + } + total += bytes; + } + + buf[total] = '\0'; + +out: + if (fd >= 0) + close(fd); + return buf; +} + diff -Nru libgit2-0.28.5+dfsg.1/examples/common.h libgit2-1.1.0+dfsg.1/examples/common.h --- libgit2-0.28.5+dfsg.1/examples/common.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/common.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,11 +11,75 @@ * with this software. If not, see * . */ +#ifndef INCLUDE_examples_common_h__ +#define INCLUDE_examples_common_h__ +#include +#include +#include #include #include #include #include +#include + +#ifdef _WIN32 +# include +# include +# define open _open +# define read _read +# define close _close +# define ssize_t int +# define sleep(a) Sleep(a * 1000) +#else +# include +#endif + +#ifndef PRIuZ +/* Define the printf format specifer to use for size_t output */ +#if defined(_MSC_VER) || defined(__MINGW32__) +# define PRIuZ "Iu" +#else +# define PRIuZ "zu" +#endif +#endif + +#ifdef _MSC_VER +#define snprintf sprintf_s +#define strcasecmp strcmpi +#endif + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) +#define UNUSED(x) (void)(x) + +#include "args.h" + +extern int lg2_add(git_repository *repo, int argc, char **argv); +extern int lg2_blame(git_repository *repo, int argc, char **argv); +extern int lg2_cat_file(git_repository *repo, int argc, char **argv); +extern int lg2_checkout(git_repository *repo, int argc, char **argv); +extern int lg2_clone(git_repository *repo, int argc, char **argv); +extern int lg2_commit(git_repository *repo, int argc, char **argv); +extern int lg2_config(git_repository *repo, int argc, char **argv); +extern int lg2_describe(git_repository *repo, int argc, char **argv); +extern int lg2_diff(git_repository *repo, int argc, char **argv); +extern int lg2_fetch(git_repository *repo, int argc, char **argv); +extern int lg2_for_each_ref(git_repository *repo, int argc, char **argv); +extern int lg2_general(git_repository *repo, int argc, char **argv); +extern int lg2_index_pack(git_repository *repo, int argc, char **argv); +extern int lg2_init(git_repository *repo, int argc, char **argv); +extern int lg2_log(git_repository *repo, int argc, char **argv); +extern int lg2_ls_files(git_repository *repo, int argc, char **argv); +extern int lg2_ls_remote(git_repository *repo, int argc, char **argv); +extern int lg2_merge(git_repository *repo, int argc, char **argv); +extern int lg2_push(git_repository *repo, int argc, char **argv); +extern int lg2_remote(git_repository *repo, int argc, char **argv); +extern int lg2_rev_list(git_repository *repo, int argc, char **argv); +extern int lg2_rev_parse(git_repository *repo, int argc, char **argv); +extern int lg2_show_index(git_repository *repo, int argc, char **argv); +extern int lg2_stash(git_repository *repo, int argc, char **argv); +extern int lg2_status(git_repository *repo, int argc, char **argv); +extern int lg2_tag(git_repository *repo, int argc, char **argv); /** * Check libgit2 error code, printing error to stderr on failure and @@ -24,80 +88,17 @@ extern void check_lg2(int error, const char *message, const char *extra); /** - * Exit the program, printing error to stderr - */ -extern void fatal(const char *message, const char *extra); - -/** - * Check if a string has the given prefix. Returns 0 if not prefixed - * or the length of the prefix if it is. - */ -extern size_t is_prefixed(const char *str, const char *pfx); - -/** - * Match an integer string, returning 1 if matched, 0 if not. - */ -extern int is_integer(int *out, const char *str, int allow_negative); - -struct args_info { - int argc; - char **argv; - int pos; -}; -#define ARGS_INFO_INIT { argc, argv, 0 } - -/** - * Check current `args` entry against `opt` string. If it matches - * exactly, take the next arg as a string; if it matches as a prefix with - * an equal sign, take the remainder as a string; if value not supplied, - * default value `def` will be given. otherwise return 0. - */ -extern int optional_str_arg( - const char **out, struct args_info *args, const char *opt, const char *def); - -/** - * Check current `args` entry against `opt` string. If it matches - * exactly, take the next arg as a string; if it matches as a prefix with - * an equal sign, take the remainder as a string; otherwise return 0. + * Read a file into a buffer + * + * @param path The path to the file that shall be read + * @return NUL-terminated buffer if the file was successfully read, NULL-pointer otherwise */ -extern int match_str_arg( - const char **out, struct args_info *args, const char *opt); +extern char *read_file(const char *path); /** - * Check current `args` entry against `opt` string parsing as uint16. If - * `opt` matches exactly, take the next arg as a uint16_t value; if `opt` - * is a prefix (equal sign optional), take the remainder of the arg as a - * uint16_t value; otherwise return 0. - */ -extern int match_uint16_arg( - uint16_t *out, struct args_info *args, const char *opt); - -/** - * Check current `args` entry against `opt` string parsing as uint32. If - * `opt` matches exactly, take the next arg as a uint16_t value; if `opt` - * is a prefix (equal sign optional), take the remainder of the arg as a - * uint32_t value; otherwise return 0. - */ -extern int match_uint32_arg( - uint32_t *out, struct args_info *args, const char *opt); - -/** - * Check current `args` entry against `opt` string parsing as int. If - * `opt` matches exactly, take the next arg as an int value; if it matches - * as a prefix (equal sign optional), take the remainder of the arg as a - * int value; otherwise return 0. - */ -extern int match_int_arg( - int *out, struct args_info *args, const char *opt, int allow_negative); - -/** - * Check current `args` entry against a "bool" `opt` (ie. --[no-]progress). - * If `opt` matches positively, out will be set to 1, or if `opt` matches - * negatively, out will be set to 0, and in both cases 1 will be returned. - * If neither the positive or the negative form of opt matched, out will be -1, - * and 0 will be returned. + * Exit the program, printing error to stderr */ -extern int match_bool_arg(int *out, struct args_info *args, const char *opt); +extern void fatal(const char *message, const char *extra); /** * Basic output function for plain text diff output @@ -122,3 +123,14 @@ * Convert a refish to an annotated commit. */ extern int resolve_refish(git_annotated_commit **commit, git_repository *repo, const char *refish); + +/** + * Acquire credentials via command line + */ +extern int cred_acquire_cb(git_credential **out, + const char *url, + const char *username_from_url, + unsigned int allowed_types, + void *payload); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/examples/config.c libgit2-1.1.0+dfsg.1/examples/config.c --- libgit2-0.28.5+dfsg.1/examples/config.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/config.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * libgit2 "config" example - shows how to use the config API + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include "common.h" + +static int config_get(git_config *cfg, const char *key) +{ + git_config_entry *entry; + int error; + + if ((error = git_config_get_entry(&entry, cfg, key)) < 0) { + if (error != GIT_ENOTFOUND) + printf("Unable to get configuration: %s\n", git_error_last()->message); + return 1; + } + + puts(entry->value); + return 0; +} + +static int config_set(git_config *cfg, const char *key, const char *value) +{ + if (git_config_set_string(cfg, key, value) < 0) { + printf("Unable to set configuration: %s\n", git_error_last()->message); + return 1; + } + return 0; +} + +int lg2_config(git_repository *repo, int argc, char **argv) +{ + git_config *cfg; + int error; + + if ((error = git_repository_config(&cfg, repo)) < 0) { + printf("Unable to obtain repository config: %s\n", git_error_last()->message); + goto out; + } + + if (argc == 2) { + error = config_get(cfg, argv[1]); + } else if (argc == 3) { + error = config_set(cfg, argv[1], argv[2]); + } else { + printf("USAGE: %s config []\n", argv[0]); + error = 1; + } + +out: + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/describe.c libgit2-1.1.0+dfsg.1/examples/describe.c --- libgit2-0.28.5+dfsg.1/examples/describe.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/describe.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,7 +13,6 @@ */ #include "common.h" -#include /** * The following example partially reimplements the `git describe` command @@ -38,32 +37,30 @@ */ /** describe_options represents the parsed command line options */ -typedef struct { +struct describe_options { const char **commits; size_t commit_count; git_describe_options describe_options; git_describe_format_options format_options; -} describe_options; +}; -typedef struct args_info args_info; - -static void opts_add_commit(describe_options *opts, const char *commit) +static void opts_add_commit(struct describe_options *opts, const char *commit) { size_t sz; assert(opts != NULL); sz = ++opts->commit_count * sizeof(opts->commits[0]); - opts->commits = xrealloc(opts->commits, sz); + opts->commits = xrealloc((void *) opts->commits, sz); opts->commits[opts->commit_count - 1] = commit; } -static void do_describe_single(git_repository *repo, describe_options *opts, const char *rev) +static void do_describe_single(git_repository *repo, struct describe_options *opts, const char *rev) { git_object *commit; git_describe_result *describe_result; git_buf buf = { 0 }; - + if (rev) { check_lg2(git_revparse_single(&commit, repo, rev), "Failed to lookup rev", rev); @@ -81,7 +78,7 @@ printf("%s\n", buf.ptr); } -static void do_describe(git_repository *repo, describe_options *opts) +static void do_describe(git_repository *repo, struct describe_options *opts) { if (opts->commit_count == 0) do_describe_single(repo, opts, NULL); @@ -100,9 +97,9 @@ } /** Parse command line arguments */ -static void parse_options(describe_options *opts, int argc, char **argv) +static void parse_options(struct describe_options *opts, int argc, char **argv) { - args_info args = ARGS_INFO_INIT; + struct args_info args = ARGS_INFO_INIT; for (args.pos = 1; args.pos < argc; ++args.pos) { const char *curr = argv[args.pos]; @@ -142,33 +139,24 @@ } /** Initialize describe_options struct */ -static void describe_options_init(describe_options *opts) +static void describe_options_init(struct describe_options *opts) { memset(opts, 0, sizeof(*opts)); opts->commits = NULL; opts->commit_count = 0; - git_describe_init_options(&opts->describe_options, GIT_DESCRIBE_OPTIONS_VERSION); - git_describe_init_format_options(&opts->format_options, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION); + git_describe_options_init(&opts->describe_options, GIT_DESCRIBE_OPTIONS_VERSION); + git_describe_format_options_init(&opts->format_options, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION); } -int main(int argc, char **argv) +int lg2_describe(git_repository *repo, int argc, char **argv) { - git_repository *repo; - describe_options opts; - - git_libgit2_init(); - - check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), - "Could not open repository", NULL); + struct describe_options opts; describe_options_init(&opts); parse_options(&opts, argc, argv); do_describe(repo, &opts); - git_repository_free(repo); - git_libgit2_shutdown(); - return 0; } diff -Nru libgit2-0.28.5+dfsg.1/examples/diff.c libgit2-1.1.0+dfsg.1/examples/diff.c --- libgit2-0.28.5+dfsg.1/examples/diff.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/diff.c 2020-10-12 18:53:06.000000000 +0000 @@ -47,11 +47,12 @@ CACHE_NONE = 2 }; -/** The 'opts' struct captures all the various parsed command line options. */ -struct opts { +/** The 'diff_options' struct captures all the various parsed command line options. */ +struct diff_options { git_diff_options diffopts; git_diff_find_options findopts; int color; + int no_index; int cache; int output; git_diff_format_t format; @@ -62,28 +63,23 @@ /** These functions are implemented at the end */ static void usage(const char *message, const char *arg); -static void parse_opts(struct opts *o, int argc, char *argv[]); +static void parse_opts(struct diff_options *o, int argc, char *argv[]); static int color_printer( const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); -static void diff_print_stats(git_diff *diff, struct opts *o); +static void diff_print_stats(git_diff *diff, struct diff_options *o); +static void compute_diff_no_index(git_diff **diff, struct diff_options *o); -int main(int argc, char *argv[]) +int lg2_diff(git_repository *repo, int argc, char *argv[]) { - git_repository *repo = NULL; git_tree *t1 = NULL, *t2 = NULL; git_diff *diff; - struct opts o = { + struct diff_options o = { GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, - -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." + -1, -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." }; - git_libgit2_init(); - parse_opts(&o, argc, argv); - check_lg2(git_repository_open_ext(&repo, o.dir, 0, NULL), - "Could not open repository", o.dir); - /** * Possible argument patterns: * @@ -92,49 +88,54 @@ * * <sha1> * * --cached * * --nocache (don't use index data in diff at all) + * * --no-index <file1> <file2> * * nothing * * Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2> * are not supported in this example */ - if (o.treeish1) - treeish_to_tree(&t1, repo, o.treeish1); - if (o.treeish2) - treeish_to_tree(&t2, repo, o.treeish2); - - if (t1 && t2) - check_lg2( - git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), - "diff trees", NULL); - else if (o.cache != CACHE_NORMAL) { - if (!t1) - treeish_to_tree(&t1, repo, "HEAD"); + if (o.no_index >= 0) { + compute_diff_no_index(&diff, &o); + } else { + if (o.treeish1) + treeish_to_tree(&t1, repo, o.treeish1); + if (o.treeish2) + treeish_to_tree(&t2, repo, o.treeish2); - if (o.cache == CACHE_NONE) + if (t1 && t2) check_lg2( - git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), + git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), + "diff trees", NULL); + else if (o.cache != CACHE_NORMAL) { + if (!t1) + treeish_to_tree(&t1, repo, "HEAD"); + + if (o.cache == CACHE_NONE) + check_lg2( + git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), + "diff tree to working directory", NULL); + else + check_lg2( + git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), + "diff tree to index", NULL); + } + else if (t1) + check_lg2( + git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( - git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), - "diff tree to index", NULL); - } - else if (t1) - check_lg2( - git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), - "diff tree to working directory", NULL); - else - check_lg2( - git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), - "diff index to working directory", NULL); + git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), + "diff index to working directory", NULL); - /** Apply rename and copy detection if requested. */ + /** Apply rename and copy detection if requested. */ - if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) - check_lg2( - git_diff_find_similar(diff, &o.findopts), - "finding renames and copies", NULL); + if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) + check_lg2( + git_diff_find_similar(diff, &o.findopts), + "finding renames and copies", NULL); + } /** Generate simple output using libgit2 display helper. */ @@ -157,17 +158,45 @@ } /** Cleanup before exiting. */ - git_diff_free(diff); git_tree_free(t1); git_tree_free(t2); - git_repository_free(repo); - - git_libgit2_shutdown(); return 0; } +static void compute_diff_no_index(git_diff **diff, struct diff_options *o) { + git_patch *patch = NULL; + char *file1_str = NULL; + char *file2_str = NULL; + git_buf buf = {0}; + + if (!o->treeish1 || !o->treeish2) { + usage("two files should be provided as arguments", NULL); + } + file1_str = read_file(o->treeish1); + if (file1_str == NULL) { + usage("file cannot be read", o->treeish1); + } + file2_str = read_file(o->treeish2); + if (file2_str == NULL) { + usage("file cannot be read", o->treeish2); + } + check_lg2( + git_patch_from_buffers(&patch, file1_str, strlen(file1_str), o->treeish1, file2_str, strlen(file2_str), o->treeish2, &o->diffopts), + "patch buffers", NULL); + check_lg2( + git_patch_to_buf(&buf, patch), + "patch to buf", NULL); + check_lg2( + git_diff_from_buffer(diff, buf.ptr, buf.size), + "diff from patch", NULL); + git_patch_free(patch); + git_buf_dispose(&buf); + free(file1_str); + free(file2_str); +} + static void usage(const char *message, const char *arg) { if (message && arg) @@ -212,11 +241,10 @@ } /** Parse arguments as copied from git-diff. */ -static void parse_opts(struct opts *o, int argc, char *argv[]) +static void parse_opts(struct diff_options *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; - for (args.pos = 1; args.pos < argc; ++args.pos) { const char *a = argv[args.pos]; @@ -233,9 +261,10 @@ o->output |= OUTPUT_DIFF; o->format = GIT_DIFF_FORMAT_PATCH; } - else if (!strcmp(a, "--cached")) + else if (!strcmp(a, "--cached")) { o->cache = CACHE_ONLY; - else if (!strcmp(a, "--nocache")) + if (o->no_index >= 0) usage("--cached and --no-index are incompatible", NULL); + } else if (!strcmp(a, "--nocache")) o->cache = CACHE_NONE; else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name")) o->format = GIT_DIFF_FORMAT_NAME_ONLY; @@ -248,7 +277,10 @@ o->format = GIT_DIFF_FORMAT_RAW; o->diffopts.id_abbrev = 40; } - else if (!strcmp(a, "--color")) + else if (!strcmp(a, "--no-index")) { + o->no_index = 0; + if (o->cache == CACHE_ONLY) usage("--cached and --no-index are incompatible", NULL); + } else if (!strcmp(a, "--color")) o->color = 0; else if (!strcmp(a, "--no-color")) o->color = -1; @@ -309,7 +341,7 @@ } /** Display diff output with "--stat", "--numstat", or "--shortstat" */ -static void diff_print_stats(git_diff *diff, struct opts *o) +static void diff_print_stats(git_diff *diff, struct diff_options *o) { git_diff_stats *stats; git_buf b = GIT_BUF_INIT_CONST(NULL, 0); diff -Nru libgit2-0.28.5+dfsg.1/examples/fetch.c libgit2-1.1.0+dfsg.1/examples/fetch.c --- libgit2-0.28.5+dfsg.1/examples/fetch.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/fetch.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,109 @@ +#include "common.h" + +static int progress_cb(const char *str, int len, void *data) +{ + (void)data; + printf("remote: %.*s", len, str); + fflush(stdout); /* We don't have the \n to force the flush */ + return 0; +} + +/** + * This function gets called for each remote-tracking branch that gets + * updated. The message we output depends on whether it's a new one or + * an update. + */ +static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) +{ + char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1]; + (void)data; + + git_oid_fmt(b_str, b); + b_str[GIT_OID_HEXSZ] = '\0'; + + if (git_oid_is_zero(a)) { + printf("[new] %.20s %s\n", b_str, refname); + } else { + git_oid_fmt(a_str, a); + a_str[GIT_OID_HEXSZ] = '\0'; + printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname); + } + + return 0; +} + +/** + * This gets called during the download and indexing. Here we show + * processed and total objects in the pack and the amount of received + * data. Most frontends will probably want to show a percentage and + * the download rate. + */ +static int transfer_progress_cb(const git_indexer_progress *stats, void *payload) +{ + (void)payload; + + if (stats->received_objects == stats->total_objects) { + printf("Resolving deltas %u/%u\r", + stats->indexed_deltas, stats->total_deltas); + } else if (stats->total_objects > 0) { + printf("Received %u/%u objects (%u) in %" PRIuZ " bytes\r", + stats->received_objects, stats->total_objects, + stats->indexed_objects, stats->received_bytes); + } + return 0; +} + +/** Entry point for this command */ +int lg2_fetch(git_repository *repo, int argc, char **argv) +{ + git_remote *remote = NULL; + const git_indexer_progress *stats; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; + + if (argc < 2) { + fprintf(stderr, "usage: %s fetch \n", argv[-1]); + return EXIT_FAILURE; + } + + /* Figure out whether it's a named remote or a URL */ + printf("Fetching %s for repo %p\n", argv[1], repo); + if (git_remote_lookup(&remote, repo, argv[1]) < 0) + if (git_remote_create_anonymous(&remote, repo, argv[1]) < 0) + goto on_error; + + /* Set up the callbacks (only update_tips for now) */ + fetch_opts.callbacks.update_tips = &update_cb; + fetch_opts.callbacks.sideband_progress = &progress_cb; + fetch_opts.callbacks.transfer_progress = transfer_progress_cb; + fetch_opts.callbacks.credentials = cred_acquire_cb; + + /** + * Perform the fetch with the configured refspecs from the + * config. Update the reflog for the updated references with + * "fetch". + */ + if (git_remote_fetch(remote, NULL, &fetch_opts, "fetch") < 0) + goto on_error; + + /** + * If there are local objects (we got a thin pack), then tell + * the user how many objects we saved from having to cross the + * network. + */ + stats = git_remote_stats(remote); + if (stats->local_objects > 0) { + printf("\rReceived %u/%u objects in %" PRIuZ " bytes (used %u local objects)\n", + stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects); + } else{ + printf("\rReceived %u/%u objects in %" PRIuZ "bytes\n", + stats->indexed_objects, stats->total_objects, stats->received_bytes); + } + + git_remote_free(remote); + + return 0; + + on_error: + git_remote_free(remote); + return -1; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/for-each-ref.c libgit2-1.1.0+dfsg.1/examples/for-each-ref.c --- libgit2-0.28.5+dfsg.1/examples/for-each-ref.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/for-each-ref.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,49 +1,44 @@ #include -#include #include "common.h" static int show_ref(git_reference *ref, void *data) { - git_repository *repo = data; - git_reference *resolved = NULL; - char hex[GIT_OID_HEXSZ+1]; - const git_oid *oid; - git_object *obj; - - if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) - check_lg2(git_reference_resolve(&resolved, ref), - "Unable to resolve symbolic reference", - git_reference_name(ref)); - - oid = git_reference_target(resolved ? resolved : ref); - git_oid_fmt(hex, oid); - hex[GIT_OID_HEXSZ] = 0; - check_lg2(git_object_lookup(&obj, repo, oid, GIT_OBJECT_ANY), - "Unable to lookup object", hex); - - printf("%s %-6s\t%s\n", - hex, - git_object_type2string(git_object_type(obj)), - git_reference_name(ref)); - - if (resolved) - git_reference_free(resolved); - return 0; + git_repository *repo = data; + git_reference *resolved = NULL; + char hex[GIT_OID_HEXSZ+1]; + const git_oid *oid; + git_object *obj; + + if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) + check_lg2(git_reference_resolve(&resolved, ref), + "Unable to resolve symbolic reference", + git_reference_name(ref)); + + oid = git_reference_target(resolved ? resolved : ref); + git_oid_fmt(hex, oid); + hex[GIT_OID_HEXSZ] = 0; + check_lg2(git_object_lookup(&obj, repo, oid, GIT_OBJECT_ANY), + "Unable to lookup object", hex); + + printf("%s %-6s\t%s\n", + hex, + git_object_type2string(git_object_type(obj)), + git_reference_name(ref)); + + if (resolved) + git_reference_free(resolved); + return 0; } -int main(int argc, char **argv) +int lg2_for_each_ref(git_repository *repo, int argc, char **argv) { - git_repository *repo; - git_libgit2_init(); - - if (argc != 1 || argv[1] /* silence -Wunused-parameter */) - fatal("Sorry, no for-each-ref options supported yet", NULL); - - check_lg2(git_repository_open(&repo, "."), - "Could not open repository", NULL); - check_lg2(git_reference_foreach(repo, show_ref, repo), - "Could not iterate over references", NULL); - - git_libgit2_shutdown(); - return 0; + UNUSED(argv); + + if (argc != 1) + fatal("Sorry, no for-each-ref options supported yet", NULL); + + check_lg2(git_reference_foreach(repo, show_ref, repo), + "Could not iterate over references", NULL); + + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/examples/general.c libgit2-1.1.0+dfsg.1/examples/general.c --- libgit2-0.28.5+dfsg.1/examples/general.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/general.c 2020-10-12 18:53:06.000000000 +0000 @@ -36,6 +36,8 @@ * [pg]: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain */ +#include "common.h" + /** * ### Includes * @@ -43,9 +45,7 @@ * that you need. It should be the only thing you need to include in order * to compile properly and get all the libgit2 API. */ -#include -#include -#include +#include "git2.h" static void oid_parsing(git_oid *out); static void object_database(git_repository *repo, git_oid *oid); @@ -76,12 +76,11 @@ exit(1); } -int main (int argc, char** argv) +int lg2_general(git_repository *repo, int argc, char** argv) { int error; git_oid oid; char *repo_path; - git_repository *repo; /** * Initialize the library, this will set up any global state which libgit2 needs @@ -625,7 +624,7 @@ static void index_walking(git_repository *repo) { git_index *index; - unsigned int i, ecount; + size_t i, ecount; printf("\n*Index Walking*\n"); @@ -708,7 +707,7 @@ git_reference_free(ref); } - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); } /** diff -Nru libgit2-0.28.5+dfsg.1/examples/index-pack.c libgit2-1.1.0+dfsg.1/examples/index-pack.c --- libgit2-0.28.5+dfsg.1/examples/index-pack.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/index-pack.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,71 @@ +#include "common.h" + +/* + * This could be run in the main loop whilst the application waits for + * the indexing to finish in a worker thread + */ +static int index_cb(const git_indexer_progress *stats, void *data) +{ + (void)data; + printf("\rProcessing %u of %u", stats->indexed_objects, stats->total_objects); + + return 0; +} + +int lg2_index_pack(git_repository *repo, int argc, char **argv) +{ + git_indexer *idx; + git_indexer_progress stats = {0, 0}; + int error; + char hash[GIT_OID_HEXSZ + 1] = {0}; + int fd; + ssize_t read_bytes; + char buf[512]; + + (void)repo; + + if (argc < 2) { + fprintf(stderr, "usage: %s index-pack \n", argv[-1]); + return EXIT_FAILURE; + } + + if (git_indexer_new(&idx, ".", 0, NULL, NULL) < 0) { + puts("bad idx"); + return -1; + } + + if ((fd = open(argv[1], 0)) < 0) { + perror("open"); + return -1; + } + + do { + read_bytes = read(fd, buf, sizeof(buf)); + if (read_bytes < 0) + break; + + if ((error = git_indexer_append(idx, buf, read_bytes, &stats)) < 0) + goto cleanup; + + index_cb(&stats, NULL); + } while (read_bytes > 0); + + if (read_bytes < 0) { + error = -1; + perror("failed reading"); + goto cleanup; + } + + if ((error = git_indexer_commit(idx, &stats)) < 0) + goto cleanup; + + printf("\rIndexing %u of %u\n", stats.indexed_objects, stats.total_objects); + + git_oid_fmt(hash, git_indexer_hash(idx)); + puts(hash); + + cleanup: + close(fd); + git_indexer_free(idx); + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/init.c libgit2-1.1.0+dfsg.1/examples/init.c --- libgit2-0.28.5+dfsg.1/examples/init.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/init.c 2020-10-12 18:53:06.000000000 +0000 @@ -27,7 +27,7 @@ */ /** Forward declarations of helpers */ -struct opts { +struct init_opts { int no_options; int quiet; int bare; @@ -38,15 +38,11 @@ const char *dir; }; static void create_initial_commit(git_repository *repo); -static void parse_opts(struct opts *o, int argc, char *argv[]); +static void parse_opts(struct init_opts *o, int argc, char *argv[]); - -int main(int argc, char *argv[]) +int lg2_init(git_repository *repo, int argc, char *argv[]) { - git_repository *repo = NULL; - struct opts o = { 1, 0, 0, 0, GIT_REPOSITORY_INIT_SHARED_UMASK, 0, 0, 0 }; - - git_libgit2_init(); + struct init_opts o = { 1, 0, 0, 0, GIT_REPOSITORY_INIT_SHARED_UMASK, 0, 0, 0 }; parse_opts(&o, argc, argv); @@ -116,7 +112,6 @@ } git_repository_free(repo); - git_libgit2_shutdown(); return 0; } @@ -215,7 +210,7 @@ return 0; } -static void parse_opts(struct opts *o, int argc, char *argv[]) +static void parse_opts(struct init_opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; const char *sharedarg; @@ -249,5 +244,5 @@ } if (!o->dir) - usage("must specify directory to init", NULL); + usage("must specify directory to init", ""); } diff -Nru libgit2-0.28.5+dfsg.1/examples/lg2.c libgit2-1.1.0+dfsg.1/examples/lg2.c --- libgit2-0.28.5+dfsg.1/examples/lg2.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/lg2.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,124 @@ +#include "common.h" + +/* This part is not strictly libgit2-dependent, but you can use this + * as a starting point for a git-like tool */ + +typedef int (*git_command_fn)(git_repository *, int , char **); + +struct { + char *name; + git_command_fn fn; + char requires_repo; +} commands[] = { + { "add", lg2_add, 1 }, + { "blame", lg2_blame, 1 }, + { "cat-file", lg2_cat_file, 1 }, + { "checkout", lg2_checkout, 1 }, + { "clone", lg2_clone, 0 }, + { "commit", lg2_commit, 1 }, + { "config", lg2_config, 1 }, + { "describe", lg2_describe, 1 }, + { "diff", lg2_diff, 1 }, + { "fetch", lg2_fetch, 1 }, + { "for-each-ref", lg2_for_each_ref, 1 }, + { "general", lg2_general, 0 }, + { "index-pack", lg2_index_pack, 1 }, + { "init", lg2_init, 0 }, + { "log", lg2_log, 1 }, + { "ls-files", lg2_ls_files, 1 }, + { "ls-remote", lg2_ls_remote, 1 }, + { "merge", lg2_merge, 1 }, + { "push", lg2_push, 1 }, + { "remote", lg2_remote, 1 }, + { "rev-list", lg2_rev_list, 1 }, + { "rev-parse", lg2_rev_parse, 1 }, + { "show-index", lg2_show_index, 0 }, + { "stash", lg2_stash, 1 }, + { "status", lg2_status, 1 }, + { "tag", lg2_tag, 1 }, +}; + +static int run_command(git_command_fn fn, git_repository *repo, struct args_info args) +{ + int error; + + /* Run the command. If something goes wrong, print the error message to stderr */ + error = fn(repo, args.argc - args.pos, &args.argv[args.pos]); + if (error < 0) { + if (git_error_last() == NULL) + fprintf(stderr, "Error without message"); + else + fprintf(stderr, "Bad news:\n %s\n", git_error_last()->message); + } + + return !!error; +} + +static int usage(const char *prog) +{ + size_t i; + + fprintf(stderr, "usage: %s ...\n\nAvailable commands:\n\n", prog); + for (i = 0; i < ARRAY_SIZE(commands); i++) + fprintf(stderr, "\t%s\n", commands[i].name); + + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + struct args_info args = ARGS_INFO_INIT; + git_repository *repo = NULL; + const char *git_dir = NULL; + int return_code = 1; + size_t i; + + if (argc < 2) + usage(argv[0]); + + git_libgit2_init(); + + for (args.pos = 1; args.pos < args.argc; ++args.pos) { + char *a = args.argv[args.pos]; + + if (a[0] != '-') { + /* non-arg */ + break; + } else if (optional_str_arg(&git_dir, &args, "--git-dir", ".git")) { + continue; + } else if (match_arg_separator(&args)) { + break; + } + } + + if (args.pos == args.argc) + usage(argv[0]); + + if (!git_dir) + git_dir = "."; + + for (i = 0; i < ARRAY_SIZE(commands); ++i) { + if (strcmp(args.argv[args.pos], commands[i].name)) + continue; + + /* + * Before running the actual command, create an instance + * of the local repository and pass it to the function. + * */ + if (commands[i].requires_repo) { + check_lg2(git_repository_open_ext(&repo, git_dir, 0, NULL), + "Unable to open repository '%s'", git_dir); + } + + return_code = run_command(commands[i].fn, repo, args); + goto shutdown; + } + + fprintf(stderr, "Command not found: %s\n", argv[1]); + +shutdown: + git_repository_free(repo); + git_libgit2_shutdown(); + + return return_code; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/log.c libgit2-1.1.0+dfsg.1/examples/log.c --- libgit2-0.28.5+dfsg.1/examples/log.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/log.c 2020-10-12 18:53:06.000000000 +0000 @@ -71,7 +71,7 @@ static int signature_matches(const git_signature *sig, const char *filter); static int log_message_matches(const git_commit *commit, const char *filter); -int main(int argc, char *argv[]) +int lg2_log(git_repository *repo, int argc, char *argv[]) { int i, count = 0, printed = 0, parents, last_arg; struct log_state s; @@ -81,11 +81,9 @@ git_commit *commit = NULL; git_pathspec *ps = NULL; - git_libgit2_init(); - /** Parse arguments and set up revwalker. */ - last_arg = parse_options(&s, &opt, argc, argv); + s.repo = repo; diffopts.pathspec.strings = &argv[last_arg]; diffopts.pathspec.count = argc - last_arg; @@ -180,8 +178,6 @@ git_pathspec_free(ps); git_revwalk_free(s.walker); - git_repository_free(s.repo); - git_libgit2_shutdown(); return 0; } @@ -243,13 +239,6 @@ git_revspec revs; int hide = 0; - /** Open repo on demand if it isn't already open. */ - if (!s->repo) { - if (!s->repodir) s->repodir = "."; - check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), - "Could not open repository", s->repodir); - } - if (!revstr) { push_rev(s, NULL, hide); return 0; @@ -435,8 +424,7 @@ else /** Try failed revision parse as filename. */ break; - } else if (!strcmp(a, "--")) { - ++args.pos; + } else if (!match_arg_separator(&args)) { break; } else if (!strcmp(a, "--date-order")) @@ -446,21 +434,28 @@ else if (!strcmp(a, "--reverse")) set_sorting(s, GIT_SORT_REVERSE); else if (match_str_arg(&opt->author, &args, "--author")) - /** Found valid --author */; + /** Found valid --author */ + ; else if (match_str_arg(&opt->committer, &args, "--committer")) - /** Found valid --committer */; + /** Found valid --committer */ + ; else if (match_str_arg(&opt->grep, &args, "--grep")) - /** Found valid --grep */; + /** Found valid --grep */ + ; else if (match_str_arg(&s->repodir, &args, "--git-dir")) - /** Found git-dir. */; + /** Found git-dir. */ + ; else if (match_int_arg(&opt->skip, &args, "--skip", 0)) - /** Found valid --skip. */; + /** Found valid --skip. */ + ; else if (match_int_arg(&opt->limit, &args, "--max-count", 0)) - /** Found valid --max-count. */; + /** Found valid --max-count. */ + ; else if (a[1] >= '0' && a[1] <= '9') is_integer(&opt->limit, a + 1, 0); else if (match_int_arg(&opt->limit, &args, "-n", 0)) - /** Found valid -n. */; + /** Found valid -n. */ + ; else if (!strcmp(a, "--merges")) opt->min_parents = 2; else if (!strcmp(a, "--no-merges")) @@ -470,9 +465,11 @@ else if (!strcmp(a, "--no-max-parents")) opt->max_parents = -1; else if (match_int_arg(&opt->max_parents, &args, "--max-parents=", 1)) - /** Found valid --max-parents. */; + /** Found valid --max-parents. */ + ; else if (match_int_arg(&opt->min_parents, &args, "--min-parents=", 0)) - /** Found valid --min_parents. */; + /** Found valid --min_parents. */ + ; else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) opt->show_diff = 1; else if (!strcmp(a, "--log-size")) diff -Nru libgit2-0.28.5+dfsg.1/examples/ls-files.c libgit2-1.1.0+dfsg.1/examples/ls-files.c --- libgit2-0.28.5+dfsg.1/examples/ls-files.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/ls-files.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,7 +13,6 @@ */ #include "common.h" -#include "array.h" /** * This example demonstrates the libgit2 index APIs to roughly @@ -26,11 +25,11 @@ * This currently supports the default behavior and the `--error-unmatch` option. */ -typedef struct { +struct ls_options { int error_unmatch; char *files[1024]; size_t file_count; -} ls_options; +}; static void usage(const char *message, const char *arg) { @@ -42,12 +41,12 @@ exit(1); } -static int parse_options(ls_options *opts, int argc, char *argv[]) +static int parse_options(struct ls_options *opts, int argc, char *argv[]) { int parsing_files = 0; int i; - memset(opts, 0, sizeof(ls_options)); + memset(opts, 0, sizeof(struct ls_options)); if (argc < 2) return 0; @@ -79,7 +78,7 @@ return 0; } -static int print_paths(ls_options *opts, git_index *index) +static int print_paths(struct ls_options *opts, git_index *index) { size_t i; const git_index_entry *entry; @@ -111,21 +110,15 @@ return 0; } -int main(int argc, char *argv[]) +int lg2_ls_files(git_repository *repo, int argc, char *argv[]) { - ls_options opts; - git_repository *repo = NULL; git_index *index = NULL; + struct ls_options opts; int error; if ((error = parse_options(&opts, argc, argv)) < 0) return error; - git_libgit2_init(); - - if ((error = git_repository_open_ext(&repo, ".", 0, NULL)) < 0) - goto cleanup; - if ((error = git_repository_index(&index, repo)) < 0) goto cleanup; @@ -133,8 +126,6 @@ cleanup: git_index_free(index); - git_repository_free(repo); - git_libgit2_shutdown(); return error; } diff -Nru libgit2-0.28.5+dfsg.1/examples/ls-remote.c libgit2-1.1.0+dfsg.1/examples/ls-remote.c --- libgit2-0.28.5+dfsg.1/examples/ls-remote.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/ls-remote.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,60 @@ +#include "common.h" + +static int use_remote(git_repository *repo, char *name) +{ + git_remote *remote = NULL; + int error; + const git_remote_head **refs; + size_t refs_len, i; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + /* Find the remote by name */ + error = git_remote_lookup(&remote, repo, name); + if (error < 0) { + error = git_remote_create_anonymous(&remote, repo, name); + if (error < 0) + goto cleanup; + } + + /** + * Connect to the remote and call the printing function for + * each of the remote references. + */ + callbacks.credentials = cred_acquire_cb; + + error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, NULL); + if (error < 0) + goto cleanup; + + /** + * Get the list of references on the remote and print out + * their name next to what they point to. + */ + if (git_remote_ls(&refs, &refs_len, remote) < 0) + goto cleanup; + + for (i = 0; i < refs_len; i++) { + char oid[GIT_OID_HEXSZ + 1] = {0}; + git_oid_fmt(oid, &refs[i]->oid); + printf("%s\t%s\n", oid, refs[i]->name); + } + +cleanup: + git_remote_free(remote); + return error; +} + +/** Entry point for this command */ +int lg2_ls_remote(git_repository *repo, int argc, char **argv) +{ + int error; + + if (argc < 2) { + fprintf(stderr, "usage: %s ls-remote \n", argv[-1]); + return EXIT_FAILURE; + } + + error = use_remote(repo, argv[1]); + + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/merge.c libgit2-1.1.0+dfsg.1/examples/merge.c --- libgit2-0.28.5+dfsg.1/examples/merge.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/merge.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,11 +13,6 @@ */ #include "common.h" -#include - -#ifdef _MSC_VER -#define snprintf sprintf_s -#endif /** The following example demonstrates how to do merges with libgit2. * @@ -28,7 +23,7 @@ * */ -typedef struct { +struct merge_options { const char **heads; size_t heads_count; @@ -36,7 +31,7 @@ size_t annotated_count; int no_commit : 1; -} merge_options; +}; static void print_usage(void) { @@ -44,7 +39,7 @@ exit(1); } -static void merge_options_init(merge_options *opts) +static void merge_options_init(struct merge_options *opts) { memset(opts, 0, sizeof(*opts)); @@ -54,18 +49,18 @@ opts->annotated_count = 0; } -static void opts_add_refish(merge_options *opts, const char *refish) +static void opts_add_refish(struct merge_options *opts, const char *refish) { size_t sz; assert(opts != NULL); sz = ++opts->heads_count * sizeof(opts->heads[0]); - opts->heads = xrealloc(opts->heads, sz); + opts->heads = xrealloc((void *) opts->heads, sz); opts->heads[opts->heads_count - 1] = refish; } -static void parse_options(const char **repo_path, merge_options *opts, int argc, char **argv) +static void parse_options(const char **repo_path, struct merge_options *opts, int argc, char **argv) { struct args_info args = ARGS_INFO_INIT; @@ -87,7 +82,7 @@ } } -static int resolve_heads(git_repository *repo, merge_options *opts) +static int resolve_heads(git_repository *repo, struct merge_options *opts) { git_annotated_commit **annotated = calloc(opts->heads_count, sizeof(git_annotated_commit *)); size_t annotated_count = 0, i; @@ -205,7 +200,7 @@ git_index_conflict_iterator_free(conflicts); } -static int create_merge_commit(git_repository *repo, git_index *index, merge_options *opts) +static int create_merge_commit(git_repository *repo, git_index *index, struct merge_options *opts) { git_oid tree_oid, commit_oid; git_tree *tree; @@ -224,6 +219,7 @@ check_lg2(git_repository_head(&head_ref, repo), "failed to get repo HEAD", NULL); if (resolve_refish(&merge_commit, repo, opts->heads[0])) { fprintf(stderr, "failed to resolve refish %s", opts->heads[0]); + free(parents); return -1; } @@ -278,10 +274,9 @@ return err; } -int main(int argc, char **argv) +int lg2_merge(git_repository *repo, int argc, char **argv) { - git_repository *repo = NULL; - merge_options opts; + struct merge_options opts; git_index *index; git_repository_state_t state; git_merge_analysis_t analysis; @@ -292,11 +287,6 @@ merge_options_init(&opts); parse_options(&path, &opts, argc, argv); - git_libgit2_init(); - - check_lg2(git_repository_open_ext(&repo, path, 0, NULL), - "Could not open repository", NULL); - state = git_repository_state(repo); if (state != GIT_REPOSITORY_STATE_NONE) { fprintf(stderr, "repository is in unexpected state %d\n", state); @@ -364,10 +354,8 @@ } cleanup: - free(opts.heads); + free((char **)opts.heads); free(opts.annotated); - git_repository_free(repo); - git_libgit2_shutdown(); return 0; } diff -Nru libgit2-0.28.5+dfsg.1/examples/network/clone.c libgit2-1.1.0+dfsg.1/examples/network/clone.c --- libgit2-0.28.5+dfsg.1/examples/network/clone.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/clone.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -#include "common.h" -#include -#include -#include -#include -#include -#ifndef _WIN32 -# include -# include -#endif - -typedef struct progress_data { - git_transfer_progress fetch_progress; - size_t completed_steps; - size_t total_steps; - const char *path; -} progress_data; - -static void print_progress(const progress_data *pd) -{ - int network_percent = pd->fetch_progress.total_objects > 0 ? - (100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects : - 0; - int index_percent = pd->fetch_progress.total_objects > 0 ? - (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects : - 0; - - int checkout_percent = pd->total_steps > 0 - ? (100 * pd->completed_steps) / pd->total_steps - : 0; - int kbytes = pd->fetch_progress.received_bytes / 1024; - - if (pd->fetch_progress.total_objects && - pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) { - printf("Resolving deltas %d/%d\r", - pd->fetch_progress.indexed_deltas, - pd->fetch_progress.total_deltas); - } else { - printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ ") %s\n", - network_percent, kbytes, - pd->fetch_progress.received_objects, pd->fetch_progress.total_objects, - index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects, - checkout_percent, - pd->completed_steps, pd->total_steps, - pd->path); - } -} - -static int sideband_progress(const char *str, int len, void *payload) -{ - (void)payload; /* unused */ - - printf("remote: %.*s", len, str); - fflush(stdout); - return 0; -} - -static int fetch_progress(const git_transfer_progress *stats, void *payload) -{ - progress_data *pd = (progress_data*)payload; - pd->fetch_progress = *stats; - print_progress(pd); - return 0; -} -static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) -{ - progress_data *pd = (progress_data*)payload; - pd->completed_steps = cur; - pd->total_steps = tot; - pd->path = path; - print_progress(pd); -} - - -int do_clone(git_repository *repo, int argc, char **argv) -{ - progress_data pd = {{0}}; - git_repository *cloned_repo = NULL; - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; - const char *url = argv[1]; - const char *path = argv[2]; - int error; - - (void)repo; /* unused */ - - /* Validate args */ - if (argc < 3) { - printf ("USAGE: %s \n", argv[0]); - return -1; - } - - /* Set up options */ - checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - checkout_opts.progress_cb = checkout_progress; - checkout_opts.progress_payload = &pd; - clone_opts.checkout_opts = checkout_opts; - clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress; - clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; - clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb; - clone_opts.fetch_opts.callbacks.payload = &pd; - - /* Do the clone */ - error = git_clone(&cloned_repo, url, path, &clone_opts); - printf("\n"); - if (error != 0) { - const git_error *err = git_error_last(); - if (err) printf("ERROR %d: %s\n", err->klass, err->message); - else printf("ERROR %d: no detailed info\n", error); - } - else if (cloned_repo) git_repository_free(cloned_repo); - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/common.c libgit2-1.1.0+dfsg.1/examples/network/common.c --- libgit2-0.28.5+dfsg.1/examples/network/common.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/common.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -#include "common.h" -#include -#include -#include - -/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/ - * with permission of the original author, Martin Pool. - * http://sourcefrog.net/weblog/software/languages/C/unused.html - */ -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - -static int readline(char **out) -{ - int c, error = 0, length = 0, allocated = 0; - char *line = NULL; - - errno = 0; - - while ((c = getchar()) != EOF) { - if (length == allocated) { - allocated += 16; - - if ((line = realloc(line, allocated)) == NULL) { - error = -1; - goto error; - } - } - - if (c == '\n') - break; - - line[length++] = c; - } - - if (errno != 0) { - error = -1; - goto error; - } - - line[length] = '\0'; - *out = line; - line = NULL; - error = length; -error: - free(line); - return error; -} - -int cred_acquire_cb(git_cred **out, - const char * UNUSED(url), - const char * UNUSED(username_from_url), - unsigned int UNUSED(allowed_types), - void * UNUSED(payload)) -{ - char *username = NULL, *password = NULL; - int error; - - printf("Username: "); - if (readline(&username) < 0) { - fprintf(stderr, "Unable to read username: %s", strerror(errno)); - return -1; - } - - /* Yup. Right there on your terminal. Careful where you copy/paste output. */ - printf("Password: "); - if (readline(&password) < 0) { - fprintf(stderr, "Unable to read password: %s", strerror(errno)); - free(username); - return -1; - } - - error = git_cred_userpass_plaintext_new(out, username, password); - - free(username); - free(password); - - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/common.h libgit2-1.1.0+dfsg.1/examples/network/common.h --- libgit2-0.28.5+dfsg.1/examples/network/common.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/common.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#ifndef __COMMON_H__ -#define __COMMON_H__ - -#include - -typedef int (*git_cb)(git_repository *, int , char **); - -int ls_remote(git_repository *repo, int argc, char **argv); -int parse_pkt_line(git_repository *repo, int argc, char **argv); -int show_remote(git_repository *repo, int argc, char **argv); -int fetch(git_repository *repo, int argc, char **argv); -int index_pack(git_repository *repo, int argc, char **argv); -int do_clone(git_repository *repo, int argc, char **argv); - -int cred_acquire_cb(git_cred **out, - const char * url, - const char * username_from_url, - unsigned int allowed_types, - void *payload); - -#ifndef PRIuZ -/* Define the printf format specifer to use for size_t output */ -#if defined(_MSC_VER) || defined(__MINGW32__) -# define PRIuZ "Iu" -#else -# define PRIuZ "zu" -#endif -#endif - -#endif /* __COMMON_H__ */ diff -Nru libgit2-0.28.5+dfsg.1/examples/network/fetch.c libgit2-1.1.0+dfsg.1/examples/network/fetch.c --- libgit2-0.28.5+dfsg.1/examples/network/fetch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/fetch.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -#include "common.h" -#include -#include -#include -#include -#ifndef _WIN32 -# include -# include -#endif - -static int progress_cb(const char *str, int len, void *data) -{ - (void)data; - printf("remote: %.*s", len, str); - fflush(stdout); /* We don't have the \n to force the flush */ - return 0; -} - -/** - * This function gets called for each remote-tracking branch that gets - * updated. The message we output depends on whether it's a new one or - * an update. - */ -static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) -{ - char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1]; - (void)data; - - git_oid_fmt(b_str, b); - b_str[GIT_OID_HEXSZ] = '\0'; - - if (git_oid_iszero(a)) { - printf("[new] %.20s %s\n", b_str, refname); - } else { - git_oid_fmt(a_str, a); - a_str[GIT_OID_HEXSZ] = '\0'; - printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname); - } - - return 0; -} - -/** - * This gets called during the download and indexing. Here we show - * processed and total objects in the pack and the amount of received - * data. Most frontends will probably want to show a percentage and - * the download rate. - */ -static int transfer_progress_cb(const git_transfer_progress *stats, void *payload) -{ - (void)payload; - - if (stats->received_objects == stats->total_objects) { - printf("Resolving deltas %d/%d\r", - stats->indexed_deltas, stats->total_deltas); - } else if (stats->total_objects > 0) { - printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r", - stats->received_objects, stats->total_objects, - stats->indexed_objects, stats->received_bytes); - } - return 0; -} - -/** Entry point for this command */ -int fetch(git_repository *repo, int argc, char **argv) -{ - git_remote *remote = NULL; - const git_transfer_progress *stats; - git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; - - if (argc < 2) { - fprintf(stderr, "usage: %s fetch \n", argv[-1]); - return EXIT_FAILURE; - } - - /* Figure out whether it's a named remote or a URL */ - printf("Fetching %s for repo %p\n", argv[1], repo); - if (git_remote_lookup(&remote, repo, argv[1]) < 0) - if (git_remote_create_anonymous(&remote, repo, argv[1]) < 0) - goto on_error; - - /* Set up the callbacks (only update_tips for now) */ - fetch_opts.callbacks.update_tips = &update_cb; - fetch_opts.callbacks.sideband_progress = &progress_cb; - fetch_opts.callbacks.transfer_progress = transfer_progress_cb; - fetch_opts.callbacks.credentials = cred_acquire_cb; - - /** - * Perform the fetch with the configured refspecs from the - * config. Update the reflog for the updated references with - * "fetch". - */ - if (git_remote_fetch(remote, NULL, &fetch_opts, "fetch") < 0) - goto on_error; - - /** - * If there are local objects (we got a thin pack), then tell - * the user how many objects we saved from having to cross the - * network. - */ - stats = git_remote_stats(remote); - if (stats->local_objects > 0) { - printf("\rReceived %d/%d objects in %" PRIuZ " bytes (used %d local objects)\n", - stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects); - } else{ - printf("\rReceived %d/%d objects in %" PRIuZ "bytes\n", - stats->indexed_objects, stats->total_objects, stats->received_bytes); - } - - git_remote_free(remote); - - return 0; - - on_error: - git_remote_free(remote); - return -1; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/git2.c libgit2-1.1.0+dfsg.1/examples/network/git2.c --- libgit2-0.28.5+dfsg.1/examples/network/git2.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/git2.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#include -#include -#include - -#include "../common.h" -#include "common.h" - -/* This part is not strictly libgit2-dependent, but you can use this - * as a starting point for a git-like tool */ - -struct { - char *name; - git_cb fn; -} commands[] = { - {"ls-remote", ls_remote}, - {"fetch", fetch}, - {"clone", do_clone}, - {"index-pack", index_pack}, - { NULL, NULL} -}; - -static int run_command(git_cb fn, git_repository *repo, struct args_info args) -{ - int error; - - /* Run the command. If something goes wrong, print the error message to stderr */ - error = fn(repo, args.argc - args.pos, &args.argv[args.pos]); - if (error < 0) { - if (git_error_last() == NULL) - fprintf(stderr, "Error without message"); - else - fprintf(stderr, "Bad news:\n %s\n", git_error_last()->message); - } - - return !!error; -} - -int main(int argc, char **argv) -{ - int i; - int return_code = 1; - int error; - git_repository *repo; - struct args_info args = ARGS_INFO_INIT; - const char *git_dir = NULL; - - if (argc < 2) { - fprintf(stderr, "usage: %s [repo]\n", argv[0]); - exit(EXIT_FAILURE); - } - - git_libgit2_init(); - - for (args.pos = 1; args.pos < args.argc; ++args.pos) { - char *a = args.argv[args.pos]; - - if (a[0] != '-') { - /* non-arg */ - break; - } else if (optional_str_arg(&git_dir, &args, "--git-dir", ".git")) { - continue; - } else if (!strcmp(a, "--")) { - /* arg separator */ - break; - } - } - - /* Before running the actual command, create an instance of the local - * repository and pass it to the function. */ - - error = git_repository_open(&repo, git_dir); - if (error < 0) - repo = NULL; - - for (i = 0; commands[i].name != NULL; ++i) { - if (!strcmp(args.argv[args.pos], commands[i].name)) { - return_code = run_command(commands[i].fn, repo, args); - goto shutdown; - } - } - - fprintf(stderr, "Command not found: %s\n", argv[1]); - -shutdown: - git_repository_free(repo); - - git_libgit2_shutdown(); - - return return_code; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/.gitignore libgit2-1.1.0+dfsg.1/examples/network/.gitignore --- libgit2-0.28.5+dfsg.1/examples/network/.gitignore 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -/git2 diff -Nru libgit2-0.28.5+dfsg.1/examples/network/index-pack.c libgit2-1.1.0+dfsg.1/examples/network/index-pack.c --- libgit2-0.28.5+dfsg.1/examples/network/index-pack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/index-pack.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# include -# include - -# define open _open -# define read _read -# define close _close - -#define ssize_t unsigned int -#else -# include -#endif -#include "common.h" - -/* - * This could be run in the main loop whilst the application waits for - * the indexing to finish in a worker thread - */ -static int index_cb(const git_transfer_progress *stats, void *data) -{ - (void)data; - printf("\rProcessing %d of %d", stats->indexed_objects, stats->total_objects); - - return 0; -} - -int index_pack(git_repository *repo, int argc, char **argv) -{ - git_indexer *idx; - git_transfer_progress stats = {0, 0}; - int error; - char hash[GIT_OID_HEXSZ + 1] = {0}; - int fd; - ssize_t read_bytes; - char buf[512]; - - (void)repo; - - if (argc < 2) { - fprintf(stderr, "usage: %s index-pack \n", argv[-1]); - return EXIT_FAILURE; - } - - if (git_indexer_new(&idx, ".", 0, NULL, NULL) < 0) { - puts("bad idx"); - return -1; - } - - if ((fd = open(argv[1], 0)) < 0) { - perror("open"); - return -1; - } - - do { - read_bytes = read(fd, buf, sizeof(buf)); - if (read_bytes < 0) - break; - - if ((error = git_indexer_append(idx, buf, read_bytes, &stats)) < 0) - goto cleanup; - - index_cb(&stats, NULL); - } while (read_bytes > 0); - - if (read_bytes < 0) { - error = -1; - perror("failed reading"); - goto cleanup; - } - - if ((error = git_indexer_commit(idx, &stats)) < 0) - goto cleanup; - - printf("\rIndexing %d of %d\n", stats.indexed_objects, stats.total_objects); - - git_oid_fmt(hash, git_indexer_hash(idx)); - puts(hash); - - cleanup: - close(fd); - git_indexer_free(idx); - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/ls-remote.c libgit2-1.1.0+dfsg.1/examples/network/ls-remote.c --- libgit2-0.28.5+dfsg.1/examples/network/ls-remote.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/ls-remote.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -#include -#include -#include -#include -#include "common.h" - -static int use_remote(git_repository *repo, char *name) -{ - git_remote *remote = NULL; - int error; - const git_remote_head **refs; - size_t refs_len, i; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - /* Find the remote by name */ - error = git_remote_lookup(&remote, repo, name); - if (error < 0) { - error = git_remote_create_anonymous(&remote, repo, name); - if (error < 0) - goto cleanup; - } - - /** - * Connect to the remote and call the printing function for - * each of the remote references. - */ - callbacks.credentials = cred_acquire_cb; - - error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, NULL); - if (error < 0) - goto cleanup; - - /** - * Get the list of references on the remote and print out - * their name next to what they point to. - */ - if (git_remote_ls(&refs, &refs_len, remote) < 0) - goto cleanup; - - for (i = 0; i < refs_len; i++) { - char oid[GIT_OID_HEXSZ + 1] = {0}; - git_oid_fmt(oid, &refs[i]->oid); - printf("%s\t%s\n", oid, refs[i]->name); - } - -cleanup: - git_remote_free(remote); - return error; -} - -/** Entry point for this command */ -int ls_remote(git_repository *repo, int argc, char **argv) -{ - int error; - - if (argc < 2) { - fprintf(stderr, "usage: %s ls-remote \n", argv[-1]); - return EXIT_FAILURE; - } - - error = use_remote(repo, argv[1]); - - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/network/Makefile libgit2-1.1.0+dfsg.1/examples/network/Makefile --- libgit2-0.28.5+dfsg.1/examples/network/Makefile 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/network/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -default: all - -CC = gcc -CFLAGS += -g -CFLAGS += -I../../include -LDFLAGS += -L../../build -L../.. -LIBRARIES += -lgit2 -lpthread - -OBJECTS = \ - git2.o \ - ls-remote.o \ - fetch.o \ - clone.o \ - index-pack.o \ - common.o - -all: $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) -o git2 $(OBJECTS) $(LIBRARIES) - -clean: - $(RM) $(OBJECTS) - $(RM) git2 diff -Nru libgit2-0.28.5+dfsg.1/examples/push.c libgit2-1.1.0+dfsg.1/examples/push.c --- libgit2-0.28.5+dfsg.1/examples/push.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/push.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * libgit2 "push" example - shows how to push to remote + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include "common.h" + +/** + * This example demonstrates the libgit2 push API to roughly + * simulate `git push`. + * + * This does not have: + * + * - Robust error handling + * - Any of the `git push` options + * + * This does have: + * + * - Example of push to origin/master + * + */ + +/** Entry point for this command */ +int lg2_push(git_repository *repo, int argc, char **argv) { + git_push_options options; + git_remote* remote = NULL; + char *refspec = "refs/heads/master"; + const git_strarray refspecs = { + &refspec, + 1 + }; + + /* Validate args */ + if (argc > 1) { + printf ("USAGE: %s\n\nsorry, no arguments supported yet\n", argv[0]); + return -1; + } + + check_lg2(git_remote_lookup(&remote, repo, "origin" ), "Unable to lookup remote", NULL); + + check_lg2(git_push_options_init(&options, GIT_PUSH_OPTIONS_VERSION ), "Error initializing push", NULL); + + check_lg2(git_remote_push(remote, &refspecs, &options), "Error pushing", NULL); + + printf("pushed\n"); + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/remote.c libgit2-1.1.0+dfsg.1/examples/remote.c --- libgit2-0.28.5+dfsg.1/examples/remote.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/remote.c 2020-10-12 18:53:06.000000000 +0000 @@ -30,7 +30,7 @@ subcmd_show, }; -struct opts { +struct remote_opts { enum subcmd cmd; /* for command-specific args */ @@ -38,34 +38,23 @@ char **argv; }; -static int cmd_add(git_repository *repo, struct opts *o); -static int cmd_remove(git_repository *repo, struct opts *o); -static int cmd_rename(git_repository *repo, struct opts *o); -static int cmd_seturl(git_repository *repo, struct opts *o); -static int cmd_show(git_repository *repo, struct opts *o); +static int cmd_add(git_repository *repo, struct remote_opts *o); +static int cmd_remove(git_repository *repo, struct remote_opts *o); +static int cmd_rename(git_repository *repo, struct remote_opts *o); +static int cmd_seturl(git_repository *repo, struct remote_opts *o); +static int cmd_show(git_repository *repo, struct remote_opts *o); static void parse_subcmd( - struct opts *opt, int argc, char **argv); + struct remote_opts *opt, int argc, char **argv); static void usage(const char *msg, const char *arg); -int main(int argc, char *argv[]) +int lg2_remote(git_repository *repo, int argc, char *argv[]) { int retval = 0; - struct opts opt = {0}; - git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); - git_repository *repo = NULL; + struct remote_opts opt = {0}; parse_subcmd(&opt, argc, argv); - git_libgit2_init(); - - check_lg2(git_repository_discover(&buf, ".", 0, NULL), - "Could not find repository", NULL); - - check_lg2(git_repository_open(&repo, buf.ptr), - "Could not open repository", NULL); - git_buf_dispose(&buf); - switch (opt.cmd) { case subcmd_add: @@ -85,12 +74,10 @@ break; } - git_libgit2_shutdown(); - return retval; } -static int cmd_add(git_repository *repo, struct opts *o) +static int cmd_add(git_repository *repo, struct remote_opts *o) { char *name, *url; git_remote *remote = {0}; @@ -107,7 +94,7 @@ return 0; } -static int cmd_remove(git_repository *repo, struct opts *o) +static int cmd_remove(git_repository *repo, struct remote_opts *o) { char *name; @@ -122,7 +109,7 @@ return 0; } -static int cmd_rename(git_repository *repo, struct opts *o) +static int cmd_rename(git_repository *repo, struct remote_opts *o) { int i, retval; char *old, *new; @@ -142,12 +129,12 @@ puts(problems.strings[0]); } - git_strarray_free(&problems); + git_strarray_dispose(&problems); return retval; } -static int cmd_seturl(git_repository *repo, struct opts *o) +static int cmd_seturl(git_repository *repo, struct remote_opts *o) { int i, retval, push = 0; char *name = NULL, *url = NULL; @@ -179,7 +166,7 @@ return 0; } -static int cmd_show(git_repository *repo, struct opts *o) +static int cmd_show(git_repository *repo, struct remote_opts *o) { int i; const char *arg, *name, *fetch, *push; @@ -220,13 +207,13 @@ git_remote_free(remote); } - git_strarray_free(&remotes); + git_strarray_dispose(&remotes); return 0; } static void parse_subcmd( - struct opts *opt, int argc, char **argv) + struct remote_opts *opt, int argc, char **argv) { char *arg = argv[1]; enum subcmd cmd = 0; diff -Nru libgit2-0.28.5+dfsg.1/examples/rev-list.c libgit2-1.1.0+dfsg.1/examples/rev-list.c --- libgit2-0.28.5+dfsg.1/examples/rev-list.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/rev-list.c 2020-10-12 18:53:06.000000000 +0000 @@ -15,20 +15,24 @@ #include "common.h" -static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts); +#include -int main (int argc, char **argv) +static int revwalk_parse_options(git_sort_t *sort, struct args_info *args); +static int revwalk_parse_revs(git_repository *repo, git_revwalk *walk, struct args_info *args); + +int lg2_rev_list(git_repository *repo, int argc, char **argv) { - git_repository *repo; + struct args_info args = ARGS_INFO_INIT; git_revwalk *walk; git_oid oid; + git_sort_t sort; char buf[GIT_OID_HEXSZ+1]; - git_libgit2_init(); + check_lg2(revwalk_parse_options(&sort, &args), "parsing options", NULL); - check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "opening repository", NULL); check_lg2(git_revwalk_new(&walk, repo), "allocating revwalk", NULL); - check_lg2(revwalk_parseopts(repo, walk, argc-1, argv+1), "parsing options", NULL); + git_revwalk_sorting(walk, sort); + check_lg2(revwalk_parse_revs(repo, walk, &args), "parsing revs", NULL); while (!git_revwalk_next(&oid, walk)) { git_oid_fmt(buf, &oid); @@ -36,7 +40,7 @@ printf("%s\n", buf); } - git_libgit2_shutdown(); + git_revwalk_free(walk); return 0; } @@ -85,33 +89,60 @@ return error; } -static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts) +static void print_usage(void) +{ + fprintf(stderr, "rev-list [--git-dir=dir] [--topo-order|--date-order] [--reverse] \n"); + exit(-1); +} + +static int revwalk_parse_options(git_sort_t *sort, struct args_info *args) +{ + assert(sort && args); + *sort = GIT_SORT_NONE; + + if (args->argc < 1) + print_usage(); + + for (args->pos = 1; args->pos < args->argc; ++args->pos) { + const char *curr = args->argv[args->pos]; + + if (!strcmp(curr, "--topo-order")) { + *sort |= GIT_SORT_TOPOLOGICAL; + } else if (!strcmp(curr, "--date-order")) { + *sort |= GIT_SORT_TIME; + } else if (!strcmp(curr, "--reverse")) { + *sort |= (*sort & ~GIT_SORT_REVERSE) ^ GIT_SORT_REVERSE; + } else { + break; + } + } + return 0; +} + +static int revwalk_parse_revs(git_repository *repo, git_revwalk *walk, struct args_info *args) { - int hide, i, error; - unsigned int sorting = GIT_SORT_NONE; + int hide, error; + git_oid oid; hide = 0; - for (i = 0; i < nopts; i++) { - if (!strcmp(opts[i], "--topo-order")) { - sorting = GIT_SORT_TOPOLOGICAL | (sorting & GIT_SORT_REVERSE); - git_revwalk_sorting(walk, sorting); - } else if (!strcmp(opts[i], "--date-order")) { - sorting = GIT_SORT_TIME | (sorting & GIT_SORT_REVERSE); - git_revwalk_sorting(walk, sorting); - } else if (!strcmp(opts[i], "--reverse")) { - sorting = (sorting & ~GIT_SORT_REVERSE) - | ((sorting & GIT_SORT_REVERSE) ? 0 : GIT_SORT_REVERSE); - git_revwalk_sorting(walk, sorting); - } else if (!strcmp(opts[i], "--not")) { + for (; args->pos < args->argc; ++args->pos) { + const char *curr = args->argv[args->pos]; + + if (!strcmp(curr, "--not")) { hide = !hide; - } else if (opts[i][0] == '^') { - if ((error = push_spec(repo, walk, opts[i] + 1, !hide))) + } else if (curr[0] == '^') { + if ((error = push_spec(repo, walk, curr + 1, !hide))) return error; - } else if (strstr(opts[i], "..")) { - if ((error = push_range(repo, walk, opts[i], hide))) + } else if (strstr(curr, "..")) { + if ((error = push_range(repo, walk, curr, hide))) return error; } else { - if ((error = push_spec(repo, walk, opts[i], hide))) + if (push_spec(repo, walk, curr, hide) == 0) + continue; + + if ((error = git_oid_fromstr(&oid, curr))) + return error; + if ((error = push_commit(walk, &oid, hide))) return error; } } diff -Nru libgit2-0.28.5+dfsg.1/examples/rev-parse.c libgit2-1.1.0+dfsg.1/examples/rev-parse.c --- libgit2-0.28.5+dfsg.1/examples/rev-parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/rev-parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,26 +16,20 @@ /** Forward declarations for helpers. */ struct parse_state { - git_repository *repo; const char *repodir; const char *spec; int not; }; static void parse_opts(struct parse_state *ps, int argc, char *argv[]); -static int parse_revision(struct parse_state *ps); +static int parse_revision(git_repository *repo, struct parse_state *ps); - -int main(int argc, char *argv[]) +int lg2_rev_parse(git_repository *repo, int argc, char *argv[]) { struct parse_state ps = {0}; - git_libgit2_init(); parse_opts(&ps, argc, argv); - check_lg2(parse_revision(&ps), "Parsing", NULL); - - git_repository_free(ps.repo); - git_libgit2_shutdown(); + check_lg2(parse_revision(repo, &ps), "Parsing", NULL); return 0; } @@ -68,19 +62,12 @@ } } -static int parse_revision(struct parse_state *ps) +static int parse_revision(git_repository *repo, struct parse_state *ps) { git_revspec rs; char str[GIT_OID_HEXSZ + 1]; - if (!ps->repo) { - if (!ps->repodir) - ps->repodir = "."; - check_lg2(git_repository_open_ext(&ps->repo, ps->repodir, 0, NULL), - "Could not open repository from", ps->repodir); - } - - check_lg2(git_revparse(&rs, ps->repo, ps->spec), "Could not parse", ps->spec); + check_lg2(git_revparse(&rs, repo, ps->spec), "Could not parse", ps->spec); if ((rs.flags & GIT_REVPARSE_SINGLE) != 0) { git_oid_tostr(str, sizeof(str), git_object_id(rs.from)); @@ -94,7 +81,7 @@ if ((rs.flags & GIT_REVPARSE_MERGE_BASE) != 0) { git_oid base; - check_lg2(git_merge_base(&base, ps->repo, + check_lg2(git_merge_base(&base, repo, git_object_id(rs.from), git_object_id(rs.to)), "Could not find merge base", ps->spec); diff -Nru libgit2-0.28.5+dfsg.1/examples/show-index.c libgit2-1.1.0+dfsg.1/examples/show-index.c --- libgit2-0.28.5+dfsg.1/examples/show-index.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/show-index.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * libgit2 "showindex" example - shows how to extract data from the index + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include "common.h" + +int lg2_show_index(git_repository *repo, int argc, char **argv) +{ + git_index *index; + size_t i, ecount; + char *dir = "."; + size_t dirlen; + char out[GIT_OID_HEXSZ+1]; + out[GIT_OID_HEXSZ] = '\0'; + + if (argc > 2) + fatal("usage: showindex []", NULL); + if (argc > 1) + dir = argv[1]; + + dirlen = strlen(dir); + if (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) { + check_lg2(git_index_open(&index, dir), "could not open index", dir); + } 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); + git_repository_free(repo); + } + + git_index_read(index, 0); + + ecount = git_index_entrycount(index); + if (!ecount) + printf("Empty index\n"); + + for (i = 0; i < ecount; ++i) { + const git_index_entry *e = git_index_get_byindex(index, i); + + git_oid_fmt(out, &e->id); + + printf("File Path: %s\n", e->path); + printf(" Stage: %d\n", git_index_entry_stage(e)); + printf(" Blob SHA: %s\n", out); + printf("File Mode: %07o\n", e->mode); + printf("File Size: %d bytes\n", (int)e->file_size); + printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); + printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); + printf(" ctime: %d\n", (int)e->ctime.seconds); + printf(" mtime: %d\n", (int)e->mtime.seconds); + printf("\n"); + } + + git_index_free(index); + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/showindex.c libgit2-1.1.0+dfsg.1/examples/showindex.c --- libgit2-0.28.5+dfsg.1/examples/showindex.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/showindex.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * libgit2 "showindex" example - shows how to extract data from the index - * - * Written by the libgit2 contributors - * - * To the extent possible under law, the author(s) have dedicated all copyright - * and related and neighboring rights to this software to the public domain - * worldwide. This software is distributed without any warranty. - * - * You should have received a copy of the CC0 Public Domain Dedication along - * with this software. If not, see - * . - */ - -#include "common.h" - -int main (int argc, char** argv) -{ - git_index *index; - unsigned int i, ecount; - char *dir = "."; - size_t dirlen; - char out[GIT_OID_HEXSZ+1]; - out[GIT_OID_HEXSZ] = '\0'; - - git_libgit2_init(); - - if (argc > 2) - fatal("usage: showindex []", NULL); - if (argc > 1) - dir = argv[1]; - - dirlen = strlen(dir); - if (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) { - check_lg2(git_index_open(&index, dir), "could not open index", dir); - } else { - git_repository *repo; - 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); - git_repository_free(repo); - } - - git_index_read(index, 0); - - ecount = git_index_entrycount(index); - if (!ecount) - printf("Empty index\n"); - - for (i = 0; i < ecount; ++i) { - const git_index_entry *e = git_index_get_byindex(index, i); - - git_oid_fmt(out, &e->id); - - printf("File Path: %s\n", e->path); - printf(" Stage: %d\n", git_index_entry_stage(e)); - printf(" Blob SHA: %s\n", out); - printf("File Mode: %07o\n", e->mode); - printf("File Size: %d bytes\n", (int)e->file_size); - printf("Dev/Inode: %d/%d\n", (int)e->dev, (int)e->ino); - printf(" UID/GID: %d/%d\n", (int)e->uid, (int)e->gid); - printf(" ctime: %d\n", (int)e->ctime.seconds); - printf(" mtime: %d\n", (int)e->mtime.seconds); - printf("\n"); - } - - git_index_free(index); - git_libgit2_shutdown(); - - return 0; -} diff -Nru libgit2-0.28.5+dfsg.1/examples/stash.c libgit2-1.1.0+dfsg.1/examples/stash.c --- libgit2-0.28.5+dfsg.1/examples/stash.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/stash.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,157 @@ +/* + * libgit2 "stash" example - shows how to use the stash API + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include + +#include "common.h" + +enum subcmd { + SUBCMD_APPLY, + SUBCMD_LIST, + SUBCMD_POP, + SUBCMD_PUSH +}; + +struct opts { + enum subcmd cmd; + int argc; + char **argv; +}; + +static void usage(const char *fmt, ...) +{ + va_list ap; + + fputs("usage: git stash list\n", stderr); + fputs(" or: git stash ( pop | apply )\n", stderr); + fputs(" or: git stash [push]\n", stderr); + fputs("\n", stderr); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + +static void parse_subcommand(struct opts *opts, int argc, char *argv[]) +{ + char *arg = (argc < 2) ? "push" : argv[1]; + enum subcmd cmd; + + if (!strcmp(arg, "apply")) { + cmd = SUBCMD_APPLY; + } else if (!strcmp(arg, "list")) { + cmd = SUBCMD_LIST; + } else if (!strcmp(arg, "pop")) { + cmd = SUBCMD_POP; + } else if (!strcmp(arg, "push")) { + cmd = SUBCMD_PUSH; + } else { + usage("invalid command %s", arg); + return; + } + + opts->cmd = cmd; + opts->argc = (argc < 2) ? argc - 1 : argc - 2; + opts->argv = argv; +} + +static int cmd_apply(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("apply does not accept any parameters"); + + check_lg2(git_stash_apply(repo, 0, NULL), + "Unable to apply stash", NULL); + + return 0; +} + +static int list_stash_cb(size_t index, const char *message, + const git_oid *stash_id, void *payload) +{ + UNUSED(stash_id); + UNUSED(payload); + printf("stash@{%"PRIuZ"}: %s\n", index, message); + return 0; +} + +static int cmd_list(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("list does not accept any parameters"); + + check_lg2(git_stash_foreach(repo, list_stash_cb, NULL), + "Unable to list stashes", NULL); + + return 0; +} + +static int cmd_push(git_repository *repo, struct opts *opts) +{ + git_signature *signature; + git_commit *stash; + git_oid stashid; + + if (opts->argc) + usage("push does not accept any parameters"); + + check_lg2(git_signature_default(&signature, repo), + "Unable to get signature", NULL); + check_lg2(git_stash_save(&stashid, repo, signature, NULL, GIT_STASH_DEFAULT), + "Unable to save stash", NULL); + check_lg2(git_commit_lookup(&stash, repo, &stashid), + "Unable to lookup stash commit", NULL); + + printf("Saved working directory %s\n", git_commit_summary(stash)); + + git_signature_free(signature); + git_commit_free(stash); + + return 0; +} + +static int cmd_pop(git_repository *repo, struct opts *opts) +{ + if (opts->argc) + usage("pop does not accept any parameters"); + + check_lg2(git_stash_pop(repo, 0, NULL), + "Unable to pop stash", NULL); + + printf("Dropped refs/stash@{0}\n"); + + return 0; +} + +int lg2_stash(git_repository *repo, int argc, char *argv[]) +{ + struct opts opts = { 0 }; + + parse_subcommand(&opts, argc, argv); + + switch (opts.cmd) { + case SUBCMD_APPLY: + return cmd_apply(repo, &opts); + case SUBCMD_LIST: + return cmd_list(repo, &opts); + case SUBCMD_PUSH: + return cmd_push(repo, &opts); + case SUBCMD_POP: + return cmd_pop(repo, &opts); + } + + return -1; +} diff -Nru libgit2-0.28.5+dfsg.1/examples/status.c libgit2-1.1.0+dfsg.1/examples/status.c --- libgit2-0.28.5+dfsg.1/examples/status.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/status.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,12 +13,6 @@ */ #include "common.h" -#ifdef _WIN32 -# include -# define sleep(a) Sleep(a * 1000) -#else -# include -#endif /** * This example demonstrates the use of the libgit2 status APIs, @@ -49,7 +43,7 @@ #define MAX_PATHSPEC 8 -struct opts { +struct status_opts { git_status_options statusopt; char *repodir; char *pathspec[MAX_PATHSPEC]; @@ -61,19 +55,16 @@ int repeat; }; -static void parse_opts(struct opts *o, int argc, char *argv[]); +static void parse_opts(struct status_opts *o, int argc, char *argv[]); static void show_branch(git_repository *repo, int format); static void print_long(git_status_list *status); static void print_short(git_repository *repo, git_status_list *status); static int print_submod(git_submodule *sm, const char *name, void *payload); -int main(int argc, char *argv[]) +int lg2_status(git_repository *repo, int argc, char *argv[]) { - git_repository *repo = NULL; git_status_list *status; - struct opts o = { GIT_STATUS_OPTIONS_INIT, "." }; - - git_libgit2_init(); + struct status_opts o = { GIT_STATUS_OPTIONS_INIT, "." }; o.statusopt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; o.statusopt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | @@ -82,13 +73,6 @@ parse_opts(&o, argc, argv); - /** - * Try to open the repository at the given path (or at the current - * directory if none was given). - */ - check_lg2(git_repository_open_ext(&repo, o.repodir, 0, NULL), - "Could not open repository", o.repodir); - if (git_repository_is_bare(repo)) fatal("Cannot report status on bare repository", git_repository_path(repo)); @@ -134,9 +118,6 @@ goto show_status; } - git_repository_free(repo); - git_libgit2_shutdown(); - return 0; } @@ -454,7 +435,7 @@ /** * Parse options that git's status command supports. */ -static void parse_opts(struct opts *o, int argc, char *argv[]) +static void parse_opts(struct status_opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; diff -Nru libgit2-0.28.5+dfsg.1/examples/tag.c libgit2-1.1.0+dfsg.1/examples/tag.c --- libgit2-0.28.5+dfsg.1/examples/tag.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/tag.c 2020-10-12 18:53:06.000000000 +0000 @@ -31,19 +31,19 @@ */ /** tag_options represents the parsed command line options */ -typedef struct { +struct tag_options { const char *message; const char *pattern; const char *tag_name; const char *target; int num_lines; int force; -} tag_options; +}; /** tag_state represents the current program state for dragging around */ typedef struct { git_repository *repo; - tag_options *opts; + struct tag_options *opts; } tag_state; /** An action to execute based on the command line arguments */ @@ -162,12 +162,12 @@ each_tag(tag_names.strings[i], state); } - git_strarray_free(&tag_names); + git_strarray_dispose(&tag_names); } static void action_delete_tag(tag_state *state) { - tag_options *opts = state->opts; + struct tag_options *opts = state->opts; git_object *obj; git_buf abbrev_oid = {0}; @@ -191,7 +191,7 @@ static void action_create_lighweight_tag(tag_state *state) { git_repository *repo = state->repo; - tag_options *opts = state->opts; + struct tag_options *opts = state->opts; git_oid oid; git_object *target; @@ -213,7 +213,7 @@ static void action_create_tag(tag_state *state) { git_repository *repo = state->repo; - tag_options *opts = state->opts; + struct tag_options *opts = state->opts; git_signature *tagger; git_oid oid; git_object *target; @@ -243,7 +243,7 @@ } /** Parse command line arguments and choose action to run when done */ -static void parse_options(tag_action *action, tag_options *opts, int argc, char **argv) +static void parse_options(tag_action *action, struct tag_options *opts, int argc, char **argv) { args_info args = ARGS_INFO_INIT; *action = &action_list_tags; @@ -281,7 +281,7 @@ } /** Initialize tag_options struct */ -static void tag_options_init(tag_options *opts) +static void tag_options_init(struct tag_options *opts) { memset(opts, 0, sizeof(*opts)); @@ -293,18 +293,12 @@ opts->force = 0; } -int main(int argc, char **argv) +int lg2_tag(git_repository *repo, int argc, char **argv) { - git_repository *repo; - tag_options opts; + struct tag_options opts; tag_action action; tag_state state; - git_libgit2_init(); - - check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), - "Could not open repository", NULL); - tag_options_init(&opts); parse_options(&action, &opts, argc, argv); @@ -312,8 +306,5 @@ state.opts = &opts; action(&state); - git_repository_free(repo); - git_libgit2_shutdown(); - return 0; } diff -Nru libgit2-0.28.5+dfsg.1/examples/test/test-rev-list.sh libgit2-1.1.0+dfsg.1/examples/test/test-rev-list.sh --- libgit2-0.28.5+dfsg.1/examples/test/test-rev-list.sh 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/examples/test/test-rev-list.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -#!/bin/bash - -THIS_FILE="$(readlink -f "$0")" -ROOT="$(dirname "$(dirname "$(dirname "$THIS_FILE")")")" -PROGRAM="$ROOT"/examples/rev-list -LIBDIR="$ROOT"/build -REPO="$ROOT"/tests/resources/testrepo.git - -cd "$REPO" - -run () { - LD_LIBRARY_PATH="$LIBDIR" "$PROGRAM" "$@" -} - -diff -u - <(run --date-order a4a7dce) </dev/null || -a4a7dce85cf63874e984719f4fdd239f5145052f -c47800c7266a2be04c571c04d5a6614691ea99bd -9fd738e8f7967c078dceed8190330fc8648ee56a -4a202b346bb0fb0db7eff3cffeb3c70babbd2045 -5b5b025afb0b4c913b4c338a42934a3863bf3644 -8496071c1b46c854b31185ea97743be6a8774479 -EOF -diff -u - <(echo "$out") </dev/null || -8496071c1b46c854b31185ea97743be6a8774479 -5b5b025afb0b4c913b4c338a42934a3863bf3644 -4a202b346bb0fb0db7eff3cffeb3c70babbd2045 -9fd738e8f7967c078dceed8190330fc8648ee56a -c47800c7266a2be04c571c04d5a6614691ea99bd -a4a7dce85cf63874e984719f4fdd239f5145052f -EOF -diff -u - <(echo "$out") </dev/null || -a4a7dce85cf63874e984719f4fdd239f5145052f -c47800c7266a2be04c571c04d5a6614691ea99bd -9fd738e8f7967c078dceed8190330fc8648ee56a -4a202b346bb0fb0db7eff3cffeb3c70babbd2045 -5b5b025afb0b4c913b4c338a42934a3863bf3644 -8496071c1b46c854b31185ea97743be6a8774479 -EOF -diff -u - <(echo "$out") < +#include "git2.h" #include "config_backend.h" -#include -#include -#include -#include -#include - #define UNUSED(x) (void)(x) int foreach_cb(const git_config_entry *entry, void *payload) Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/037cbbe0dc03807dd9d9e8629f1712d7df34ee18 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/039ee34fef8f323ed618a10abc0109df123d0cb5 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/054ee2c82bdb6a170106eb5d35f21bde2119d584 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãMÿãa \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/055ca4cbc961ebf5fd5c922b4f73880d3fbfe39d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/05c4e5eb1b97bc9b6973921fcb30d4c5e2eb79e4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0672eeda541a191cfc68d521a3c7ac0aac4057a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/06a58d1bd5562a668ebf01ef297fd774e0e587a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/06bf7c2461ae1049030f31b83ae76babfcc20c83 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/06c2db67ea65758d971346bfd6beaa61ed12f22c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/07f88eefaf12609b7370fe78b82be2955f1b41fd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/08495c5f3828a56c167de870d385c46ffdce03c5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/08ec8594e5b35fb9e8e0726584f720154f0b2b5d differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0903e378a493c596298074d6bff8de7f9ac25aa7 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãü7 \ No newline at end of file diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/09144a846f90f894049ef8a0ed0cc7ab4588dc6c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ÃØseed \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/09b40dd618373bfe4d3f2838f686a70f645e640b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0a00ef44d234c18d365ec41724dbf4f21b09d0c5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0a94e9f4a9b8cf56d52a9e3e7f2fa9a0a5c80d30 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0b35a123104b7872a7f15a710a23ef3594ace04d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0c3d7e6be32c014ea873440b0f095961d391af1a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0c65de477b89afc312a7e89cde06f8a17f65bd54 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0c81d0f368e979d2a0eb4598cbf1c9283936ba0c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0c95a44ae995070a5279a2991c36de2251081460 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0de38e2cb13167df7d5a882570633596f64bc4f4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0de96aa193045315457ade63c2614610c503db9e differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0e02deca2b16d71f8637933bd56dc8592ed9fdff 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãH \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0e44fc9176fe2c1bae4209369da5bc057f54b2d2 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/0f6c5fc9b6a68835364bbef8937560ee5a481938 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +©* \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/10d542d5c7da060a5f0664e21478a0d598e29844 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/118735f7786ae6b4c2f6b36314ab1f2cafe9c3c8 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛŠÛÛÛÛÛÛÛÛÛÛËÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛËÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/119b58eb353aa344264005016297fb911510ea0d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ec and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/127626832c30d6d94bb29384c0fde7ac6bca75ec differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1284f1a162588d4de87ca17149474644a0863b27 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1458599f19f1a967c787562bf8ec3e67677da9c8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/14ba6c1ddd05b22c6f2eae5f894721cd3efcbb16 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/158cdc0a5aa005f167a8588d0beed9eee4aa36f2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/15dafc6fa800327f694b5eb2fc4ebf007be9c117 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1613ed4b2e909871f8897fd6354ff80a4ac12f87 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/16daf4cb967bb47cf4566e9be7d96d3125bd2e12 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/177783dce78efee878f6d6020fd87ab107bb11a1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/17a5090400a1fedc45070e4b530a26f320a89097 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7cc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/17dea5cfa498f4d54384289a1daed0d15a85e7cc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdea and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/17e76ae5b54316679981113f52c27edc87dbcdea differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/191ed5e9334693c53fc843f692dbc3c2c63e8241 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/196a0ba4edb5bbfd66c1cda669abf0496573cf0e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/19742b6cee79fa5bf9b27dcbe367c82d0a399904 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1a21d7581d3b0a8d67934d48e91d45bd818836e8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1b2f96c5d75c7ca09b1012be4e6c3a7b248ed924 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1b604ff0683d0e23dc7945431f6514ba30d6ca0d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1b771dd5bd3ae2b1c42c4efe6c896c83b88a4f91 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1b793a4ee73fa8bf423da70fca5f39ef32a8d288 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1c9599ce00978780519272be279f508c402e3268 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1cc0068f9f63b12dc8fdd38f9ebfb96c42664e95 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1de6e1f5579da6e5c40f4ee23ac62e29e4f90541 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1eec93083260ebfab5f4c6d13119cf27c374b7e9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1f0f574addd363d1fed131289f301c5c033aaa8f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1f3e85cffdb545c1ba7c8bbe1ca18ec13e341038 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/1f6a66a92d5f083a73a82280a0a1ae0800e56ae5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/208e422322052efcdaeb1a09bbf06c5f476b8efc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1fe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/22d75b2c3937957b14eded621b638283ce7fe1fe differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/22f90ff68166a409acf8f89bf60a31ad2c64ab37 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/236ebad449d432b039d6ace1f250ef1fa2aa364d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/252a4e4bf7fb21792ec2f305fd88fa7c9168505f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/259e1faf7b7f12250062d36ded1193a9dbcae0f5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/25ad3dfb655ab4c853d0d277872310d9579c8e83 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/26210f5b8fdbf81b312feea48659ec6e2e083c0b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/263a2a0915be36d8cb2bc30774e37e0344262347 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2679bfbc2f4f7c10a304245da4e156e235377b63 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/270b7b567a63dd94bb2a90448bbbc2e2bbc4a261 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/271cd5c5e254a293d115588ee130040ef26b59e8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/27839a8035b48f8c19ab073808a03a95b6a90cc3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbad and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2810c385c9285cbdb65bcdab5175999fe547cbad differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/28afaf4ab4b092ccf987661e58009f96126bba63 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/29f842e86a891cff9f0b44c8aec19f7e23a47000 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2aa2549f617f19402d1feac61d4ca1af3545cc8a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2b73c2902eda6da41321493601003b29c3445713 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2bcec1274c5e7b2d7a581d851c016ef5b553fabe differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2dd9a328b6d4e29e42684347be5c4b7cd7dc1a66 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2ddc17ee7ee89bb7dbc673328d5f3e55c76e686e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2f71d5e99dc93618ed99fdb7c244a8f5e4a7eb4a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2f7cd0154d71a83e7b104670b2a77fbd285ffde2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/2f9d40ef790f5213234e95d123dce942b2d1d389 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/31577bacbca7017308d2a0c9ebfdd4fce513bbe4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcf and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3278f1bab88b80597d0066812d49f8bd3c7b1dcf differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/328160cae6235605ff70951a2f6ac669ba7bb397 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/337ed1bf91701a4c8926840259077e55938c6efc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/33a97d83ff7a774797b1751ea4bffbb4a22c58d9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/341021da9516401cf364ed2b7dfdda346db04f2f differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/341773a439cdecc58f55fb205ac584cd93ffe0f2 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãyyyyyššyyyyyyyyÅÅ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697de and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/366091157510e40bca08fc2102b9018ccf4697de differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/37096157e2f9f2ec8e0b97b21d335bd653f3edbd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/373a74b8613d09babcb567f91047e7b556a8de90 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3748b07ee7bec7bdd202ee14222cefca182417d1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/38b7906b9f956dca01dc92d0a901388ec1cbc8b1 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/38ddf3424559f1a6e7687eff8469a358184b833b 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ðã½D \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/38e31d0a7dcc3835ce1a4afeeda8446fb3d7ed73 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3955ec4497b226391ef9eb40f38af6dee4fa26b7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3b6b424342133feb0f587f22bcd8f21595c004e5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3bb71f41200e0ebf8d19532e7d6e384c48aa2d03 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3c5a6063797aba9ffe5ea9903bbfcf87193652d3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3dfb9927d959f2462f6944a32d080b60a265abfe differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3e19242a63ec92a0c3f7138ebbc31bfe7cbd40cd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3ec53ce4ea1f41f040a3c2beed929572af95dd43 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3f0762fdf49a58c0d8fd6683964a85caddee391b differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3f71ae863c4e9bac98e49a554b8ec4d78b17492d 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï*ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïéïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3f9df30bfb66a28fbe6f1951ef7ae4ca9f19fdf2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/3fabb14670c008c22094c1d7cd7b1e23b4c48b3d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/408fba9c66c5d1deb31e4c69f1dd0677844dbc1b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/40ca8645081087e950ad61bccf8d43450366356e differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/412faec949b9d04498de939561664ee559a583a7 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïñïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïçïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïÿÿÿÿ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4148bd5336f89e73b2a5416c67d491c0ec4a2b7d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/41933e61fa20fbe2b190f9ae7ceae4a4b1220021 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/423d90f3fc7ddc146095ec5a4b4f455aa876b69b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/42a6c52249aa12cfef1db1bf302a483a01c972f3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/42a82726f0e70da9b87b6c52bc1b3415576025f2 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4458e19f99e38c61ad9792b0b3bf8ac79f8236f1 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ã]]ÿÿÿÿÿÿs4 \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/44a4411a8d6ed67ee3ea61d91d2afafe89295b0f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/44e04754d1b6c0c045e05509dd7033d19a926b10 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/45259e9f0a2cc7739a94eccaafb37c1570f73884 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/46c0d7e952200cabc08b9cd776a9f6759f4208c3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabade and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/46deac8631633ea3c32005124e20a2bc2bbabade differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/46e7edf6e9d6cbcdabde3b48f1c4efd93be40348 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/46fe9556c28c94f7321baa2519a3cbeabbd54d09 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/49223681729e73b48b26a2262e4a66b2ba00e176 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/499e61b689f6cc7e4efb0631684739c2a6f97c7d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4a06ad8c4d717bd048a7a1315a3d609d70f0162d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4adb7d4791a4c6370478dff2eb987d715554bf09 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4b01c479cdc9b750a31d5e7ac5004309222d218d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4bce7460a6becba6d26984bb438d7d3aa4e4fc56 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4cc96483b6800dda296f00887b12a35154115090 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/4f3aa59bae0619c9a06b631d9cb7767591810ab0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/501840d963cedd2945018de59e0202444d7ebf4b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/50479958c030d1addceb1ca8c27f24447e555e65 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/508ba8ef164a809f739834a39d690e700101a7a1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/521d345313812e54bc6c944485e19dbb39a87768 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5369d74ac157f85b597c1b28bbd6768105e9327b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/53997b0146ff49bfe464be203b130a67ea93fd26 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/560ea8bd7d11b00e0d21631b6d9ec7e63f0a5286 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5682ebc6878e247ce9bc636d34ada6ad338fcaf0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5762abb5234edd913754b69e1ab03274c711ee68 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/579406f055070559bda3c6120107feb3e637c481 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +ÿ&ã +ÿÿ)Å \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5837d16af4a9c1f2616467cc4aa9ec8836e05c58 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/58901e865fe20b9fa136cca4b253d3ae73c2b78e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/58a87098a14572e46b53c87340083f999d8fcfc2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/59ae139a21448e0eb7371ddc6ef57f0c9dfe9c85 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5a7e81419f895168c555ac9b4e75a1ad4f04b34a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5b848c1f56a150d64020e9b0bb398a286dca4096 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5bd311bd846336149b2815666052fdb7e8bf2ea6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5ce77eb98473a2e01d04909939edf7aabef5762c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5e5cd5819811507ac69bd8abad27433ccd6b7521 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5ea114ae3dbb140364000c416152b0f32ce3de23 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5f181bb0a79603c84534a9b8e37ecdeb1d2aeeb5 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãÂë®<™“ V¨Ý`oÓ¤Ük @rÜshuffleéDHE-PSK-ARÿÿÿÿÿÿÿ'MIDÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛàÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÙÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÙÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ[ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5f428ce1169e28353cedb8be3e2f6edd0ef354e4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/5f9bc7729dc331e3c4d8e52df0688abad6d4aee8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/619527e1d650cd1c26e9bc61e424c9fdc04b17b9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/625d3676de25188865e05db2a3933c38508406fc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6368569cfde7fbe369a0ee4695fa4d5a7d7887a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6388fe4d630064ea1ea33aa85381d9c82e328e95 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/64cff4e110f0bcb3ea833c1afda6e27a57dac0bc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/66449b87ce47b681c6326f337bebf03366a0ee99 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/66ae3584497a1823a955c33e5bc53f7434c13e49 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/66e238a6ad70fb30c82171ff1b73ea71b4379355 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/66f345dc060ac5a1fe8bcf0828102d072deb1111 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fa and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/66f839146ef46deed25fd2cd169a4f1a2a3533fa differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168ee and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/671720ee2b7ba45920b41b8016eb5206b88168ee differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/679c7140ad60ed32aeb7ee464499dd52b0fc212f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/67c5e6ce7bb47cefe54d749374f3288a2c915936 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/69592399b45f2f83e0cc823c5f0e3865ac3fa611 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6abf97508f0ed808b7fe0d9bb2439981153badd2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6b2dfb51b35b78680cb02ff54e06f0c983c04866 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6bbf6ab605fedd41ed6c7581ec9f87c75403e9c3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6c0656104902e1323f3a19c46df7cffecae94f1c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1ba and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6c0ce8006b3ebd8202e61fe5f4cc2285248bd1ba differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6cc635e6dd4e430ed4fb68a9f5add38aa02ae14f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6d1b281d7bdd9887e53505fd5d040731db18ba48 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6d5c35f9d87253b2fbe383bfde3775a9f737da12 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãÿÿÿÿÿÿÿïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïÿÿÿÿÿÿÓïïïïïïïïïïïïïïïïïïïï÷ïïïïïïïïïïïÿ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6d95355018cadedd97bed65c45a44a7ff6f065f7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6dd70e887ab94db3327d9aaa0335914a1f4986b7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6ed51a953a8b6671de417406e340d8d0a211aa12 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6f911f19652a4457c93ef92b594bc1dc2ca900f8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/6fa76cbaeb3cf0417c7a372132167bcd737db66b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/71f66d3f7da318d69681a22ebbceb1a2bb290658 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7227a2dc335af13e7225536c49969f46a800750a 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãj \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/72fce27bbccf582f2023f5e168853251e576592a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/738e5543ae005a6de85dfcd960eb8e3e6faa8947 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/739d9c8868445202305d0a4e5766df1c68932688 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7438b07314917c84d348e7d9629e3712190c7da7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7490f00d660f5d8dedfa606cca241bd07be86a4f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/75c64e8b61af41b28516c2c0fe902362d55a24f3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/75e94b59a41e7f086b6f7ab3bca801251744ae3d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7612ceb3a989f97a7bb19f57c7f9c61366953642 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73ea and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/76ac2328e1c979bca648b4082b8bfe6f2e2e73ea differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/76f296039ba4d666c9147ad234d43b55050808e3 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/777f248eea53e3dd2b726e1e0de5eeda43b6d323 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +› \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/792fcd0075bd8031a98a68ce04d6a9f23feef7b4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7a936c3e69013b2c71dcb72f0eccd99c93367533 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7b30d0cd07108f2e45ce1a3fab3f971b25dcf5cd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15ba and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7b87f367b5fa3bf29bae19031814e5d0120a15ba differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7c12e4bca60858eae13c47a66e54cd9e96a50909 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7c59f95e649b3be6344f4f835afd0d9a894c1144 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7dcb6494c3614a8690dc496309f90e0f23634c37 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/7e64b86827ea98f0a4eb54736c460a59b0c30420 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8125d9eaa09b3d2283fea73223866cb36877c4a4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/81c7fc514fa9a07b5b87b94cf9c00df2b1325a74 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/81f9df0493052d980ca13918637bc6ce565615b3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/82556b9345134dd689cb9d0d08d3dc8459454181 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/82d35a7a6ffb333b02d0d597e88ffdd481237a8b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/82e931da372a2c69c0f10274342173c2be091f1c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/83e2b53f22afe8f7ee21d30fae2619ad0d6a71e3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/83f4d70189dbc0d3aaf5025977c53d4d34fc5893 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/85e17cceba7850be893afdc04c8233bea1ef6e72 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/874d4abdcd7db751eb930928231669afe90589f5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/87894ec663568153d7837f49b80f6d2e99818bd7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/88052b76108b4ede342f3dd87bb6835b2f71ea83 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/884c54256c0ec2cf1c5fa08a0b3d9c2fea021300 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8858f36373db5fd6b805a768af55c21019c664b2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/88fe8b6767c1bd32308208b22e0b00697e5eddf7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/898cac1610f2f2fb67eb092cd053f0006c3070e3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/89d0f5573ae1b524e7e9bdb1fb54ea4ce99e3ef0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55ed and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8a55300e400efd56be5e12258ebf575c4f3b55ed differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8bf7b464aaa2c2b536aa1d76a1297c19155f5603 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +à \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8c05e8ef26302a79c89670ad3aa4e8d0bc921923 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8c15f5a268ded9663197d66e8d7d4098e0ae9bf5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8ca9e85a9e628f0016ea4e6413945b3830730c24 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5ba and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8e74126a239927900a8f655c813a4b230191a5ba differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/8ee63e791c004427dd033b468b2ed7446ee6e2e0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5da and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9028113aa78b649e13ff259027a4e450d469e5da differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/90db2115b8262ebecbefbe8f0a07c451e39bca07 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/923f28a4d1917e20ee0736b90695c2123c0c987c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/92a5c74e0506d65d1a12686496452870367b169a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/92dcf94eb2f92b4e1a232eab3b3f808f4236f118 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575ac and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9414502aedbef5e307897683625418dd4ac575ac differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9422e25bec5fec9f84603a85673b54b1a5e77a40 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/943754e865888063e0684aec838222522390d43e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/943e067806ae069afbc029ea7a612410e5395687 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9547646cc1a5d260df099b00ea7ee2b95567aee1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/968f7027ec9fbf75a519069ea5189e85a81448b2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9691046a2f8b31319a6fdfde0506c9a72aed839a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/96a8cd5c33986cc26cc00eb2de627149f5259e33 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/972466bbc33d2d7d7c21be21c7594b51e78675c5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/980f21a3609762154030f7cf0fe98a892d20f220 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9865f12189ef977418d8410fceebb6830c74d820 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/98a1096d609545083878d5126743bbc5985786a9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/98c3b6bbf5dc19bc4aad894087277a36d7c79669 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/98f9cd44400b592f809596004125267acf848435 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9a97260f04ecfe0918499ede95cf4bcb3dbc2b51 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9ba0dba2ca4405d04113086309882dac6182e6b8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9c329ee4b02f2d26ee1a399c873b0452aedca3c0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9e8e638837e202d83ff606a22dd0e310150fa260 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9ee03d17e070df72547e423a412da0b6a60ad565 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9fad6bd2b07d65e607039bb2bcda0816410cf983 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/9fcbd21f4dd194a623d832422384a1519742f0bb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a019fb7f17aa36a9743c530e1f11d5613b8b1158 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a0b8c6ef20198377b19f59e41f08f4cf2107f460 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a14079a3e8cbc2112da4fa747ef20cdfd580e068 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a14d61ba0c609665d37e6c6da929cb53c5b70545 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a15cf2a13e408cb76af0091a0c286af7ffce58e1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a1ddedbdd05eac99b8b31322635771cd9c999f8a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a235661c3f8b0174a1658e9c435a69577c49256a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a261397a4db5ac196c72d73ba6999e9fd4fc5c1f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a3a803fd6a56d31269717983bbdf2fceebb626c3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a3d5b0b21d977e8f94d401250de1bbd4fa1d0ee0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a42f2900ca519bd15b8d6f507449d1a07de2ef75 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a4884775b414eaf9643224564f3be405519cf99a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a48da63e9a5709c24cb66f598a7a964cbc7ccfc7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a5789fd83dff18079ea7ba41c999f57bee4db41b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a5bb1c60191742df4a91afb622e9b22a2f0b7765 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a5fdfade1cef5e7e494dd6e3791bca5a663d7012 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a6c66f79f5aaf2c1a26ff16754fe1a8c22627e0c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a7478a05a1fc04a9e035be5593bfb6a281ec460f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a75193dd600661d2b417d4e29b23faa7d721c214 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a7ccae74c641ffcdda0042e6c04438d5b32c4cf3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a94aa5881abdea5374775b8155812121673f89c3 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a98d794f0f24be7a36917826121fc14a24120893 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +Ñã \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/a993077e321bc4e1831bb5a8ac7511d90d32ae27 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfa and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/aa3bc67656945e43f9342d3aaaef247584d96cfa differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ab111c4d72e3d6796e3d7391e9f35b4e6fefc04a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ab248c42f77952d5d17d6f5203adaa5925c05c64 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ab8451fadf805e5087837d9f6d91ef7eb6fa5edb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/abbee3b37aff879b1cef47390001b89b0f6ebc0a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ac15b23f03af8be6dbbb3bbb8d3877a1f9e074a3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ac47bda12269c06d773f5f3c6517f78513a54a08 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ad1f4fb57f481a00a9bb231517a3155ef0d0877f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ad25e7ffabedd94833d2529886af4d459529ec9d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ad796ebb423f58187806c4a7ee7b787394353ce6 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ + Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ae14b80f26f5cee2d85d5154c2cef1eefafa8cc9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ae3ba892de543801b3c1dfbce370eb2c80a6fb27 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/aecc0c7f08810803da234e26e7c6fa7a9f1c0593 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/aed2e85d5d39d25e738a34f30a722680bde30368 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b00a75de1987c6f549bf73a63e8f23a2de6641b3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b02e9f951ce9f10a8eb80f1fc61cd3d2832dd7f4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b04aff8ab2e133d45bf44565bd4bf9e33b795a97 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b12097ed83db761f7bb79411a59e2474de9b1199 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b1beb2f462b4cb30a09d534b9f49f2e08d76363c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãðc½D \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b201733b6165f4544578bd6aad3f55aeafd9a194 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b2699f25c21ffe453dcce20e31b3093e0f9b2abf 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +Åç \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b34a5760a1036f909e0243cd857fcef65e40d752 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b3fdacd639073cc1954bcb1f31046d094e2d2296 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b40a6dbe32c8e6a9b777331e7fd97f0d94ceca1c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b52ff2010f22ae6758cde5d529fd19de2a7d5fc5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b53a7a2afd9dfc55c328b4e06a36882c53126e95 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b548ae8a77a62b7f375b8b48e7184ceed59bc8f8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b66eaf0b689495cc7c194ab1fca7d36ae9da9758 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b680bf23da22b8b7e77d847169fe9b6968d79e8b 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãoÙ¬ÿÿ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059fe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b70d6e7d230fb1393b8f665adcd5658cad7059fe differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b87a59f78adb3ef18b0176a8e7fe7e90c2ab4ef7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/b88c5233090e859e923acbdfa9b168f95d7fc14b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ba1923ea69eec8fe765e8d1222eccb928ca6c3c2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ba4d695c1eb02c702bd99a3db27838c7ba617d79 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ba7e4f999dc22d223c7f75db36646bfa05848572 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cda and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bc5f0cd338d1d17a230378390aa810bc7b103cda differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bcbb4cf10018a177dd9a6c642d887e0de3d8e522 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bcfeb114df6d5c6e0c85cbe1081631bc321ff65b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bf and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bd582237a9293e2a53d8222722a69e7d215822bf differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bdc83a415da40f74825379203538a2e4d27cffa7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aecc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/be160536594c87dc07554a71c7d24cd1d718aecc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/be8f3c744a23f67fb316a39609ca11ddac025b58 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bf873b027b48f3fd7b727473c832486d99ddb196 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bf8e20ef6b79131ef9bab8c9c1bb7dbecbead6a5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bf90507b8f7c7eebb89edeaabf6a432d86e7df4a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bfa7a5ce666899fb3e2a7216dbf59886da672658 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/bfeaa454d8db33efabba88f146bee6c803369ba0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c0388910e8d88dcd2e65848ba2cef465caa6b258 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c0db293f75bb44668bcbb79286ebed87df141a85 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c1234da1441255244aba15ecad2a4fa7fd47115e differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c2206ac3c289a759ee0e9d0d31cc336f0802f7bc 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï;ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c22340ab36e5cff088a58272f63cf69e54a1a9f4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c242c9336c4c22b316e0e56d616b2d45b3318ca4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c25a51d8dfaf58d5b609729bb156a80e3b0d892f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c3419450240d06982b0d828911b188a903355216 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c36ea7651f76ae817d8d60cae580e47638741372 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c42300c021bfd35702f564e917839503922cbe9a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0be and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c45d82ddade99ef857b563e435f2efe89e58b0be differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c4d1e9187de1e13353b3beb3c1ab16dd62cda571 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c4e98278a25011c54734494d4534a97489cf4c24 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c4f996ab08f56ce2e9fec7a0428ded510dd6a04a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c544850a7325e7226583895204f99de730525803 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c56629528d5bebdb94f85522caf0f36bbcb19106 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c5c75b58883ccf41b20b140740e2ce763c6086cd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c62da85dca0d4dfb1d7af5d0520eb74993a1e3b0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c6379aaaecd282b8ed6d0b4291d0d9fdc763160a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c6431921184e3edf4fd3e47384c69654cdac0189 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c6f2ca17c6d313a35676cbacd094eb40fd74b23e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c83e04d58e04fccac37b9dd313eab72011fe8ea1 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c88dc350b98a5c5ae0503683318c1f30443906a8 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ãp \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c89ee2e9e30a474b5f9532ec61d7aad78377baa0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4be and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c921be4abeb44d1ff07f76f632a16e86526bc4be differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c98bdc0431aaece1e8a721aff0ea511cfb8062a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/c9c456fd3e35a942ef4ab756e04e725cf1f71167 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cf and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/cd1f1a31b79af77e1e764102942ba7a79dcd24cf differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/cd57e5904254c2278e9ecf28ed7414d7aed8eef1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/cd665cdc2bd6a26eb68c9af6d1728a7d4f6eb309 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ce72111c4314b22c4c7824bc8ea340ebd6d3fa84 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ceacc7ace2f4be962b0db2eeeea3fe6a00ca9dd6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcdd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/cf40769d8b4fcbac1b10ced2e0c3c1294f23fcdd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d120111a77a3e3d1d504a04bbfc5f53effa14eb0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d1ce81240a32aec2de1b0d779aa29a62c36f291f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffcc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d21869b290cd2b448e7b8103dced97e62fefffcc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d2bffcd01e87ce9860007b244ff1e79ecd3d4d0f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d2d668b6e28fca83da5146021879c2b006406fa4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d37abe0d299b8ad1e90f5b7af302c24f411a7ed1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d3d689a12ab3808313d5ba0044e8c67ecb4337e4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d48eb559213edf05aa2850a14194885ae2086ba4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d490f365693e49ebdeaf658b3f549311a399c6a8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d54821b652a8611c486bedd8645081d3a4b1c8d1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d5586a91f9a879e8a67ec7b09a48038909918ad9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4ae and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d696362920a2fad8e280293e8d1c92b18c87e4ae differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d6b546a2b1bc1c8f80028e4be10c45a06014b32d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d7f04cbca92b2122e0f437ed4dd8fd1782d40f7f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d81944a0c1ed56d11129533d9a3d0d038113d53d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d8524e83ea63c9b365c2e93af75a8100a08b1b69 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d8d9a2d06763cf6feb433cef92a80ef14baab31a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d917fbd641cc40786246387456a636899d56b5a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d99f9ec8b504029457185ac03ea8ba21c2611737 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d9c9c90c1bbc55beb81875838e9067c473d0fa92 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d9e908317a6ef08a7528924672836a550d34cb5f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/d9ef71deb57fa6f40e027be2c84fa37d288e1cc5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/da8841b9d04382d62d4aeb3fde4dc78466f31543 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/db3fbb74c9c9c4185f91eca85f14c3d2c3d9f487 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/db7a31de22258d4dc17d44a27d9340946e9c9ee9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/dbbe57fc653930b4ff43f168565ba84ef25f60c2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/dbe74c0d9e7b62c1fd87d5e3ea73ee04f0337154 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/dbebf36a6b91568ac059142c3ca3211226da12a8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ddacbb379242b31a00d62fdff5777dffc1e899c2 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/decd2cd9cef352610ac9e5cc461df1829543f9f0 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,3 @@ +ã +yã +y \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/deeae69363db06972798b296a0c5c99e02cb2b4c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e03e105323e6e7b2af90ad876b5c547af90d8f6b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e3133215848c9cde428338c9d51424c8a81b96f5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e32a25f0347b0e95d4bea16c27a1f374847683bd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e45ce97522194abcdd7ff9beb931e20b86c97a79 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e484023d50fc1036e46a437053b965c527700d42 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e4e60e77fe3a050940d0afcc7dbab7ef06b04ba3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e51629784092d9cf811ea1bd894297f062ed7ec4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e5a7e837029178b3fb6a26d77ea4574ffeaa219d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e5c616e9efdd9c80181f9210d0e3a81c08fe9b4d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e5e6e84e2c7770537c744bcfdbe8303afe39ef92 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e5fb20928feec1ee3114597317edc0e06c413749 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e789319791fe704e5a8ffd7cb570c8d2722ac35f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/e9fdb9f08f225b4231f01dda9c7b61e7b78bf7d3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ea6780324dca9a06db28598dfb590436d846d99f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdf and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ea6afcc92b8a6c9e14cc053d351909ad5b0a3fdf differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ea8c569029c0cacc4ae75e95b2f4e84abb6867f4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/eb3e80c3ea9cfe9e08b2eef117aaa522a51a619c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ec55b30741fe8fffeec584176c8d20f6a679cfa1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ed0724a6c3804a3ab20a980b5ca48671689a602f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/edeb545d1cf852dc9582fa764010fe844a5e3515 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ee70b920de91f1be6b4448070ee2d1bd9e08286d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ef004af4e947d25b4d1d1dd16502260d4c7a99cd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158be and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f009d226503b73aed0f1fd952ef8725433d158be differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f0a821dffe21afd357932febaf6e8ee331f53197 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f101a2fe93dfaaed1c596022b4e509cf3a591c8a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f1101f71657385174f8cb920026a761404b4395d differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f138c84e42d3cc61a219c4be9db791750f0541c8 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ã]]ÿÿÿÿÿs5e \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f1da273522bfff4a4971b4ffc31e365f60fdbbfe differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f2fe69d30ec47e78a9e92f1423698a52270672b2 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f368bb6f633587a7bb271de7e20695f178c89686 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f38ced5a16edaceb5f527ebc35e7870f42586c90 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f404371362ae68ffb2837ce1766346ebb645d173 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f473b5e1cf51502345f5c1840ec3948d308dd314 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f4ad43d6f913c3be6243dfc439e4b6f5b2e814b9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f4cde4083a974d755a38bf5ea3820f78b576754a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f5888d0dcacda196d73772aabc18fe2ad6e1dfa2 differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318 libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318 --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f5c3577a62d401f071d5edaa77c54ae98d6a0318 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +Ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïï \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f5dee0d9da0d6950069ac36b1880090a20f50f3e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f605fff495fef2719585c706c05c350812402a35 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f6fdaf4e77e29c780b9e0b91637777575bebfab4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f72700bd65fa86c588607ec50d60a9c684c86f43 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f777db12ef18f002febd5af13e2b948c95d964c3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f777e9274d508e7ac1069e2a04bedc042942491c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209eb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f81306f8ceaec3d06d5d34afa9769d15f0d209eb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f84c2b36689f22809d9bda00febab557c381ffa4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0ce and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/f98168fa74c26b17ad0c3002f2263beb0af7c0ce differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fa6759d6a2807bbad83ba21761772c0119122c35 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fa8b927b25a67fa3d60b12c53ac365366cc2b52d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fc5e4b78e59daebed1118389b57a386981f2430e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fdaf408880429153cfcf5d978727cd7b84c3d60e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fe50e7564a28683b24c57f8bcdcb3fbfa61f5c6a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fe64b998872d3ad87df2019173ddc52686841d7d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/fec56c7cc86871aaa9c7a947c4084307cac2778d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ff164dfc56dd28709488130dc6dfc17406bf9e9d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/fuzzers/corpora/midx/ff7035b3c055718728a6025b3cdf55c34c4c744b differ diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/patch_parse/edit-file.diff libgit2-1.1.0+dfsg.1/fuzzers/corpora/patch_parse/edit-file.diff --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/patch_parse/edit-file.diff 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/patch_parse/edit-file.diff 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,13 @@ +diff --git a/fuzzers/patch_fuzzer.c b/fuzzers/patch_fuzzer.c +index 76186b6fb..f7ce73ac8 100644 +--- a/fuzzers/patch_fuzzer.c ++++ b/fuzzers/patch_fuzzer.c +@@ -32,7 +32,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) + git_patch* patch; + git_patch_options opts = {(uint32_t)data[0]}; + int status = git_patch_from_buffer(&patch, (const char*)data+1, size-1, &opts); +- if (status == 0 && patch) { ++ if (patch) { + git_patch_free(patch); + } + return 0; diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff libgit2-1.1.0+dfsg.1/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff --- libgit2-0.28.5+dfsg.1/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/corpora/patch_parse/patch_fuzzer-patch.diff 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,45 @@ +diff --git a/fuzzers/patch_fuzzer.c b/fuzzers/patch_fuzzer.c +new file mode 100644 +index 000000000..76186b6fb +--- /dev/null ++++ b/fuzzers/patch_fuzzer.c +@@ -0,0 +1,39 @@ ++/* ++ * libgit2 patch fuzzer target. ++ * ++ * Copyright (C) the libgit2 contributors. All rights reserved. ++ * ++ * This file is part of libgit2, distributed under the GNU GPL v2 with ++ * a Linking Exception. For full terms see the included COPYING file. ++ */ ++ ++#include "git2.h" ++#include "patch.h" ++#include "patch_parse.h" ++ ++#define UNUSED(x) (void)(x) ++ ++int LLVMFuzzerInitialize(int *argc, char ***argv) ++{ ++ UNUSED(argc); ++ UNUSED(argv); ++ ++ if (git_libgit2_init() < 0) ++ abort(); ++ ++ return 0; ++} ++ ++int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ++{ ++ if (size < 1) { ++ return 0; ++ } ++ git_patch* patch; ++ git_patch_options opts = {(uint32_t)data[0]}; ++ int status = git_patch_from_buffer(&patch, (const char*)data+1, size-1, &opts); ++ if (status == 0 && patch) { ++ git_patch_free(patch); ++ } ++ return 0; ++} diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/download_refs_fuzzer.c libgit2-1.1.0+dfsg.1/fuzzers/download_refs_fuzzer.c --- libgit2-0.28.5+dfsg.1/fuzzers/download_refs_fuzzer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/download_refs_fuzzer.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,14 +7,13 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include +#include #include #include -#include -#include #include "git2.h" #include "git2/sys/transport.h" +#include "futils.h" #define UNUSED(x) (void)(x) @@ -166,10 +165,23 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) { - char tmp[] = "/tmp/git2.XXXXXX"; +#if defined(_WIN32) + char tmpdir[MAX_PATH], path[MAX_PATH]; - UNUSED(argc); - UNUSED(argv); + if (GetTempPath((DWORD)sizeof(tmpdir), tmpdir) == 0) + abort(); + + if (GetTempFileName(tmpdir, "lg2", 1, path) == 0) + abort(); + + if (git_futils_mkdir(path, 0700, 0) < 0) + abort(); +#else + char path[] = "/tmp/git2.XXXXXX"; + + if (mkdtemp(path) != path) + abort(); +#endif if (git_libgit2_init() < 0) abort(); @@ -177,10 +189,10 @@ if (git_libgit2_opts(GIT_OPT_SET_PACK_MAX_OBJECTS, 10000000) < 0) abort(); - if (mkdtemp(tmp) != tmp) - abort(); + UNUSED(argc); + UNUSED(argv); - if (git_repository_init(&repo, tmp, 1) < 0) + if (git_repository_init(&repo, path, 1) < 0) fuzzer_git_abort("git_repository_init"); return 0; diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/midx_fuzzer.c libgit2-1.1.0+dfsg.1/fuzzers/midx_fuzzer.c --- libgit2-0.28.5+dfsg.1/fuzzers/midx_fuzzer.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/midx_fuzzer.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * libgit2 multi-pack-index fuzzer target. + * + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include + +#include "git2.h" + +#include "buffer.h" +#include "common.h" +#include "futils.h" +#include "hash.h" +#include "midx.h" + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + GIT_UNUSED(argc); + GIT_UNUSED(argv); + + if (git_libgit2_init() < 0) { + fprintf(stderr, "Failed to initialize libgit2\n"); + abort(); + } + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + git_midx_file idx = {{0}}; + git_midx_entry e; + git_buf midx_buf = GIT_BUF_INIT; + git_oid oid = {{0}}; + bool append_hash = false; + + if (size < 4) + return 0; + + /* + * If the first byte in the stream has the high bit set, append the + * SHA1 hash so that the packfile is somewhat valid. + */ + append_hash = *data & 0x80; + /* Keep a 4-byte alignment to avoid unaligned accesses. */ + data += 4; + size -= 4; + + if (append_hash) { + if (git_buf_init(&midx_buf, size + sizeof(oid)) < 0) + goto cleanup; + if (git_hash_buf(&oid, data, size) < 0) { + fprintf(stderr, "Failed to compute the SHA1 hash\n"); + abort(); + } + memcpy(midx_buf.ptr, data, size); + memcpy(midx_buf.ptr + size, &oid, sizeof(oid)); + } else { + git_buf_attach_notowned(&midx_buf, (char *)data, size); + } + + if (git_midx_parse(&idx, (const unsigned char *)git_buf_cstr(&midx_buf), git_buf_len(&midx_buf)) < 0) + goto cleanup; + + /* Search for any oid, just to exercise that codepath. */ + if (git_midx_entry_find(&e, &idx, &oid, GIT_OID_HEXSZ) < 0) + goto cleanup; + +cleanup: + git_midx_close(&idx); + git_buf_dispose(&midx_buf); + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/packfile_fuzzer.c libgit2-1.1.0+dfsg.1/fuzzers/packfile_fuzzer.c --- libgit2-0.28.5+dfsg.1/fuzzers/packfile_fuzzer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/packfile_fuzzer.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,16 +7,12 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include -#include #include -#include -#include #include "git2.h" #include "git2/sys/mempack.h" - -#define UNUSED(x) (void)(x) +#include "common.h" +#include "buffer.h" static git_odb *odb = NULL; static git_odb_backend *mempack = NULL; @@ -27,8 +23,9 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) { - UNUSED(argc); - UNUSED(argv); + GIT_UNUSED(argc); + GIT_UNUSED(argv); + if (git_libgit2_init() < 0) { fprintf(stderr, "Failed to initialize libgit2\n"); abort(); @@ -54,12 +51,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + git_indexer_progress stats = {0, 0}; git_indexer *indexer = NULL; - git_transfer_progress stats = {0, 0}; + git_buf path = GIT_BUF_INIT; + git_oid oid; bool append_hash = false; - git_oid id; - char hash[GIT_OID_HEXSZ + 1] = {0}; - char path[PATH_MAX]; if (size == 0) return 0; @@ -70,7 +66,7 @@ } git_mempack_reset(mempack); - if (git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJECT_BLOB) < 0) { + if (git_odb_write(&oid, odb, base_obj, base_obj_len, GIT_OBJECT_BLOB) < 0) { fprintf(stderr, "Failed to add an object to the odb\n"); abort(); } @@ -92,7 +88,6 @@ if (git_indexer_append(indexer, data, size, &stats) < 0) goto cleanup; if (append_hash) { - git_oid oid; if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB) < 0) { fprintf(stderr, "Failed to compute the SHA1 hash\n"); abort(); @@ -104,19 +99,19 @@ if (git_indexer_commit(indexer, &stats) < 0) goto cleanup; - /* - * We made it! We managed to produce a valid packfile. - * Let's clean it up. - */ - git_oid_fmt(hash, git_indexer_hash(indexer)); - printf("Generated packfile %s\n", hash); - snprintf(path, sizeof(path), "pack-%s.idx", hash); - unlink(path); - snprintf(path, sizeof(path), "pack-%s.pack", hash); - unlink(path); + if (git_buf_printf(&path, "pack-%s.idx", git_oid_tostr_s(git_indexer_hash(indexer))) < 0) + goto cleanup; + p_unlink(git_buf_cstr(&path)); + + git_buf_clear(&path); + + if (git_buf_printf(&path, "pack-%s.pack", git_oid_tostr_s(git_indexer_hash(indexer))) < 0) + goto cleanup; + p_unlink(git_buf_cstr(&path)); cleanup: git_mempack_reset(mempack); git_indexer_free(indexer); + git_buf_dispose(&path); return 0; } diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/patch_parse_fuzzer.c libgit2-1.1.0+dfsg.1/fuzzers/patch_parse_fuzzer.c --- libgit2-0.28.5+dfsg.1/fuzzers/patch_parse_fuzzer.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/patch_parse_fuzzer.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * libgit2 patch parser fuzzer target. + * + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2.h" +#include "patch.h" +#include "patch_parse.h" + +#define UNUSED(x) (void)(x) + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + UNUSED(argc); + UNUSED(argv); + + if (git_libgit2_init() < 0) + abort(); + + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size) { + git_patch *patch = NULL; + git_patch_options opts = GIT_PATCH_OPTIONS_INIT; + opts.prefix_len = (uint32_t)data[0]; + git_patch_from_buffer(&patch, (const char *)data + 1, size - 1, + &opts); + git_patch_free(patch); + } + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/fuzzers/standalone_driver.c libgit2-1.1.0+dfsg.1/fuzzers/standalone_driver.c --- libgit2-0.28.5+dfsg.1/fuzzers/standalone_driver.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/fuzzers/standalone_driver.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,14 +5,10 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include -#include #include -#include -#include #include "git2.h" -#include "fileops.h" +#include "futils.h" #include "path.h" extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); @@ -24,7 +20,7 @@ int error = 0; if (git_futils_readbuffer(&buf, filename) < 0) { - fprintf(stderr, "Failed to read %s: %m\n", filename); + fprintf(stderr, "Failed to read %s: %s\n", filename, git_error_last()->message); error = -1; goto exit; } @@ -57,7 +53,8 @@ LLVMFuzzerInitialize(&argc, &argv); if (git_path_dirload(&corpus_files, argv[1], 0, 0x0) < 0) { - fprintf(stderr, "Failed to scan corpus directory: %m\n"); + fprintf(stderr, "Failed to scan corpus directory '%s': %s\n", + argv[1], git_error_last()->message); error = -1; goto exit; } diff -Nru libgit2-0.28.5+dfsg.1/.github/workflows/main.yml libgit2-1.1.0+dfsg.1/.github/workflows/main.yml --- libgit2-0.28.5+dfsg.1/.github/workflows/main.yml 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/.github/workflows/main.yml 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,244 @@ +# Continuous integration and pull request validation builds for the +# master and maintenance branches. +name: CI Build + +on: + push: + branches: [ master, maint/* ] + pull_request: + branches: [ master, maint/* ] + +env: + docker-registry: docker.pkg.github.com + docker-config-path: azure-pipelines/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. + build_containers: + name: Create docker image + strategy: + matrix: + container: + - xenial + - bionic + - focal + - docurium + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + if: github.event_name == 'push' + - name: Download existing container + run: azure-pipelines/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.container }} + env: + DOCKER_REGISTRY: ${{ env.docker-registry }} + GITHUB_TOKEN: ${{ secrets.github_token }} + if: github.event_name == 'push' + - name: Build and publish image + run: | + docker build -t ${{ env.docker-registry-container-sha }} --build-arg BASE=${{ matrix.container.base }} -f ${{ matrix.container }} . + docker push ${{ env.docker-registry-container-sha }} + working-directory: ${{ env.docker-config-path }} + if: github.event_name == 'push' && env.docker-container-exists != 'true' + + # 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) + # or on the actual hosts (macOS, Windows). + build: + name: Build + needs: [build_containers] + strategy: + matrix: + platform: + - # Xenial, GCC, OpenSSL + image: xenial + env: + CC: gcc + CMAKE_GENERATOR: Ninja + CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + os: ubuntu-latest + - # Xenial, GCC, mbedTLS + image: xenial + env: + CC: gcc + CMAKE_GENERATOR: Ninja + CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + os: ubuntu-latest + - # Xenial, Clang, OpenSSL + image: xenial + env: + CC: clang + CMAKE_GENERATOR: Ninja + CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + os: ubuntu-latest + - # Xenial, Clang, mbedTLS + image: xenial + env: + CC: clang + CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON + CMAKE_GENERATOR: Ninja + os: ubuntu-latest + - # Focal, Clang 10, mbedTLS, MemorySanitizer + image: focal + env: + CC: clang-10 + CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer + CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local/msan -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON + CMAKE_GENERATOR: Ninja + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true + ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10 + os: ubuntu-latest + - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer + image: focal + env: + CC: clang-10 + CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer + CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON + CMAKE_GENERATOR: Ninja + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true + ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10 + os: ubuntu-latest + - # macOS + os: macos-10.15 + env: + CC: clang + CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON + CMAKE_GENERATOR: Ninja + PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true + setup-script: osx + - # Windows amd64 Visual Studio + os: windows-2019 + env: + ARCH: amd64 + CMAKE_GENERATOR: Visual Studio 16 2019 + CMAKE_OPTIONS: -A x64 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true + - # Windows x86 Visual Studio + os: windows-2019 + env: + ARCH: x86 + CMAKE_GENERATOR: Visual Studio 16 2019 + CMAKE_OPTIONS: -A Win32 -DMSVC_CRTDBG=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON + SKIP_SSH_TESTS: true + SKIP_NEGOTIATE_TESTS: true + - # Windows amd64 mingw + os: windows-2019 + setup-script: mingw + env: + ARCH: amd64 + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON + BUILD_TEMP: D:\Temp + 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 + - # Windows x86 mingw + os: windows-2019 + setup-script: mingw + env: + ARCH: x86 + CMAKE_GENERATOR: MinGW Makefiles + CMAKE_OPTIONS: -DDEPRECATE_HARD=ON + 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 + fail-fast: false + env: ${{ matrix.platform.env }} + runs-on: ${{ matrix.platform.os }} + steps: + - name: Check out repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up build environment + run: azure-pipelines/setup-${{ matrix.platform.setup-script }}.sh + shell: bash + if: matrix.platform.setup-script != '' + - name: Download container + run: azure-pipelines/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.platform.image }} + env: + DOCKER_REGISTRY: ${{ env.docker-registry }} + GITHUB_TOKEN: ${{ secrets.github_token }} + if: matrix.platform.image != '' + - name: Create container + run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ matrix.platform.image }} . + working-directory: ${{ env.docker-config-path }} + if: matrix.platform.image != '' && env.docker-container-exists != 'true' + - name: Build and test + run: | + export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}" + + if [ -n "${{ matrix.platform.image }}" ]; then + docker run \ + --rm \ + -v "$(pwd):/home/libgit2/source" \ + -w /home/libgit2/source \ + -e ASAN_SYMBOLIZER_PATH \ + -e CC \ + -e CFLAGS \ + -e CMAKE_GENERATOR \ + -e CMAKE_OPTIONS \ + -e GITTEST_NEGOTIATE_PASSWORD \ + -e PKG_CONFIG_PATH \ + -e SKIP_NEGOTIATE_TESTS \ + -e SKIP_SSH_TESTS \ + ${{ env.docker-registry-container-sha }} \ + /bin/bash -c "mkdir build && cd build && ../azure-pipelines/build.sh && ../azure-pipelines/test.sh" + else + mkdir build && cd build + ../azure-pipelines/build.sh + ../azure-pipelines/test.sh + fi + shell: bash + + # Generate documentation using docurium. We'll upload the documentation + # as a build artifact so that it can be reviewed as part of a pull + # request or in a forked build. For CI builds in the main repository's + # master branch, we'll push the gh-pages branch back up so that it is + # published to our documentation site. + documentation: + name: Generate documentation + needs: [build_containers] + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Generate documentation + run: | + git config user.name 'Documentation Generation' + git config user.email 'libgit2@users.noreply.github.com' + git branch gh-pages origin/gh-pages + docker login https://${{ env.docker-registry }} -u ${{ github.actor }} -p ${{ github.token }} + docker run \ + --rm \ + -v "$(pwd):/home/libgit2/source" \ + -w /home/libgit2/source \ + ${{ env.docker-registry }}/${{ github.repository }}/docurium:latest \ + cm doc api.docurium + git checkout gh-pages + zip --exclude .git/\* --exclude .gitignore --exclude .gitattributes -r api-documentation.zip . + - uses: actions/upload-artifact@v2 + name: Upload artifact + with: + name: api-documentation + path: api-documentation.zip + - name: Push documentation branch + run: git push origin gh-pages + if: github.event_name == 'push' && github.repository == 'libgit2/libgit2' diff -Nru libgit2-0.28.5+dfsg.1/.gitignore libgit2-1.1.0+dfsg.1/.gitignore --- libgit2-0.28.5+dfsg.1/.gitignore 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/.gitignore 2020-10-12 18:53:06.000000000 +0000 @@ -1,35 +1,7 @@ -/tests/clar.suite -/tests/clar.suite.rule -/tests/.clarcache -/apidocs -/trash-*.exe -/libgit2.pc -/config.mak -*.o -*.a -*.exe -*.gcda -*.gcno -*.gcov -.lock-wafbuild -.waf* build/ -build-amiga/ -tests/tmp/ -msvc/Debug/ -msvc/Release/ -*.sln -*.suo -*.vc*proj* -*.sdf -*.opensdf -*.aps -*.cmake -!cmake/Modules/*.cmake .DS_Store *~ .*.swp tags -mkmf.log -*.profdata -*.profraw +CMakeSettings.json +.vs diff -Nru libgit2-0.28.5+dfsg.1/include/git2/annotated_commit.h libgit2-1.1.0+dfsg.1/include/git2/annotated_commit.h --- libgit2-0.28.5+dfsg.1/include/git2/annotated_commit.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/annotated_commit.h 2020-10-12 18:53:06.000000000 +0000 @@ -78,7 +78,7 @@ const git_oid *id); /** - * Creates a `git_annotated_comit` from a revision string. + * Creates a `git_annotated_commit` from a revision string. * * See `man gitrevisions`, or * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for diff -Nru libgit2-0.28.5+dfsg.1/include/git2/apply.h libgit2-1.1.0+dfsg.1/include/git2/apply.h --- libgit2-0.28.5+dfsg.1/include/git2/apply.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/apply.h 2020-10-12 18:53:06.000000000 +0000 @@ -53,25 +53,44 @@ const git_diff_hunk *hunk, void *payload); +/** Flags controlling the behavior of git_apply */ +typedef enum { + /** + * Don't actually make changes, just test that the patch applies. + * This is the equivalent of `git apply --check`. + */ + GIT_APPLY_CHECK = (1 << 0), +} git_apply_flags_t; + /** * Apply options structure * * Initialize with `GIT_APPLY_OPTIONS_INIT`. Alternatively, you can - * use `git_apply_init_options`. + * use `git_apply_options_init`. * * @see git_apply_to_tree, git_apply */ typedef struct { - unsigned int version; + unsigned int version; /**< The version */ + /** When applying a patch, callback that will be made per delta (file). */ git_apply_delta_cb delta_cb; + + /** When applying a patch, callback that will be made per hunk. */ git_apply_hunk_cb hunk_cb; + + /** Payload passed to both delta_cb & hunk_cb. */ void *payload; + + /** Bitmask of git_apply_flags_t */ + unsigned int flags; } git_apply_options; #define GIT_APPLY_OPTIONS_VERSION 1 #define GIT_APPLY_OPTIONS_INIT {GIT_APPLY_OPTIONS_VERSION} +GIT_EXTERN(int) git_apply_options_init(git_apply_options *opts, unsigned int version); + /** * Apply a `git_diff` to a `git_tree`, and return the resulting image * as an index. @@ -89,6 +108,7 @@ git_diff *diff, const git_apply_options *options); +/** Possible application locations for git_apply */ typedef enum { /** * Apply the patch to the workdir, leaving the index untouched. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/attr.h libgit2-1.1.0+dfsg.1/include/git2/attr.h --- libgit2-0.28.5+dfsg.1/include/git2/attr.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/attr.h 2020-10-12 18:53:06.000000000 +0000 @@ -30,7 +30,7 @@ * Then for file `xyz.c` looking up attribute "foo" gives a value for * which `GIT_ATTR_TRUE(value)` is true. */ -#define GIT_ATTR_TRUE(attr) (git_attr_value(attr) == GIT_ATTR_TRUE_T) +#define GIT_ATTR_IS_TRUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_TRUE) /** * GIT_ATTR_FALSE checks if an attribute is set off. In core git @@ -44,7 +44,7 @@ * Then for file `zyx.h` looking up attribute "foo" gives a value for * which `GIT_ATTR_FALSE(value)` is true. */ -#define GIT_ATTR_FALSE(attr) (git_attr_value(attr) == GIT_ATTR_FALSE_T) +#define GIT_ATTR_IS_FALSE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_FALSE) /** * GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified. This @@ -62,7 +62,7 @@ * file `onefile.rb` or looking up "bar" on any file will all give * `GIT_ATTR_UNSPECIFIED(value)` of true. */ -#define GIT_ATTR_UNSPECIFIED(attr) (git_attr_value(attr) == GIT_ATTR_UNSPECIFIED_T) +#define GIT_ATTR_IS_UNSPECIFIED(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_UNSPECIFIED) /** * GIT_ATTR_HAS_VALUE checks if an attribute is set to a value (as @@ -74,17 +74,17 @@ * Given this, looking up "eol" for `onefile.txt` will give back the * string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true. */ -#define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_T) +#define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_STRING) /** * Possible states for an attribute */ typedef enum { - GIT_ATTR_UNSPECIFIED_T = 0, /**< The attribute has been left unspecified */ - GIT_ATTR_TRUE_T, /**< The attribute has been set */ - GIT_ATTR_FALSE_T, /**< The attribute has been unset */ - GIT_ATTR_VALUE_T, /**< This attribute has a value */ -} git_attr_t; + GIT_ATTR_VALUE_UNSPECIFIED = 0, /**< The attribute has been left unspecified */ + GIT_ATTR_VALUE_TRUE, /**< The attribute has been set */ + GIT_ATTR_VALUE_FALSE, /**< The attribute has been unset */ + GIT_ATTR_VALUE_STRING, /**< This attribute has a value */ +} git_attr_value_t; /** * Return the value type for a given attribute. @@ -99,7 +99,7 @@ * @param attr The attribute * @return the value type for the attribute */ -GIT_EXTERN(git_attr_t) git_attr_value(const char *attr); +GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr); /** * Check attribute flags: Reading values from index and working directory. @@ -119,13 +119,20 @@ #define GIT_ATTR_CHECK_INDEX_ONLY 2 /** - * Check attribute flags: Using the system attributes file. + * Check attribute flags: controlling extended attribute behavior. * * Normally, attribute checks include looking in the /etc (or system * equivalent) directory for a `gitattributes` file. Passing this * flag will cause attribute checks to ignore that file. + * equivalent) directory for a `gitattributes` file. Passing the + * `GIT_ATTR_CHECK_NO_SYSTEM` flag will cause attribute checks to + * ignore that file. + * + * Passing the `GIT_ATTR_CHECK_INCLUDE_HEAD` flag will use attributes + * from a `.gitattributes` file in the repository at the HEAD revision. */ -#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2) +#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2) +#define GIT_ATTR_CHECK_INCLUDE_HEAD (1 << 3) /** * Look up the value of one git attribute for path. @@ -231,8 +238,11 @@ * disk no longer match the cached contents of memory. This will cause * the attributes files to be reloaded the next time that an attribute * access function is called. + * + * @param repo The repository containing the gitattributes cache + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_attr_cache_flush( +GIT_EXTERN(int) git_attr_cache_flush( git_repository *repo); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/blame.h libgit2-1.1.0+dfsg.1/include/git2/blame.h --- libgit2-0.28.5+dfsg.1/include/git2/blame.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/blame.h 2020-10-12 18:53:06.000000000 +0000 @@ -47,13 +47,15 @@ * to canonical real names and email addresses. The mailmap will be read * from the working directory, or HEAD in a bare repository. */ GIT_BLAME_USE_MAILMAP = (1<<5), + /** Ignore whitespace differences */ + GIT_BLAME_IGNORE_WHITESPACE = (1<<6), } git_blame_flag_t; /** * Blame options structure * * Initialize with `GIT_BLAME_OPTIONS_INIT`. Alternatively, you can - * use `git_blame_init_options`. + * use `git_blame_options_init`. * */ typedef struct git_blame_options { @@ -100,7 +102,7 @@ * @param version The struct version; pass `GIT_BLAME_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_blame_init_options( +GIT_EXTERN(int) git_blame_options_init( git_blame_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/blob.h libgit2-1.1.0+dfsg.1/include/git2/blob.h --- libgit2-0.28.5+dfsg.1/include/git2/blob.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/blob.h 2020-10-12 18:53:06.000000000 +0000 @@ -94,7 +94,40 @@ * @param blob pointer to the blob * @return size on bytes */ -GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob); +GIT_EXTERN(git_object_size_t) git_blob_rawsize(const git_blob *blob); + +/** + * Flags to control the functionality of `git_blob_filter`. + */ +typedef enum { + /** When set, filters will not be applied to binary files. */ + GIT_BLOB_FILTER_CHECK_FOR_BINARY = (1 << 0), + + /** + * When set, filters will not load configuration from the + * system-wide `gitattributes` in `/etc` (or system equivalent). + */ + GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES = (1 << 1), + + /** + * When set, filters will be loaded from a `.gitattributes` file + * in the HEAD commit. + */ + GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD = (1 << 2), +} git_blob_filter_flag_t; + +/** + * The options used when applying filter options to a file. + */ +typedef struct { + int version; + + /** Flags to control the filtering process, see `git_blob_filter_flag_t` above */ + uint32_t flags; +} git_blob_filter_options; + +#define GIT_BLOB_FILTER_OPTIONS_VERSION 1 +#define GIT_BLOB_FILTER_OPTIONS_INIT {GIT_BLOB_FILTER_OPTIONS_VERSION, GIT_BLOB_FILTER_CHECK_FOR_BINARY} /** * Get a buffer with the filtered content of a blob. @@ -115,15 +148,14 @@ * @param out The git_buf to be filled in * @param blob Pointer to the blob * @param as_path Path used for file attribute lookups, etc. - * @param check_for_binary_data Should this test if blob content contains - * NUL bytes / looks like binary data before applying filters? + * @param opts Options to use for filtering the blob * @return 0 on success or an error code */ -GIT_EXTERN(int) git_blob_filtered_content( +GIT_EXTERN(int) git_blob_filter( git_buf *out, git_blob *blob, const char *as_path, - int check_for_binary_data); + git_blob_filter_options *opts); /** * Read a file from the working folder of a repository @@ -136,7 +168,7 @@ * relative to the repository's working dir * @return 0 or an error code */ -GIT_EXTERN(int) git_blob_create_fromworkdir(git_oid *id, git_repository *repo, const char *relative_path); +GIT_EXTERN(int) git_blob_create_from_workdir(git_oid *id, git_repository *repo, const char *relative_path); /** * Read a file from the filesystem and write its content @@ -148,7 +180,7 @@ * @param path file from which the blob will be created * @return 0 or an error code */ -GIT_EXTERN(int) git_blob_create_fromdisk(git_oid *id, git_repository *repo, const char *path); +GIT_EXTERN(int) git_blob_create_from_disk(git_oid *id, git_repository *repo, const char *path); /** * Create a stream to write a new blob into the object db @@ -156,12 +188,12 @@ * This function may need to buffer the data on disk and will in * general not be the right choice if you know the size of the data * to write. If you have data in memory, use - * `git_blob_create_frombuffer()`. If you do not, but know the size of + * `git_blob_create_from_buffer()`. If you do not, but know the size of * the contents (and don't want/need to perform filtering), use * `git_odb_open_wstream()`. * * Don't close this stream yourself but pass it to - * `git_blob_create_fromstream_commit()` to commit the write to the + * `git_blob_create_from_stream_commit()` to commit the write to the * object db and get the object id. * * If the `hintpath` parameter is filled, it will be used to determine @@ -175,7 +207,7 @@ * to apply onto the content of the blob to be created. * @return 0 or error code */ -GIT_EXTERN(int) git_blob_create_fromstream( +GIT_EXTERN(int) git_blob_create_from_stream( git_writestream **out, git_repository *repo, const char *hintpath); @@ -189,7 +221,7 @@ * @param stream the stream to close * @return 0 or an error code */ -GIT_EXTERN(int) git_blob_create_fromstream_commit( +GIT_EXTERN(int) git_blob_create_from_stream_commit( git_oid *out, git_writestream *stream); @@ -202,7 +234,7 @@ * @param len length of the data * @return 0 or an error code */ -GIT_EXTERN(int) git_blob_create_frombuffer( +GIT_EXTERN(int) git_blob_create_from_buffer( git_oid *id, git_repository *repo, const void *buffer, size_t len); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/branch.h libgit2-1.1.0+dfsg.1/include/git2/branch.h --- libgit2-0.28.5+dfsg.1/include/git2/branch.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/branch.h 2020-10-12 18:53:06.000000000 +0000 @@ -75,9 +75,9 @@ /** * Delete an existing branch reference. * - * If the branch is successfully deleted, the passed reference - * object will be invalidated. The reference must be freed manually - * by the user. + * Note that if the deletion succeeds, the reference object will not + * be valid anymore, and should be freed immediately by the user using + * `git_reference_free()`. * * @param branch A valid reference representing a branch * @return 0 on success, or an error code. @@ -126,6 +126,12 @@ * The new branch name will be checked for validity. * See `git_tag_create()` for rules about valid names. * + * Note that if the move succeeds, the old reference object will not + + be valid anymore, and should be freed immediately by the user using + + `git_reference_free()`. + * + * @param out New reference object for the updated name. + * * @param branch Current underlying reference of the branch. * * @param new_branch_name Target name of the branch once the move @@ -145,17 +151,14 @@ * Lookup a branch by its name in a repository. * * The generated reference must be freed by the user. - * * The branch name will be checked for validity. - * See `git_tag_create()` for rules about valid names. * - * @param out pointer to the looked-up branch reference + * @see git_tag_create for rules about valid names. * + * @param out pointer to the looked-up branch reference * @param repo the repository to look up the branch - * * @param branch_name Name of the branch to be looked-up; * this name is validated for consistency. - * * @param branch_type Type of the considered branch. This should * be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE. * @@ -169,65 +172,74 @@ git_branch_t branch_type); /** - * Return the name of the given local or remote branch. + * Get the branch name + * + * Given a reference object, this will check that it really is a branch (ie. + * it lives under "refs/heads/" or "refs/remotes/"), and return the branch part + * of it. * - * The name of the branch matches the definition of the name - * for git_branch_lookup. That is, if the returned name is given - * to git_branch_lookup() then the reference is returned that - * was given to this function. - * - * @param out where the pointer of branch name is stored; - * this is valid as long as the ref is not freed. - * @param ref the reference ideally pointing to a branch + * @param out Pointer to the abbreviated reference name. + * Owned by ref, do not free. * - * @return 0 on success; otherwise an error code (e.g., if the - * ref is no local or remote branch). + * @param ref A reference object, ideally pointing to a branch + * + * @return 0 on success; GIT_EINVALID if the reference isn't either a local or + * remote branch, otherwise an error code. */ GIT_EXTERN(int) git_branch_name( const char **out, const git_reference *ref); /** - * Return the reference supporting the remote tracking branch, - * given a local branch reference. + * Get the upstream of a branch + * + * Given a reference, this will return a new reference object corresponding + * to its remote tracking branch. The reference must be a local branch. * - * @param out Pointer where to store the retrieved - * reference. + * @see git_branch_upstream_name for details on the resolution. * + * @param out Pointer where to store the retrieved reference. * @param branch Current underlying reference of the branch. * * @return 0 on success; GIT_ENOTFOUND when no remote tracking - * reference exists, otherwise an error code. + * reference exists, otherwise an error code. */ GIT_EXTERN(int) git_branch_upstream( git_reference **out, const git_reference *branch); /** - * Set the upstream configuration for a given local branch + * Set a branch's upstream branch * - * @param branch the branch to configure + * This will update the configuration to set the branch named `branch_name` as the upstream of `branch`. + * Pass a NULL name to unset the upstream information. + * + * @note the actual tracking reference must have been already created for the + * operation to succeed. * - * @param upstream_name remote-tracking or local branch to set as - * upstream. Pass NULL to unset. + * @param branch the branch to configure + * @param branch_name remote-tracking or local branch to set as upstream. * - * @return 0 or an error code + * @return 0 on success; GIT_ENOTFOUND if there's no branch named `branch_name` + * or an error code */ -GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstream_name); +GIT_EXTERN(int) git_branch_set_upstream( + git_reference *branch, + const char *branch_name); /** - * Return the name of the reference supporting the remote tracking branch, - * given the name of a local branch reference. - * - * @param out Pointer to the user-allocated git_buf which will be - * filled with the name of the reference. + * Get the upstream name of a branch * - * @param repo the repository where the branches live + * Given a local branch, this will return its remote-tracking branch information, + * as a full reference name, ie. "feature/nice" would become + * "refs/remote/origin/feature/nice", depending on that branch's configuration. * + * @param out the buffer into which the name will be written. + * @param repo the repository where the branches live. * @param refname reference name of the local branch. * - * @return 0, GIT_ENOTFOUND when no remote tracking reference exists, - * otherwise an error code. + * @return 0 on success, GIT_ENOTFOUND when no remote tracking reference exists, + * or an error code. */ GIT_EXTERN(int) git_branch_upstream_name( git_buf *out, @@ -235,50 +247,55 @@ const char *refname); /** - * Determine if the current local branch is pointed at by HEAD. + * Determine if HEAD points to the given branch * - * @param branch Current underlying reference of the branch. + * @param branch A reference to a local branch. * - * @return 1 if HEAD points at the branch, 0 if it isn't, - * error code otherwise. + * @return 1 if HEAD points at the branch, 0 if it isn't, or a negative value + * as an error code. */ GIT_EXTERN(int) git_branch_is_head( const git_reference *branch); /** - * Determine if the current branch is checked out in any linked - * repository. + * Determine if any HEAD points to the current branch * - * @param branch Reference to the branch. + * This will iterate over all known linked repositories (usually in the form of + * worktrees) and report whether any HEAD is pointing at the current branch. * - * @return 1 if branch is checked out, 0 if it isn't, - * error code otherwise. + * @param branch A reference to a local branch. + * + * @return 1 if branch is checked out, 0 if it isn't, an error code otherwise. */ GIT_EXTERN(int) git_branch_is_checked_out( const git_reference *branch); /** - * Return the name of remote that the remote tracking branch belongs to. + * Find the remote name of a remote-tracking branch * - * @param out Pointer to the user-allocated git_buf which will be filled with the name of the remote. + * This will return the name of the remote whose fetch refspec is matching + * the given branch. E.g. given a branch "refs/remotes/test/master", it will + * extract the "test" part. If refspecs from multiple remotes match, + * the function will return GIT_EAMBIGUOUS. * + * @param out The buffer into which the name will be written. * @param repo The repository where the branch lives. + * @param refname complete name of the remote tracking branch. * - * @param canonical_branch_name name of the remote tracking branch. - * - * @return 0, GIT_ENOTFOUND - * when no remote matching remote was found, - * GIT_EAMBIGUOUS when the branch maps to several remotes, - * otherwise an error code. + * @return 0 on success, GIT_ENOTFOUND when no matching remote was found, + * GIT_EAMBIGUOUS when the branch maps to several remotes, + * otherwise an error code. */ GIT_EXTERN(int) git_branch_remote_name( git_buf *out, git_repository *repo, - const char *canonical_branch_name); - + const char *refname); /** - * Retrieve the name of the upstream remote of a local branch + * Retrieve the upstream remote of a local branch + * + * This will return the currently configured "branch.*.remote" for a given + * branch. This branch must be local. * * @param buf the buffer into which to write the name * @param repo the repository in which to look diff -Nru libgit2-0.28.5+dfsg.1/include/git2/buffer.h libgit2-1.1.0+dfsg.1/include/git2/buffer.h --- libgit2-0.28.5+dfsg.1/include/git2/buffer.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/buffer.h 2020-10-12 18:53:06.000000000 +0000 @@ -32,26 +32,32 @@ * a block of memory they hold. In this case, libgit2 will not resize or * free the memory, but will read from it as needed. * - * A `git_buf` is a public structure with three fields: - * - * - `ptr` points to the start of the allocated memory. If it is NULL, - * then the `git_buf` is considered empty and libgit2 will feel free - * to overwrite it with new data. - * - * - `size` holds the size (in bytes) of the data that is actually used. - * - * - `asize` holds the known total amount of allocated memory if the `ptr` - * was allocated by libgit2. It may be larger than `size`. If `ptr` - * was not allocated by libgit2 and should not be resized and/or freed, - * then `asize` will be set to zero. - * * Some APIs may occasionally do something slightly unusual with a buffer, * such as setting `ptr` to a value that was passed in by the user. In * those cases, the behavior will be clearly documented by the API. */ typedef struct { + /** + * The buffer contents. + * + * `ptr` points to the start of the allocated memory. If it is NULL, + * then the `git_buf` is considered empty and libgit2 will feel free + * to overwrite it with new data. + */ char *ptr; - size_t asize, size; + + /** + * `asize` holds the known total amount of allocated memory if the `ptr` + * was allocated by libgit2. It may be larger than `size`. If `ptr` + * was not allocated by libgit2 and should not be resized and/or freed, + * then `asize` will be set to zero. + */ + size_t asize; + + /** + * `size` holds the size (in bytes) of the data that is actually used. + */ + size_t size; } git_buf; /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/cert.h libgit2-1.1.0+dfsg.1/include/git2/cert.h --- libgit2-0.28.5+dfsg.1/include/git2/cert.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/cert.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_git_cert_h__ +#define INCLUDE_git_cert_h__ + +#include "common.h" + +/** + * @file git2/cert.h + * @brief Git certificate objects + * @defgroup git_cert Certificate objects + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Type of host certificate structure that is passed to the check callback + */ +typedef enum git_cert_t { + /** + * No information about the certificate is available. This may + * happen when using curl. + */ + GIT_CERT_NONE, + /** + * The `data` argument to the callback will be a pointer to + * the DER-encoded data. + */ + GIT_CERT_X509, + /** + * The `data` argument to the callback will be a pointer to a + * `git_cert_hostkey` structure. + */ + GIT_CERT_HOSTKEY_LIBSSH2, + /** + * The `data` argument to the callback will be a pointer to a + * `git_strarray` with `name:content` strings containing + * information about the certificate. This is used when using + * curl. + */ + GIT_CERT_STRARRAY, +} git_cert_t; + +/** + * Parent type for `git_cert_hostkey` and `git_cert_x509`. + */ +struct git_cert { + /** + * Type of certificate. A `GIT_CERT_` value. + */ + git_cert_t cert_type; +}; + +/** + * Callback for the user's custom certificate checks. + * + * @param cert The host certificate + * @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think + * this certificate is valid + * @param host Hostname of the host libgit2 connected to + * @param payload Payload provided by the caller + * @return 0 to proceed with the connection, < 0 to fail the connection + * or > 0 to indicate that the callback refused to act and that + * the existing validity determination should be honored + */ +typedef int GIT_CALLBACK(git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload); + +/** + * Type of SSH host fingerprint + */ +typedef enum { + /** MD5 is available */ + GIT_CERT_SSH_MD5 = (1 << 0), + /** SHA-1 is available */ + GIT_CERT_SSH_SHA1 = (1 << 1), + /** SHA-256 is available */ + GIT_CERT_SSH_SHA256 = (1 << 2), +} git_cert_ssh_t; + +/** + * Hostkey information taken from libssh2 + */ +typedef struct { + git_cert parent; /**< The parent cert */ + + /** + * A hostkey type from libssh2, either + * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1` + */ + git_cert_ssh_t type; + + /** + * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will + * have the MD5 hash of the hostkey. + */ + unsigned char hash_md5[16]; + + /** + * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will + * have the SHA-1 hash of the hostkey. + */ + unsigned char hash_sha1[20]; + + /** + * Hostkey hash. If type has `GIT_CERT_SSH_SHA256` set, this will + * have the SHA-256 hash of the hostkey. + */ + unsigned char hash_sha256[32]; +} git_cert_hostkey; + +/** + * X.509 certificate information + */ +typedef struct { + git_cert parent; /**< The parent cert */ + + /** + * Pointer to the X.509 certificate data + */ + void *data; + + /** + * Length of the memory block pointed to by `data`. + */ + size_t len; +} git_cert_x509; + +/** @} */ +GIT_END_DECL +#endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/checkout.h libgit2-1.1.0+dfsg.1/include/git2/checkout.h --- libgit2-0.28.5+dfsg.1/include/git2/checkout.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/checkout.h 2020-10-12 18:53:06.000000000 +0000 @@ -106,10 +106,22 @@ typedef enum { GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */ - /** Allow safe updates that cannot overwrite uncommitted data */ + /** + * Allow safe updates that cannot overwrite uncommitted data. + * If the uncommitted changes don't conflict with the checked out files, + * the checkout will still proceed, leaving the changes intact. + * + * Mutually exclusive with GIT_CHECKOUT_FORCE. + * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE. + */ GIT_CHECKOUT_SAFE = (1u << 0), - /** Allow all updates to force working directory to look like index */ + /** + * Allow all updates to force working directory to look like index. + * + * Mutually exclusive with GIT_CHECKOUT_SAFE. + * GIT_CHECKOUT_FORCE takes precedence over GIT_CHECKOUT_SAFE. + */ GIT_CHECKOUT_FORCE = (1u << 1), @@ -213,6 +225,7 @@ GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu } git_checkout_notify_t; +/** Checkout performance-reporting structure */ typedef struct { size_t mkdir_calls; size_t stat_calls; @@ -244,11 +257,11 @@ * Checkout options structure * * Initialize with `GIT_CHECKOUT_OPTIONS_INIT`. Alternatively, you can - * use `git_checkout_init_options`. + * use `git_checkout_options_init`. * */ typedef struct git_checkout_options { - unsigned int version; + unsigned int version; /**< The version */ unsigned int checkout_strategy; /**< default will be a safe checkout */ @@ -258,29 +271,46 @@ int file_open_flags; /**< default is O_CREAT | O_TRUNC | O_WRONLY */ unsigned int notify_flags; /**< see `git_checkout_notify_t` above */ + + /** + * Optional callback to get notifications on specific file states. + * @see git_checkout_notify_t + */ git_checkout_notify_cb notify_cb; + + /** Payload passed to notify_cb */ void *notify_payload; /** Optional callback to notify the consumer of checkout progress. */ git_checkout_progress_cb progress_cb; + + /** Payload passed to progress_cb */ void *progress_payload; - /** When not zeroed out, array of fnmatch patterns specifying which - * paths should be taken into account, otherwise all files. Use - * GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as simple list. + /** + * A list of wildmatch patterns or paths. + * + * By default, all paths are processed. If you pass an array of wildmatch + * patterns, those will be used to filter which paths should be taken into + * account. + * + * Use GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as a simple list. */ git_strarray paths; - /** The expected content of the working directory; defaults to HEAD. - * If the working directory does not match this baseline information, - * that will produce a checkout conflict. + /** + * The expected content of the working directory; defaults to HEAD. + * + * If the working directory does not match this baseline information, + * that will produce a checkout conflict. */ git_tree *baseline; - /** Like `baseline` above, though expressed as an index. This - * option overrides `baseline`. + /** + * Like `baseline` above, though expressed as an index. This + * option overrides `baseline`. */ - git_index *baseline_index; /**< expected content of workdir, expressed as an index. */ + git_index *baseline_index; const char *target_directory; /**< alternative checkout path to workdir */ @@ -290,6 +320,8 @@ /** Optional callback to notify the consumer of performance data. */ git_checkout_perfdata_cb perfdata_cb; + + /** Payload passed to perfdata_cb */ void *perfdata_payload; } git_checkout_options; @@ -306,7 +338,7 @@ * @param version The struct version; pass `GIT_CHECKOUT_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_checkout_init_options( +GIT_EXTERN(int) git_checkout_options_init( git_checkout_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/cherrypick.h libgit2-1.1.0+dfsg.1/include/git2/cherrypick.h --- libgit2-0.28.5+dfsg.1/include/git2/cherrypick.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/cherrypick.h 2020-10-12 18:53:06.000000000 +0000 @@ -46,7 +46,7 @@ * @param version The struct version; pass `GIT_CHERRYPICK_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_cherrypick_init_options( +GIT_EXTERN(int) git_cherrypick_options_init( git_cherrypick_options *opts, unsigned int version); @@ -59,8 +59,8 @@ * @param out pointer to store the index result in * @param repo the repository that contains the given commits * @param cherrypick_commit the commit to cherry-pick - * @param our_commit the commit to revert against (eg, HEAD) - * @param mainline the parent of the revert commit, if it is a merge + * @param our_commit the commit to cherry-pick against (eg, HEAD) + * @param mainline the parent of the `cherrypick_commit`, if it is a merge * @param merge_options the merge options (or null for defaults) * @return zero on success, -1 on failure. */ diff -Nru libgit2-0.28.5+dfsg.1/include/git2/clone.h libgit2-1.1.0+dfsg.1/include/git2/clone.h --- libgit2-0.28.5+dfsg.1/include/git2/clone.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/clone.h 2020-10-12 18:53:06.000000000 +0000 @@ -97,7 +97,7 @@ * Clone options structure * * Initialize with `GIT_CLONE_OPTIONS_INIT`. Alternatively, you can - * use `git_clone_init_options`. + * use `git_clone_options_init`. * */ typedef struct git_clone_options { @@ -178,7 +178,7 @@ * @param version The struct version; pass `GIT_CLONE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_clone_init_options( +GIT_EXTERN(int) git_clone_options_init( git_clone_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/commit.h libgit2-1.1.0+dfsg.1/include/git2/commit.h --- libgit2-0.28.5+dfsg.1/include/git2/commit.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/commit.h 2020-10-12 18:53:06.000000000 +0000 @@ -480,7 +480,8 @@ * * @param out the resulting commit id * @param commit_content the content of the unsigned commit object - * @param signature the signature to add to the commit + * @param signature the signature to add to the commit. Leave `NULL` + * to create a commit without adding a signature field. * @param signature_field which header field should contain this * signature. Leave `NULL` for the default of "gpgsig" * @return 0 or an error code @@ -501,6 +502,27 @@ */ GIT_EXTERN(int) git_commit_dup(git_commit **out, git_commit *source); +/** + * Commit signing callback. + * + * The callback will be called with the commit content, giving a user an + * opportunity to sign the commit content. The signature_field + * buf may be left empty to specify the default field "gpgsig". + * + * Signatures can take the form of any string, and can be created on an arbitrary + * header field. Signatures are most commonly used for verifying authorship of a + * commit using GPG or a similar cryptographically secure signing algorithm. + * See https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work for more + * details. + * + * When the callback: + * - returns GIT_PASSTHROUGH, no signature will be added to the commit. + * - returns < 0, commit creation will be aborted. + * - returns GIT_OK, the signature parameter is expected to be filled. + */ +typedef int (*git_commit_signing_cb)( + git_buf *signature, git_buf *signature_field, const char *commit_content, void *payload); + /** @} */ GIT_END_DECL #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/common.h libgit2-1.1.0+dfsg.1/include/git2/common.h --- libgit2-0.28.5+dfsg.1/include/git2/common.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/common.h 2020-10-12 18:53:06.000000000 +0000 @@ -21,10 +21,7 @@ #endif #if defined(_MSC_VER) && _MSC_VER < 1800 - GIT_BEGIN_DECL -# include "inttypes.h" - GIT_END_DECL -/** This check is needed for importing this file in an iOS/OS X framework throws an error in Xcode otherwise.*/ +# include #elif !defined(__CLANG_INTTYPES_H) # include #endif @@ -120,8 +117,9 @@ * @param major Store the major version number * @param minor Store the minor version number * @param rev Store the revision (patch) number + * @return 0 on success or an error code on failure */ -GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); +GIT_EXTERN(int) git_libgit2_version(int *major, int *minor, int *rev); /** * Combinations of these values describe the features with which libgit2 @@ -205,7 +203,11 @@ GIT_OPT_SET_ALLOCATOR, GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, GIT_OPT_GET_PACK_MAX_OBJECTS, - GIT_OPT_SET_PACK_MAX_OBJECTS + GIT_OPT_SET_PACK_MAX_OBJECTS, + GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, + GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, + GIT_OPT_GET_MWINDOW_FILE_LIMIT, + GIT_OPT_SET_MWINDOW_FILE_LIMIT } git_libgit2_opt_t; /** @@ -227,8 +229,18 @@ * * * opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size_t): * - * >Set the maximum amount of memory that can be mapped at any time - * by the library + * > Set the maximum amount of memory that can be mapped at any time + * > by the library + * + * * opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, size_t *): + * + * > Get the maximum number of files that will be mapped at any time by the + * > library + * + * * opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, size_t): + * + * > Set the maximum number of files that can be mapped at any time + * > by the library. The default (0) is unlimited. * * * opts(GIT_OPT_GET_SEARCH_PATH, int level, git_buf *buf) * @@ -395,6 +407,15 @@ * > Set the maximum number of objects libgit2 will allow in a pack * > file when downloading a pack file from a remote. * + * opts(GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, int enabled) + * > This will cause .keep file existence checks to be skipped when + * > accessing packfiles, which can help performance with remote filesystems. + * + * opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, int enabled) + * > When connecting to a server using NTLM or Negotiate + * > authentication, use expect/continue when POSTing data. + * > This option is not available on Windows. + * * @param option Option key * @param ... value to set the option * @return 0 on success, <0 on failure diff -Nru libgit2-0.28.5+dfsg.1/include/git2/config.h libgit2-1.1.0+dfsg.1/include/git2/config.h --- libgit2-0.28.5+dfsg.1/include/git2/config.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/config.h 2020-10-12 18:53:06.000000000 +0000 @@ -92,20 +92,20 @@ * Config var type */ typedef enum { - GIT_CVAR_FALSE = 0, - GIT_CVAR_TRUE = 1, - GIT_CVAR_INT32, - GIT_CVAR_STRING -} git_cvar_t; + GIT_CONFIGMAP_FALSE = 0, + GIT_CONFIGMAP_TRUE = 1, + GIT_CONFIGMAP_INT32, + GIT_CONFIGMAP_STRING +} git_configmap_t; /** * Mapping from config variables to values. */ typedef struct { - git_cvar_t cvar_type; + git_configmap_t type; const char *str_match; int map_value; -} git_cvar_map; +} git_configmap; /** * Locate the path to the global configuration file @@ -623,7 +623,7 @@ * * A mapping array looks as follows: * - * git_cvar_map autocrlf_mapping[] = { + * git_configmap autocrlf_mapping[] = { * {GIT_CVAR_FALSE, NULL, GIT_AUTO_CRLF_FALSE}, * {GIT_CVAR_TRUE, NULL, GIT_AUTO_CRLF_TRUE}, * {GIT_CVAR_STRING, "input", GIT_AUTO_CRLF_INPUT}, @@ -644,7 +644,7 @@ * @param out place to store the result of the mapping * @param cfg config file to get the variables from * @param name name of the config variable to lookup - * @param maps array of `git_cvar_map` objects specifying the possible mappings + * @param maps array of `git_configmap` objects specifying the possible mappings * @param map_n number of mapping objects in `maps` * @return 0 on success, error code otherwise */ @@ -652,20 +652,20 @@ int *out, const git_config *cfg, const char *name, - const git_cvar_map *maps, + const git_configmap *maps, size_t map_n); /** * Maps a string value to an integer constant * * @param out place to store the result of the parsing - * @param maps array of `git_cvar_map` objects specifying the possible mappings + * @param maps array of `git_configmap` objects specifying the possible mappings * @param map_n number of mapping objects in `maps` * @param value value to parse */ GIT_EXTERN(int) git_config_lookup_map_value( int *out, - const git_cvar_map *maps, + const git_configmap *maps, size_t map_n, const char *value); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/credential.h libgit2-1.1.0+dfsg.1/include/git2/credential.h --- libgit2-0.28.5+dfsg.1/include/git2/credential.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/credential.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * 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_git_credential_h__ +#define INCLUDE_git_credential_h__ + +#include "common.h" + +/** + * @file git2/credential.h + * @brief Git authentication & credential management + * @defgroup git_credential Authentication & credential management + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Supported credential types + * + * This represents the various types of authentication methods supported by + * the library. + */ +typedef enum { + /** + * A vanilla user/password request + * @see git_credential_userpass_plaintext_new + */ + GIT_CREDENTIAL_USERPASS_PLAINTEXT = (1u << 0), + + /** + * An SSH key-based authentication request + * @see git_credential_ssh_key_new + */ + GIT_CREDENTIAL_SSH_KEY = (1u << 1), + + /** + * An SSH key-based authentication request, with a custom signature + * @see git_credential_ssh_custom_new + */ + GIT_CREDENTIAL_SSH_CUSTOM = (1u << 2), + + /** + * An NTLM/Negotiate-based authentication request. + * @see git_credential_default + */ + GIT_CREDENTIAL_DEFAULT = (1u << 3), + + /** + * An SSH interactive authentication request + * @see git_credential_ssh_interactive_new + */ + GIT_CREDENTIAL_SSH_INTERACTIVE = (1u << 4), + + /** + * Username-only authentication request + * + * Used as a pre-authentication step if the underlying transport + * (eg. SSH, with no username in its URL) does not know which username + * to use. + * + * @see git_credential_username_new + */ + GIT_CREDENTIAL_USERNAME = (1u << 5), + + /** + * An SSH key-based authentication request + * + * Allows credentials to be read from memory instead of files. + * Note that because of differences in crypto backend support, it might + * not be functional. + * + * @see git_credential_ssh_key_memory_new + */ + GIT_CREDENTIAL_SSH_MEMORY = (1u << 6), +} git_credential_t; + +/** + * The base structure for all credential types + */ +typedef struct git_credential git_credential; + +typedef struct git_credential_userpass_plaintext git_credential_userpass_plaintext; + +/** Username-only credential information */ +typedef struct git_credential_username git_credential_username; + +/** A key for NTLM/Kerberos "default" credentials */ +typedef struct git_credential git_credential_default; + +/** + * A ssh key from disk + */ +typedef struct git_credential_ssh_key git_credential_ssh_key; + +/** + * Keyboard-interactive based ssh authentication + */ +typedef struct git_credential_ssh_interactive git_credential_ssh_interactive; + +/** + * A key with a custom signature function + */ +typedef struct git_credential_ssh_custom git_credential_ssh_custom; + +/** + * Credential acquisition callback. + * + * This callback is usually involved any time another system might need + * authentication. As such, you are expected to provide a valid + * git_credential object back, depending on allowed_types (a + * git_credential_t bitmask). + * + * Note that most authentication details are your responsibility - this + * callback will be called until the authentication succeeds, or you report + * an error. As such, it's easy to get in a loop if you fail to stop providing + * the same incorrect credentials. + * + * @param out The newly created credential object. + * @param url The resource for which we are demanding a credential. + * @param username_from_url The username that was embedded in a "user\@host" + * remote url, or NULL if not included. + * @param allowed_types A bitmask stating which credential types are OK to return. + * @param payload The payload provided when specifying this callback. + * @return 0 for success, < 0 to indicate an error, > 0 to indicate + * no credential was acquired + */ +typedef int GIT_CALLBACK(git_credential_acquire_cb)( + git_credential **out, + const char *url, + const char *username_from_url, + unsigned int allowed_types, + void *payload); + +/** + * Free a credential. + * + * This is only necessary if you own the object; that is, if you are a + * transport. + * + * @param cred the object to free + */ +GIT_EXTERN(void) git_credential_free(git_credential *cred); + +/** + * Check whether a credential object contains username information. + * + * @param cred object to check + * @return 1 if the credential object has non-NULL username, 0 otherwise + */ +GIT_EXTERN(int) git_credential_has_username(git_credential *cred); + +/** + * Return the username associated with a credential object. + * + * @param cred object to check + * @return the credential username, or NULL if not applicable + */ +GIT_EXTERN(const char *) git_credential_get_username(git_credential *cred); + +/** + * Create a new plain-text username and password credential object. + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username The username of the credential. + * @param password The password of the credential. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_userpass_plaintext_new( + git_credential **out, + const char *username, + const char *password); + +/** + * Create a "default" credential usable for Negotiate mechanisms like NTLM + * or Kerberos authentication. + * + * @param out The newly created credential object. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_default_new(git_credential **out); + +/** + * Create a credential to specify a username. + * + * This is used with ssh authentication to query for the username if + * none is specified in the url. + * + * @param out The newly created credential object. + * @param username The username to authenticate with + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_username_new(git_credential **out, const char *username); + +/** + * Create a new passphrase-protected ssh key credential object. + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username username to use to authenticate + * @param publickey The path to the public key of the credential. + * @param privatekey The path to the private key of the credential. + * @param passphrase The passphrase of the credential. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_ssh_key_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase); + +/** + * Create a new ssh key credential object reading the keys from memory. + * + * @param out The newly created credential object. + * @param username username to use to authenticate. + * @param publickey The public key of the credential. + * @param privatekey The private key of the credential. + * @param passphrase The passphrase of the credential. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_ssh_key_memory_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase); + +/* + * If the user hasn't included libssh2.h before git2.h, we need to + * define a few types for the callback signatures. + */ +#ifndef LIBSSH2_VERSION +typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; +typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT; +typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE; +#endif + +typedef void GIT_CALLBACK(git_credential_ssh_interactive_cb)( + const char *name, + int name_len, + const char *instruction, int instruction_len, + int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract); + + +/** + * Create a new ssh keyboard-interactive based credential object. + * The supplied credential parameter will be internally duplicated. + * + * @param username Username to use to authenticate. + * @param prompt_callback The callback method used for prompts. + * @param payload Additional data to pass to the callback. + * @return 0 for success or an error code for failure. + */ +GIT_EXTERN(int) git_credential_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload); + +/** + * Create a new ssh key credential object used for querying an ssh-agent. + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username username to use to authenticate + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_ssh_key_from_agent( + git_credential **out, + const char *username); + +typedef int GIT_CALLBACK(git_credential_sign_cb)( + LIBSSH2_SESSION *session, + unsigned char **sig, size_t *sig_len, + const unsigned char *data, size_t data_len, + void **abstract); + +/** + * Create an ssh key credential with a custom signing function. + * + * This lets you use your own function to sign the challenge. + * + * This function and its credential type is provided for completeness + * and wraps `libssh2_userauth_publickey()`, which is undocumented. + * + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username username to use to authenticate + * @param publickey The bytes of the public key. + * @param publickey_len The length of the public key in bytes. + * @param sign_callback The callback method to sign the data during the challenge. + * @param payload Additional data to pass to the callback. + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_credential_ssh_custom_new( + git_credential **out, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload); + +/** @} */ +GIT_END_DECL +#endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/credential_helpers.h libgit2-1.1.0+dfsg.1/include/git2/credential_helpers.h --- libgit2-0.28.5+dfsg.1/include/git2/credential_helpers.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/credential_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * 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_git_credential_helpers_h__ +#define INCLUDE_git_credential_helpers_h__ + +#include "transport.h" + +/** + * @file git2/credential_helpers.h + * @brief Utility functions for credential management + * @defgroup git_credential_helpers credential management helpers + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Payload for git_credential_userpass_plaintext. + */ +typedef struct git_credential_userpass_payload { + const char *username; + const char *password; +} git_credential_userpass_payload; + + +/** + * Stock callback usable as a git_credential_acquire_cb. This calls + * git_cred_userpass_plaintext_new unless the protocol has not specified + * `GIT_CREDENTIAL_USERPASS_PLAINTEXT` as an allowed type. + * + * @param out The newly created credential object. + * @param url The resource for which we are demanding a credential. + * @param user_from_url The username that was embedded in a "user\@host" + * remote url, or NULL if not included. + * @param allowed_types A bitmask stating which credential types are OK to return. + * @param payload The payload provided when specifying this callback. (This is + * interpreted as a `git_credential_userpass_payload*`.) + */ +GIT_EXTERN(int) git_credential_userpass( + git_credential **out, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload); + +/** @} */ +GIT_END_DECL +#endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/cred_helpers.h libgit2-1.1.0+dfsg.1/include/git2/cred_helpers.h --- libgit2-0.28.5+dfsg.1/include/git2/cred_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/cred_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -7,47 +7,9 @@ #ifndef INCLUDE_git_cred_helpers_h__ #define INCLUDE_git_cred_helpers_h__ -#include "transport.h" - -/** - * @file git2/cred_helpers.h - * @brief Utility functions for credential management - * @defgroup git_cred_helpers credential management helpers - * @ingroup Git - * @{ - */ -GIT_BEGIN_DECL - -/** - * Payload for git_cred_stock_userpass_plaintext. - */ -typedef struct git_cred_userpass_payload { - const char *username; - const char *password; -} git_cred_userpass_payload; - - -/** - * Stock callback usable as a git_cred_acquire_cb. This calls - * git_cred_userpass_plaintext_new unless the protocol has not specified - * `GIT_CREDTYPE_USERPASS_PLAINTEXT` as an allowed type. - * - * @param cred The newly created credential object. - * @param url The resource for which we are demanding a credential. - * @param user_from_url The username that was embedded in a "user\@host" - * remote url, or NULL if not included. - * @param allowed_types A bitmask stating which cred types are OK to return. - * @param payload The payload provided when specifying this callback. (This is - * interpreted as a `git_cred_userpass_payload*`.) - */ -GIT_EXTERN(int) git_cred_userpass( - git_cred **cred, - const char *url, - const char *user_from_url, - unsigned int allowed_types, - void *payload); - +/* These declarations have moved. */ +#ifndef GIT_DEPRECATE_HARD +# include "git2/credential_helpers.h" +#endif -/** @} */ -GIT_END_DECL #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/deprecated.h libgit2-1.1.0+dfsg.1/include/git2/deprecated.h --- libgit2-0.28.5+dfsg.1/include/git2/deprecated.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/deprecated.h 2020-10-12 18:53:06.000000000 +0000 @@ -7,18 +7,47 @@ #ifndef INCLUDE_git_deprecated_h__ #define INCLUDE_git_deprecated_h__ +#include "attr.h" +#include "config.h" #include "common.h" +#include "blame.h" #include "buffer.h" +#include "checkout.h" +#include "cherrypick.h" +#include "clone.h" +#include "describe.h" +#include "diff.h" #include "errors.h" #include "index.h" +#include "indexer.h" +#include "merge.h" #include "object.h" +#include "proxy.h" #include "refs.h" +#include "rebase.h" +#include "remote.h" +#include "trace.h" +#include "repository.h" +#include "revert.h" +#include "stash.h" +#include "status.h" +#include "submodule.h" +#include "worktree.h" +#include "credential.h" +#include "credential_helpers.h" /* * Users can avoid deprecated functions by defining `GIT_DEPRECATE_HARD`. */ #ifndef GIT_DEPRECATE_HARD +/* + * The credential structures are now opaque by default, and their + * definition has moved into the `sys/credential.h` header; include + * them here for backward compatibility. + */ +#include "sys/credential.h" + /** * @file git2/deprecated.h * @brief libgit2 deprecated functions and values @@ -27,6 +56,65 @@ */ GIT_BEGIN_DECL +/** @name Deprecated Attribute Constants + * + * These enumeration values are retained for backward compatibility. + * The newer versions of these functions should be preferred in all + * new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +#define GIT_ATTR_UNSPECIFIED_T GIT_ATTR_VALUE_UNSPECIFIED +#define GIT_ATTR_TRUE_T GIT_ATTR_VALUE_TRUE +#define GIT_ATTR_FALSE_T GIT_ATTR_VALUE_FALSE +#define GIT_ATTR_VALUE_T GIT_ATTR_VALUE_STRING + +#define GIT_ATTR_TRUE(attr) GIT_ATTR_IS_TRUE(attr) +#define GIT_ATTR_FALSE(attr) GIT_ATTR_IS_FALSE(attr) +#define GIT_ATTR_UNSPECIFIED(attr) GIT_ATTR_IS_UNSPECIFIED(attr) + +typedef git_attr_value_t git_attr_t; + +/**@}*/ + +/** @name Deprecated Blob Functions + * + * These functions are retained for backward compatibility. The newer + * versions of these functions should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +GIT_EXTERN(int) git_blob_create_fromworkdir(git_oid *id, git_repository *repo, const char *relative_path); +GIT_EXTERN(int) git_blob_create_fromdisk(git_oid *id, git_repository *repo, const char *path); +GIT_EXTERN(int) git_blob_create_fromstream( + git_writestream **out, + git_repository *repo, + const char *hintpath); +GIT_EXTERN(int) git_blob_create_fromstream_commit( + git_oid *out, + git_writestream *stream); +GIT_EXTERN(int) git_blob_create_frombuffer( + git_oid *id, git_repository *repo, const void *buffer, size_t len); + +/** Deprecated in favor of `git_blob_filter`. + * + * @deprecated Use git_blob_filter + * @see git_blob_filter + */ +GIT_EXTERN(int) git_blob_filtered_content( + git_buf *out, + git_blob *blob, + const char *as_path, + int check_for_binary_data); + +/**@}*/ + /** @name Deprecated Buffer Functions * * These functions and enumeration values are retained for backward @@ -52,6 +140,19 @@ /**@}*/ +/** @name Deprecated Config Functions and Constants + */ +/**@{*/ + +#define GIT_CVAR_FALSE GIT_CONFIGMAP_FALSE +#define GIT_CVAR_TRUE GIT_CONFIGMAP_TRUE +#define GIT_CVAR_INT32 GIT_CONFIGMAP_INT32 +#define GIT_CVAR_STRING GIT_CONFIGMAP_STRING + +typedef git_configmap git_cvar_map; + +/**@}*/ + /** @name Deprecated Error Functions and Constants * * These functions and enumeration values are retained for backward @@ -136,7 +237,7 @@ GIT_EXTERN(void) giterr_set_str(int error_class, const char *string); /** - * Indicates that an out-of-memory situation occured. This is an alias + * Indicates that an out-of-memory situation occurred. This is an alias * of `git_error_set_oom` and is preserved for backward compatibility. * * This function is deprecated, but there is no plan to remove this @@ -149,10 +250,11 @@ /**@}*/ -/** @name Deprecated Index Constants +/** @name Deprecated Index Functions and Constants * - * These enumeration values are retained for backward compatibility. - * The newer versions of these values should be preferred in all new code. + * These functions and enumeration values are retained for backward + * compatibility. The newer versions of these values should be + * preferred in all new code. * * There is no plan to remove these backward compatibility values at * this time. @@ -192,6 +294,11 @@ #define GIT_INDEXCAP_NO_SYMLINKS GIT_INDEX_CAPABILITY_NO_SYMLINKS #define GIT_INDEXCAP_FROM_OWNER GIT_INDEX_CAPABILITY_FROM_OWNER +GIT_EXTERN(int) git_index_add_frombuffer( + git_index *index, + const git_index_entry *entry, + const void *buffer, size_t len); + /**@}*/ /** @name Deprecated Object Constants @@ -217,6 +324,20 @@ #define GIT_OBJ_OFS_DELTA GIT_OBJECT_OFS_DELTA #define GIT_OBJ_REF_DELTA GIT_OBJECT_REF_DELTA +/** + * Get the size in bytes for the structure which + * acts as an in-memory representation of any given + * object type. + * + * For all the core types, this would the equivalent + * of calling `sizeof(git_commit)` if the core types + * were not opaque on the external API. + * + * @param type object type to get its size + * @return size in bytes of the object + */ +GIT_EXTERN(size_t) git_object__size(git_object_t type); + /**@}*/ /** @name Deprecated Reference Constants @@ -243,6 +364,243 @@ #define GIT_REF_FORMAT_REFSPEC_PATTERN GIT_REFERENCE_FORMAT_REFSPEC_PATTERN #define GIT_REF_FORMAT_REFSPEC_SHORTHAND GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND +GIT_EXTERN(int) git_tag_create_frombuffer( + git_oid *oid, + git_repository *repo, + const char *buffer, + int force); + +/**@}*/ + +/** @name Deprecated Credential Types + * + * These types are retained for backward compatibility. The newer + * versions of these values should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ + +typedef git_credential git_cred; +typedef git_credential_userpass_plaintext git_cred_userpass_plaintext; +typedef git_credential_username git_cred_username; +typedef git_credential_default git_cred_default; +typedef git_credential_ssh_key git_cred_ssh_key; +typedef git_credential_ssh_interactive git_cred_ssh_interactive; +typedef git_credential_ssh_custom git_cred_ssh_custom; + +typedef git_credential_acquire_cb git_cred_acquire_cb; +typedef git_credential_sign_cb git_cred_sign_callback; +typedef git_credential_sign_cb git_cred_sign_cb; +typedef git_credential_ssh_interactive_cb git_cred_ssh_interactive_callback; +typedef git_credential_ssh_interactive_cb git_cred_ssh_interactive_cb; + +#define git_credtype_t git_credential_t + +#define GIT_CREDTYPE_USERPASS_PLAINTEXT GIT_CREDENTIAL_USERPASS_PLAINTEXT +#define GIT_CREDTYPE_SSH_KEY GIT_CREDENTIAL_SSH_KEY +#define GIT_CREDTYPE_SSH_CUSTOM GIT_CREDENTIAL_SSH_CUSTOM +#define GIT_CREDTYPE_DEFAULT GIT_CREDENTIAL_DEFAULT +#define GIT_CREDTYPE_SSH_INTERACTIVE GIT_CREDENTIAL_SSH_INTERACTIVE +#define GIT_CREDTYPE_USERNAME GIT_CREDENTIAL_USERNAME +#define GIT_CREDTYPE_SSH_MEMORY GIT_CREDENTIAL_SSH_MEMORY + +GIT_EXTERN(void) git_cred_free(git_credential *cred); +GIT_EXTERN(int) git_cred_has_username(git_credential *cred); +GIT_EXTERN(const char *) git_cred_get_username(git_credential *cred); +GIT_EXTERN(int) git_cred_userpass_plaintext_new( + git_credential **out, + const char *username, + const char *password); +GIT_EXTERN(int) git_cred_default_new(git_credential **out); +GIT_EXTERN(int) git_cred_username_new(git_credential **out, const char *username); +GIT_EXTERN(int) git_cred_ssh_key_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase); +GIT_EXTERN(int) git_cred_ssh_key_memory_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase); +GIT_EXTERN(int) git_cred_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload); +GIT_EXTERN(int) git_cred_ssh_key_from_agent( + git_credential **out, + const char *username); +GIT_EXTERN(int) git_cred_ssh_custom_new( + git_credential **out, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload); + +/* Deprecated Credential Helper Types */ + +typedef git_credential_userpass_payload git_cred_userpass_payload; + +GIT_EXTERN(int) git_cred_userpass( + git_credential **out, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload); + +/**@}*/ + +/** @name Deprecated Trace Callback Types + * + * These types are retained for backward compatibility. The newer + * versions of these values should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +typedef git_trace_cb git_trace_callback; + +/**@}*/ + +/** @name Deprecated Object ID Types + * + * These types are retained for backward compatibility. The newer + * versions of these values should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +GIT_EXTERN(int) git_oid_iszero(const git_oid *id); + +/**@}*/ + +/** @name Deprecated Transfer Progress Types + * + * These types are retained for backward compatibility. The newer + * versions of these values should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +/** + * This structure is used to provide callers information about the + * progress of indexing a packfile. + * + * This type is deprecated, but there is no plan to remove this + * type definition at this time. + */ +typedef git_indexer_progress git_transfer_progress; + +/** + * Type definition for progress callbacks during indexing. + * + * This type is deprecated, but there is no plan to remove this + * type definition at this time. + */ +typedef git_indexer_progress_cb git_transfer_progress_cb; + +/** + * Type definition for push transfer progress callbacks. + * + * This type is deprecated, but there is no plan to remove this + * type definition at this time. + */ +typedef git_push_transfer_progress_cb git_push_transfer_progress; + + /** The type of a remote completion event */ +#define git_remote_completion_type git_remote_completion_t + +/** + * Callback for listing the remote heads + */ +typedef int GIT_CALLBACK(git_headlist_cb)(git_remote_head *rhead, void *payload); + +/**@}*/ + +/** @name Deprecated String Array Functions + * + * These types are retained for backward compatibility. The newer + * versions of these values should be preferred in all new code. + * + * There is no plan to remove these backward compatibility values at + * this time. + */ +/**@{*/ + +/** + * Copy a string array object from source to target. + * + * This function is deprecated, but there is no plan to remove this + * function at this time. + * + * @param tgt target + * @param src source + * @return 0 on success, < 0 on allocation failure + */ +GIT_EXTERN(int) git_strarray_copy(git_strarray *tgt, const git_strarray *src); + +/** + * Free the memory referred to by the git_strarray. This is an alias of + * `git_strarray_dispose` and is preserved for backward compatibility. + * + * This function is deprecated, but there is no plan to remove this + * function at this time. + * + * @deprecated Use git_strarray_dispose + * @see git_strarray_dispose + */ +GIT_EXTERN(void) git_strarray_free(git_strarray *array); + +/**@}*/ + +/** @name Deprecated Options Initialization Functions + * + * These functions are retained for backward compatibility. The newer + * versions of these functions should be preferred in all new code. + * + * There is no plan to remove these backward compatibility functions at + * this time. + */ +/**@{*/ + +GIT_EXTERN(int) git_blame_init_options(git_blame_options *opts, unsigned int version); +GIT_EXTERN(int) git_checkout_init_options(git_checkout_options *opts, unsigned int version); +GIT_EXTERN(int) git_cherrypick_init_options(git_cherrypick_options *opts, unsigned int version); +GIT_EXTERN(int) git_clone_init_options(git_clone_options *opts, unsigned int version); +GIT_EXTERN(int) git_describe_init_options(git_describe_options *opts, unsigned int version); +GIT_EXTERN(int) git_describe_init_format_options(git_describe_format_options *opts, unsigned int version); +GIT_EXTERN(int) git_diff_init_options(git_diff_options *opts, unsigned int version); +GIT_EXTERN(int) git_diff_find_init_options(git_diff_find_options *opts, unsigned int version); +GIT_EXTERN(int) git_diff_format_email_init_options(git_diff_format_email_options *opts, unsigned int version); +GIT_EXTERN(int) git_diff_patchid_init_options(git_diff_patchid_options *opts, unsigned int version); +GIT_EXTERN(int) git_fetch_init_options(git_fetch_options *opts, unsigned int version); +GIT_EXTERN(int) git_indexer_init_options(git_indexer_options *opts, unsigned int version); +GIT_EXTERN(int) git_merge_init_options(git_merge_options *opts, unsigned int version); +GIT_EXTERN(int) git_merge_file_init_input(git_merge_file_input *input, unsigned int version); +GIT_EXTERN(int) git_merge_file_init_options(git_merge_file_options *opts, unsigned int version); +GIT_EXTERN(int) git_proxy_init_options(git_proxy_options *opts, unsigned int version); +GIT_EXTERN(int) git_push_init_options(git_push_options *opts, unsigned int version); +GIT_EXTERN(int) git_rebase_init_options(git_rebase_options *opts, unsigned int version); +GIT_EXTERN(int) git_remote_create_init_options(git_remote_create_options *opts, unsigned int version); +GIT_EXTERN(int) git_repository_init_init_options(git_repository_init_options *opts, unsigned int version); +GIT_EXTERN(int) git_revert_init_options(git_revert_options *opts, unsigned int version); +GIT_EXTERN(int) git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version); +GIT_EXTERN(int) git_status_init_options(git_status_options *opts, unsigned int version); +GIT_EXTERN(int) git_submodule_update_init_options(git_submodule_update_options *opts, unsigned int version); +GIT_EXTERN(int) git_worktree_add_init_options(git_worktree_add_options *opts, unsigned int version); +GIT_EXTERN(int) git_worktree_prune_init_options(git_worktree_prune_options *opts, unsigned int version); + /**@}*/ /** @} */ diff -Nru libgit2-0.28.5+dfsg.1/include/git2/describe.h libgit2-1.1.0+dfsg.1/include/git2/describe.h --- libgit2-0.28.5+dfsg.1/include/git2/describe.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/describe.h 2020-10-12 18:53:06.000000000 +0000 @@ -37,7 +37,7 @@ * Describe options structure * * Initialize with `GIT_DESCRIBE_OPTIONS_INIT`. Alternatively, you can - * use `git_describe_init_options`. + * use `git_describe_options_init`. * */ typedef struct git_describe_options { @@ -79,13 +79,13 @@ * @param version The struct version; pass `GIT_DESCRIBE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_describe_init_options(git_describe_options *opts, unsigned int version); +GIT_EXTERN(int) git_describe_options_init(git_describe_options *opts, unsigned int version); /** * Describe format options structure * * Initialize with `GIT_DESCRIBE_FORMAT_OPTIONS_INIT`. Alternatively, you can - * use `git_describe_format_init_options`. + * use `git_describe_format_options_init`. * */ typedef struct { @@ -126,7 +126,7 @@ * @param version The struct version; pass `GIT_DESCRIBE_FORMAT_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_describe_init_format_options(git_describe_format_options *opts, unsigned int version); +GIT_EXTERN(int) git_describe_format_options_init(git_describe_format_options *opts, unsigned int version); /** * A struct that stores the result of a describe operation. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/diff.h libgit2-1.1.0+dfsg.1/include/git2/diff.h --- libgit2-0.28.5+dfsg.1/include/git2/diff.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/diff.h 2020-10-12 18:53:06.000000000 +0000 @@ -119,7 +119,7 @@ /** Include unreadable files in the diff */ GIT_DIFF_INCLUDE_UNREADABLE = (1u << 16), - + /** Include unreadable files in the diff */ GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 17), @@ -258,12 +258,12 @@ * abbreviated to something reasonable, like 7 characters. */ typedef struct { - git_oid id; - const char *path; - git_off_t size; - uint32_t flags; - uint16_t mode; - uint16_t id_abbrev; + git_oid id; + const char *path; + git_object_size_t size; + uint32_t flags; + uint16_t mode; + uint16_t id_abbrev; } git_diff_file; /** @@ -451,7 +451,7 @@ * @param version The struct version; pass `GIT_DIFF_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_diff_init_options( +GIT_EXTERN(int) git_diff_options_init( git_diff_options *opts, unsigned int version); @@ -784,7 +784,7 @@ * @param version The struct version; pass `GIT_DIFF_FIND_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_diff_find_init_options( +GIT_EXTERN(int) git_diff_find_options_init( git_diff_find_options *opts, unsigned int version); @@ -1093,6 +1093,7 @@ GIT_DIFF_FORMAT_RAW = 3u, /**< like git diff --raw */ GIT_DIFF_FORMAT_NAME_ONLY = 4u, /**< like git diff --name-only */ GIT_DIFF_FORMAT_NAME_STATUS = 5u, /**< like git diff --name-status */ + GIT_DIFF_FORMAT_PATCH_ID = 6u, /**< git diff as used by git patch-id */ } git_diff_format_t; /** @@ -1378,7 +1379,8 @@ typedef struct { unsigned int version; - git_diff_format_email_flags_t flags; + /** see `git_diff_format_email_flags_t` above */ + uint32_t flags; /** This patch number */ size_t patch_no; @@ -1435,7 +1437,7 @@ git_commit *commit, size_t patch_no, size_t total_patches, - git_diff_format_email_flags_t flags, + uint32_t flags, const git_diff_options *diff_opts); /** @@ -1448,7 +1450,7 @@ * @param version The struct version; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_diff_format_email_init_options( +GIT_EXTERN(int) git_diff_format_email_options_init( git_diff_format_email_options *opts, unsigned int version); @@ -1456,7 +1458,7 @@ * Patch ID options structure * * Initialize with `GIT_PATCHID_OPTIONS_INIT`. Alternatively, you can - * use `git_patchid_init_options`. + * use `git_diff_patchid_options_init`. * */ typedef struct git_diff_patchid_options { @@ -1476,7 +1478,7 @@ * @param version The struct version; pass `GIT_DIFF_PATCHID_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_diff_patchid_init_options( +GIT_EXTERN(int) git_diff_patchid_options_init( git_diff_patchid_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/errors.h libgit2-1.1.0+dfsg.1/include/git2/errors.h --- libgit2-0.28.5+dfsg.1/include/git2/errors.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/errors.h 2020-10-12 18:53:06.000000000 +0000 @@ -106,7 +106,9 @@ GIT_ERROR_FILESYSTEM, GIT_ERROR_PATCH, GIT_ERROR_WORKTREE, - GIT_ERROR_SHA1 + GIT_ERROR_SHA1, + GIT_ERROR_HTTP, + GIT_ERROR_INTERNAL } git_error_t; /** @@ -142,8 +144,9 @@ * @param error_class One of the `git_error_t` enum above describing the * general subsystem that is responsible for the error. * @param string The formatted error message to keep + * @return 0 on success or -1 on failure */ -GIT_EXTERN(void) git_error_set_str(int error_class, const char *string); +GIT_EXTERN(int) git_error_set_str(int error_class, const char *string); /** * Set the error message to a special value for memory allocation failure. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/filter.h libgit2-1.1.0+dfsg.1/include/git2/filter.h --- libgit2-0.28.5+dfsg.1/include/git2/filter.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/filter.h 2020-10-12 18:53:06.000000000 +0000 @@ -40,7 +40,15 @@ */ typedef enum { GIT_FILTER_DEFAULT = 0u, + + /** Don't error for `safecrlf` violations, allow them to continue. */ GIT_FILTER_ALLOW_UNSAFE = (1u << 0), + + /** Don't load `/etc/gitattributes` (or the system equivalent) */ + GIT_FILTER_NO_SYSTEM_ATTRIBUTES = (1u << 1), + + /** Load attributes from `.gitattributes` in the root of HEAD */ + GIT_FILTER_ATTRIBUTES_FROM_HEAD = (1u << 2), } git_filter_flag_t; /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/indexer.h libgit2-1.1.0+dfsg.1/include/git2/indexer.h --- libgit2-0.28.5+dfsg.1/include/git2/indexer.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/indexer.h 2020-10-12 18:53:06.000000000 +0000 @@ -13,13 +13,57 @@ GIT_BEGIN_DECL +/** A git indexer object */ typedef struct git_indexer git_indexer; +/** + * This structure is used to provide callers information about the + * progress of indexing a packfile, either directly or part of a + * fetch or clone that downloads a packfile. + */ +typedef struct git_indexer_progress { + /** number of objects in the packfile being indexed */ + unsigned int total_objects; + + /** received objects that have been hashed */ + unsigned int indexed_objects; + + /** received_objects: objects which have been downloaded */ + unsigned int received_objects; + + /** + * locally-available objects that have been injected in order + * to fix a thin pack + */ + unsigned int local_objects; + + /** number of deltas in the packfile being indexed */ + unsigned int total_deltas; + + /** received deltas that have been indexed */ + unsigned int indexed_deltas; + + /** size of the packfile received up to now */ + size_t received_bytes; +} git_indexer_progress; + +/** + * Type for progress callbacks during indexing. Return a value less + * than zero to cancel the indexing or download. + * + * @param stats Structure containing information about the state of the tran sfer + * @param payload Payload provided by caller + */ +typedef int GIT_CALLBACK(git_indexer_progress_cb)(const git_indexer_progress *stats, void *payload); + +/** + * Options for indexer configuration + */ typedef struct git_indexer_options { unsigned int version; /** progress_cb function to call with progress information */ - git_transfer_progress_cb progress_cb; + git_indexer_progress_cb progress_cb; /** progress_cb_payload payload for the progress callback */ void *progress_cb_payload; @@ -38,7 +82,7 @@ * @param version Version of struct; pass `GIT_INDEXER_OPTIONS_VERSION` * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_indexer_init_options( +GIT_EXTERN(int) git_indexer_options_init( git_indexer_options *opts, unsigned int version); @@ -69,7 +113,7 @@ * @param size the size of the data in bytes * @param stats stat storage */ -GIT_EXTERN(int) git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats); +GIT_EXTERN(int) git_indexer_append(git_indexer *idx, const void *data, size_t size, git_indexer_progress *stats); /** * Finalize the pack and index @@ -78,7 +122,7 @@ * * @param idx the indexer */ -GIT_EXTERN(int) git_indexer_commit(git_indexer *idx, git_transfer_progress *stats); +GIT_EXTERN(int) git_indexer_commit(git_indexer *idx, git_indexer_progress *stats); /** * Get the packfile's hash diff -Nru libgit2-0.28.5+dfsg.1/include/git2/index.h libgit2-1.1.0+dfsg.1/include/git2/index.h --- libgit2-0.28.5+dfsg.1/include/git2/index.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/index.h 2020-10-12 18:53:06.000000000 +0000 @@ -143,6 +143,7 @@ GIT_INDEX_ADD_CHECK_PATHSPEC = (1u << 2), } git_index_add_option_t; +/** Git index stage states */ typedef enum { /** * Match any index stage. @@ -554,8 +555,7 @@ * * If a previous index entry exists that has the same path as the * given 'entry', it will be replaced. Otherwise, the 'entry' will be - * added. The `id` and the `file_size` of the 'entry' are updated with the - * real value of the blob. + * added. * * This forces the file to be added to the index, not looking * at gitignore rules. Those rules can be evaluated through @@ -571,7 +571,7 @@ * @param len length of the data * @return 0 or an error code */ -GIT_EXTERN(int) git_index_add_frombuffer( +GIT_EXTERN(int) git_index_add_from_buffer( git_index *index, const git_index_entry *entry, const void *buffer, size_t len); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/inttypes.h libgit2-1.1.0+dfsg.1/include/git2/inttypes.h --- libgit2-0.28.5+dfsg.1/include/git2/inttypes.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/inttypes.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,309 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#if _MSC_VER >= 1600 -#include -#else -#include "stdint.h" -#endif - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -#endif // __STDC_FORMAT_MACROS ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - - -#endif // _MSC_INTTYPES_H_ ] diff -Nru libgit2-0.28.5+dfsg.1/include/git2/merge.h libgit2-1.1.0+dfsg.1/include/git2/merge.h --- libgit2-0.28.5+dfsg.1/include/git2/merge.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/merge.h 2020-10-12 18:53:06.000000000 +0000 @@ -57,7 +57,7 @@ * `GIT_MERGE_FILE_INPUT_VERSION` here. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_merge_file_init_input( +GIT_EXTERN(int) git_merge_file_input_init( git_merge_file_input *opts, unsigned int version); @@ -192,7 +192,7 @@ git_merge_file_favor_t favor; /** see `git_merge_file_flag_t` above */ - git_merge_file_flag_t flags; + uint32_t flags; /** The size of conflict markers (eg, "<<<<<<<"). Default is * GIT_MERGE_CONFLICT_MARKER_SIZE. */ @@ -212,9 +212,7 @@ * @param version The struct version; pass `GIT_MERGE_FILE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_merge_file_init_options( - git_merge_file_options *opts, - unsigned int version); +GIT_EXTERN(int) git_merge_file_options_init(git_merge_file_options *opts, unsigned int version); /** * Information about file-level merging @@ -249,7 +247,7 @@ unsigned int version; /** See `git_merge_flag_t` above */ - git_merge_flag_t flags; + uint32_t flags; /** * Similarity to consider a file renamed (default 50). If @@ -293,7 +291,7 @@ git_merge_file_favor_t file_favor; /** see `git_merge_file_flag_t` above */ - git_merge_file_flag_t file_flags; + uint32_t file_flags; } git_merge_options; #define GIT_MERGE_OPTIONS_VERSION 1 @@ -310,9 +308,7 @@ * @param version The struct version; pass `GIT_MERGE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_merge_init_options( - git_merge_options *opts, - unsigned int version); +GIT_EXTERN(int) git_merge_options_init(git_merge_options *opts, unsigned int version); /** * The results of `git_merge_analysis` indicate the merge opportunities. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/net.h libgit2-1.1.0+dfsg.1/include/git2/net.h --- libgit2-0.28.5+dfsg.1/include/git2/net.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/net.h 2020-10-12 18:53:06.000000000 +0000 @@ -49,11 +49,6 @@ char *symref_target; }; -/** - * Callback for listing the remote heads - */ -typedef int GIT_CALLBACK(git_headlist_cb)(git_remote_head *rhead, void *payload); - /** @} */ GIT_END_DECL #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/object.h libgit2-1.1.0+dfsg.1/include/git2/object.h --- libgit2-0.28.5+dfsg.1/include/git2/object.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/object.h 2020-10-12 18:53:06.000000000 +0000 @@ -21,6 +21,8 @@ */ GIT_BEGIN_DECL +#define GIT_OBJECT_SIZE_MAX UINT64_MAX + /** * Lookup a reference to one of the objects in a repository. * @@ -186,20 +188,6 @@ GIT_EXTERN(int) git_object_typeisloose(git_object_t type); /** - * Get the size in bytes for the structure which - * acts as an in-memory representation of any given - * object type. - * - * For all the core types, this would the equivalent - * of calling `sizeof(git_commit)` if the core types - * were not opaque on the external API. - * - * @param type object type to get its size - * @return size in bytes of the object - */ -GIT_EXTERN(size_t) git_object__size(git_object_t type); - -/** * Recursively peel an object until an object of the specified type is met. * * If the query cannot be satisfied due to the object model, diff -Nru libgit2-0.28.5+dfsg.1/include/git2/odb_backend.h libgit2-1.1.0+dfsg.1/include/git2/odb_backend.h --- libgit2-0.28.5+dfsg.1/include/git2/odb_backend.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/odb_backend.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,6 +9,7 @@ #include "common.h" #include "types.h" +#include "indexer.h" /** * @file git2/backend.h @@ -86,8 +87,8 @@ unsigned int mode; void *hash_ctx; - git_off_t declared_size; - git_off_t received_bytes; + git_object_size_t declared_size; + git_object_size_t received_bytes; /** * Write at most `len` bytes into `buffer` and advance the stream. @@ -124,8 +125,8 @@ struct git_odb_writepack { git_odb_backend *backend; - int GIT_CALLBACK(append)(git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats); - int GIT_CALLBACK(commit)(git_odb_writepack *writepack, git_transfer_progress *stats); + int GIT_CALLBACK(append)(git_odb_writepack *writepack, const void *data, size_t size, git_indexer_progress *stats); + int GIT_CALLBACK(commit)(git_odb_writepack *writepack, git_indexer_progress *stats); void GIT_CALLBACK(free)(git_odb_writepack *writepack); }; diff -Nru libgit2-0.28.5+dfsg.1/include/git2/odb.h libgit2-1.1.0+dfsg.1/include/git2/odb.h --- libgit2-0.28.5+dfsg.1/include/git2/odb.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/odb.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "oidarray.h" +#include "indexer.h" /** * @file git2/odb.h @@ -293,7 +294,7 @@ * @param type type of the object that will be written * @return 0 if the stream was created; error code otherwise */ -GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, git_off_t size, git_object_t type); +GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, git_object_size_t size, git_object_t type); /** * Write to an odb stream @@ -391,7 +392,7 @@ GIT_EXTERN(int) git_odb_write_pack( git_odb_writepack **out, git_odb *db, - git_transfer_progress_cb progress_cb, + git_indexer_progress_cb progress_cb, void *progress_payload); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/oid.h libgit2-1.1.0+dfsg.1/include/git2/oid.h --- libgit2-0.28.5+dfsg.1/include/git2/oid.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/oid.h 2020-10-12 18:53:06.000000000 +0000 @@ -73,8 +73,9 @@ * * @param out oid structure the result is written into. * @param raw the raw input bytes to be copied. + * @return 0 on success or error code */ -GIT_EXTERN(void) git_oid_fromraw(git_oid *out, const unsigned char *raw); +GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw); /** * Format a git_oid into a hex string. @@ -85,8 +86,9 @@ * oid digits are written; a '\\0' terminator must be added * by the caller if it is required. * @param id oid structure to format. + * @return 0 on success or error code */ -GIT_EXTERN(void) git_oid_fmt(char *out, const git_oid *id); +GIT_EXTERN(int) git_oid_fmt(char *out, const git_oid *id); /** * Format a git_oid into a partial hex string. @@ -96,8 +98,9 @@ * will be zeroed; if not, a '\0' terminator is NOT added. * @param n number of characters to write into out string * @param id oid structure to format. + * @return 0 on success or error code */ -GIT_EXTERN(void) git_oid_nfmt(char *out, size_t n, const git_oid *id); +GIT_EXTERN(int) git_oid_nfmt(char *out, size_t n, const git_oid *id); /** * Format a git_oid into a loose-object path string. @@ -111,8 +114,9 @@ * oid digits are written; a '\\0' terminator must be added * by the caller if it is required. * @param id oid structure to format. + * @return 0 on success, non-zero callback return value, or error code */ -GIT_EXTERN(void) git_oid_pathfmt(char *out, const git_oid *id); +GIT_EXTERN(int) git_oid_pathfmt(char *out, const git_oid *id); /** * Format a git_oid into a statically allocated c-string. @@ -151,8 +155,9 @@ * * @param out oid structure the result is written into. * @param src oid structure to copy from. + * @return 0 on success or error code */ -GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src); +GIT_EXTERN(int) git_oid_cpy(git_oid *out, const git_oid *src); /** * Compare two oid structures. @@ -207,7 +212,7 @@ * * @return 1 if all zeros, 0 otherwise. */ -GIT_EXTERN(int) git_oid_iszero(const git_oid *id); +GIT_EXTERN(int) git_oid_is_zero(const git_oid *id); /** * OID Shortener object diff -Nru libgit2-0.28.5+dfsg.1/include/git2/pack.h libgit2-1.1.0+dfsg.1/include/git2/pack.h --- libgit2-0.28.5+dfsg.1/include/git2/pack.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/pack.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,6 +9,7 @@ #include "common.h" #include "oid.h" +#include "indexer.h" /** * @file git2/pack.h @@ -154,7 +155,7 @@ * Write the new pack and corresponding index file to path. * * @param pb The packbuilder - * @param path to the directory where the packfile and index should be stored + * @param path Path to the directory where the packfile and index should be stored, or NULL for default location * @param mode permissions to use creating a packfile or 0 for defaults * @param progress_cb function to call with progress information from the indexer (optional) * @param progress_cb_payload payload for the progress callback (optional) @@ -165,7 +166,7 @@ git_packbuilder *pb, const char *path, unsigned int mode, - git_transfer_progress_cb progress_cb, + git_indexer_progress_cb progress_cb, void *progress_cb_payload); /** @@ -178,6 +179,16 @@ */ GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb); +/** + * Callback used to iterate over packed objects + * + * @see git_packbuilder_foreach + * + * @param buf A pointer to the object's data + * @param size The size of the underlying object + * @param payload Payload passed to git_packbuilder_foreach + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/proxy.h libgit2-1.1.0+dfsg.1/include/git2/proxy.h --- libgit2-0.28.5+dfsg.1/include/git2/proxy.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/proxy.h 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,9 @@ #define INCLUDE_git_proxy_h__ #include "common.h" -#include "transport.h" + +#include "cert.h" +#include "credential.h" GIT_BEGIN_DECL @@ -59,7 +61,7 @@ * Returning GIT_PASSTHROUGH will make libgit2 behave as * though this field isn't set. */ - git_cred_acquire_cb credentials; + git_credential_acquire_cb credentials; /** * If cert verification fails, this will be called to let the @@ -67,7 +69,7 @@ * connection to proceed. Returns 0 to allow the connection * or a negative value to indicate an error. */ - git_transport_certificate_check_cb certificate_check; + git_transport_certificate_check_cb certificate_check; /** * Payload to be provided to the credentials and certificate @@ -89,7 +91,7 @@ * @param version The struct version; pass `GIT_PROXY_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_proxy_init_options(git_proxy_options *opts, unsigned int version); +GIT_EXTERN(int) git_proxy_options_init(git_proxy_options *opts, unsigned int version); GIT_END_DECL diff -Nru libgit2-0.28.5+dfsg.1/include/git2/rebase.h libgit2-1.1.0+dfsg.1/include/git2/rebase.h --- libgit2-0.28.5+dfsg.1/include/git2/rebase.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/rebase.h 2020-10-12 18:53:06.000000000 +0000 @@ -13,6 +13,7 @@ #include "annotated_commit.h" #include "merge.h" #include "checkout.h" +#include "commit.h" /** * @file git2/rebase.h @@ -72,6 +73,21 @@ * `abort` to match git semantics. */ git_checkout_options checkout_options; + + /** + * If provided, this will be called with the commit content, allowing + * a signature to be added to the rebase commit. Can be skipped with + * GIT_PASSTHROUGH. If GIT_PASSTHROUGH is returned, a commit will be made + * without a signature. + * This field is only used when performing git_rebase_commit. + */ + git_commit_signing_cb signing_cb; + + /** + * This will be passed to each of the callbacks in this struct + * as the last parameter. + */ + void *payload; } git_rebase_options; /** @@ -118,7 +134,7 @@ #define GIT_REBASE_OPTIONS_VERSION 1 #define GIT_REBASE_OPTIONS_INIT \ { GIT_REBASE_OPTIONS_VERSION, 0, 0, NULL, GIT_MERGE_OPTIONS_INIT, \ - GIT_CHECKOUT_OPTIONS_INIT} + GIT_CHECKOUT_OPTIONS_INIT, NULL, NULL } /** Indicates that a rebase operation is not (yet) in progress. */ #define GIT_REBASE_NO_OPERATION SIZE_MAX @@ -156,7 +172,7 @@ * @param version The struct version; pass `GIT_REBASE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_rebase_init_options( +GIT_EXTERN(int) git_rebase_options_init( git_rebase_options *opts, unsigned int version); @@ -200,6 +216,34 @@ const git_rebase_options *opts); /** + * Gets the original `HEAD` ref name for merge rebases. + * + * @return The original `HEAD` ref name + */ +GIT_EXTERN(const char *) git_rebase_orig_head_name(git_rebase *rebase); + +/** + * Gets the original `HEAD` id for merge rebases. + * + * @return The original `HEAD` id + */ +GIT_EXTERN(const git_oid *) git_rebase_orig_head_id(git_rebase *rebase); + +/** + * Gets the `onto` ref name for merge rebases. + * + * @return The `onto` ref name + */ +GIT_EXTERN(const char *) git_rebase_onto_name(git_rebase *rebase); + +/** + * Gets the `onto` id for merge rebases. + * + * @return The `onto` id + */ +GIT_EXTERN(const git_oid *) git_rebase_onto_id(git_rebase *rebase); + +/** * Gets the count of rebase operations that are to be applied. * * @param rebase The in-progress rebase diff -Nru libgit2-0.28.5+dfsg.1/include/git2/refs.h libgit2-1.1.0+dfsg.1/include/git2/refs.h --- libgit2-0.28.5+dfsg.1/include/git2/refs.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/refs.h 2020-10-12 18:53:06.000000000 +0000 @@ -422,7 +422,26 @@ */ GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo); +/** + * Callback used to iterate over references + * + * @see git_reference_foreach + * + * @param reference The reference object + * @param payload Payload passed to git_reference_foreach + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_reference_foreach_cb)(git_reference *reference, void *payload); + +/** + * Callback used to iterate over reference names + * + * @see git_reference_foreach_name + * + * @param name The reference name + * @param payload Payload passed to git_reference_foreach_name + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_reference_foreach_name_cb)(const char *name, void *payload); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/remote.h libgit2-1.1.0+dfsg.1/include/git2/remote.h --- libgit2-0.28.5+dfsg.1/include/git2/remote.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/remote.h 2020-10-12 18:53:06.000000000 +0000 @@ -56,7 +56,7 @@ * Remote creation options structure * * Initialize with `GIT_REMOTE_CREATE_OPTIONS_INIT`. Alternatively, you can - * use `git_remote_create_init_options`. + * use `git_remote_create_options_init`. * */ typedef struct git_remote_create_options { @@ -94,7 +94,7 @@ * @param version The struct version; pass `GIT_REMOTE_CREATE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_remote_create_init_options( +GIT_EXTERN(int) git_remote_create_options_init( git_remote_create_options *opts, unsigned int version); @@ -378,8 +378,9 @@ * the operation has been cancelled and if so stops the operation. * * @param remote the remote + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_remote_stop(git_remote *remote); +GIT_EXTERN(int) git_remote_stop(git_remote *remote); /** * Disconnect from the remote @@ -387,8 +388,9 @@ * Close the connection to the remote. * * @param remote the remote to disconnect from + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_remote_disconnect(git_remote *remote); +GIT_EXTERN(int) git_remote_disconnect(git_remote *remote); /** * Free the memory associated with a remote @@ -415,18 +417,19 @@ * Argument to the completion callback which tells it which operation * finished. */ -typedef enum git_remote_completion_type { +typedef enum git_remote_completion_t { GIT_REMOTE_COMPLETION_DOWNLOAD, GIT_REMOTE_COMPLETION_INDEXING, GIT_REMOTE_COMPLETION_ERROR, -} git_remote_completion_type; +} git_remote_completion_t; /** Push network progress notification function */ -typedef int GIT_CALLBACK(git_push_transfer_progress)( +typedef int GIT_CALLBACK(git_push_transfer_progress_cb)( unsigned int current, unsigned int total, size_t bytes, void* payload); + /** * Represents an update which will be performed on the remote during push */ @@ -474,13 +477,28 @@ typedef int GIT_CALLBACK(git_push_update_reference_cb)(const char *refname, const char *status, void *data); /** + * Callback to resolve URLs before connecting to remote + * + * If you return GIT_PASSTHROUGH, you don't need to write anything to + * url_resolved. + * + * @param url_resolved The buffer to write the resolved URL to + * @param url The URL to resolve + * @param direction GIT_DIRECTION_FETCH or GIT_DIRECTION_PUSH + * @param payload Payload provided by the caller + * @return 0 on success, GIT_PASSTHROUGH or an error + */ +typedef int GIT_CALLBACK(git_url_resolve_cb)(git_buf *url_resolved, const char *url, int direction, void *payload); + +/** * The callback settings structure * * Set the callbacks to be called by the remote when informing the user * about the progress of the network operations. */ struct git_remote_callbacks { - unsigned int version; + unsigned int version; /**< The version */ + /** * Textual progress from the remote. Text send over the * progress side-band will be passed to this function (this is @@ -492,7 +510,7 @@ * Completion is called when different parts of the download * process are done (currently unused). */ - int GIT_CALLBACK(completion)(git_remote_completion_type type, void *data); + int GIT_CALLBACK(completion)(git_remote_completion_t type, void *data); /** * This will be called if the remote host requires @@ -501,7 +519,7 @@ * Returning GIT_PASSTHROUGH will make libgit2 behave as * though this field isn't set. */ - git_cred_acquire_cb credentials; + git_credential_acquire_cb credentials; /** * If cert verification fails, this will be called to let the @@ -516,7 +534,7 @@ * called with the current count of progress done by the * indexer. */ - git_transfer_progress_cb transfer_progress; + git_indexer_progress_cb transfer_progress; /** * Each time a reference is updated locally, this function @@ -537,7 +555,7 @@ * inline with pack building operations, so performance may be * affected. */ - git_push_transfer_progress push_transfer_progress; + git_push_transfer_progress_cb push_transfer_progress; /** * See documentation of git_push_update_reference_cb @@ -561,6 +579,12 @@ * as the last parameter. */ void *payload; + + /** + * Resolve URL before connecting to remote. + * The returned URL will be used to connect to the remote instead. + */ + git_url_resolve_cb resolve_url; }; #define GIT_REMOTE_CALLBACKS_VERSION 1 @@ -578,6 +602,7 @@ git_remote_callbacks *opts, unsigned int version); +/** Acceptable prune settings when fetching */ typedef enum { /** * Use the setting from the configuration @@ -679,7 +704,7 @@ * @param version The struct version; pass `GIT_FETCH_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_fetch_init_options( +GIT_EXTERN(int) git_fetch_options_init( git_fetch_options *opts, unsigned int version); @@ -729,7 +754,7 @@ * @param version The struct version; pass `GIT_PUSH_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_push_init_options( +GIT_EXTERN(int) git_push_options_init( git_push_options *opts, unsigned int version); @@ -832,7 +857,7 @@ /** * Get the statistics structure that is filled in by the fetch operation. */ -GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); +GIT_EXTERN(const git_indexer_progress *) git_remote_stats(git_remote *remote); /** * Retrieve the tag auto-follow setting diff -Nru libgit2-0.28.5+dfsg.1/include/git2/repository.h libgit2-1.1.0+dfsg.1/include/git2/repository.h --- libgit2-0.28.5+dfsg.1/include/git2/repository.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/repository.h 2020-10-12 18:53:06.000000000 +0000 @@ -323,7 +323,7 @@ * @param version The struct version; pass `GIT_REPOSITORY_INIT_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_repository_init_init_options( +GIT_EXTERN(int) git_repository_init_options_init( git_repository_init_options *opts, unsigned int version); @@ -438,7 +438,8 @@ GIT_REPOSITORY_ITEM_HOOKS, GIT_REPOSITORY_ITEM_LOGS, GIT_REPOSITORY_ITEM_MODULES, - GIT_REPOSITORY_ITEM_WORKTREES + GIT_REPOSITORY_ITEM_WORKTREES, + GIT_REPOSITORY_ITEM__LAST } git_repository_item_t; /** @@ -480,10 +481,11 @@ 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 is not a worktree, the git directory - * path is returned. + * 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. * * @param repo A repository object * @return the path to the common dir @@ -640,6 +642,18 @@ */ GIT_EXTERN(int) git_repository_state_cleanup(git_repository *repo); +/** + * Callback used to iterate over each FETCH_HEAD entry + * + * @see git_repository_fetchhead_foreach + * + * @param ref_name The reference name + * @param remote_url The remote URL + * @param oid The reference target OID + * @param is_merge Was the reference the result of a merge + * @param payload Payload passed to git_repository_fetchhead_foreach + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_repository_fetchhead_foreach_cb)(const char *ref_name, const char *remote_url, const git_oid *oid, @@ -662,6 +676,15 @@ git_repository_fetchhead_foreach_cb callback, void *payload); +/** + * Callback used to iterate over each MERGE_HEAD entry + * + * @see git_repository_mergehead_foreach + * + * @param oid The merge OID + * @param payload Payload passed to git_repository_mergehead_foreach + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_repository_mergehead_foreach_cb)(const git_oid *oid, void *payload); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/revert.h libgit2-1.1.0+dfsg.1/include/git2/revert.h --- libgit2-0.28.5+dfsg.1/include/git2/revert.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/revert.h 2020-10-12 18:53:06.000000000 +0000 @@ -46,7 +46,7 @@ * @param version The struct version; pass `GIT_REVERT_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_revert_init_options( +GIT_EXTERN(int) git_revert_options_init( git_revert_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/revwalk.h libgit2-1.1.0+dfsg.1/include/git2/revwalk.h --- libgit2-0.28.5+dfsg.1/include/git2/revwalk.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/revwalk.h 2020-10-12 18:53:06.000000000 +0000 @@ -84,8 +84,9 @@ * is over. * * @param walker handle to reset. + * @return 0 or an error code */ -GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker); +GIT_EXTERN(int) git_revwalk_reset(git_revwalk *walker); /** * Add a new root for the traversal @@ -224,8 +225,9 @@ * * @param walk the walker being used for the traversal. * @param sort_mode combination of GIT_SORT_XXX flags + * @return 0 or an error code */ -GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode); +GIT_EXTERN(int) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode); /** * Push and hide the respective endpoints of the given range. @@ -246,8 +248,10 @@ * Simplify the history by first-parent * * No parents other than the first for each commit will be enqueued. + * + * @return 0 or an error code */ -GIT_EXTERN(void) git_revwalk_simplify_first_parent(git_revwalk *walk); +GIT_EXTERN(int) git_revwalk_simplify_first_parent(git_revwalk *walk); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/stash.h libgit2-1.1.0+dfsg.1/include/git2/stash.h --- libgit2-0.28.5+dfsg.1/include/git2/stash.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/stash.h 2020-10-12 18:53:06.000000000 +0000 @@ -120,14 +120,14 @@ * Stash application options structure * * Initialize with `GIT_STASH_APPLY_OPTIONS_INIT`. Alternatively, you can - * use `git_stash_apply_init_options`. + * use `git_stash_apply_options_init`. * */ typedef struct git_stash_apply_options { unsigned int version; - /** See `git_stash_apply_flags_t`, above. */ - git_stash_apply_flags flags; + /** See `git_stash_apply_flags`, above. */ + uint32_t flags; /** Options to use when writing files to the working directory. */ git_checkout_options checkout_options; @@ -153,7 +153,7 @@ * @param version The struct version; pass `GIT_STASH_APPLY_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_stash_apply_init_options( +GIT_EXTERN(int) git_stash_apply_options_init( git_stash_apply_options *opts, unsigned int version); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/status.h libgit2-1.1.0+dfsg.1/include/git2/status.h --- libgit2-0.28.5+dfsg.1/include/git2/status.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/status.h 2020-10-12 18:53:06.000000000 +0000 @@ -163,27 +163,36 @@ /** * Options to control how `git_status_foreach_ext()` will issue callbacks. * - * This structure is set so that zeroing it out will give you relatively - * sane defaults. + * Initialize with `GIT_STATUS_OPTIONS_INIT`. Alternatively, you can + * use `git_status_options_init`. * - * The `show` value is one of the `git_status_show_t` constants that - * control which files to scan and in what order. - * - * The `flags` value is an OR'ed combination of the `git_status_opt_t` - * values above. - * - * The `pathspec` is an array of path patterns to match (using - * fnmatch-style matching), or just an array of paths to match exactly if - * `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags. - * - * The `baseline` is the tree to be used for comparison to the working directory - * and index; defaults to HEAD. */ typedef struct { - unsigned int version; + unsigned int version; /**< The version */ + + /** + * The `show` value is one of the `git_status_show_t` constants that + * control which files to scan and in what order. + */ git_status_show_t show; + + /** + * The `flags` value is an OR'ed combination of the `git_status_opt_t` + * values above. + */ unsigned int flags; + + /** + * The `pathspec` is an array of path patterns to match (using + * fnmatch-style matching), or just an array of paths to match exactly if + * `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags. + */ git_strarray pathspec; + + /** + * The `baseline` is the tree to be used for comparison to the working directory + * and index; defaults to HEAD. + */ git_tree *baseline; } git_status_options; @@ -200,7 +209,7 @@ * @param version The struct version; pass `GIT_STATUS_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_status_init_options( +GIT_EXTERN(int) git_status_options_init( git_status_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/strarray.h libgit2-1.1.0+dfsg.1/include/git2/strarray.h --- libgit2-0.28.5+dfsg.1/include/git2/strarray.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/strarray.h 2020-10-12 18:53:06.000000000 +0000 @@ -25,20 +25,16 @@ } git_strarray; /** - * Close a string array object - * - * This method should be called on `git_strarray` objects where the strings - * array is allocated and contains allocated strings, such as what you - * would get from `git_strarray_copy()`. Not doing so, will result in a - * memory leak. + * Free the strings contained in a string array. This method should + * be called on `git_strarray` objects that were provided by the + * library. Not doing so, will result in a memory leak. * * This does not free the `git_strarray` itself, since the library will - * never allocate that object directly itself (it is more commonly embedded - * inside another struct or created on the stack). + * never allocate that object directly itself. * - * @param array git_strarray from which to free string data + * @param array The git_strarray that contains strings to free */ -GIT_EXTERN(void) git_strarray_free(git_strarray *array); +GIT_EXTERN(void) git_strarray_dispose(git_strarray *array); /** * Copy a string array object from source to target. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/submodule.h libgit2-1.1.0+dfsg.1/include/git2/submodule.h --- libgit2-0.28.5+dfsg.1/include/git2/submodule.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/submodule.h 2020-10-12 18:53:06.000000000 +0000 @@ -122,7 +122,7 @@ * Submodule update options structure * * Initialize with `GIT_SUBMODULE_UPDATE_OPTIONS_INIT`. Alternatively, you can - * use `git_submodule_update_init_options`. + * use `git_submodule_update_options_init`. * */ typedef struct git_submodule_update_options { @@ -168,7 +168,7 @@ * @param version The struct version; pass `GIT_SUBMODULE_UPDATE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_submodule_update_init_options( +GIT_EXTERN(int) git_submodule_update_options_init( git_submodule_update_options *opts, unsigned int version); /** @@ -263,7 +263,8 @@ * from the working directory to the new repo. * * To fully emulate "git submodule add" call this function, then open the - * submodule repo and perform the clone step as needed. Lastly, call + * submodule repo and perform the clone step as needed (if you don't need + * anything custom see `git_submodule_add_clone()`). Lastly, call * `git_submodule_add_finalize()` to wrap up adding the new submodule and * .gitmodules to the index to be ready to commit. * @@ -286,6 +287,22 @@ int use_gitlink); /** + * Perform the clone step for a newly created submodule. + * + * This performs the necessary `git_clone` to setup a newly-created submodule. + * + * @param out The newly created repository object. Optional. + * @param submodule The submodule currently waiting for its clone. + * @param opts The options to use. + * + * @return 0 on success, -1 on other errors (see git_clone). + */ +GIT_EXTERN(int) git_submodule_clone( + git_repository **out, + git_submodule *submodule, + const git_submodule_update_options *opts); + +/** * Resolve the setup of a new git submodule. * * This should be called on a submodule once you have called add setup diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/alloc.h libgit2-1.1.0+dfsg.1/include/git2/sys/alloc.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/alloc.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/alloc.h 2020-10-12 18:53:06.000000000 +0000 @@ -21,51 +21,51 @@ * that all fields need to be set to a proper function. */ typedef struct { - /* Allocate `n` bytes of memory */ + /** 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. */ + /** 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 * case `ptr` is `NULL`, a new array shall be allocated. */ 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. */ diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/credential.h libgit2-1.1.0+dfsg.1/include/git2/sys/credential.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/credential.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/credential.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_sys_git_credential_h__ +#define INCLUDE_sys_git_credential_h__ + +#include "git2/common.h" +#include "git2/credential.h" + +/** + * @file git2/sys/cred.h + * @brief Git credentials low-level implementation + * @defgroup git_credential Git credentials low-level implementation + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * The base structure for all credential types + */ +struct git_credential { + git_credential_t credtype; /**< A type of credential */ + + /** The deallocator for this type of credentials */ + void GIT_CALLBACK(free)(git_credential *cred); +}; + +/** A plaintext username and password */ +struct git_credential_userpass_plaintext { + git_credential parent; /**< The parent credential */ + char *username; /**< The username to authenticate as */ + char *password; /**< The password to use */ +}; + +/** Username-only credential information */ +struct git_credential_username { + git_credential parent; /**< The parent credential */ + char username[1]; /**< The username to authenticate as */ +}; + +/** + * A ssh key from disk + */ +struct git_credential_ssh_key { + git_credential parent; /**< The parent credential */ + char *username; /**< The username to authenticate as */ + char *publickey; /**< The path to a public key */ + char *privatekey; /**< The path to a private key */ + char *passphrase; /**< Passphrase to decrypt the private key */ +}; + +/** + * Keyboard-interactive based ssh authentication + */ +struct git_credential_ssh_interactive { + git_credential parent; /**< The parent credential */ + char *username; /**< The username to authenticate as */ + + /** + * Callback used for authentication. + */ + git_credential_ssh_interactive_cb prompt_callback; + + void *payload; /**< Payload passed to prompt_callback */ +}; + +/** + * A key with a custom signature function + */ +struct git_credential_ssh_custom { + git_credential parent; /**< The parent credential */ + char *username; /**< The username to authenticate as */ + char *publickey; /**< The public key data */ + size_t publickey_len; /**< Length of the public key */ + + /** + * Callback used to sign the data. + */ + git_credential_sign_cb sign_callback; + + void *payload; /**< Payload passed to prompt_callback */ +}; + +GIT_END_DECL + +#endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/cred.h libgit2-1.1.0+dfsg.1/include/git2/sys/cred.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/cred.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/cred.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,15 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_sys_git_cred_h__ +#define INCLUDE_sys_git_cred_h__ + +/* These declarations have moved. */ +#ifndef GIT_DEPRECATE_HARD +# include "git2/sys/credential.h" +#endif + +#endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/index.h libgit2-1.1.0+dfsg.1/include/git2/sys/index.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/index.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/index.h 2020-10-12 18:53:06.000000000 +0000 @@ -75,8 +75,9 @@ * Remove all filename conflict entries. * * @param index an existing index object + * @return 0 or an error code */ -GIT_EXTERN(void) git_index_name_clear(git_index *index); +GIT_EXTERN(int) git_index_name_clear(git_index *index); /**@}*/ @@ -170,8 +171,9 @@ * Remove all resolve undo entries from the index * * @param index an existing index object + * @return 0 or an error code */ -GIT_EXTERN(void) git_index_reuc_clear(git_index *index); +GIT_EXTERN(int) git_index_reuc_clear(git_index *index); /**@}*/ diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/mempack.h libgit2-1.1.0+dfsg.1/include/git2/sys/mempack.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/mempack.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/mempack.h 2020-10-12 18:53:06.000000000 +0000 @@ -78,8 +78,9 @@ * semantics to the Git repository. * * @param backend The mempack backend + * @return 0 on success; error code otherwise */ -GIT_EXTERN(void) git_mempack_reset(git_odb_backend *backend); +GIT_EXTERN(int) git_mempack_reset(git_odb_backend *backend); GIT_END_DECL diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/merge.h libgit2-1.1.0+dfsg.1/include/git2/sys/merge.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/merge.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/merge.h 2020-10-12 18:53:06.000000000 +0000 @@ -41,7 +41,7 @@ typedef struct git_merge_driver_source git_merge_driver_source; /** Get the repository that the source data is coming from. */ -GIT_EXTERN(const git_repository *) git_merge_driver_source_repo( +GIT_EXTERN(git_repository *) git_merge_driver_source_repo( const git_merge_driver_source *src); /** Gets the ancestor of the file to merge. */ diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/odb_backend.h libgit2-1.1.0+dfsg.1/include/git2/sys/odb_backend.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/odb_backend.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/odb_backend.h 2020-10-12 18:53:06.000000000 +0000 @@ -30,8 +30,8 @@ /* read and read_prefix each return to libgit2 a buffer which * will be freed later. The buffer should be allocated using - * the function git_odb_backend_malloc to ensure that it can - * be safely freed later. */ + * the function git_odb_backend_data_alloc to ensure that libgit2 + * can safely free it later. */ int GIT_CALLBACK(read)( void **, size_t *, git_object_t *, git_odb_backend *, const git_oid *); @@ -53,7 +53,7 @@ git_odb_backend *, const git_oid *, const void *, size_t, git_object_t); int GIT_CALLBACK(writestream)( - git_odb_stream **, git_odb_backend *, git_off_t, git_object_t); + git_odb_stream **, git_odb_backend *, git_object_size_t, git_object_t); int GIT_CALLBACK(readstream)( git_odb_stream **, size_t *, git_object_t *, @@ -82,7 +82,7 @@ int GIT_CALLBACK(writepack)( git_odb_writepack **, git_odb_backend *, git_odb *odb, - git_transfer_progress_cb progress_cb, void *progress_payload); + git_indexer_progress_cb progress_cb, void *progress_payload); /** * "Freshens" an already existing object, updating its last-used @@ -117,8 +117,52 @@ git_odb_backend *backend, unsigned int version); +/** + * Allocate data for an ODB object. Custom ODB backends may use this + * to provide data back to the ODB from their read function. This + * memory should not be freed once it is returned to libgit2. If a + * custom ODB uses this function but encounters an error and does not + * return this data to libgit2, then they should use the corresponding + * git_odb_backend_data_free function. + * + * @param backend the ODB backend that is allocating this memory + * @param len the number of bytes to allocate + * @return the allocated buffer on success or NULL if out of memory + */ +GIT_EXTERN(void *) git_odb_backend_data_alloc(git_odb_backend *backend, size_t len); + +/** + * Frees custom allocated ODB data. This should only be called when + * memory allocated using git_odb_backend_data_alloc is not returned + * to libgit2 because the backend encountered an error in the read + * function after allocation and did not return this data to libgit2. + * + * @param backend the ODB backend that is freeing this memory + * @param data the buffer to free + */ +GIT_EXTERN(void) git_odb_backend_data_free(git_odb_backend *backend, void *data); + + +/* + * Users can avoid deprecated functions by defining `GIT_DEPRECATE_HARD`. + */ +#ifndef GIT_DEPRECATE_HARD + +/** + * Allocate memory for an ODB object from a custom backend. This is + * an alias of `git_odb_backend_data_alloc` and is preserved for + * backward compatibility. + * + * This function is deprecated, but there is no plan to remove this + * function at this time. + * + * @deprecated git_odb_backend_data_alloc + * @see git_odb_backend_data_alloc + */ GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len); +#endif + GIT_END_DECL #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/refdb_backend.h libgit2-1.1.0+dfsg.1/include/git2/sys/refdb_backend.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/refdb_backend.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/refdb_backend.h 2020-10-12 18:53:06.000000000 +0000 @@ -58,11 +58,18 @@ /** An instance for a custom backend */ struct git_refdb_backend { - unsigned int version; + unsigned int version; /**< The backend API version */ /** - * Queries the refdb backend to determine if the given ref_name - * exists. A refdb implementation must provide this function. + * Queries the refdb backend for the existence of a reference. + * + * A refdb implementation must provide this function. + * + * @arg exists The implementation shall set this to `0` if a ref does + * not exist, otherwise to `1`. + * @arg ref_name The reference's name that should be checked for + * existence. + * @return `0` on success, a negative error value code. */ int GIT_CALLBACK(exists)( int *exists, @@ -70,8 +77,16 @@ const char *ref_name); /** - * Queries the refdb backend for a given reference. A refdb - * implementation must provide this function. + * Queries the refdb backend for a given reference. + * + * A refdb implementation must provide this function. + * + * @arg out The implementation shall set this to the allocated + * reference, if it could be found, otherwise to `NULL`. + * @arg ref_name The reference's name that should be checked for + * existence. + * @return `0` on success, `GIT_ENOTFOUND` if the reference does + * exist, otherwise a negative error code. */ int GIT_CALLBACK(lookup)( git_reference **out, @@ -82,88 +97,216 @@ * Allocate an iterator object for the backend. * * A refdb implementation must provide this function. + * + * @arg out The implementation shall set this to the allocated + * reference iterator. A custom structure may be used with an + * embedded `git_reference_iterator` structure. Both `next` + * and `next_name` functions of `git_reference_iterator` need + * to be populated. + * @arg glob A pattern to filter references by. If given, the iterator + * shall only return references that match the glob when + * passed to `wildmatch`. + * @return `0` on success, otherwise a negative error code. */ int GIT_CALLBACK(iterator)( git_reference_iterator **iter, struct git_refdb_backend *backend, const char *glob); - /* - * Writes the given reference to the refdb. A refdb implementation - * must provide this function. + /** + * Writes the given reference to the refdb. + * + * A refdb implementation must provide this function. + * + * @arg ref The reference to persist. May either be a symbolic or + * direct reference. + * @arg force Whether to write the reference if a reference with the + * same name already exists. + * @arg who The person updating the reference. Shall be used to create + * a reflog entry. + * @arg message The message detailing what kind of reference update is + * performed. Shall be used to create a reflog entry. + * @arg old If not `NULL` and `force` is not set, then the + * implementation needs to ensure that the reference is currently at + * the given OID before writing the new value. If both `old` + * and `old_target` are `NULL`, then the reference should not + * exist at the point of writing. + * @arg old_target If not `NULL` and `force` is not set, then the + * implementation needs to ensure that the symbolic + * reference is currently at the given target before + * writing the new value. If both `old` and + * `old_target` are `NULL`, then the reference should + * not exist at the point of writing. + * @return `0` on success, otherwise a negative error code. */ int GIT_CALLBACK(write)(git_refdb_backend *backend, const git_reference *ref, int force, const git_signature *who, const char *message, const git_oid *old, const char *old_target); + /** + * Rename a reference in the refdb. + * + * A refdb implementation must provide this function. + * + * @arg out The implementation shall set this to the newly created + * reference or `NULL` on error. + * @arg old_name The current name of the reference that is to be renamed. + * @arg new_name The new name that the old reference shall be renamed to. + * @arg force Whether to write the reference if a reference with the + * target name already exists. + * @arg who The person updating the reference. Shall be used to create + * a reflog entry. + * @arg message The message detailing what kind of reference update is + * performed. Shall be used to create a reflog entry. + * @return `0` on success, otherwise a negative error code. + */ int GIT_CALLBACK(rename)( git_reference **out, git_refdb_backend *backend, const char *old_name, const char *new_name, int force, const git_signature *who, const char *message); /** - * Deletes the given reference (and if necessary its reflog) - * from the refdb. A refdb implementation must provide this - * function. + * Deletes the given reference from the refdb. + * + * If it exists, its reflog should be deleted as well. + * + * A refdb implementation must provide this function. + * + * @arg ref_name The name of the reference name that shall be deleted. + * @arg old_id If not `NULL` and `force` is not set, then the + * implementation needs to ensure that the reference is currently at + * the given OID before writing the new value. + * @arg old_target If not `NULL` and `force` is not set, then the + * implementation needs to ensure that the symbolic + * reference is currently at the given target before + * writing the new value. + * @return `0` on success, otherwise a negative error code. */ int GIT_CALLBACK(del)(git_refdb_backend *backend, const char *ref_name, const git_oid *old_id, const char *old_target); /** * Suggests that the given refdb compress or optimize its references. - * This mechanism is implementation specific. (For on-disk reference - * databases, this may pack all loose references.) A refdb - * implementation may provide this function; if it is not provided, - * nothing will be done. + * + * This mechanism is implementation specific. For on-disk reference + * databases, this may pack all loose references. + * + * A refdb implementation may provide this function; if it is not + * provided, nothing will be done. + * + * @return `0` on success a negative error code otherwise */ int GIT_CALLBACK(compress)(git_refdb_backend *backend); /** * Query whether a particular reference has a log (may be empty) + * + * Shall return 1 if it has a reflog, 0 it it doesn't and negative in + * case an error occurred. + * + * A refdb implementation must provide this function. + * + * @return `0` on success, `1` if the reflog for the given reference + * exists, a negative error code otherwise */ int GIT_CALLBACK(has_log)(git_refdb_backend *backend, const char *refname); /** * Make sure a particular reference will have a reflog which * will be appended to on writes. + * + * A refdb implementation must provide this function. + * + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(ensure_log)(git_refdb_backend *backend, const char *refname); /** * Frees any resources held by the refdb (including the `git_refdb_backend` - * itself). A refdb backend implementation must provide this function. + * itself). + * + * A refdb backend implementation must provide this function. */ void GIT_CALLBACK(free)(git_refdb_backend *backend); /** * Read the reflog for the given reference name. + * + * A refdb implementation must provide this function. + * + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(reflog_read)(git_reflog **out, git_refdb_backend *backend, const char *name); /** * Write a reflog to disk. + * + * A refdb implementation must provide this function. + * + * @arg reflog The complete reference log for a given reference. Note + * that this may contain entries that have already been + * written to disk. + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(reflog_write)(git_refdb_backend *backend, git_reflog *reflog); /** - * Rename a reflog + * Rename a reflog. + * + * A refdb implementation must provide this function. + * + * @arg old_name The name of old reference whose reflog shall be renamed from. + * @arg new_name The name of new reference whose reflog shall be renamed to. + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(reflog_rename)(git_refdb_backend *_backend, const char *old_name, const char *new_name); /** * Remove a reflog. + * + * A refdb implementation must provide this function. + * + * @arg name The name of the reference whose reflog shall be deleted. + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(reflog_delete)(git_refdb_backend *backend, const char *name); /** - * Lock a reference. The opaque parameter will be passed to the unlock function + * Lock a reference. + * + * A refdb implementation may provide this function; if it is not + * provided, the transaction API will fail to work. + * + * @arg payload_out Opaque parameter that will be passed verbosely to + * `unlock`. + * @arg refname Reference that shall be locked. + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(lock)(void **payload_out, git_refdb_backend *backend, const char *refname); /** - * Unlock a reference. Only one of target or symbolic_target - * will be set. success indicates whether to update the - * reference or discard the lock (if it's false) + * Unlock a reference. + * + * Only one of target or symbolic_target will be set. + * `success` will be true if the reference should be update, false if + * the lock must be discarded. + * + * A refdb implementation must provide this function if a `lock` + * implementation is provided. + * + * @arg payload The payload returned by `lock`. + * @arg success `1` if a reference should be updated, `2` if + * a reference should be deleted, `0` if the lock must be + * discarded. + * @arg update_reflog `1` in case the reflog should be updated, `0` + * otherwise. + * @arg ref The reference which should be unlocked. + * @arg who The person updating the reference. Shall be used to create + * a reflog entry in case `update_reflog` is set. + * @arg message The message detailing what kind of reference update is + * performed. Shall be used to create a reflog entry in + * case `update_reflog` is set. + * @return `0` on success, a negative error code otherwise */ int GIT_CALLBACK(unlock)(git_refdb_backend *backend, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/repository.h libgit2-1.1.0+dfsg.1/include/git2/sys/repository.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/repository.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/repository.h 2020-10-12 18:53:06.000000000 +0000 @@ -25,6 +25,10 @@ * Note that this is only useful if you wish to associate the repository * with a non-filesystem-backed object database and config store. * + * Caveats: since this repository has no physical location, some systems + * can fail to function properly: locations under $GIT_DIR, $GIT_COMMON_DIR, + * or $GIT_INFO_DIR are impacted. + * * @param out The blank repository * @return 0 on success, or an error code */ @@ -39,9 +43,12 @@ * There's no need to call this function directly unless you're * trying to aggressively cleanup the repo before its * deallocation. `git_repository_free` already performs this operation - * before deallocation the repo. + * before deallocating the repo. + * + * @param repo The repository to clean up + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_repository__cleanup(git_repository *repo); +GIT_EXTERN(int) git_repository__cleanup(git_repository *repo); /** * Update the filesystem config settings for an open repository @@ -74,8 +81,9 @@ * * @param repo A repository object * @param config A Config object + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config); +GIT_EXTERN(int) git_repository_set_config(git_repository *repo, git_config *config); /** * Set the Object Database for this repository @@ -89,8 +97,9 @@ * * @param repo A repository object * @param odb An ODB object + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb); +GIT_EXTERN(int) git_repository_set_odb(git_repository *repo, git_odb *odb); /** * Set the Reference Database Backend for this repository @@ -104,8 +113,9 @@ * * @param repo A repository object * @param refdb An refdb object + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb); +GIT_EXTERN(int) git_repository_set_refdb(git_repository *repo, git_refdb *refdb); /** * Set the index file for this repository @@ -119,8 +129,9 @@ * * @param repo A repository object * @param index An index object + * @return 0 on success, or an error code */ -GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index); +GIT_EXTERN(int) git_repository_set_index(git_repository *repo, git_index *index); /** * Set a repository to be bare. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/time.h libgit2-1.1.0+dfsg.1/include/git2/sys/time.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/time.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/time.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +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_git_time_h__ -#define INCLUDE_git_time_h__ - -#include "git2/common.h" - -GIT_BEGIN_DECL - -/** - * Return a monotonic time value, useful for measuring running time - * and setting up timeouts. - * - * The returned value is an arbitrary point in time -- it can only be - * used when comparing it to another `git_time_monotonic` call. - * - * The time is returned in seconds, with a decimal fraction that differs - * on accuracy based on the underlying system, but should be least - * accurate to Nanoseconds. - * - * This function cannot fail. - */ -GIT_EXTERN(double) git_time_monotonic(void); - -GIT_END_DECL -#endif - diff -Nru libgit2-0.28.5+dfsg.1/include/git2/sys/transport.h libgit2-1.1.0+dfsg.1/include/git2/sys/transport.h --- libgit2-0.28.5+dfsg.1/include/git2/sys/transport.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/sys/transport.h 2020-10-12 18:53:06.000000000 +0000 @@ -55,7 +55,7 @@ int GIT_CALLBACK(connect)( git_transport *transport, const char *url, - git_cred_acquire_cb cred_acquire_cb, + git_credential_acquire_cb cred_acquire_cb, void *cred_acquire_payload, const git_proxy_options *proxy_opts, int direction, @@ -98,8 +98,8 @@ int GIT_CALLBACK(download_pack)( git_transport *transport, git_repository *repo, - git_transfer_progress *stats, - git_transfer_progress_cb progress_cb, + git_indexer_progress *stats, + git_indexer_progress_cb progress_cb, void *progress_payload); /** Checks to see if the transport is connected */ @@ -266,7 +266,7 @@ * refused to provide credentials and callers should behave as if no * callback was set), or < 0 for an error */ -GIT_EXTERN(int) git_transport_smart_credentials(git_cred **out, git_transport *transport, const char *user, int methods); +GIT_EXTERN(int) git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods); /** * Get a copy of the proxy options diff -Nru libgit2-0.28.5+dfsg.1/include/git2/tag.h libgit2-1.1.0+dfsg.1/include/git2/tag.h --- libgit2-0.28.5+dfsg.1/include/git2/tag.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/tag.h 2020-10-12 18:53:06.000000000 +0000 @@ -217,7 +217,7 @@ * @param force Overwrite existing tags * @return 0 on success; error code otherwise */ -GIT_EXTERN(int) git_tag_create_frombuffer( +GIT_EXTERN(int) git_tag_create_from_buffer( git_oid *oid, git_repository *repo, const char *buffer, @@ -317,7 +317,16 @@ const char *pattern, git_repository *repo); - +/** + * Callback used to iterate over tag names + * + * @see git_tag_foreach + * + * @param name The tag name + * @param oid The tag's OID + * @param payload Payload passed to git_tag_foreach + * @return non-zero to terminate the iteration + */ typedef int GIT_CALLBACK(git_tag_foreach_cb)(const char *name, git_oid *oid, void *payload); /** diff -Nru libgit2-0.28.5+dfsg.1/include/git2/trace.h libgit2-1.1.0+dfsg.1/include/git2/trace.h --- libgit2-0.28.5+dfsg.1/include/git2/trace.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/trace.h 2020-10-12 18:53:06.000000000 +0000 @@ -49,7 +49,7 @@ /** * An instance for a tracing function */ -typedef void GIT_CALLBACK(git_trace_callback)(git_trace_level_t level, const char *msg); +typedef void GIT_CALLBACK(git_trace_cb)(git_trace_level_t level, const char *msg); /** * Sets the system tracing configuration to the specified level with the @@ -60,7 +60,7 @@ * @param cb Function to call with trace data * @return 0 or an error code */ -GIT_EXTERN(int) git_trace_set(git_trace_level_t level, git_trace_callback cb); +GIT_EXTERN(int) git_trace_set(git_trace_level_t level, git_trace_cb cb); /** @} */ GIT_END_DECL diff -Nru libgit2-0.28.5+dfsg.1/include/git2/transport.h libgit2-1.1.0+dfsg.1/include/git2/transport.h --- libgit2-0.28.5+dfsg.1/include/git2/transport.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/transport.h 2020-10-12 18:53:06.000000000 +0000 @@ -10,6 +10,8 @@ #include "indexer.h" #include "net.h" #include "types.h" +#include "cert.h" +#include "credential.h" /** * @file git2/transport.h @@ -20,352 +22,21 @@ */ GIT_BEGIN_DECL -/** Signature of a function which creates a transport */ -typedef int GIT_CALLBACK(git_transport_cb)(git_transport **out, git_remote *owner, void *param); - -/** - * Type of SSH host fingerprint - */ -typedef enum { - /** MD5 is available */ - GIT_CERT_SSH_MD5 = (1 << 0), - /** SHA-1 is available */ - GIT_CERT_SSH_SHA1 = (1 << 1), -} git_cert_ssh_t; - -/** - * Hostkey information taken from libssh2 - */ -typedef struct { - git_cert parent; - - /** - * A hostkey type from libssh2, either - * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1` - */ - git_cert_ssh_t type; - - /** - * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will - * have the MD5 hash of the hostkey. - */ - unsigned char hash_md5[16]; - - /** - * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will - * have the SHA-1 hash of the hostkey. - */ - unsigned char hash_sha1[20]; -} git_cert_hostkey; - -/** - * X.509 certificate information - */ -typedef struct { - git_cert parent; - /** - * Pointer to the X.509 certificate data - */ - void *data; - /** - * Length of the memory block pointed to by `data`. - */ - size_t len; -} git_cert_x509; - -/* - *** Begin interface for credentials acquisition *** - */ - -/** - * Supported credential types - * - * This represents the various types of authentication methods supported by - * the library. - */ -typedef enum { - /** - * A vanilla user/password request - * @see git_cred_userpass_plaintext_new - */ - GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0), - - /** - * An SSH key-based authentication request - * @see git_cred_ssh_key_new - */ - GIT_CREDTYPE_SSH_KEY = (1u << 1), - - /** - * An SSH key-based authentication request, with a custom signature - * @see git_cred_ssh_custom_new - */ - GIT_CREDTYPE_SSH_CUSTOM = (1u << 2), - - /** - * An NTLM/Negotiate-based authentication request. - * @see git_cred_default - */ - GIT_CREDTYPE_DEFAULT = (1u << 3), - - /** - * An SSH interactive authentication request - * @see git_cred_ssh_interactive_new - */ - GIT_CREDTYPE_SSH_INTERACTIVE = (1u << 4), - - /** - * Username-only authentication request - * - * Used as a pre-authentication step if the underlying transport - * (eg. SSH, with no username in its URL) does not know which username - * to use. - * - * @see git_cred_username_new - */ - GIT_CREDTYPE_USERNAME = (1u << 5), - - /** - * An SSH key-based authentication request - * - * Allows credentials to be read from memory instead of files. - * Note that because of differences in crypto backend support, it might - * not be functional. - * - * @see git_cred_ssh_key_memory_new - */ - GIT_CREDTYPE_SSH_MEMORY = (1u << 6), -} git_credtype_t; - -typedef struct git_cred git_cred; - -/** - * The base structure for all credential types - */ -struct git_cred { - git_credtype_t credtype; /**< A type of credential */ - void GIT_CALLBACK(free)(git_cred *cred); -}; - -/** A plaintext username and password */ -typedef struct { - git_cred parent; - char *username; - char *password; -} git_cred_userpass_plaintext; - - -/* - * If the user hasn't included libssh2.h before git2.h, we need to - * define a few types for the callback signatures. - */ -#ifndef LIBSSH2_VERSION -typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; -typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT; -typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE; -#endif - -typedef int GIT_CALLBACK(git_cred_sign_callback)(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract); -typedef void GIT_CALLBACK(git_cred_ssh_interactive_callback)(const char* name, int name_len, const char* instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract); - -/** - * A ssh key from disk - */ -typedef struct git_cred_ssh_key { - git_cred parent; - char *username; - char *publickey; - char *privatekey; - char *passphrase; -} git_cred_ssh_key; - -/** - * Keyboard-interactive based ssh authentication - */ -typedef struct git_cred_ssh_interactive { - git_cred parent; - char *username; - git_cred_ssh_interactive_callback prompt_callback; - void *payload; -} git_cred_ssh_interactive; - -/** - * A key with a custom signature function - */ -typedef struct git_cred_ssh_custom { - git_cred parent; - char *username; - char *publickey; - size_t publickey_len; - git_cred_sign_callback sign_callback; - void *payload; -} git_cred_ssh_custom; - -/** A key for NTLM/Kerberos "default" credentials */ -typedef struct git_cred git_cred_default; - -/** Username-only credential information */ -typedef struct git_cred_username { - git_cred parent; - char username[1]; -} git_cred_username; - -/** - * Check whether a credential object contains username information. - * - * @param cred object to check - * @return 1 if the credential object has non-NULL username, 0 otherwise - */ -GIT_EXTERN(int) git_cred_has_username(git_cred *cred); - -/** - * Create a new plain-text username and password credential object. - * The supplied credential parameter will be internally duplicated. - * - * @param out The newly created credential object. - * @param username The username of the credential. - * @param password The password of the credential. - * @return 0 for success or an error code for failure - */ -GIT_EXTERN(int) git_cred_userpass_plaintext_new( - git_cred **out, - const char *username, - const char *password); - -/** - * Create a new passphrase-protected ssh key credential object. - * The supplied credential parameter will be internally duplicated. - * - * @param out The newly created credential object. - * @param username username to use to authenticate - * @param publickey The path to the public key of the credential. - * @param privatekey The path to the private key of the credential. - * @param passphrase The passphrase of the credential. - * @return 0 for success or an error code for failure - */ -GIT_EXTERN(int) git_cred_ssh_key_new( - git_cred **out, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase); - -/** - * Create a new ssh keyboard-interactive based credential object. - * The supplied credential parameter will be internally duplicated. - * - * @param username Username to use to authenticate. - * @param prompt_callback The callback method used for prompts. - * @param payload Additional data to pass to the callback. - * @return 0 for success or an error code for failure. - */ -GIT_EXTERN(int) git_cred_ssh_interactive_new( - git_cred **out, - const char *username, - git_cred_ssh_interactive_callback prompt_callback, - void *payload); - -/** - * Create a new ssh key credential object used for querying an ssh-agent. - * The supplied credential parameter will be internally duplicated. - * - * @param out The newly created credential object. - * @param username username to use to authenticate - * @return 0 for success or an error code for failure - */ -GIT_EXTERN(int) git_cred_ssh_key_from_agent( - git_cred **out, - const char *username); - /** - * Create an ssh key credential with a custom signing function. + * Callback for messages recieved by the transport. * - * This lets you use your own function to sign the challenge. + * Return a negative value to cancel the network operation. * - * This function and its credential type is provided for completeness - * and wraps `libssh2_userauth_publickey()`, which is undocumented. - * - * The supplied credential parameter will be internally duplicated. - * - * @param out The newly created credential object. - * @param username username to use to authenticate - * @param publickey The bytes of the public key. - * @param publickey_len The length of the public key in bytes. - * @param sign_callback The callback method to sign the data during the challenge. - * @param payload Additional data to pass to the callback. - * @return 0 for success or an error code for failure + * @param str The message from the transport + * @param len The length of the message + * @param payload Payload provided by the caller */ -GIT_EXTERN(int) git_cred_ssh_custom_new( - git_cred **out, - const char *username, - const char *publickey, - size_t publickey_len, - git_cred_sign_callback sign_callback, - void *payload); +typedef int GIT_CALLBACK(git_transport_message_cb)(const char *str, int len, void *payload); -/** - * Create a "default" credential usable for Negotiate mechanisms like NTLM - * or Kerberos authentication. - * - * @return 0 for success or an error code for failure - */ -GIT_EXTERN(int) git_cred_default_new(git_cred **out); - -/** - * Create a credential to specify a username. - * - * This is used with ssh authentication to query for the username if - * none is specified in the url. - */ -GIT_EXTERN(int) git_cred_username_new(git_cred **cred, const char *username); - -/** - * Create a new ssh key credential object reading the keys from memory. - * - * @param out The newly created credential object. - * @param username username to use to authenticate. - * @param publickey The public key of the credential. - * @param privatekey The private key of the credential. - * @param passphrase The passphrase of the credential. - * @return 0 for success or an error code for failure - */ -GIT_EXTERN(int) git_cred_ssh_key_memory_new( - git_cred **out, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase); - - -/** - * Free a credential. - * - * This is only necessary if you own the object; that is, if you are a - * transport. - * - * @param cred the object to free - */ -GIT_EXTERN(void) git_cred_free(git_cred *cred); - -/** - * Signature of a function which acquires a credential object. - * - * @param cred The newly created credential object. - * @param url The resource for which we are demanding a credential. - * @param username_from_url The username that was embedded in a "user\@host" - * remote url, or NULL if not included. - * @param allowed_types A bitmask stating which cred types are OK to return. - * @param payload The payload provided when specifying this callback. - * @return 0 for success, < 0 to indicate an error, > 0 to indicate - * no credential was acquired - */ -typedef int GIT_CALLBACK(git_cred_acquire_cb)( - git_cred **cred, - const char *url, - const char *username_from_url, - unsigned int allowed_types, - void *payload); +/** Signature of a function which creates a transport */ +typedef int GIT_CALLBACK(git_transport_cb)(git_transport **out, git_remote *owner, void *param); /** @} */ GIT_END_DECL + #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/tree.h libgit2-1.1.0+dfsg.1/include/git2/tree.h --- libgit2-0.28.5+dfsg.1/include/git2/tree.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/tree.h 2020-10-12 18:53:06.000000000 +0000 @@ -258,8 +258,9 @@ * Clear all the entires in the builder * * @param bld Builder to clear + * @return 0 on success; error code otherwise */ -GIT_EXTERN(void) git_treebuilder_clear(git_treebuilder *bld); +GIT_EXTERN(int) git_treebuilder_clear(git_treebuilder *bld); /** * Get the number of entries listed in a treebuilder @@ -267,7 +268,7 @@ * @param bld a previously loaded treebuilder. * @return the number of entries in the treebuilder */ -GIT_EXTERN(unsigned int) git_treebuilder_entrycount(git_treebuilder *bld); +GIT_EXTERN(size_t) git_treebuilder_entrycount(git_treebuilder *bld); /** * Free a tree builder @@ -357,8 +358,9 @@ * @param bld Tree builder * @param filter Callback to filter entries * @param payload Extra data to pass to filter callback + * @return 0 on success, non-zero callback return value, or error code */ -GIT_EXTERN(void) git_treebuilder_filter( +GIT_EXTERN(int) git_treebuilder_filter( git_treebuilder *bld, git_treebuilder_filter_cb filter, void *payload); diff -Nru libgit2-0.28.5+dfsg.1/include/git2/types.h libgit2-1.1.0+dfsg.1/include/git2/types.h --- libgit2-0.28.5+dfsg.1/include/git2/types.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/types.h 2020-10-12 18:53:06.000000000 +0000 @@ -63,6 +63,9 @@ #endif +/** The maximum size of an object */ +typedef uint64_t git_object_size_t; + #include "buffer.h" #include "oid.h" @@ -245,97 +248,9 @@ typedef struct git_remote_callbacks git_remote_callbacks; /** - * This is passed as the first argument to the callback to allow the - * user to see the progress. - * - * - total_objects: number of objects in the packfile being downloaded - * - indexed_objects: received objects that have been hashed - * - received_objects: objects which have been downloaded - * - local_objects: locally-available objects that have been injected - * in order to fix a thin pack. - * - received-bytes: size of the packfile received up to now - */ -typedef struct git_transfer_progress { - unsigned int total_objects; - unsigned int indexed_objects; - unsigned int received_objects; - unsigned int local_objects; - unsigned int total_deltas; - unsigned int indexed_deltas; - size_t received_bytes; -} git_transfer_progress; - -/** - * Type for progress callbacks during indexing. Return a value less than zero - * to cancel the transfer. - * - * @param stats Structure containing information about the state of the transfer - * @param payload Payload provided by caller - */ -typedef int GIT_CALLBACK(git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload); - -/** - * Type for messages delivered by the transport. Return a negative value - * to cancel the network operation. - * - * @param str The message from the transport - * @param len The length of the message - * @param payload Payload provided by the caller - */ -typedef int GIT_CALLBACK(git_transport_message_cb)(const char *str, int len, void *payload); - - -/** - * Type of host certificate structure that is passed to the check callback - */ -typedef enum git_cert_t { - /** - * No information about the certificate is available. This may - * happen when using curl. - */ - GIT_CERT_NONE, - /** - * The `data` argument to the callback will be a pointer to - * the DER-encoded data. - */ - GIT_CERT_X509, - /** - * The `data` argument to the callback will be a pointer to a - * `git_cert_hostkey` structure. - */ - GIT_CERT_HOSTKEY_LIBSSH2, - /** - * The `data` argument to the callback will be a pointer to a - * `git_strarray` with `name:content` strings containing - * information about the certificate. This is used when using - * curl. - */ - GIT_CERT_STRARRAY, -} git_cert_t; - -/** * Parent type for `git_cert_hostkey` and `git_cert_x509`. */ -typedef struct { - /** - * Type of certificate. A `GIT_CERT_` value. - */ - git_cert_t cert_type; -} git_cert; - -/** - * Callback for the user's custom certificate checks. - * - * @param cert The host certificate - * @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think - * this certificate is valid - * @param host Hostname of the host libgit2 connected to - * @param payload Payload provided by the caller - * @return 0 to proceed with the connection, < 0 to fail the connection - * or > 0 to indicate that the callback refused to act and that - * the existing validity determination should be honored - */ -typedef int GIT_CALLBACK(git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload); +typedef struct git_cert git_cert; /** * Opaque structure representing a submodule. diff -Nru libgit2-0.28.5+dfsg.1/include/git2/version.h libgit2-1.1.0+dfsg.1/include/git2/version.h --- libgit2-0.28.5+dfsg.1/include/git2/version.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/version.h 2020-10-12 18:53:06.000000000 +0000 @@ -7,12 +7,12 @@ #ifndef INCLUDE_git_version_h__ #define INCLUDE_git_version_h__ -#define LIBGIT2_VERSION "0.28.5" -#define LIBGIT2_VER_MAJOR 0 -#define LIBGIT2_VER_MINOR 28 -#define LIBGIT2_VER_REVISION 5 +#define LIBGIT2_VERSION "1.1.0" +#define LIBGIT2_VER_MAJOR 1 +#define LIBGIT2_VER_MINOR 1 +#define LIBGIT2_VER_REVISION 0 #define LIBGIT2_VER_PATCH 0 -#define LIBGIT2_SOVERSION 28 +#define LIBGIT2_SOVERSION "1.1" #endif diff -Nru libgit2-0.28.5+dfsg.1/include/git2/worktree.h libgit2-1.1.0+dfsg.1/include/git2/worktree.h --- libgit2-0.28.5+dfsg.1/include/git2/worktree.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2/worktree.h 2020-10-12 18:53:06.000000000 +0000 @@ -78,7 +78,7 @@ * Worktree add options structure * * Initialize with `GIT_WORKTREE_ADD_OPTIONS_INIT`. Alternatively, you can - * use `git_worktree_add_init_options`. + * use `git_worktree_add_options_init`. * */ typedef struct git_worktree_add_options { @@ -101,7 +101,7 @@ * @param version The struct version; pass `GIT_WORKTREE_ADD_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_worktree_add_init_options(git_worktree_add_options *opts, +GIT_EXTERN(int) git_worktree_add_options_init(git_worktree_add_options *opts, unsigned int version); /** @@ -174,7 +174,7 @@ * is valid for the lifetime of the git_worktree. */ GIT_EXTERN(const char *) git_worktree_path(const git_worktree *wt); - + /** * Flags which can be passed to git_worktree_prune to alter its * behavior. @@ -192,7 +192,7 @@ * Worktree prune options structure * * Initialize with `GIT_WORKTREE_PRUNE_OPTIONS_INIT`. Alternatively, you can - * use `git_worktree_prune_init_options`. + * use `git_worktree_prune_options_init`. * */ typedef struct git_worktree_prune_options { @@ -214,7 +214,7 @@ * @param version The struct version; pass `GIT_WORKTREE_PRUNE_OPTIONS_VERSION`. * @return Zero on success; -1 on failure. */ -GIT_EXTERN(int) git_worktree_prune_init_options( +GIT_EXTERN(int) git_worktree_prune_options_init( git_worktree_prune_options *opts, unsigned int version); diff -Nru libgit2-0.28.5+dfsg.1/include/git2.h libgit2-1.1.0+dfsg.1/include/git2.h --- libgit2-0.28.5+dfsg.1/include/git2.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/include/git2.h 2020-10-12 18:53:06.000000000 +0000 @@ -15,12 +15,14 @@ #include "git2/blame.h" #include "git2/branch.h" #include "git2/buffer.h" +#include "git2/cert.h" #include "git2/checkout.h" #include "git2/cherrypick.h" #include "git2/clone.h" #include "git2/commit.h" #include "git2/common.h" #include "git2/config.h" +#include "git2/credential.h" #include "git2/deprecated.h" #include "git2/describe.h" #include "git2/diff.h" diff -Nru libgit2-0.28.5+dfsg.1/libgit2_clar.supp libgit2-1.1.0+dfsg.1/libgit2_clar.supp --- libgit2-0.28.5+dfsg.1/libgit2_clar.supp 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/libgit2_clar.supp 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -{ - ignore-zlib-errors-cond - Memcheck:Cond - obj:*libz.so* -} - -{ - ignore-giterror-set-leak - Memcheck:Leak - ... - fun:giterror_set -} - -{ - ignore-git-global-state-leak - Memcheck:Leak - ... - fun:git__global_state -} - -{ - ignore-openssl-ssl-leak - Memcheck:Leak - ... - obj:*libssl.so* - ... -} - -{ - ignore-openssl-crypto-leak - Memcheck:Leak - ... - obj:*libcrypto.so* - ... -} - -{ - ignore-openssl-crypto-cond - Memcheck:Cond - obj:*libcrypto.so* - ... -} - -{ - ignore-glibc-getaddrinfo-cache - Memcheck:Leak - ... - fun:__check_pf -} - -{ - ignore-curl-global-init - Memcheck:Leak - ... - fun:curl_global_init -} - -{ - ignore-libssh2-gcrypt-control-leak - Memcheck:Leak - ... - fun:gcry_control - obj:*libssh2.so* -} - -{ - ignore-libssh2-gcrypt-mpinew-leak - Memcheck:Leak - ... - fun:gcry_mpi_new - obj:*libssh2.so* -} - -{ - ignore-libssh2-gcrypt-mpiscan-leak - Memcheck:Leak - ... - fun:gcry_mpi_scan - obj:*libssh2.so* -} - -{ - ignore-libssh2-gcrypt-randomize-leak - Memcheck:Leak - ... - fun:gcry_randomize - obj:*libssh2.so* -} - -{ - ignore-libssh2-gcrypt-sexpfindtoken-leak - Memcheck:Leak - ... - fun:gcry_sexp_find_token - obj:*libssh2.so* -} - -{ - ignore-libssh2-gcrypt-pksign-leak - Memcheck:Leak - ... - fun:gcry_pk_sign - obj:*libssh2.so* -} - -{ - ignore-noai6ai_cached-double-free - Memcheck:Free - fun:free - fun:__libc_freeres - ... - fun:exit - ... -} diff -Nru libgit2-0.28.5+dfsg.1/libgit2.pc.in libgit2-1.1.0+dfsg.1/libgit2.pc.in --- libgit2-0.28.5+dfsg.1/libgit2.pc.in 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/libgit2.pc.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -prefix="@PKGCONFIG_PREFIX@" -libdir=@PKGCONFIG_LIBDIR@ -includedir=@PKGCONFIG_INCLUDEDIR@ - -Name: libgit2 -Description: The git library, take 2 -Version: @LIBGIT2_VERSION_STRING@ - -Libs: -L${libdir} -lgit2 -Libs.private: @LIBGIT2_PC_LIBS@ -Requires.private: @LIBGIT2_PC_REQUIRES@ - -Cflags: -I${includedir} diff -Nru libgit2-0.28.5+dfsg.1/package.json libgit2-1.1.0+dfsg.1/package.json --- libgit2-0.28.5+dfsg.1/package.json 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/package.json 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ { "name": "libgit2", - "version": "0.27.0", + "version": "1.1.0", "repo": "https://github.com/libgit2/libgit2", "description": " A cross-platform, linkable library implementation of Git that you can use in your application.", "install": "mkdir build && cd build && cmake .. && cmake --build ." diff -Nru libgit2-0.28.5+dfsg.1/README.md libgit2-1.1.0+dfsg.1/README.md --- libgit2-0.28.5+dfsg.1/README.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/README.md 2020-10-12 18:53:06.000000000 +0000 @@ -4,9 +4,8 @@ | Build Status | | | ------------ | - | | **master** branch CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=master)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=master) | +| **v1.0 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v1.0)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v1.0) | | **v0.28 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.28)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.28) | -| **v0.27 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.27)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.27) | -| **v0.26 branch** CI builds | [![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2?branchName=maint/v0.26)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7&branchName=maint/v0.26) | | **Nightly** builds | [![Azure Pipelines Build Status](https://libgit2.visualstudio.com/libgit2/_apis/build/status/nightly?branchName=master&label=Full+Build)](https://libgit2.visualstudio.com/libgit2/_build/latest?definitionId=9&branchName=master) [![Coverity Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/coverity?branchName=master&label=Coverity+Build)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=21?branchName=master) [![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) | `libgit2` is a portable, pure C implementation of the Git core methods @@ -48,6 +47,7 @@ * [Compiler and linker options](#compiler-and-linker-options) * [MacOS X](#macos-x) * [Android](#android) + * [MinGW](#mingw) * [Language Bindings](#language-bindings) * [How Can I Contribute?](#how-can-i-contribute) * [License](#license) @@ -73,17 +73,17 @@ 2. Create the cmake build environment: `cmake ..` 3. Build libgit2: `cmake --build .` -Trouble with these steps? Read our (troubleshooting guide)[docs/troubleshooting.md]. +Trouble with these steps? Read our [troubleshooting guide](docs/troubleshooting.md). More detailed build guidance is available below. Getting Help ============ -**Join us on Slack** +**Chat with us** -Visit [slack.libgit2.org](http://slack.libgit2.org/) to sign up, then join -us in `#libgit2`. If you prefer IRC, you can also point your client to our -slack channel once you've registered. +- via IRC: join [#libgit2](https://webchat.freenode.net/#libgit2) on Freenode +- via Slack: visit [slack.libgit2.org](http://slack.libgit2.org/) to sign up, + then join us in `#libgit2` **Getting Help** @@ -103,9 +103,7 @@ **Reporting Security Issues** -In case you think to have found a security issue with libgit2, please do not -open a public issue. Instead, you can report the issue to the private mailing -list [security@libgit2.com](mailto:security@libgit2.com). +Please have a look at SECURITY.md. What It Can Do ============== @@ -250,9 +248,9 @@ The following CMake variables are declared: -- `BIN_INSTALL_DIR`: Where to install binaries to. -- `LIB_INSTALL_DIR`: Where to install libraries to. -- `INCLUDE_INSTALL_DIR`: Where to install headers to. +- `CMAKE_INSTALL_BINDIR`: Where to install binaries to. +- `CMAKE_INSTALL_LIBDIR`: Where to install libraries to. +- `CMAKE_INSTALL_INCLUDEDIR`: Where to install headers to. - `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to ON) - `BUILD_CLAR`: Build [Clar](https://github.com/vmg/clar)-based test suite (defaults to ON) - `THREADSAFE`: Build libgit2 with threading support (defaults to ON) @@ -307,6 +305,20 @@ Add `-DCMAKE_TOOLCHAIN_FILE={pathToToolchainFile}` to cmake command when configuring. +MinGW +----- + +If you want to build the library in MinGW environment with SSH support enabled, +you may need to pass `-DCMAKE_LIBRARY_PATH="${MINGW_PREFIX}/${MINGW_CHOST}/lib/"` flag +to CMake when configuring. This is because CMake cannot find the Win32 libraries in +MinGW folders by default and you might see an error message stating that CMake +could not resolve `ws2_32` library during configuration. + +Another option would be to install `msys2-w32api-runtime` package before configuring. +This package installs the Win32 libraries into `/usr/lib` folder which is by default +recognized as the library path by CMake. Please note though that this package is meant +for MSYS subsystem which is different from MinGW. + Language Bindings ================================== @@ -332,8 +344,10 @@ * hgit2 * Java * Jagged +* Javascript / WebAssembly ( browser and nodejs ) + * WASM-git * Julia - * LibGit2.jl + * LibGit2.jl * Lua * luagit2 * .NET @@ -359,7 +373,7 @@ * Ruby * Rugged * Rust - * git2-rs + * git2-rs * Swift * SwiftGit2 * Vala diff -Nru libgit2-0.28.5+dfsg.1/script/leaks.sh libgit2-1.1.0+dfsg.1/script/leaks.sh --- libgit2-0.28.5+dfsg.1/script/leaks.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/script/leaks.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,6 @@ +#!/bin/sh +export MallocStackLogging=1 +export MallocScribble=1 +export MallocLogFile=/dev/null +export CLAR_AT_EXIT="leaks -quiet \$PPID" +exec "$@" diff -Nru libgit2-0.28.5+dfsg.1/script/release.py libgit2-1.1.0+dfsg.1/script/release.py --- libgit2-0.28.5+dfsg.1/script/release.py 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/script/release.py 2020-10-12 18:53:06.000000000 +0000 @@ -37,9 +37,18 @@ 'VER_MINOR': [ str(version.minor), None ], 'VER_REVISION': [ str(version.revision), None ], 'VER_PATCH': [ '0', None ], - 'SOVERSION': [ '{}'.format(version.minor), None ], + 'SOVERSION': [ '"{}.{}"'.format(version.major, version.minor), None ], } + # Parse CMakeLists + with open('CMakeLists.txt') as f: + for line in f.readlines(): + if line.startswith('project(libgit2 VERSION "{}"'.format(version)): + break + else: + raise Error("cmake: invalid project definition") + + # Parse version.h with open('include/git2/version.h') as f: lines = f.readlines() @@ -56,6 +65,17 @@ if v[0] != v[1]: raise Error("version.h: define '{}' does not match (got '{}', expected '{}')".format(k, v[0], v[1])) + with open('package.json') as f: + pkg = json.load(f) + + try: + pkg_version = Version(pkg["version"]) + except KeyError as err: + raise Error("package.json: missing the field {}".format(err)) + + if pkg_version != version: + raise Error("package.json: version does not match (got '{}', expected '{}')".format(pkg_version, version)) + def generate_relnotes(tree, version): with open('docs/changelog.md') as f: lines = f.readlines() @@ -155,7 +175,7 @@ parser.add_argument('--tree', default='HEAD', help='tree to create release for (default: HEAD)') parser.add_argument('--dryrun', action='store_true', help='generate release, but do not post it') parser.add_argument('--repository', default='libgit2/libgit2', help='GitHub repository to create repository in') - parser.add_argument('--user', help='user to authenitcate as') + parser.add_argument('--user', help='user to authenticate as') parser.add_argument('--password', help='password to authenticate with') parser.add_argument('version', type=Version, help='version of the new release') args = parser.parse_args() diff -Nru libgit2-0.28.5+dfsg.1/script/sanitizers.supp libgit2-1.1.0+dfsg.1/script/sanitizers.supp --- libgit2-0.28.5+dfsg.1/script/sanitizers.supp 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/script/sanitizers.supp 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,4 @@ +[undefined] +# This library allows unaligned access on Intel-like processors. Prevent UBSan +# from complaining about that. +fun:sha1_compression_states diff -Nru libgit2-0.28.5+dfsg.1/script/valgrind.sh libgit2-1.1.0+dfsg.1/script/valgrind.sh --- libgit2-0.28.5+dfsg.1/script/valgrind.sh 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/script/valgrind.sh 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +#!/bin/bash +exec valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions="$(dirname "${BASH_SOURCE[0]}")/valgrind.supp" "$@" diff -Nru libgit2-0.28.5+dfsg.1/script/valgrind.supp libgit2-1.1.0+dfsg.1/script/valgrind.supp --- libgit2-0.28.5+dfsg.1/script/valgrind.supp 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/script/valgrind.supp 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,180 @@ +{ + ignore-zlib-errors-cond + Memcheck:Cond + obj:*libz.so* +} + +{ + ignore-giterror-set-leak + Memcheck:Leak + ... + fun:giterror_set +} + +{ + ignore-git-global-state-leak + Memcheck:Leak + ... + fun:git__global_state +} + +{ + ignore-openssl-ssl-leak + Memcheck:Leak + ... + obj:*libssl.so* + ... +} + +{ + ignore-openssl-crypto-leak + Memcheck:Leak + ... + obj:*libcrypto.so* + ... +} + +{ + ignore-openssl-crypto-cond + Memcheck:Cond + obj:*libcrypto.so* + ... +} + +{ + ignore-glibc-getaddrinfo-cache + Memcheck:Leak + ... + fun:__check_pf +} + +{ + ignore-curl-global-init + Memcheck:Leak + ... + fun:curl_global_init +} + +{ + ignore-libssh2-init + Memcheck:Leak + ... + fun:gcry_control + fun:libssh2_init + ... +} + +{ + ignore-libssh2-gcrypt-control-leak + Memcheck:Leak + ... + fun:gcry_control + obj:*libssh2.so* +} + +{ + ignore-libssh2-gcrypt-mpinew-leak + Memcheck:Leak + ... + fun:gcry_mpi_new + obj:*libssh2.so* +} + +{ + ignore-libssh2-gcrypt-mpiscan-leak + Memcheck:Leak + ... + fun:gcry_mpi_scan + obj:*libssh2.so* + ... +} + +{ + ignore-libssh2-gcrypt-randomize-leak + Memcheck:Leak + ... + fun:gcry_randomize + obj:*libssh2.so* +} + +{ + ignore-libssh2-gcrypt-sexpfindtoken-leak + Memcheck:Leak + ... + fun:gcry_sexp_find_token + obj:*libssh2.so* +} + +{ + ignore-libssh2-gcrypt-pksign-leak + Memcheck:Leak + ... + fun:gcry_pk_sign + obj:*libssh2.so* +} + +{ + ignore-libssh2-gcrypt-session-handshake + Memcheck:Leak + ... + obj:*libssh2.so* + obj:*libssh2.so* + fun:libssh2_session_handshake + ... +} + +{ + ignore-openssl-undefined-in-read + Memcheck:Cond + ... + obj:*libssl.so* + ... + fun:openssl_read + ... +} + +{ + ignore-openssl-undefined-in-connect + Memcheck:Cond + ... + obj:*libssl.so* + ... + fun:openssl_connect + ... +} + +{ + ignore-libssh2-rsa-sha1-sign + Memcheck:Leak + ... + obj:*libgcrypt.so* + fun:_libssh2_rsa_sha1_sign + ... +} + +{ + ignore-libssh2-kexinit + Memcheck:Leak + ... + obj:*libssh2.so* + fun:kexinit + ... +} + +{ + ignore-noai6ai_cached-double-free + Memcheck:Free + fun:free + fun:__libc_freeres + ... + fun:exit + ... +} + +{ + ignore-libcrypto-uninitialized-read-for-entropy + Memcheck:Value8 + ... + obj:*libcrypto.so* + ... +} diff -Nru libgit2-0.28.5+dfsg.1/SECURITY.md libgit2-1.1.0+dfsg.1/SECURITY.md --- libgit2-0.28.5+dfsg.1/SECURITY.md 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/SECURITY.md 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +This project will always provide security fixes for the latest two released +versions. E.g. if the latest version is v0.28.x, then we will provide security +fixes for both v0.28.x and v0.27.y, but no later versions. + +## Reporting a Vulnerability + +In case you think to have found a security issue with libgit2, please do not +open a public issue. Instead, you can report the issue to the private mailing +list [security@libgit2.com](mailto:security@libgit2.com). We will acknowledge +receipt of your message in at most three days and try to clarify further steps. diff -Nru libgit2-0.28.5+dfsg.1/src/allocators/stdalloc.c libgit2-1.1.0+dfsg.1/src/allocators/stdalloc.c --- libgit2-0.28.5+dfsg.1/src/allocators/stdalloc.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/allocators/stdalloc.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,119 @@ +/* + * 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 "stdalloc.h" + +static void *stdalloc__malloc(size_t len, const char *file, int line) +{ + void *ptr = malloc(len); + + GIT_UNUSED(file); + GIT_UNUSED(line); + + if (!ptr) git_error_set_oom(); + return ptr; +} + +static void *stdalloc__calloc(size_t nelem, size_t elsize, const char *file, int line) +{ + void *ptr = calloc(nelem, elsize); + + GIT_UNUSED(file); + GIT_UNUSED(line); + + if (!ptr) git_error_set_oom(); + return ptr; +} + +static char *stdalloc__strdup(const char *str, const char *file, int line) +{ + char *ptr = strdup(str); + + GIT_UNUSED(file); + GIT_UNUSED(line); + + if (!ptr) git_error_set_oom(); + return ptr; +} + +static char *stdalloc__strndup(const char *str, size_t n, const char *file, int line) +{ + size_t length = 0, alloclength; + char *ptr; + + length = p_strnlen(str, n); + + if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) || + !(ptr = stdalloc__malloc(alloclength, file, line))) + return NULL; + + if (length) + memcpy(ptr, str, length); + + ptr[length] = '\0'; + + return ptr; +} + +static char *stdalloc__substrdup(const char *start, size_t n, const char *file, int line) +{ + char *ptr; + size_t alloclen; + + if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) || + !(ptr = stdalloc__malloc(alloclen, file, line))) + return NULL; + + memcpy(ptr, start, n); + ptr[n] = '\0'; + return ptr; +} + +static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line) +{ + void *new_ptr = realloc(ptr, size); + + GIT_UNUSED(file); + GIT_UNUSED(line); + + if (!new_ptr) git_error_set_oom(); + return new_ptr; +} + +static void *stdalloc__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line) +{ + size_t newsize; + + if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize)) + return NULL; + + return stdalloc__realloc(ptr, newsize, file, line); +} + +static void *stdalloc__mallocarray(size_t nelem, size_t elsize, const char *file, int line) +{ + return stdalloc__reallocarray(NULL, nelem, elsize, file, line); +} + +static void stdalloc__free(void *ptr) +{ + free(ptr); +} + +int git_stdalloc_init_allocator(git_allocator *allocator) +{ + allocator->gmalloc = stdalloc__malloc; + allocator->gcalloc = stdalloc__calloc; + allocator->gstrdup = stdalloc__strdup; + allocator->gstrndup = stdalloc__strndup; + allocator->gsubstrdup = stdalloc__substrdup; + allocator->grealloc = stdalloc__realloc; + allocator->greallocarray = stdalloc__reallocarray; + allocator->gmallocarray = stdalloc__mallocarray; + allocator->gfree = stdalloc__free; + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/allocators/stdalloc.h libgit2-1.1.0+dfsg.1/src/allocators/stdalloc.h --- libgit2-0.28.5+dfsg.1/src/allocators/stdalloc.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/allocators/stdalloc.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,17 @@ +/* + * 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_allocators_stdalloc_h__ +#define INCLUDE_allocators_stdalloc_h__ + +#include "common.h" + +#include "alloc.h" + +int git_stdalloc_init_allocator(git_allocator *allocator); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/allocators/win32_crtdbg.c libgit2-1.1.0+dfsg.1/src/allocators/win32_crtdbg.c --- libgit2-0.28.5+dfsg.1/src/allocators/win32_crtdbg.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/allocators/win32_crtdbg.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "win32_crtdbg.h" + +#if defined(GIT_MSVC_CRTDBG) + +#include "win32/w32_crtdbg_stacktrace.h" + +static void *crtdbg__malloc(size_t len, const char *file, int line) +{ + void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); + if (!ptr) git_error_set_oom(); + return ptr; +} + +static void *crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line) +{ + void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); + if (!ptr) git_error_set_oom(); + return ptr; +} + +static char *crtdbg__strdup(const char *str, const char *file, int line) +{ + char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); + if (!ptr) git_error_set_oom(); + return ptr; +} + +static char *crtdbg__strndup(const char *str, size_t n, const char *file, int line) +{ + size_t length = 0, alloclength; + char *ptr; + + length = p_strnlen(str, n); + + if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) || + !(ptr = crtdbg__malloc(alloclength, file, line))) + return NULL; + + if (length) + memcpy(ptr, str, length); + + ptr[length] = '\0'; + + return ptr; +} + +static char *crtdbg__substrdup(const char *start, size_t n, const char *file, int line) +{ + char *ptr; + size_t alloclen; + + if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) || + !(ptr = crtdbg__malloc(alloclen, file, line))) + return NULL; + + memcpy(ptr, start, n); + ptr[n] = '\0'; + return ptr; +} + +static void *crtdbg__realloc(void *ptr, size_t size, const char *file, int line) +{ + void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); + if (!new_ptr) git_error_set_oom(); + return new_ptr; +} + +static void *crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line) +{ + size_t newsize; + + if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize)) + return NULL; + + return crtdbg__realloc(ptr, newsize, file, line); +} + +static void *crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line) +{ + return crtdbg__reallocarray(NULL, nelem, elsize, file, line); +} + +static void crtdbg__free(void *ptr) +{ + free(ptr); +} + +int git_win32_crtdbg_init_allocator(git_allocator *allocator) +{ + allocator->gmalloc = crtdbg__malloc; + allocator->gcalloc = crtdbg__calloc; + allocator->gstrdup = crtdbg__strdup; + allocator->gstrndup = crtdbg__strndup; + allocator->gsubstrdup = crtdbg__substrdup; + allocator->grealloc = crtdbg__realloc; + allocator->greallocarray = crtdbg__reallocarray; + allocator->gmallocarray = crtdbg__mallocarray; + allocator->gfree = crtdbg__free; + return 0; +} + +#else + +int git_win32_crtdbg_init_allocator(git_allocator *allocator) +{ + GIT_UNUSED(allocator); + git_error_set(GIT_EINVALID, "crtdbg memory allocator not available"); + return -1; +} + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/allocators/win32_crtdbg.h libgit2-1.1.0+dfsg.1/src/allocators/win32_crtdbg.h --- libgit2-0.28.5+dfsg.1/src/allocators/win32_crtdbg.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/allocators/win32_crtdbg.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,17 @@ +/* + * 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_allocators_crtdbg_h +#define INCLUDE_allocators_crtdbg_h + +#include "common.h" + +#include "alloc.h" + +int git_win32_crtdbg_init_allocator(git_allocator *allocator); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/alloc.c libgit2-1.1.0+dfsg.1/src/alloc.c --- libgit2-0.28.5+dfsg.1/src/alloc.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/alloc.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,11 +7,8 @@ #include "alloc.h" -#if defined(GIT_MSVC_CRTDBG) -# include "win32/w32_crtdbg_stacktrace.h" -#else -# include "stdalloc.h" -#endif +#include "allocators/stdalloc.h" +#include "allocators/win32_crtdbg.h" git_allocator git__allocator; @@ -44,12 +41,3 @@ memcpy(&git__allocator, allocator, sizeof(*allocator)); return 0; } - -#if !defined(GIT_MSVC_CRTDBG) -int git_win32_crtdbg_init_allocator(git_allocator *allocator) -{ - GIT_UNUSED(allocator); - git_error_set(GIT_EINVALID, "crtdbg memory allocator not available"); - return -1; -} -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/apply.c libgit2-1.1.0+dfsg.1/src/apply.c --- libgit2-0.28.5+dfsg.1/src/apply.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/apply.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,8 +7,6 @@ #include "apply.h" -#include - #include "git2/apply.h" #include "git2/patch.h" #include "git2/filter.h" @@ -18,15 +16,12 @@ #include "git2/repository.h" #include "array.h" #include "patch.h" -#include "fileops.h" +#include "futils.h" #include "delta.h" #include "zstream.h" #include "reader.h" #include "index.h" -#define apply_err(...) \ - ( git_error_set(GIT_ERROR_PATCH, __VA_ARGS__), GIT_EAPPLYFAIL ) - typedef struct { /* The lines that we allocate ourself are allocated out of the pool. * (Lines may have been allocated out of the diff.) @@ -35,6 +30,18 @@ git_vector lines; } patch_image; +static int apply_err(const char *fmt, ...) GIT_FORMAT_PRINTF(1, 2); +static int apply_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + git_error_vset(GIT_ERROR_PATCH, fmt, ap); + va_end(ap); + + return GIT_EAPPLYFAIL; +} + static void patch_line_init( git_diff_line *out, const char *in, @@ -56,7 +63,11 @@ memset(out, 0x0, sizeof(patch_image)); - git_pool_init(&out->pool, sizeof(git_diff_line)); + if (git_pool_init(&out->pool, sizeof(git_diff_line)) < 0) + return -1; + + if (!in_len) + return 0; for (start = in; start < in + in_len; start = end) { end = memchr(start, '\n', in_len - (start - in)); @@ -450,7 +461,6 @@ git_filemode_t pre_filemode; git_index_entry pre_entry, post_entry; bool skip_preimage = false; - size_t pos; int error; if ((error = git_patch_from_diff(&patch, diff, i)) < 0) @@ -475,8 +485,7 @@ */ if (delta->status != GIT_DELTA_RENAMED && delta->status != GIT_DELTA_ADDED) { - pos = git_strmap_lookup_index(removed_paths, delta->old_file.path); - if (git_strmap_valid_index(removed_paths, pos)) { + if (git_strmap_exists(removed_paths, delta->old_file.path)) { error = apply_err("path '%s' has been renamed or deleted", delta->old_file.path); goto done; } @@ -545,7 +554,7 @@ if (delta->status != GIT_DELTA_DELETED) { if ((error = git_apply__patch(&post_contents, &filename, &mode, pre_contents.ptr, pre_contents.size, patch, opts)) < 0 || - (error = git_blob_create_frombuffer(&post_id, repo, + (error = git_blob_create_from_buffer(&post_id, repo, post_contents.ptr, post_contents.size)) < 0) goto done; @@ -560,7 +569,7 @@ if (delta->status == GIT_DELTA_RENAMED || delta->status == GIT_DELTA_DELETED) - git_strmap_insert(removed_paths, delta->old_file.path, (char *)delta->old_file.path, &error); + error = git_strmap_set(removed_paths, delta->old_file.path, (char *) delta->old_file.path); if (delta->status == GIT_DELTA_RENAMED || delta->status == GIT_DELTA_ADDED) @@ -588,7 +597,7 @@ size_t i; int error = 0; - if (git_strmap_alloc(&removed_paths) < 0) + if (git_strmap_new(&removed_paths) < 0) return -1; for (i = 0; i < git_diff_num_deltas(diff); i++) { @@ -761,6 +770,13 @@ return error; } +int git_apply_options_init(git_apply_options *opts, unsigned int version) +{ + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_apply_options, GIT_APPLY_OPTIONS_INIT); + return 0; +} + /* * Handle the three application options ("locations"): * @@ -831,13 +847,17 @@ (error = git_reader_for_index(&post_reader, repo, postimage)) < 0) goto done; - if ((error = git_repository_index(&index, repo)) < 0 || - (error = git_indexwriter_init(&indexwriter, index)) < 0) - goto done; + if (!(opts.flags & GIT_APPLY_CHECK)) + if ((error = git_repository_index(&index, repo)) < 0 || + (error = git_indexwriter_init(&indexwriter, index)) < 0) + goto done; if ((error = apply_deltas(repo, pre_reader, preimage, post_reader, postimage, diff, &opts)) < 0) goto done; + if ((opts.flags & GIT_APPLY_CHECK)) + goto done; + switch (location) { case GIT_APPLY_LOCATION_BOTH: error = git_apply__to_workdir(repo, diff, preimage, postimage, location, &opts); diff -Nru libgit2-0.28.5+dfsg.1/src/assert_safe.h libgit2-1.1.0+dfsg.1/src/assert_safe.h --- libgit2-0.28.5+dfsg.1/src/assert_safe.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/assert_safe.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * 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_assert_safe_h__ +#define INCLUDE_assert_safe_h__ + +/* + * In a debug build, we'll assert(3) for aide in debugging. In release + * builds, we will provide macros that will set an error message that + * indicate a failure and return. Note that memory leaks can occur in + * a release-mode assertion failure -- it is impractical to provide + * safe clean up routines in these very extreme failures, but care + * should be taken to not leak very large objects. + */ + +#if (defined(_DEBUG) || defined(GIT_ASSERT_HARD)) && GIT_ASSERT_HARD != 0 +# include + +# define GIT_ASSERT(expr) assert(expr) +# define GIT_ASSERT_ARG(expr) assert(expr) + +# define GIT_ASSERT_WITH_RETVAL(expr, fail) assert(expr) +# define GIT_ASSERT_ARG_WITH_RETVAL(expr, fail) assert(expr) +#else + +/** Internal consistency check to stop the function. */ +# define GIT_ASSERT(expr) GIT_ASSERT_WITH_RETVAL(expr, -1) + +/** + * Assert that a consumer-provided argument is valid, setting an + * actionable error message and returning -1 if it is not. + */ +# define GIT_ASSERT_ARG(expr) GIT_ASSERT_ARG_WITH_RETVAL(expr, -1) + +/** Internal consistency check to return the `fail` param on failure. */ +# define GIT_ASSERT_WITH_RETVAL(expr, fail) \ + GIT_ASSERT__WITH_RETVAL(expr, GIT_ERROR_INTERNAL, "unrecoverable internal error", fail) + +/** + * Assert that a consumer-provided argument is valid, setting an + * actionable error message and returning the `fail` param if not. + */ +# define GIT_ASSERT_ARG_WITH_RETVAL(expr, fail) \ + GIT_ASSERT__WITH_RETVAL(expr, GIT_ERROR_INVALID, "invalid argument", fail) + +# define GIT_ASSERT__WITH_RETVAL(expr, code, msg, fail) do { \ + if (!(expr)) { \ + git_error_set(code, "%s: '%s'", msg, #expr); \ + return fail; \ + } \ + } while(0) + +#endif /* GIT_ASSERT_HARD */ + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/attr.c libgit2-1.1.0+dfsg.1/src/attr.c --- libgit2-0.28.5+dfsg.1/src/attr.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/attr.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,18 +19,18 @@ const char *git_attr__false = "[internal]__FALSE__"; const char *git_attr__unset = "[internal]__UNSET__"; -git_attr_t git_attr_value(const char *attr) +git_attr_value_t git_attr_value(const char *attr) { if (attr == NULL || attr == git_attr__unset) - return GIT_ATTR_UNSPECIFIED_T; + return GIT_ATTR_VALUE_UNSPECIFIED; if (attr == git_attr__true) - return GIT_ATTR_TRUE_T; + return GIT_ATTR_VALUE_TRUE; if (attr == git_attr__false) - return GIT_ATTR_FALSE_T; + return GIT_ATTR_VALUE_FALSE; - return GIT_ATTR_VALUE_T; + return GIT_ATTR_VALUE_STRING; } static int collect_attr_files( @@ -215,7 +215,7 @@ return -1; if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 || - (error = git_strmap_alloc(&seen)) < 0) + (error = git_strmap_new(&seen)) < 0) goto cleanup; git_vector_foreach(&files, i, file) { @@ -227,8 +227,7 @@ if (git_strmap_exists(seen, assign->name)) continue; - git_strmap_insert(seen, assign->name, assign, &error); - if (error < 0) + if ((error = git_strmap_set(seen, assign->name, assign)) < 0) goto cleanup; error = callback(assign->name, assign->value, payload); @@ -253,15 +252,16 @@ git_attr_session *attr_session, git_attr_file_source source, const char *base, - const char *file) + const char *file, + bool allow_macros) { int error; git_attr_file *preload = NULL; if (!file) return 0; - if (!(error = git_attr_cache__get( - &preload, repo, attr_session, source, base, file, git_attr_file__parse_buffer))) + if (!(error = git_attr_cache__get(&preload, repo, attr_session, source, base, file, + git_attr_file__parse_buffer, allow_macros))) git_attr_file__free(preload); return error; @@ -305,12 +305,15 @@ return 0; } -static int attr_setup(git_repository *repo, git_attr_session *attr_session) +static int attr_setup( + git_repository *repo, + git_attr_session *attr_session, + uint32_t flags) { - int error = 0; - const char *workdir = git_repository_workdir(repo); - git_index *idx = NULL; git_buf path = GIT_BUF_INIT; + git_index *idx = NULL; + const char *workdir; + int error = 0; if (attr_session && attr_session->init_setup) return 0; @@ -318,41 +321,43 @@ if ((error = git_attr_cache__init(repo)) < 0) return error; - /* preload attribute files that could contain macros so the - * definitions will be available for later file parsing + /* + * Preload attribute files that could contain macros so the + * definitions will be available for later file parsing. */ - error = system_attr_file(&path, attr_session); - - if (error == 0) - error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, path.ptr); - - if (error != GIT_ENOTFOUND) - goto out; - - if ((error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0) - goto out; + if ((error = system_attr_file(&path, attr_session)) < 0 || + (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, + NULL, path.ptr, true)) < 0) { + if (error != GIT_ENOTFOUND) + goto out; + } - if ((error = git_repository_item_path(&path, - repo, GIT_REPOSITORY_ITEM_INFO)) < 0) + if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, + NULL, git_repository_attr_cache(repo)->cfg_attr_file, true)) < 0) goto out; - if ((error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - path.ptr, GIT_ATTR_FILE_INREPO)) < 0) - goto out; + git_buf_clear(&path); /* git_repository_item_path expects an empty buffer, because it uses git_buf_set */ + if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, + path.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) { + if (error != GIT_ENOTFOUND) + goto out; + } - if (workdir != NULL && - (error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0) - goto out; + if ((workdir = git_repository_workdir(repo)) != NULL && + (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, + workdir, GIT_ATTR_FILE, true)) < 0) + goto out; if ((error = git_repository_index__weakptr(&idx, repo)) < 0 || - (error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0) + (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, + NULL, GIT_ATTR_FILE, true)) < 0) + goto out; + + if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0 && + (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_HEAD, + NULL, GIT_ATTR_FILE, true)) < 0) goto out; if (attr_session) @@ -431,6 +436,9 @@ break; } + if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0) + srcs[count++] = GIT_ATTR_FILE__FROM_HEAD; + return count; } @@ -440,13 +448,14 @@ git_vector *list, git_attr_file_source source, const char *base, - const char *filename) + const char *filename, + bool allow_macros) { int error = 0; git_attr_file *file = NULL; error = git_attr_cache__get(&file, repo, attr_session, - source, base, filename, git_attr_file__parse_buffer); + source, base, filename, git_attr_file__parse_buffer, allow_macros); if (error < 0) return error; @@ -461,16 +470,18 @@ static int push_one_attr(void *ref, const char *path) { - int error = 0, n_src, i; attr_walk_up_info *info = (attr_walk_up_info *)ref; - git_attr_file_source src[2]; + git_attr_file_source src[GIT_ATTR_FILE_NUM_SOURCES]; + int error = 0, n_src, i; + bool allow_macros; n_src = attr_decide_sources( info->flags, info->workdir != NULL, info->index != NULL, src); + allow_macros = info->workdir ? !strcmp(info->workdir, path) : false; for (i = 0; !error && i < n_src; ++i) - error = push_attr_file(info->repo, info->attr_session, - info->files, src[i], path, GIT_ATTR_FILE); + error = push_attr_file(info->repo, info->attr_session, info->files, + src[i], path, GIT_ATTR_FILE, allow_macros); return error; } @@ -499,7 +510,7 @@ const char *workdir = git_repository_workdir(repo); attr_walk_up_info info = { NULL }; - if ((error = attr_setup(repo, attr_session)) < 0) + if ((error = attr_setup(repo, attr_session, flags)) < 0) return error; /* Resolve path in a non-bare repo */ @@ -517,15 +528,12 @@ * - $GIT_PREFIX/etc/gitattributes */ - error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO); - if (error < 0) - goto cleanup; - - error = push_attr_file( - repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - attrfile.ptr, GIT_ATTR_FILE_INREPO); - if (error < 0) - goto cleanup; + if ((error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + (error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, + attrfile.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) { + if (error != GIT_ENOTFOUND) + goto cleanup; + } info.repo = repo; info.attr_session = attr_session; @@ -544,9 +552,8 @@ goto cleanup; if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) { - error = push_attr_file( - repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - NULL, git_repository_attr_cache(repo)->cfg_attr_file); + error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, + NULL, git_repository_attr_cache(repo)->cfg_attr_file, true); if (error < 0) goto cleanup; } @@ -555,9 +562,8 @@ error = system_attr_file(&dir, attr_session); if (!error) - error = push_attr_file( - repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - NULL, dir.ptr); + error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, + NULL, dir.ptr, true); else if (error == GIT_ENOTFOUND) error = 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/attrcache.c libgit2-1.1.0+dfsg.1/src/attrcache.c --- libgit2-0.28.5+dfsg.1/src/attrcache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/attrcache.c 2020-10-12 18:53:06.000000000 +0000 @@ -33,12 +33,7 @@ GIT_INLINE(git_attr_file_entry *) attr_cache_lookup_entry( git_attr_cache *cache, const char *path) { - size_t pos = git_strmap_lookup_index(cache->files, path); - - if (git_strmap_valid_index(cache->files, pos)) - return git_strmap_value_at(cache->files, pos); - else - return NULL; + return git_strmap_get(cache->files, path); } int git_attr_cache__alloc_file_entry( @@ -59,7 +54,7 @@ cachesize++; } - ce = git_pool_mallocz(pool, (uint32_t)cachesize); + ce = git_pool_mallocz(pool, cachesize); GIT_ERROR_CHECK_ALLOC(ce); if (baselen) { @@ -80,18 +75,16 @@ static int attr_cache_make_entry( git_attr_file_entry **out, git_repository *repo, const char *path) { - int error = 0; git_attr_cache *cache = git_repository_attr_cache(repo); git_attr_file_entry *entry = NULL; + int error; - error = git_attr_cache__alloc_file_entry( - &entry, git_repository_workdir(repo), path, &cache->pool); + if ((error = git_attr_cache__alloc_file_entry(&entry, git_repository_workdir(repo), + path, &cache->pool)) < 0) + return error; - if (!error) { - git_strmap_insert(cache->files, entry->path, entry, &error); - if (error > 0) - error = 0; - } + if ((error = git_strmap_set(cache->files, entry->path, entry)) < 0) + return error; *out = entry; return error; @@ -215,7 +208,8 @@ git_attr_file_source source, const char *base, const char *filename, - git_attr_file_parser parser) + git_attr_file_parser parser, + bool allow_macros) { int error = 0; git_attr_cache *cache = git_repository_attr_cache(repo); @@ -228,7 +222,7 @@ /* load file if we don't have one or if existing one is out of date */ if (!file || (error = git_attr_file__out_of_date(repo, attr_session, file)) > 0) - error = git_attr_file__load(&updated, repo, attr_session, entry, source, parser); + error = git_attr_file__load(&updated, repo, attr_session, entry, source, parser, allow_macros); /* if we loaded the file, insert into and/or update cache */ if (updated) { @@ -265,19 +259,15 @@ const char *filename) { git_attr_cache *cache = git_repository_attr_cache(repo); - git_strmap *files; - size_t pos; git_attr_file_entry *entry; + git_strmap *files; if (!cache || !(files = cache->files)) return false; - pos = git_strmap_lookup_index(files, filename); - if (!git_strmap_valid_index(files, pos)) + if ((entry = git_strmap_get(files, filename)) == NULL) return false; - entry = git_strmap_value_at(files, pos); - return entry && (entry->file[source] != NULL); } @@ -400,12 +390,11 @@ /* allocate hashtable for attribute and ignore file contents, * hashtable for attribute macros, and string pool */ - if ((ret = git_strmap_alloc(&cache->files)) < 0 || - (ret = git_strmap_alloc(&cache->macros)) < 0) + if ((ret = git_strmap_new(&cache->files)) < 0 || + (ret = git_strmap_new(&cache->macros)) < 0 || + (ret = git_pool_init(&cache->pool, 1)) < 0) goto cancel; - git_pool_init(&cache->pool, 1); - cache = git__compare_and_swap(&repo->attrcache, NULL, cache); if (cache) goto cancel; /* raced with another thread, free this but no error */ @@ -421,7 +410,7 @@ return ret; } -void git_attr_cache_flush(git_repository *repo) +int git_attr_cache_flush(git_repository *repo) { git_attr_cache *cache; @@ -430,40 +419,50 @@ */ if (repo && (cache = git__swap(repo->attrcache, NULL)) != NULL) attr_cache__free(cache); + + return 0; } int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) { git_attr_cache *cache = git_repository_attr_cache(repo); - git_strmap *macros = cache->macros; - int error; - - /* TODO: generate warning log if (macro->assigns.length == 0) */ - if (macro->assigns.length == 0) - return 0; + git_attr_rule *preexisting; + bool locked = false; + int error = 0; - if (attr_cache_lock(cache) < 0) { - git_error_set(GIT_ERROR_OS, "unable to get attr cache lock"); - error = -1; - } else { - git_strmap_insert(macros, macro->match.pattern, macro, &error); - git_mutex_unlock(&cache->lock); + /* + * Callers assume that if we return success, that the + * macro will have been adopted by the attributes cache. + * Thus, we have to free the macro here if it's not being + * added to the cache. + * + * TODO: generate warning log if (macro->assigns.length == 0) + */ + if (macro->assigns.length == 0) { + git_attr_rule__free(macro); + goto out; } - return (error < 0) ? -1 : 0; + if ((error = attr_cache_lock(cache)) < 0) + goto out; + locked = true; + + if ((preexisting = git_strmap_get(cache->macros, macro->match.pattern)) != NULL) + git_attr_rule__free(preexisting); + + if ((error = git_strmap_set(cache->macros, macro->match.pattern, macro)) < 0) + goto out; + +out: + if (locked) + attr_cache_unlock(cache); + return error; } git_attr_rule *git_attr_cache__lookup_macro( git_repository *repo, const char *name) { git_strmap *macros = git_repository_attr_cache(repo)->macros; - size_t pos; - pos = git_strmap_lookup_index(macros, name); - - if (!git_strmap_valid_index(macros, pos)) - return NULL; - - return (git_attr_rule *)git_strmap_value_at(macros, pos); + return git_strmap_get(macros, name); } - diff -Nru libgit2-0.28.5+dfsg.1/src/attrcache.h libgit2-1.1.0+dfsg.1/src/attrcache.h --- libgit2-0.28.5+dfsg.1/src/attrcache.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/attrcache.h 2020-10-12 18:53:06.000000000 +0000 @@ -34,7 +34,8 @@ git_attr_file_source source, const char *base, const char *filename, - git_attr_file_parser parser); + git_attr_file_parser parser, + bool allow_macros); extern bool git_attr_cache__is_cached( git_repository *repo, diff -Nru libgit2-0.28.5+dfsg.1/src/attr_file.c libgit2-1.1.0+dfsg.1/src/attr_file.c --- libgit2-0.28.5+dfsg.1/src/attr_file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/attr_file.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,10 +10,12 @@ #include "repository.h" #include "filebuf.h" #include "attrcache.h" +#include "buf_text.h" #include "git2/blob.h" #include "git2/tree.h" #include "blob.h" #include "index.h" +#include "wildmatch.h" #include static void attr_file_free(git_attr_file *file) @@ -39,16 +41,21 @@ if (git_mutex_init(&attrs->lock) < 0) { git_error_set(GIT_ERROR_OS, "failed to initialize lock"); - git__free(attrs); - return -1; + goto on_error; } - git_pool_init(&attrs->pool, 1); + if (git_pool_init(&attrs->pool, 1) < 0) + goto on_error; + GIT_REFCOUNT_INC(attrs); attrs->entry = entry; attrs->source = source; *out = attrs; return 0; + +on_error: + git__free(attrs); + return -1; } int git_attr_file__clear_rules(git_attr_file *file, bool need_lock) @@ -103,14 +110,22 @@ git_attr_session *attr_session, git_attr_file_entry *entry, git_attr_file_source source, - git_attr_file_parser parser) + git_attr_file_parser parser, + bool allow_macros) { int error = 0; + git_tree *tree = NULL; + git_tree_entry *tree_entry = NULL; git_blob *blob = NULL; git_buf content = GIT_BUF_INIT; + const char *content_str; git_attr_file *file; struct stat st; bool nonexistent = false; + int bom_offset; + git_bom_t bom; + git_oid id; + git_object_size_t blobsize; *out = NULL; @@ -119,9 +134,6 @@ /* in-memory attribute file doesn't need data */ break; case GIT_ATTR_FILE__FROM_INDEX: { - git_oid id; - git_off_t blobsize; - if ((error = attr_file_oid_from_index(&id, repo, entry->path)) < 0 || (error = git_blob_lookup(&blob, repo, &id)) < 0) return error; @@ -151,6 +163,25 @@ break; } + case GIT_ATTR_FILE__FROM_HEAD: { + if ((error = git_repository_head_tree(&tree, repo)) < 0 || + (error = git_tree_entry_bypath(&tree_entry, tree, entry->path)) < 0 || + (error = git_blob_lookup(&blob, repo, git_tree_entry_id(tree_entry))) < 0) + goto cleanup; + + /* + * Do not assume that data straight from the ODB is NULL-terminated; + * copy the contents of a file to a buffer to work on. + */ + blobsize = git_blob_rawsize(blob); + + GIT_ERROR_CHECK_BLOBSIZE(blobsize); + if ((error = git_buf_put(&content, + git_blob_rawcontent(blob), (size_t)blobsize)) < 0) + goto cleanup; + + break; + } default: git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source); return -1; @@ -159,13 +190,20 @@ if ((error = git_attr_file__new(&file, entry, source)) < 0) goto cleanup; + /* advance over a UTF8 BOM */ + content_str = git_buf_cstr(&content); + bom_offset = git_buf_text_detect_bom(&bom, &content); + + if (bom == GIT_BOM_UTF8) + content_str += bom_offset; + /* store the key of the attr_reader; don't bother with cache * invalidation during the same attr reader session. */ if (attr_session) file->session_key = attr_session->key; - if (parser && (error = parser(repo, file, git_buf_cstr(&content))) < 0) { + if (parser && (error = parser(repo, file, content_str, allow_macros)) < 0) { git_attr_file__free(file); goto cleanup; } @@ -175,6 +213,8 @@ file->nonexistent = 1; else if (source == GIT_ATTR_FILE__FROM_INDEX) git_oid_cpy(&file->cache_data.oid, git_blob_id(blob)); + else if (source == GIT_ATTR_FILE__FROM_HEAD) + git_oid_cpy(&file->cache_data.oid, git_tree_id(tree)); else if (source == GIT_ATTR_FILE__FROM_FILE) git_futils_filestamp_set_from_stat(&file->cache_data.stamp, &st); /* else always cacheable */ @@ -183,6 +223,8 @@ cleanup: git_blob_free(blob); + git_tree_entry_free(tree_entry); + git_tree_free(tree); git_buf_dispose(&content); return error; @@ -223,6 +265,19 @@ return (git_oid__cmp(&file->cache_data.oid, &id) != 0); } + case GIT_ATTR_FILE__FROM_HEAD: { + git_tree *tree; + int error; + + if ((error = git_repository_head_tree(&tree, repo)) < 0) + return error; + + error = git_oid__cmp(&file->cache_data.oid, git_tree_id(tree)); + + git_tree_free(tree); + return error; + } + default: git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source); return -1; @@ -237,16 +292,15 @@ const char *pattern); int git_attr_file__parse_buffer( - git_repository *repo, git_attr_file *attrs, const char *data) + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros) { - int error = 0; const char *scan = data, *context = NULL; git_attr_rule *rule = NULL; + int error = 0; - /* if subdir file path, convert context for file paths */ - if (attrs->entry && - git_path_root(attrs->entry->path) < 0 && - !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE)) + /* If subdir file path, convert context for file paths */ + if (attrs->entry && git_path_root(attrs->entry->path) < 0 && + !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE)) context = attrs->entry->path; if (git_mutex_lock(&attrs->lock) < 0) { @@ -255,38 +309,38 @@ } while (!error && *scan) { - /* allocate rule if needed */ - if (!rule && !(rule = git__calloc(1, sizeof(*rule)))) { - error = -1; - break; - } - - rule->match.flags = - GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO; - - /* parse the next "pattern attr attr attr" line */ - if (!(error = git_attr_fnmatch__parse( - &rule->match, &attrs->pool, context, &scan)) && - !(error = git_attr_assignment__parse( - repo, &attrs->pool, &rule->assigns, &scan))) + /* Allocate rule if needed, otherwise re-use previous rule */ + if (!rule) { + rule = git__calloc(1, sizeof(*rule)); + GIT_ERROR_CHECK_ALLOC(rule); + } else + git_attr_rule__clear(rule); + + rule->match.flags = GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO; + + /* Parse the next "pattern attr attr attr" line */ + if ((error = git_attr_fnmatch__parse(&rule->match, &attrs->pool, context, &scan)) < 0 || + (error = git_attr_assignment__parse(repo, &attrs->pool, &rule->assigns, &scan)) < 0) { - if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) - /* TODO: warning if macro found in file below repo root */ - error = git_attr_cache__insert_macro(repo, rule); - else - error = git_vector_insert(&attrs->rules, rule); + if (error != GIT_ENOTFOUND) + goto out; + error = 0; + continue; } - /* if the rule wasn't a pattern, on to the next */ - if (error < 0) { - git_attr_rule__clear(rule); /* reset rule contents */ - if (error == GIT_ENOTFOUND) - error = 0; - } else { - rule = NULL; /* vector now "owns" the rule */ - } + if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) { + /* TODO: warning if macro found in file below repo root */ + if (!allow_macros) + continue; + if ((error = git_attr_cache__insert_macro(repo, rule)) < 0) + goto out; + } else if ((error = git_vector_insert(&attrs->rules, rule)) < 0) + goto out; + + rule = NULL; } +out: git_mutex_unlock(&attrs->lock); git_attr_rule__free(rule); @@ -333,33 +387,28 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path) { - int error; - git_attr_file *file; git_buf content = GIT_BUF_INIT; + git_attr_file *file = NULL; + int error; - error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE); - if (error < 0) - return error; + if ((error = git_futils_readbuffer(&content, path)) < 0) + goto out; - error = git_attr_cache__alloc_file_entry( - &file->entry, NULL, path, &file->pool); - if (error < 0) { - git_attr_file__free(file); - return error; - } - /* because the cache entry is allocated from the file's own pool, we + /* + * Because the cache entry is allocated from the file's own pool, we * don't have to free it - freeing file+pool will free cache entry, too. */ - if (!(error = git_futils_readbuffer(&content, path))) { - error = git_attr_file__parse_buffer(NULL, file, content.ptr); - git_buf_dispose(&content); - } + if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 || + (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 || + (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0) + goto out; + *out = file; +out: if (error < 0) git_attr_file__free(file); - else - *out = file; + git_buf_dispose(&content); return error; } @@ -390,18 +439,13 @@ } if (match->flags & GIT_ATTR_FNMATCH_ICASE) - flags |= FNM_CASEFOLD; - if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR) - flags |= FNM_LEADING_DIR; + flags |= WM_CASEFOLD; if (match->flags & GIT_ATTR_FNMATCH_FULLPATH) { filename = relpath; - flags |= FNM_PATHNAME; + flags |= WM_PATHNAME; } else { filename = path->basename; - - if (path->is_dir) - flags |= FNM_LEADING_DIR; } if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) { @@ -416,8 +460,6 @@ path->basename == relpath) return false; - flags |= FNM_LEADING_DIR; - /* fail match if this is a file with same name as ignored folder */ samename = (match->flags & GIT_ATTR_FNMATCH_ICASE) ? !strcasecmp(match->pattern, relpath) : @@ -426,10 +468,10 @@ if (samename) return false; - return (p_fnmatch(match->pattern, relpath, flags) != FNM_NOMATCH); + return (wildmatch(match->pattern, relpath, flags) == WM_MATCH); } - return (p_fnmatch(match->pattern, filename, flags) != FNM_NOMATCH); + return (wildmatch(match->pattern, filename, flags) == WM_MATCH); } bool git_attr_rule__match( @@ -549,6 +591,61 @@ */ /* + * Determine the length of trailing spaces. Escaped spaces do not count as + * trailing whitespace. + */ +static size_t trailing_space_length(const char *p, size_t len) +{ + size_t n, i; + for (n = len; n; n--) { + if (p[n-1] != ' ' && p[n-1] != '\t') + break; + + /* + * Count escape-characters before space. In case where it's an + * even number of escape characters, then the escape char itself + * is escaped and the whitespace is an unescaped whitespace. + * Otherwise, the last escape char is not escaped and the + * whitespace in an escaped whitespace. + */ + i = n; + while (i > 1 && p[i-2] == '\\') + i--; + if ((n - i) % 2) + break; + } + return len - n; +} + +static size_t unescape_spaces(char *str) +{ + char *scan, *pos = str; + bool escaped = false; + + if (!str) + return 0; + + for (scan = str; *scan; scan++) { + if (!escaped && *scan == '\\') { + escaped = true; + continue; + } + + /* Only insert the escape character for escaped non-spaces */ + if (escaped && !git__isspace(*scan)) + *pos++ = '\\'; + + *pos++ = *scan; + escaped = false; + } + + if (pos != scan) + *pos = '\0'; + + return (pos - str); +} + +/* * This will return 0 if the spec was filled out, * GIT_ENOTFOUND if the fnmatch does not require matching, or * another error code there was an actual problem. @@ -561,6 +658,7 @@ { const char *pattern, *scan; int slash_count, allow_space; + bool escaped; assert(spec && base && *base); @@ -572,8 +670,11 @@ pattern = *base; - while (git__isspace(*pattern)) pattern++; - if (!*pattern || *pattern == '#') { + while (!allow_space && git__isspace(*pattern)) + pattern++; + + if (!*pattern || *pattern == '#' || *pattern == '\n' || + (*pattern == '\r' && *(pattern + 1) == '\n')) { *base = git__next_line(pattern); return GIT_ENOTFOUND; } @@ -588,29 +689,33 @@ if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) { spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE; - if ((spec->flags & GIT_ATTR_FNMATCH_NOLEADINGDIR) == 0) - spec->flags |= GIT_ATTR_FNMATCH_LEADINGDIR; pattern++; } slash_count = 0; + escaped = false; + /* Scan until a non-escaped whitespace. */ for (scan = pattern; *scan != '\0'; ++scan) { - /* scan until (non-escaped) white space */ - if (git__isspace(*scan) && *(scan - 1) != '\\') { - if (!allow_space || (*scan != ' ' && *scan != '\t' && *scan != '\r')) - break; - } + char c = *scan; - if (*scan == '/') { + if (c == '\\' && !escaped) { + escaped = true; + continue; + } else if (git__isspace(c) && !escaped) { + if (!allow_space || (c != ' ' && c != '\t' && c != '\r')) + break; + } else if (c == '/') { spec->flags = spec->flags | GIT_ATTR_FNMATCH_FULLPATH; slash_count++; - if (pattern == scan) + + if (slash_count == 1 && pattern == scan) pattern++; - } - /* remember if we see an unescaped wildcard in pattern */ - else if (git__iswildcard(*scan) && - (scan == pattern || (*(scan - 1) != '\\'))) + } else if (git__iswildcard(c) && !escaped) { + /* remember if we see an unescaped wildcard in pattern */ spec->flags = spec->flags | GIT_ATTR_FNMATCH_HASWILD; + } + + escaped = false; } *base = scan; @@ -628,9 +733,10 @@ return GIT_ENOTFOUND; /* Remove trailing spaces. */ - while (pattern[spec->length - 1] == ' ' || pattern[spec->length - 1] == '\t') - if (--spec->length == 0) - return GIT_ENOTFOUND; + spec->length -= trailing_space_length(pattern, spec->length); + + if (spec->length == 0) + return GIT_ENOTFOUND; if (pattern[spec->length - 1] == '/') { spec->length--; @@ -638,14 +744,6 @@ if (--slash_count <= 0) spec->flags = spec->flags & ~GIT_ATTR_FNMATCH_FULLPATH; } - if ((spec->flags & GIT_ATTR_FNMATCH_NOLEADINGDIR) == 0 && - spec->length >= 2 && - pattern[spec->length - 1] == '*' && - pattern[spec->length - 2] == '/') { - spec->length -= 2; - spec->flags = spec->flags | GIT_ATTR_FNMATCH_LEADINGDIR; - /* leave FULLPATH match on, however */ - } if (context) { char *slash = strrchr(context, '/'); @@ -664,9 +762,8 @@ *base = git__next_line(pattern); return -1; } else { - /* strip '\' that might have be used for internal whitespace */ - spec->length = git__unescape(spec->pattern); - /* TODO: convert remaining '\' into '/' for POSIX ??? */ + /* strip '\' that might have been used for internal whitespace */ + spec->length = unescape_spaces(spec->pattern); } return 0; @@ -859,6 +956,7 @@ { assert(repo); + memset(session, 0, sizeof(*session)); session->key = git_atomic_inc(&repo->attr_session_key); return 0; diff -Nru libgit2-0.28.5+dfsg.1/src/attr_file.h libgit2-1.1.0+dfsg.1/src/attr_file.h --- libgit2-0.28.5+dfsg.1/src/attr_file.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/attr_file.h 2020-10-12 18:53:06.000000000 +0000 @@ -14,7 +14,7 @@ #include "vector.h" #include "pool.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #define GIT_ATTR_FILE ".gitattributes" #define GIT_ATTR_FILE_INREPO "attributes" @@ -32,19 +32,17 @@ #define GIT_ATTR_FNMATCH_MATCH_ALL (1U << 8) #define GIT_ATTR_FNMATCH_ALLOWNEG (1U << 9) #define GIT_ATTR_FNMATCH_ALLOWMACRO (1U << 10) -#define GIT_ATTR_FNMATCH_LEADINGDIR (1U << 11) -#define GIT_ATTR_FNMATCH_NOLEADINGDIR (1U << 12) #define GIT_ATTR_FNMATCH__INCOMING \ - (GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG | \ - GIT_ATTR_FNMATCH_ALLOWMACRO | GIT_ATTR_FNMATCH_NOLEADINGDIR) + (GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO) typedef enum { GIT_ATTR_FILE__IN_MEMORY = 0, GIT_ATTR_FILE__FROM_FILE = 1, GIT_ATTR_FILE__FROM_INDEX = 2, + GIT_ATTR_FILE__FROM_HEAD = 3, - GIT_ATTR_FILE_NUM_SOURCES = 3 + GIT_ATTR_FILE_NUM_SOURCES = 4 } git_attr_file_source; extern const char *git_attr__true; @@ -134,7 +132,8 @@ typedef int (*git_attr_file_parser)( git_repository *repo, git_attr_file *file, - const char *data); + const char *data, + bool allow_macros); /* * git_attr_file API @@ -153,7 +152,8 @@ git_attr_session *attr_session, git_attr_file_entry *ce, git_attr_file_source source, - git_attr_file_parser parser); + git_attr_file_parser parser, + bool allow_macros); int git_attr_file__load_standalone( git_attr_file **out, const char *path); @@ -162,7 +162,7 @@ git_repository *repo, git_attr_session *session, git_attr_file *file); int git_attr_file__parse_buffer( - git_repository *repo, git_attr_file *attrs, const char *data); + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros); int git_attr_file__clear_rules( git_attr_file *file, bool need_lock); diff -Nru libgit2-0.28.5+dfsg.1/src/blame.c libgit2-1.1.0+dfsg.1/src/blame.c --- libgit2-0.28.5+dfsg.1/src/blame.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/blame.c 2020-10-12 18:53:06.000000000 +0000 @@ -204,7 +204,7 @@ memcpy(out, in, sizeof(git_blame_options)); /* No newest_commit => HEAD */ - if (git_oid_iszero(&out->newest_commit)) { + if (git_oid_is_zero(&out->newest_commit)) { if (git_reference_name_to_id(&out->newest_commit, repo, "HEAD") < 0) { return -1; } @@ -268,7 +268,7 @@ static int index_blob_lines(git_blame *blame) { const char *buf = blame->final_buf; - git_off_t len = blame->final_buf_size; + size_t len = blame->final_buf_size; int num = 0, incomplete = 0, bol = 1; size_t *i; @@ -335,8 +335,15 @@ if ((error = load_blob(blame)) < 0 || (error = git_blame__get_origin(&o, blame, blame->final, blame->path)) < 0) goto cleanup; + + if (git_blob_rawsize(blame->final_blob) > SIZE_MAX) { + git_error_set(GIT_ERROR_NOMEMORY, "blob is too large to blame"); + error = -1; + goto cleanup; + } + blame->final_buf = git_blob_rawcontent(blame->final_blob); - blame->final_buf_size = git_blob_rawsize(blame->final_blob); + blame->final_buf_size = (size_t)git_blob_rawsize(blame->final_blob); ent = git__calloc(1, sizeof(git_blame__entry)); GIT_ERROR_CHECK_ALLOC(ent); @@ -408,7 +415,7 @@ static bool hunk_is_bufferblame(git_blame_hunk *hunk) { - return hunk && git_oid_iszero(&hunk->final_commit_id); + return hunk && git_oid_is_zero(&hunk->final_commit_id); } static int buffer_hunk_cb( @@ -524,9 +531,16 @@ return 0; } -int git_blame_init_options(git_blame_options *opts, unsigned int version) +int git_blame_options_init(git_blame_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_blame_options, GIT_BLAME_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_blame_init_options(git_blame_options *opts, unsigned int version) +{ + return git_blame_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/blame_git.c libgit2-1.1.0+dfsg.1/src/blame_git.c --- libgit2-0.28.5+dfsg.1/src/blame_git.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/blame_git.c 2020-10-12 18:53:06.000000000 +0000 @@ -219,7 +219,7 @@ * split_overlap() divided an existing blame e into up to three parts in split. * Adjust the linked list of blames in the scoreboard to reflect the split. */ -static void split_blame(git_blame *blame, git_blame__entry *split, git_blame__entry *e) +static int split_blame(git_blame *blame, git_blame__entry *split, git_blame__entry *e) { git_blame__entry *new_entry; @@ -229,11 +229,13 @@ /* The last part -- me */ new_entry = git__malloc(sizeof(*new_entry)); + GIT_ERROR_CHECK_ALLOC(new_entry); memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); add_blame_entry(blame, new_entry); /* ... and the middle part -- parent */ new_entry = git__malloc(sizeof(*new_entry)); + GIT_ERROR_CHECK_ALLOC(new_entry); memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); add_blame_entry(blame, new_entry); } else if (!split[0].suspect && !split[2].suspect) { @@ -246,15 +248,19 @@ /* me and then parent */ dup_entry(e, &split[0]); new_entry = git__malloc(sizeof(*new_entry)); + GIT_ERROR_CHECK_ALLOC(new_entry); memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); add_blame_entry(blame, new_entry); } else { /* parent and then me */ dup_entry(e, &split[1]); new_entry = git__malloc(sizeof(*new_entry)); + GIT_ERROR_CHECK_ALLOC(new_entry); memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); add_blame_entry(blame, new_entry); } + + return 0; } /* @@ -272,7 +278,7 @@ * Helper for blame_chunk(). blame_entry e is known to overlap with the patch * hunk; split it and pass blame to the parent. */ -static void blame_overlap( +static int blame_overlap( git_blame *blame, git_blame__entry *e, size_t tlno, @@ -284,8 +290,11 @@ split_overlap(split, e, tlno, plno, same, parent); if (split[1].suspect) - split_blame(blame, split, e); + if (split_blame(blame, split, e) < 0) + return -1; decref_split(split); + + return 0; } /* @@ -293,7 +302,7 @@ * e and its parent. Find and split the overlap, and pass blame to the * overlapping part to the parent. */ -static void blame_chunk( +static int blame_chunk( git_blame *blame, size_t tlno, size_t plno, @@ -309,9 +318,12 @@ if (same <= e->s_lno) continue; if (tlno < e->s_lno + e->num_lines) { - blame_overlap(blame, e, tlno, plno, same, parent); + if (blame_overlap(blame, e, tlno, plno, same, parent) < 0) + return -1; } } + + return 0; } static int my_emit( @@ -321,7 +333,8 @@ { blame_chunk_cb_data *d = (blame_chunk_cb_data *)cb_data; - blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent); + if (blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent) < 0) + return -1; d->plno = start_a + count_a; d->tlno = start_b + count_b; @@ -352,11 +365,14 @@ b->size -= trimmed - recovered; } -static int diff_hunks(mmfile_t file_a, mmfile_t file_b, void *cb_data) +static int diff_hunks(mmfile_t file_a, mmfile_t file_b, void *cb_data, git_blame_options *options) { - xpparam_t xpp = {0}; xdemitconf_t xecfg = {0}; xdemitcb_t ecb = {0}; + xpparam_t xpp = {0}; + + if (options->flags & GIT_BLAME_IGNORE_WHITESPACE) + xpp.flags |= XDF_IGNORE_WHITESPACE; xecfg.hunk_func = my_emit; ecb.priv = cb_data; @@ -396,11 +412,12 @@ fill_origin_blob(parent, &file_p); fill_origin_blob(target, &file_o); - if (diff_hunks(file_p, file_o, &d) < 0) + if (diff_hunks(file_p, file_o, &d, &blame->options) < 0) return -1; /* The reset (i.e. anything after tlno) are the same as the parent */ - blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent); + if (blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent) < 0) + return -1; return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/blame.h libgit2-1.1.0+dfsg.1/src/blame.h --- libgit2-0.28.5+dfsg.1/src/blame.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/blame.h 2020-10-12 18:53:06.000000000 +0000 @@ -84,7 +84,7 @@ git_blame__entry *ent; int num_lines; const char *final_buf; - git_off_t final_buf_size; + size_t final_buf_size; }; git_blame *git_blame__alloc( diff -Nru libgit2-0.28.5+dfsg.1/src/blob.c libgit2-1.1.0+dfsg.1/src/blob.c --- libgit2-0.28.5+dfsg.1/src/blob.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/blob.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,18 +25,18 @@ return git_odb_object_data(blob->data.odb); } -git_off_t git_blob_rawsize(const git_blob *blob) +git_object_size_t git_blob_rawsize(const git_blob *blob) { assert(blob); if (blob->raw) return blob->data.raw.size; else - return (git_off_t)git_odb_object_size(blob->data.odb); + return (git_object_size_t)git_odb_object_size(blob->data.odb); } int git_blob__getbuf(git_buf *buffer, git_blob *blob) { - git_off_t size = git_blob_rawsize(blob); + git_object_size_t size = git_blob_rawsize(blob); GIT_ERROR_CHECK_BLOBSIZE(size); return git_buf_set(buffer, git_blob_rawcontent(blob), (size_t)size); @@ -70,7 +70,7 @@ return 0; } -int git_blob_create_frombuffer( +int git_blob_create_from_buffer( git_oid *id, git_repository *repo, const void *buffer, size_t len) { int error; @@ -91,13 +91,13 @@ } static int write_file_stream( - git_oid *id, git_odb *odb, const char *path, git_off_t file_size) + git_oid *id, git_odb *odb, const char *path, git_object_size_t file_size) { int fd, error; char buffer[FILEIO_BUFSIZE]; git_odb_stream *stream = NULL; ssize_t read_len = -1; - git_off_t written = 0; + git_object_size_t written = 0; if ((error = git_odb_open_wstream( &stream, odb, file_size, GIT_OBJECT_BLOB)) < 0) @@ -129,7 +129,7 @@ static int write_file_filtered( git_oid *id, - git_off_t *size, + git_object_size_t *size, git_odb *odb, const char *full_path, git_filter_list *fl) @@ -184,7 +184,7 @@ int error; struct stat st; git_odb *odb = NULL; - git_off_t size; + git_object_size_t size; mode_t mode; git_buf path = GIT_BUF_INIT; @@ -263,13 +263,13 @@ return error; } -int git_blob_create_fromworkdir( +int git_blob_create_from_workdir( git_oid *id, git_repository *repo, const char *path) { return git_blob__create_from_paths(id, NULL, repo, NULL, path, 0, true); } -int git_blob_create_fromdisk( +int git_blob_create_from_disk( git_oid *id, git_repository *repo, const char *path) { int error; @@ -325,7 +325,7 @@ return git_filebuf_write(&stream->fbuf, buffer, len); } -int git_blob_create_fromstream(git_writestream **out, git_repository *repo, const char *hintpath) +int git_blob_create_from_stream(git_writestream **out, git_repository *repo, const char *hintpath) { int error; git_buf path = GIT_BUF_INIT; @@ -364,7 +364,7 @@ return error; } -int git_blob_create_fromstream_commit(git_oid *out, git_writestream *_stream) +int git_blob_create_from_stream_commit(git_oid *out, git_writestream *_stream) { int error; blob_writestream *stream = (blob_writestream *) _stream; @@ -389,7 +389,7 @@ int git_blob_is_binary(const git_blob *blob) { git_buf content = GIT_BUF_INIT; - git_off_t size; + git_object_size_t size; assert(blob); @@ -400,25 +400,40 @@ return git_buf_text_is_binary(&content); } -int git_blob_filtered_content( +int git_blob_filter( git_buf *out, git_blob *blob, const char *path, - int check_for_binary_data) + git_blob_filter_options *given_opts) { int error = 0; git_filter_list *fl = NULL; + git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT; + git_filter_flag_t flags = GIT_FILTER_DEFAULT; assert(blob && path && out); git_buf_sanitize(out); - if (check_for_binary_data && git_blob_is_binary(blob)) + GIT_ERROR_CHECK_VERSION( + given_opts, GIT_BLOB_FILTER_OPTIONS_VERSION, "git_blob_filter_options"); + + if (given_opts != NULL) + memcpy(&opts, given_opts, sizeof(git_blob_filter_options)); + + if ((opts.flags & GIT_BLOB_FILTER_CHECK_FOR_BINARY) != 0 && + git_blob_is_binary(blob)) return 0; + if ((opts.flags & GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES) != 0) + flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES; + + if ((opts.flags & GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD) != 0) + flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD; + if (!(error = git_filter_list_load( &fl, git_blob_owner(blob), blob, path, - GIT_FILTER_TO_WORKTREE, GIT_FILTER_DEFAULT))) { + GIT_FILTER_TO_WORKTREE, flags))) { error = git_filter_list_apply_to_blob(out, fl, blob); @@ -427,3 +442,54 @@ return error; } + +/* Deprecated functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_blob_create_frombuffer( + git_oid *id, git_repository *repo, const void *buffer, size_t len) +{ + return git_blob_create_from_buffer(id, repo, buffer, len); +} + +int git_blob_create_fromworkdir(git_oid *id, git_repository *repo, const char *relative_path) +{ + return git_blob_create_from_workdir(id, repo, relative_path); +} + +int git_blob_create_fromdisk(git_oid *id, git_repository *repo, const char *path) +{ + return git_blob_create_from_disk(id, repo, path); +} + +int git_blob_create_fromstream( + git_writestream **out, + git_repository *repo, + const char *hintpath) +{ + return git_blob_create_from_stream(out, repo, hintpath); +} + +int git_blob_create_fromstream_commit( + git_oid *out, + git_writestream *stream) +{ + return git_blob_create_from_stream_commit(out, stream); +} + +int git_blob_filtered_content( + git_buf *out, + git_blob *blob, + const char *path, + int check_for_binary_data) +{ + git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT; + + if (check_for_binary_data) + opts.flags |= GIT_BLOB_FILTER_CHECK_FOR_BINARY; + else + opts.flags &= ~GIT_BLOB_FILTER_CHECK_FOR_BINARY; + + return git_blob_filter(out, blob, path, &opts); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/blob.h libgit2-1.1.0+dfsg.1/src/blob.h --- libgit2-0.28.5+dfsg.1/src/blob.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/blob.h 2020-10-12 18:53:06.000000000 +0000 @@ -12,7 +12,7 @@ #include "git2/blob.h" #include "repository.h" #include "odb.h" -#include "fileops.h" +#include "futils.h" struct git_blob { git_object object; @@ -21,7 +21,7 @@ git_odb_object *odb; struct { const char *data; - git_off_t size; + git_object_size_t size; } raw; } data; unsigned int raw:1; diff -Nru libgit2-0.28.5+dfsg.1/src/branch.c libgit2-1.1.0+dfsg.1/src/branch.c --- libgit2-0.28.5+dfsg.1/src/branch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/branch.c 2020-10-12 18:53:06.000000000 +0000 @@ -22,7 +22,7 @@ git_reference **branch_reference_out, git_repository *repo, const char *branch_name, - int is_remote) + bool is_remote) { git_reference *branch = NULL; int error = 0; @@ -134,29 +134,37 @@ repository, branch_name, commit->commit, commit->description, force); } -static int branch_equals(git_repository *repo, const char *path, void *payload) +static int branch_is_checked_out(git_repository *worktree, void *payload) { git_reference *branch = (git_reference *) payload; git_reference *head = NULL; - int equal = 0; + int error; - if (git_reference__read_head(&head, repo, path) < 0 || - git_reference_type(head) != GIT_REFERENCE_SYMBOLIC) - goto done; + if (git_repository_is_bare(worktree)) + return 0; - equal = !git__strcmp(head->target.symbolic, branch->name); + if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0) { + if (error == GIT_ENOTFOUND) + error = 0; + goto out; + } -done: + if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC) + goto out; + + error = !git__strcmp(head->target.symbolic, branch->name); + +out: git_reference_free(head); - return equal; + return error; } int git_branch_is_checked_out(const git_reference *branch) { - assert(branch && git_reference_is_branch(branch)); - - return git_repository_foreach_head(git_reference_owner(branch), - branch_equals, (void *) branch) == 1; + if (!git_reference_is_branch(branch)) + return 0; + return git_repository_foreach_worktree(git_reference_owner(branch), + branch_is_checked_out, (void *)branch) == 1; } int git_branch_delete(git_reference *branch) @@ -324,9 +332,23 @@ const char *branch_name, git_branch_t branch_type) { + int error = -1; assert(ref_out && repo && branch_name); - return retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE); + switch (branch_type) { + case GIT_BRANCH_LOCAL: + case GIT_BRANCH_REMOTE: + error = retrieve_branch_reference(ref_out, repo, branch_name, branch_type == GIT_BRANCH_REMOTE); + break; + case GIT_BRANCH_ALL: + error = retrieve_branch_reference(ref_out, repo, branch_name, false); + if (error == GIT_ENOTFOUND) + error = retrieve_branch_reference(ref_out, repo, branch_name, true); + break; + default: + assert(false); + } + return error; } int git_branch_name( @@ -524,7 +546,7 @@ if (error < 0) git_buf_dispose(buf); - git_strarray_free(&remote_list); + git_strarray_dispose(&remote_list); return error; } @@ -573,35 +595,36 @@ return -1; } -int git_branch_set_upstream(git_reference *branch, const char *upstream_name) +int git_branch_set_upstream(git_reference *branch, const char *branch_name) { - git_buf key = GIT_BUF_INIT, value = GIT_BUF_INIT; + git_buf key = GIT_BUF_INIT, remote_name = GIT_BUF_INIT, merge_refspec = GIT_BUF_INIT; git_reference *upstream; git_repository *repo; git_remote *remote = NULL; git_config *config; - const char *name, *shortname; + const char *refname, *shortname; int local, error; const git_refspec *fetchspec; - name = git_reference_name(branch); - if (!git_reference__is_branch(name)) - return not_a_local_branch(name); + refname = git_reference_name(branch); + if (!git_reference__is_branch(refname)) + return not_a_local_branch(refname); if (git_repository_config__weakptr(&config, git_reference_owner(branch)) < 0) return -1; - shortname = name + strlen(GIT_REFS_HEADS_DIR); + shortname = refname + strlen(GIT_REFS_HEADS_DIR); - if (upstream_name == NULL) + /* We're unsetting, delegate and bail-out */ + if (branch_name == NULL) return unset_upstream(config, shortname); repo = git_reference_owner(branch); - /* First we need to figure out whether it's a branch or remote-tracking */ - if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_LOCAL) == 0) + /* First we need to resolve name to a branch */ + if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_LOCAL) == 0) local = 1; - else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0) + else if (git_branch_lookup(&upstream, repo, branch_name, GIT_BRANCH_REMOTE) == 0) local = 0; else { git_error_set(GIT_ERROR_REFERENCE, @@ -610,60 +633,63 @@ } /* - * If it's local, the remote is "." and the branch name is - * simply the refname. Otherwise we need to figure out what - * the remote-tracking branch's name on the remote is and use - * that. + * If it's a local-tracking branch, its remote is "." (as "the local + * repository"), and the branch name is simply the refname. + * Otherwise we need to figure out what the remote-tracking branch's + * name on the remote is and use that. */ if (local) - error = git_buf_puts(&value, "."); + error = git_buf_puts(&remote_name, "."); else - error = git_branch_remote_name(&value, repo, git_reference_name(upstream)); + error = git_branch_remote_name(&remote_name, repo, git_reference_name(upstream)); if (error < 0) goto on_error; + /* Update the upsteam branch config with the new name */ if (git_buf_printf(&key, "branch.%s.remote", shortname) < 0) goto on_error; - if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0) + if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&remote_name)) < 0) goto on_error; if (local) { - git_buf_clear(&value); - if (git_buf_puts(&value, git_reference_name(upstream)) < 0) + /* A local branch uses the upstream refname directly */ + if (git_buf_puts(&merge_refspec, git_reference_name(upstream)) < 0) goto on_error; } else { - /* Get the remoe-tracking branch's refname in its repo */ - if (git_remote_lookup(&remote, repo, git_buf_cstr(&value)) < 0) + /* We transform the upstream branch name according to the remote's refspecs */ + if (git_remote_lookup(&remote, repo, git_buf_cstr(&remote_name)) < 0) goto on_error; fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream)); - git_buf_clear(&value); - if (!fetchspec || git_refspec_rtransform(&value, fetchspec, git_reference_name(upstream)) < 0) + if (!fetchspec || git_refspec_rtransform(&merge_refspec, fetchspec, git_reference_name(upstream)) < 0) goto on_error; git_remote_free(remote); remote = NULL; } + /* Update the merge branch config with the refspec */ git_buf_clear(&key); if (git_buf_printf(&key, "branch.%s.merge", shortname) < 0) goto on_error; - if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&value)) < 0) + if (git_config_set_string(config, git_buf_cstr(&key), git_buf_cstr(&merge_refspec)) < 0) goto on_error; git_reference_free(upstream); git_buf_dispose(&key); - git_buf_dispose(&value); + git_buf_dispose(&remote_name); + git_buf_dispose(&merge_refspec); return 0; on_error: git_reference_free(upstream); git_buf_dispose(&key); - git_buf_dispose(&value); + git_buf_dispose(&remote_name); + git_buf_dispose(&merge_refspec); git_remote_free(remote); return -1; diff -Nru libgit2-0.28.5+dfsg.1/src/buffer.c libgit2-1.1.0+dfsg.1/src/buffer.c --- libgit2-0.28.5+dfsg.1/src/buffer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/buffer.c 2020-10-12 18:53:06.000000000 +0000 @@ -133,10 +133,12 @@ git_buf_init(buf, 0); } +#ifndef GIT_DEPRECATE_HARD void git_buf_free(git_buf *buf) { git_buf_dispose(buf); } +#endif void git_buf_sanitize(git_buf *buf) { @@ -363,7 +365,7 @@ for (i = 24; i >= 0; i -= 8) { uint8_t ch = *data++; - acc |= ch << i; + acc |= (uint32_t)ch << i; if (--len == 0) break; @@ -567,6 +569,11 @@ data[copylen] = '\0'; } +void git_buf_consume_bytes(git_buf *buf, size_t len) +{ + git_buf_consume(buf, buf->ptr + len); +} + void git_buf_consume(git_buf *buf, const char *end) { if (end > buf->ptr && end <= buf->ptr + buf->size) { @@ -752,7 +759,8 @@ ssize_t offset_a = -1; /* not safe to have str_b point internally to the buffer */ - assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size); + if (buf->size) + assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size); /* figure out if we need to insert a separator */ if (separator && strlen_a) { @@ -762,7 +770,7 @@ } /* str_a could be part of the buffer */ - if (str_a >= buf->ptr && str_a < buf->ptr + buf->size) + if (buf->size && str_a >= buf->ptr && str_a < buf->ptr + buf->size) offset_a = str_a - buf->ptr; GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b); diff -Nru libgit2-0.28.5+dfsg.1/src/buffer.h libgit2-1.1.0+dfsg.1/src/buffer.h --- libgit2-0.28.5+dfsg.1/src/buffer.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/buffer.h 2020-10-12 18:53:06.000000000 +0000 @@ -113,6 +113,7 @@ int git_buf_printf(git_buf *buf, const char *format, ...) GIT_FORMAT_PRINTF(2, 3); int git_buf_vprintf(git_buf *buf, const char *format, va_list ap); void git_buf_clear(git_buf *buf); +void git_buf_consume_bytes(git_buf *buf, size_t len); void git_buf_consume(git_buf *buf, const char *end); void git_buf_truncate(git_buf *buf, size_t len); void git_buf_shorten(git_buf *buf, size_t amount); diff -Nru libgit2-0.28.5+dfsg.1/src/cache.c libgit2-1.1.0+dfsg.1/src/cache.c --- libgit2-0.28.5+dfsg.1/src/cache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/cache.c 2020-10-12 18:53:06.000000000 +0000 @@ -41,36 +41,18 @@ return 0; } -void git_cache_dump_stats(git_cache *cache) -{ - git_cached_obj *object; - - if (git_cache_size(cache) == 0) - return; - - printf("Cache %p: %"PRIuZ" items cached, %"PRIdZ" bytes\n", - cache, git_cache_size(cache), cache->used_memory); - - git_oidmap_foreach_value(cache->map, object, { - char oid_str[9]; - printf(" %s%c %s (%"PRIuZ")\n", - git_object_type2string(object->type), - object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ', - git_oid_tostr(oid_str, sizeof(oid_str), &object->oid), - object->size - ); - }); -} - int git_cache_init(git_cache *cache) { memset(cache, 0, sizeof(*cache)); - cache->map = git_oidmap_alloc(); - GIT_ERROR_CHECK_ALLOC(cache->map); + + if ((git_oidmap_new(&cache->map)) < 0) + return -1; + if (git_rwlock_init(&cache->lock)) { git_error_set(GIT_ERROR_OS, "failed to initialize cache rwlock"); return -1; } + return 0; } @@ -101,7 +83,7 @@ git_rwlock_wrunlock(&cache->lock); } -void git_cache_free(git_cache *cache) +void git_cache_dispose(git_cache *cache) { git_cache_clear(cache); git_oidmap_free(cache->map); @@ -112,28 +94,30 @@ /* Called with lock */ static void cache_evict_entries(git_cache *cache) { - uint32_t seed = rand(); - size_t evict_count = 8; + size_t evict_count = git_cache_size(cache) / 2048, i; ssize_t evicted_memory = 0; + if (evict_count < 8) + evict_count = 8; + /* do not infinite loop if there's not enough entries to evict */ if (evict_count > git_cache_size(cache)) { clear_cache(cache); return; } + i = 0; while (evict_count > 0) { - size_t pos = seed++ % git_oidmap_end(cache->map); - - if (git_oidmap_has_data(cache->map, pos)) { - git_cached_obj *evict = git_oidmap_value_at(cache->map, pos); + git_cached_obj *evict; + const git_oid *key; - evict_count--; - evicted_memory += evict->size; - git_cached_obj_decref(evict); + if (git_oidmap_iterate((void **) &evict, cache->map, &i, &key) == GIT_ITEROVER) + break; - git_oidmap_delete_at(cache->map, pos); - } + evict_count--; + evicted_memory += evict->size; + git_oidmap_delete(cache->map, key); + git_cached_obj_decref(evict); } cache->used_memory -= evicted_memory; @@ -148,16 +132,12 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags) { - size_t pos; - git_cached_obj *entry = NULL; + git_cached_obj *entry; if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0) return NULL; - pos = git_oidmap_lookup_index(cache->map, oid); - if (git_oidmap_valid_index(cache->map, pos)) { - entry = git_oidmap_value_at(cache->map, pos); - + if ((entry = git_oidmap_get(cache->map, oid)) != NULL) { if (flags && entry->flags != flags) { entry = NULL; } else { @@ -172,7 +152,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) { - size_t pos; + git_cached_obj *stored_entry; git_cached_obj_incref(entry); @@ -188,17 +168,12 @@ return entry; /* soften the load on the cache */ - if (git_cache__current_storage.val > git_cache__max_storage) + if (git_atomic_ssize_get(&git_cache__current_storage) > git_cache__max_storage) cache_evict_entries(cache); - pos = git_oidmap_lookup_index(cache->map, &entry->oid); - /* not found */ - if (!git_oidmap_valid_index(cache->map, pos)) { - int rval; - - git_oidmap_insert(cache->map, &entry->oid, entry, &rval); - if (rval >= 0) { + if ((stored_entry = git_oidmap_get(cache->map, &entry->oid)) == NULL) { + if (git_oidmap_set(cache->map, &entry->oid, entry) == 0) { git_cached_obj_incref(entry); cache->used_memory += entry->size; git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size); @@ -206,19 +181,20 @@ } /* found */ else { - git_cached_obj *stored_entry = git_oidmap_value_at(cache->map, pos); - if (stored_entry->flags == entry->flags) { git_cached_obj_decref(entry); git_cached_obj_incref(stored_entry); entry = stored_entry; } else if (stored_entry->flags == GIT_CACHE_STORE_RAW && - entry->flags == GIT_CACHE_STORE_PARSED) { - git_cached_obj_decref(stored_entry); - git_cached_obj_incref(entry); - - git_oidmap_set_key_at(cache->map, pos, &entry->oid); - git_oidmap_set_value_at(cache->map, pos, entry); + entry->flags == GIT_CACHE_STORE_PARSED) { + if (git_oidmap_set(cache->map, &entry->oid, entry) == 0) { + git_cached_obj_decref(stored_entry); + git_cached_obj_incref(entry); + } else { + git_cached_obj_decref(entry); + git_cached_obj_incref(stored_entry); + entry = stored_entry; + } } else { /* NO OP */ } diff -Nru libgit2-0.28.5+dfsg.1/src/cache.h libgit2-1.1.0+dfsg.1/src/cache.h --- libgit2-0.28.5+dfsg.1/src/cache.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/cache.h 2020-10-12 18:53:06.000000000 +0000 @@ -43,7 +43,7 @@ int git_cache_set_max_object_size(git_object_t type, size_t size); int git_cache_init(git_cache *cache); -void git_cache_free(git_cache *cache); +void git_cache_dispose(git_cache *cache); void git_cache_clear(git_cache *cache); void *git_cache_store_raw(git_cache *cache, git_odb_object *entry); diff -Nru libgit2-0.28.5+dfsg.1/src/cc-compat.h libgit2-1.1.0+dfsg.1/src/cc-compat.h --- libgit2-0.28.5+dfsg.1/src/cc-compat.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/cc-compat.h 2020-10-12 18:53:06.000000000 +0000 @@ -48,6 +48,11 @@ /* Define the printf format specifer to use for size_t output */ #if defined(_MSC_VER) || defined(__MINGW32__) +/* Visual Studio 2012 and prior lack PRId64 entirely */ +# ifndef PRId64 +# define PRId64 "I64d" +# endif + /* The first block is needed to avoid warnings on MingW amd64 */ # if (SIZE_MAX == ULLONG_MAX) # define PRIuZ "I64u" diff -Nru libgit2-0.28.5+dfsg.1/src/checkout.c libgit2-1.1.0+dfsg.1/src/checkout.c --- libgit2-0.28.5+dfsg.1/src/checkout.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/checkout.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,8 +7,6 @@ #include "checkout.h" -#include - #include "git2/repository.h" #include "git2/refs.h" #include "git2/tree.h" @@ -46,7 +44,6 @@ CHECKOUT_ACTION__REMOVE_CONFLICT = 16, CHECKOUT_ACTION__UPDATE_CONFLICT = 32, CHECKOUT_ACTION__MAX = 32, - CHECKOUT_ACTION__DEFER_REMOVE = 64, CHECKOUT_ACTION__REMOVE_AND_UPDATE = (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), }; @@ -198,7 +195,7 @@ } if (git_submodule_status(&sm_status, data->repo, wditem->path, GIT_SUBMODULE_IGNORE_UNSPECIFIED) < 0 || - GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) + GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) rval = true; else if ((sm_oid = git_submodule_wd_id(sm)) == NULL) rval = false; @@ -219,9 +216,10 @@ ie = git_index_get_bypath(data->index, wditem->path, 0); if (ie != NULL && - git_index_time_eq(&wditem->mtime, &ie->mtime) && - wditem->file_size == ie->file_size && - !is_filemode_changed(wditem->mode, ie->mode, data->respect_filemode)) { + !git_index_entry_newer_than_index(ie, data->index) && + git_index_time_eq(&wditem->mtime, &ie->mtime) && + wditem->file_size == ie->file_size && + !is_filemode_changed(wditem->mode, ie->mode, data->respect_filemode)) { /* The workdir is modified iff the index entry is modified */ return !is_workdir_base_or_new(&ie->id, baseitem, newitem) || @@ -275,9 +273,8 @@ /* if the file is on disk and doesn't match our mode, force update */ if (wd && - GIT_PERMS_IS_EXEC(wd->mode) != - GIT_PERMS_IS_EXEC(delta->new_file.mode)) - *action |= CHECKOUT_ACTION__REMOVE; + GIT_PERMS_IS_EXEC(wd->mode) != GIT_PERMS_IS_EXEC(delta->new_file.mode)) + *action |= CHECKOUT_ACTION__REMOVE; notify = GIT_CHECKOUT_NOTIFY_UPDATED; } @@ -373,8 +370,13 @@ if (!git_pathspec__match( pathspec, wd->path, (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL, NULL)) - return git_iterator_advance(wditem, workdir); + git_iterator_ignore_case(workdir), NULL, NULL)) { + + if (wd->mode == GIT_FILEMODE_TREE) + return git_iterator_advance_into(wditem, workdir); + else + return git_iterator_advance(wditem, workdir); + } /* check if item is tracked in the index but not in the checkout diff */ if (data->index != NULL) { @@ -796,13 +798,13 @@ int diff; if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 && - (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) + (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) diff = checkout_idxentry_cmp(ca->theirs, cb->theirs); return diff; } -int checkout_conflictdata_empty( +static int checkout_conflictdata_empty( const git_vector *conflicts, size_t idx, void *payload) { checkout_conflictdata *conflict; @@ -1175,7 +1177,7 @@ /* Find d/f conflicts */ git_vector_foreach(&data->update_conflicts, i, conflict) { if ((conflict->ours && conflict->theirs) || - (!conflict->ours && !conflict->theirs)) + (!conflict->ours && !conflict->theirs)) continue; path = conflict->ours ? @@ -1224,8 +1226,8 @@ return 0; if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 || - (error = checkout_conflicts_coalesce_renames(data)) < 0 || - (error = checkout_conflicts_mark_directoryfile(data)) < 0) + (error = checkout_conflicts_coalesce_renames(data)) < 0 || + (error = checkout_conflicts_mark_directoryfile(data)) < 0) goto done; done: @@ -1306,14 +1308,15 @@ size_t i, *counts = NULL; uint32_t *actions = NULL; - git_pool_init(&pathpool, 1); + if (git_pool_init(&pathpool, 1) < 0) + return -1; if (data->opts.paths.count > 0 && - git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0) + git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0) return -1; if ((error = git_iterator_current(&wditem, workdir)) < 0 && - error != GIT_ITEROVER) + error != GIT_ITEROVER) goto fail; deltas = &data->diff->deltas; @@ -1352,8 +1355,7 @@ counts[CHECKOUT_ACTION__REMOVE] += data->removes.length; if (counts[CHECKOUT_ACTION__CONFLICT] > 0 && - (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0) - { + (data->strategy & GIT_CHECKOUT_ALLOW_CONFLICTS) == 0) { git_error_set(GIT_ERROR_CHECKOUT, "%"PRIuZ" %s checkout", counts[CHECKOUT_ACTION__CONFLICT], counts[CHECKOUT_ACTION__CONFLICT] == 1 ? @@ -1364,7 +1366,7 @@ if ((error = checkout_get_remove_conflicts(data, workdir, &pathspec)) < 0 || - (error = checkout_get_update_conflicts(data, workdir, &pathspec)) < 0) + (error = checkout_get_update_conflicts(data, workdir, &pathspec)) < 0) goto fail; counts[CHECKOUT_ACTION__REMOVE_CONFLICT] = git_vector_length(&data->remove_conflicts); @@ -1391,7 +1393,7 @@ { int ignorecase; - if (git_repository__cvar(&ignorecase, data->repo, GIT_CVAR_IGNORECASE) < 0) { + if (git_repository__configmap_lookup(&ignorecase, data->repo, GIT_CONFIGMAP_IGNORECASE) < 0) { ignorecase = 0; } @@ -1855,26 +1857,6 @@ return 0; } -static int checkout_deferred_remove(git_repository *repo, const char *path) -{ -#if 0 - int error = git_futils_rmdir_r( - path, data->opts.target_directory, GIT_RMDIR_EMPTY_PARENTS); - - if (error == GIT_ENOTFOUND) { - error = 0; - git_error_clear(); - } - - return error; -#else - GIT_UNUSED(repo); - GIT_UNUSED(path); - assert(false); - return 0; -#endif -} - static int checkout_create_the_new( unsigned int *actions, checkout_data *data) @@ -1884,20 +1866,18 @@ size_t i; git_vector_foreach(&data->diff->deltas, i, delta) { - if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) { - /* this had a blocker directory that should only be removed iff - * all of the contents of the directory were safely removed - */ - if ((error = checkout_deferred_remove( - data->repo, delta->old_file.path)) < 0) + if (actions[i] & CHECKOUT_ACTION__UPDATE_BLOB && !S_ISLNK(delta->new_file.mode)) { + if ((error = checkout_blob(data, &delta->new_file)) < 0) return error; + data->completed_steps++; + report_progress(data, delta->new_file.path); } + } - if (actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) { - error = checkout_blob(data, &delta->new_file); - if (error < 0) + git_vector_foreach(&data->diff->deltas, i, delta) { + if (actions[i] & CHECKOUT_ACTION__UPDATE_BLOB && S_ISLNK(delta->new_file.mode)) { + if ((error = checkout_blob(data, &delta->new_file)) < 0) return error; - data->completed_steps++; report_progress(data, delta->new_file.path); } @@ -1910,20 +1890,10 @@ unsigned int *actions, checkout_data *data) { - int error = 0; git_diff_delta *delta; size_t i; git_vector_foreach(&data->diff->deltas, i, delta) { - if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) { - /* this has a blocker directory that should only be removed iff - * all of the contents of the directory were safely removed - */ - if ((error = checkout_deferred_remove( - data->repo, delta->old_file.path)) < 0) - return error; - } - if (actions[i] & CHECKOUT_ACTION__UPDATE_SUBMODULE) { int error = checkout_submodule(data, &delta->new_file); if (error < 0) @@ -2463,12 +2433,12 @@ data->pfx = git_pathspec_prefix(&data->opts.paths); - if ((error = git_repository__cvar( - &data->can_symlink, repo, GIT_CVAR_SYMLINKS)) < 0) + if ((error = git_repository__configmap_lookup( + &data->can_symlink, repo, GIT_CONFIGMAP_SYMLINKS)) < 0) goto cleanup; - if ((error = git_repository__cvar( - &data->respect_filemode, repo, GIT_CVAR_FILEMODE)) < 0) + if ((error = git_repository__configmap_lookup( + &data->respect_filemode, repo, GIT_CONFIGMAP_FILEMODE)) < 0) goto cleanup; if (!data->opts.baseline && !data->opts.baseline_index) { @@ -2515,14 +2485,13 @@ git_config_entry_free(conflict_style); } - git_pool_init(&data->pool, 1); - - if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || - (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 || - (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 || - (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 || - (error = git_path_to_dir(&data->target_path)) < 0 || - (error = git_strmap_alloc(&data->mkdir_map)) < 0) + if ((error = git_pool_init(&data->pool, 1)) < 0 || + (error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || + (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 || + (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 || + (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 || + (error = git_path_to_dir(&data->target_path)) < 0 || + (error = git_strmap_new(&data->mkdir_map)) < 0) goto cleanup; data->target_len = git_buf_len(&data->target_path); @@ -2539,6 +2508,17 @@ #define CHECKOUT_INDEX_DONT_WRITE_MASK \ (GIT_CHECKOUT_DONT_UPDATE_INDEX | GIT_CHECKOUT_DONT_WRITE_INDEX) +GIT_INLINE(void) setup_pathspecs( + git_iterator_options *iter_opts, + const git_checkout_options *checkout_opts) +{ + if (checkout_opts && + (checkout_opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { + iter_opts->pathlist.count = checkout_opts->paths.count; + iter_opts->pathlist.strings = checkout_opts->paths.strings; + } +} + int git_checkout_iterator( git_iterator *target, git_index *index, @@ -2581,6 +2561,8 @@ workdir_opts.start = data.pfx; workdir_opts.end = data.pfx; + setup_pathspecs(&workdir_opts, opts); + if ((error = git_iterator_reset_range(target, data.pfx, data.pfx)) < 0 || (error = git_iterator_for_workdir_ext( &workdir, data.repo, data.opts.target_directory, index, NULL, @@ -2591,10 +2573,8 @@ GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; baseline_opts.start = data.pfx; baseline_opts.end = data.pfx; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - baseline_opts.pathlist.count = opts->paths.count; - baseline_opts.pathlist.strings = opts->paths.strings; - } + + setup_pathspecs(&baseline_opts, opts); if (data.opts.baseline_index) { if ((error = git_iterator_for_index( @@ -2684,6 +2664,7 @@ git_index *index, const git_checkout_options *opts) { + git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; int error, owned = 0; git_iterator *index_i; @@ -2711,7 +2692,9 @@ return error; GIT_REFCOUNT_INC(index); - if (!(error = git_iterator_for_index(&index_i, repo, index, NULL))) + setup_pathspecs(&iter_opts, opts); + + if (!(error = git_iterator_for_index(&index_i, repo, index, &iter_opts))) error = git_checkout_iterator(index_i, index, opts); if (owned) @@ -2768,10 +2751,7 @@ if ((error = git_repository_index(&index, repo)) < 0) return error; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - iter_opts.pathlist.count = opts->paths.count; - iter_opts.pathlist.strings = opts->paths.strings; - } + setup_pathspecs(&iter_opts, opts); if (!(error = git_iterator_for_tree(&tree_i, tree, &iter_opts))) error = git_checkout_iterator(tree_i, index, opts); @@ -2791,9 +2771,16 @@ return git_checkout_tree(repo, NULL, opts); } -int git_checkout_init_options(git_checkout_options *opts, unsigned int version) +int git_checkout_options_init(git_checkout_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_checkout_options, GIT_CHECKOUT_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_checkout_init_options(git_checkout_options *opts, unsigned int version) +{ + return git_checkout_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/cherrypick.c libgit2-1.1.0+dfsg.1/src/cherrypick.c --- libgit2-0.28.5+dfsg.1/src/cherrypick.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/cherrypick.c 2020-10-12 18:53:06.000000000 +0000 @@ -221,10 +221,18 @@ return error; } -int git_cherrypick_init_options( +int git_cherrypick_options_init( git_cherrypick_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_cherrypick_options, GIT_CHERRYPICK_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_cherrypick_init_options( + git_cherrypick_options *opts, unsigned int version) +{ + return git_cherrypick_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/clone.c libgit2-1.1.0+dfsg.1/src/clone.c --- libgit2-0.28.5+dfsg.1/src/clone.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/clone.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,8 +7,6 @@ #include "clone.h" -#include - #include "git2/clone.h" #include "git2/remote.h" #include "git2/revparse.h" @@ -19,7 +17,7 @@ #include "git2/tree.h" #include "remote.h" -#include "fileops.h" +#include "futils.h" #include "refs.h" #include "path.h" #include "repository.h" @@ -139,6 +137,80 @@ return error; } +static int update_head_to_default(git_repository *repo) +{ + git_buf initialbranch = GIT_BUF_INIT; + const char *branch_name; + int error = 0; + + if ((error = git_repository_initialbranch(&initialbranch, repo)) < 0) + goto done; + + if (git__prefixcmp(initialbranch.ptr, GIT_REFS_HEADS_DIR) != 0) { + git_error_set(GIT_ERROR_INVALID, "invalid initial branch '%s'", initialbranch.ptr); + error = -1; + goto done; + } + + branch_name = initialbranch.ptr + strlen(GIT_REFS_HEADS_DIR); + + error = setup_tracking_config(repo, branch_name, GIT_REMOTE_ORIGIN, + initialbranch.ptr); + +done: + git_buf_dispose(&initialbranch); + return error; +} + +static int update_remote_head( + git_repository *repo, + git_remote *remote, + git_buf *target, + const char *reflog_message) +{ + git_refspec *refspec; + git_reference *remote_head = NULL; + git_buf remote_head_name = GIT_BUF_INIT; + git_buf remote_branch_name = GIT_BUF_INIT; + int error; + + /* Determine the remote tracking ref name from the local branch */ + refspec = git_remote__matching_refspec(remote, git_buf_cstr(target)); + + if (refspec == NULL) { + git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration"); + error = GIT_EINVALIDSPEC; + goto cleanup; + } + + if ((error = git_refspec_transform( + &remote_branch_name, + refspec, + git_buf_cstr(target))) < 0) + goto cleanup; + + if ((error = git_buf_printf(&remote_head_name, + "%s%s/%s", + GIT_REFS_REMOTES_DIR, + git_remote_name(remote), + GIT_HEAD_FILE)) < 0) + goto cleanup; + + error = git_reference_symbolic_create( + &remote_head, + repo, + git_buf_cstr(&remote_head_name), + git_buf_cstr(&remote_branch_name), + true, + reflog_message); + +cleanup: + git_reference_free(remote_head); + git_buf_dispose(&remote_branch_name); + git_buf_dispose(&remote_head_name); + return error; +} + static int update_head_to_remote( git_repository *repo, git_remote *remote, @@ -146,10 +218,8 @@ { int error = 0; size_t refs_len; - git_refspec *refspec; const git_remote_head *remote_head, **refs; const git_oid *remote_head_id; - git_buf remote_master_name = GIT_BUF_INIT; git_buf branch = GIT_BUF_INIT; if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0) @@ -157,8 +227,7 @@ /* We cloned an empty repository or one with an unborn HEAD */ if (refs_len == 0 || strcmp(refs[0]->name, GIT_HEAD_FILE)) - return setup_tracking_config( - repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE); + return update_head_to_default(repo); /* We know we have HEAD, let's see where it points */ remote_head = refs[0]; @@ -173,19 +242,7 @@ goto cleanup; } - refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch)); - - if (refspec == NULL) { - git_error_set(GIT_ERROR_NET, "the remote's default branch does not fit the refspec configuration"); - error = GIT_EINVALIDSPEC; - goto cleanup; - } - - /* Determine the remote tracking reference name from the local master */ - if ((error = git_refspec_transform( - &remote_master_name, - refspec, - git_buf_cstr(&branch))) < 0) + if ((error = update_remote_head(repo, remote, &branch, reflog_message)) < 0) goto cleanup; error = update_head_to_new_branch( @@ -195,7 +252,6 @@ reflog_message); cleanup: - git_buf_dispose(&remote_master_name); git_buf_dispose(&branch); return error; @@ -382,11 +438,12 @@ return is_local; } -int git_clone( +static int git__clone( git_repository **out, const char *url, const char *local_path, - const git_clone_options *_options) + const git_clone_options *_options, + int use_existing) { int error = 0; git_repository *repo = NULL; @@ -403,7 +460,7 @@ GIT_ERROR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ - if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { + if (git_path_exists(local_path) && !use_existing && !git_path_is_empty_dir(local_path)) { git_error_set(GIT_ERROR_INVALID, "'%s' exists and is not an empty directory", local_path); return GIT_EEXISTS; @@ -455,13 +512,38 @@ return error; } -int git_clone_init_options(git_clone_options *opts, unsigned int version) +int git_clone( + git_repository **out, + const char *url, + const char *local_path, + const git_clone_options *_options) +{ + return git__clone(out, url, local_path, _options, 0); +} + +int git_clone__submodule( + git_repository **out, + const char *url, + const char *local_path, + const git_clone_options *_options) +{ + return git__clone(out, url, local_path, _options, 1); +} + +int git_clone_options_init(git_clone_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_clone_options, GIT_CLONE_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_clone_init_options(git_clone_options *opts, unsigned int version) +{ + return git_clone_options_init(opts, version); +} +#endif + static bool can_link(const char *src, const char *dst, int link) { #ifdef GIT_WIN32 diff -Nru libgit2-0.28.5+dfsg.1/src/clone.h libgit2-1.1.0+dfsg.1/src/clone.h --- libgit2-0.28.5+dfsg.1/src/clone.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/clone.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,6 +11,10 @@ #include "git2/clone.h" +extern int git_clone__submodule(git_repository **out, + const char *url, const char *local_path, + const git_clone_options *_options); + extern int git_clone__should_clone_local(const char *url, git_clone_local_t local); #endif diff -Nru libgit2-0.28.5+dfsg.1/src/CMakeLists.txt libgit2-1.1.0+dfsg.1/src/CMakeLists.txt --- libgit2-0.28.5+dfsg.1/src/CMakeLists.txt 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/CMakeLists.txt 2020-10-12 18:53:06.000000000 +0000 @@ -1,8 +1,13 @@ +add_library(git2internal OBJECT) +set_target_properties(git2internal PROPERTIES C_STANDARD 90) + IF(DEBUG_POOL) SET(GIT_DEBUG_POOL 1) ENDIF() ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator") +INCLUDE(PkgBuildConfig) + # This variable will contain the libraries we need to put into # libgit2.pc's Requires.private. That is, what we're linking to or # what someone who's statically linking us needs to link to. @@ -19,52 +24,14 @@ SET(LIBGIT2_SYSTEM_INCLUDES "") SET(LIBGIT2_LIBS "") -# Installation paths -# -SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.") -SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.") -SET(INCLUDE_INSTALL_DIR include CACHE PATH "Where to install headers to.") - -# Set a couple variables to be substituted inside the .pc file. -# We can't just use LIB_INSTALL_DIR in the .pc file, as passing them as absolue -# or relative paths is both valid and supported by cmake. -SET (PKGCONFIG_PREFIX ${CMAKE_INSTALL_PREFIX}) - -IF(IS_ABSOLUTE ${LIB_INSTALL_DIR}) - SET (PKGCONFIG_LIBDIR ${LIB_INSTALL_DIR}) -ELSE(IS_ABSOLUTE ${LIB_INSTALL_DIR}) - SET (PKGCONFIG_LIBDIR "\${prefix}/${LIB_INSTALL_DIR}") -ENDIF (IS_ABSOLUTE ${LIB_INSTALL_DIR}) - -IF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR}) - SET (PKGCONFIG_INCLUDEDIR ${INCLUDE_INSTALL_DIR}) -ELSE(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR}) - SET (PKGCONFIG_INCLUDEDIR "\${prefix}/${INCLUDE_INSTALL_DIR}") -ENDIF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR}) +enable_warnings(missing-declarations) # Enable tracing -IF (ENABLE_TRACE STREQUAL "ON") +IF(ENABLE_TRACE) SET(GIT_TRACE 1) ENDIF() ADD_FEATURE_INFO(tracing GIT_TRACE "tracing support") -# Use `regcomp_l` if available -CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L) -IF (HAVE_REGCOMP_L) - SET(GIT_USE_REGCOMP_L 1) -ENDIF () - -# Otherwise, we either want to use system's `regcomp` or our -# bundled regcomp code, if system doesn't provide `regcomp`. -IF(NOT HAVE_REGCOMP_L) - CHECK_FUNCTION_EXISTS(regcomp HAVE_REGCOMP) - IF(NOT HAVE_REGCOMP) - ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/regex" "${libgit2_BINARY_DIR}/deps/regex") - LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/regex") - LIST(APPEND LIBGIT2_OBJECTS $) - ENDIF() -ENDIF() - CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS) IF (HAVE_FUTIMENS) SET(GIT_USE_FUTIMENS 1) @@ -74,19 +41,19 @@ "void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))" "" "stdlib.h" HAVE_QSORT_R_BSD) IF (HAVE_QSORT_R_BSD) - ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD) + target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_BSD) ENDIF() 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" HAVE_QSORT_R_GNU) IF (HAVE_QSORT_R_GNU) - ADD_DEFINITIONS(-DHAVE_QSORT_R_GNU) + target_compile_definitions(git2internal PRIVATE HAVE_QSORT_R_GNU) ENDIF() CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S) IF (HAVE_QSORT_S) - ADD_DEFINITIONS(-DHAVE_QSORT_S) + target_compile_definitions(git2internal PRIVATE HAVE_QSORT_S) ENDIF () # Find required dependencies @@ -114,12 +81,15 @@ ADD_FEATURE_INFO(threadsafe THREADSAFE "threadsafe support") -IF (WIN32 AND EMBED_SSH_PATH) - FILE(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c") - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include") - FILE(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"") - SET(GIT_SSH 1) -ENDIF() +if(WIN32 AND EMBED_SSH_PATH) + file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c") + list(SORT SRC_SSH) + target_sources(git2internal PRIVATE ${SRC_SSH}) + + list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include") + file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"") + set(GIT_SSH 1) +endif() IF (WIN32 AND WINHTTP) SET(GIT_WINHTTP 1) @@ -139,180 +109,74 @@ LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32") ENDIF() -IF (USE_HTTPS) - # We try to find any packages our backends might use - FIND_PACKAGE(OpenSSL) - FIND_PACKAGE(mbedTLS) - IF (CMAKE_SYSTEM_NAME MATCHES "Darwin") - FIND_PACKAGE(Security) - FIND_PACKAGE(CoreFoundation) - ENDIF() - - # Auto-select TLS backend - IF (USE_HTTPS STREQUAL ON) - IF (SECURITY_FOUND) - IF (SECURITY_HAS_SSLCREATECONTEXT) - SET(HTTPS_BACKEND "SecureTransport") - ELSE() - MESSAGE("-- Security framework is too old, falling back to OpenSSL") - SET(HTTPS_BACKEND "OpenSSL") - ENDIF() - ELSEIF (WINHTTP) - SET(HTTPS_BACKEND "WinHTTP") - ELSEIF(OPENSSL_FOUND) - SET(HTTPS_BACKEND "OpenSSL") - ELSEIF(MBEDTLS_FOUND) - SET(HTTPS_BACKEND "mbedTLS") - ELSE() - MESSAGE(FATAL_ERROR "Unable to autodetect a usable HTTPS backend." - "Please pass the backend name explicitly (-DUSE_HTTPS=backend)") - ENDIF() +include(SelectHTTPSBackend) +include(SelectHashes) +target_sources(git2internal PRIVATE ${SRC_SHA1}) + +# Specify regular expression implementation +FIND_PACKAGE(PCRE) + +IF(REGEX_BACKEND STREQUAL "") + CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L) + + IF(HAVE_REGCOMP_L) + SET(REGEX_BACKEND "regcomp_l") + ELSEIF(PCRE_FOUND) + SET(REGEX_BACKEND "pcre") ELSE() - # Backend was explicitly set - SET(HTTPS_BACKEND ${USE_HTTPS}) - ENDIF() - - # Check that we can find what's required for the selected backend - IF (HTTPS_BACKEND STREQUAL "SecureTransport") - IF (NOT COREFOUNDATION_FOUND) - MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, CoreFoundation.framework not found") - ENDIF() - IF (NOT SECURITY_FOUND) - MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, Security.framework not found") - ENDIF() - IF (NOT SECURITY_HAS_SSLCREATECONTEXT) - MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, SSLCreateContext not supported") - ENDIF() - - SET(GIT_SECURE_TRANSPORT 1) - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${SECURITY_INCLUDE_DIR}) - LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LIBRARIES} ${SECURITY_LIBRARIES}) - LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS}) - ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL") - IF (NOT OPENSSL_FOUND) - MESSAGE(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found") - ENDIF() - - SET(GIT_OPENSSL 1) - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${OPENSSL_INCLUDE_DIR}) - LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES}) - LIST(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS}) - LIST(APPEND LIBGIT2_PC_REQUIRES "openssl") - ELSEIF(HTTPS_BACKEND STREQUAL "mbedTLS") - IF (NOT MBEDTLS_FOUND) - MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found") - ENDIF() - - IF(NOT CERT_LOCATION) - MESSAGE("Auto-detecting default certificates location") - IF(CMAKE_SYSTEM_NAME MATCHES Darwin) - # Check for an Homebrew installation - SET(OPENSSL_CMD "/usr/local/opt/openssl/bin/openssl") - ELSE() - SET(OPENSSL_CMD "openssl") - ENDIF() - EXECUTE_PROCESS(COMMAND ${OPENSSL_CMD} version -d OUTPUT_VARIABLE OPENSSL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) - IF(OPENSSL_DIR) - STRING(REGEX REPLACE "^OPENSSLDIR: \"(.*)\"$" "\\1/" OPENSSL_DIR ${OPENSSL_DIR}) - - SET(OPENSSL_CA_LOCATIONS - "ca-bundle.pem" # OpenSUSE Leap 42.1 - "cert.pem" # Ubuntu 14.04, FreeBSD - "certs/ca-certificates.crt" # Ubuntu 16.04 - "certs/ca.pem" # Debian 7 - ) - FOREACH(SUFFIX IN LISTS OPENSSL_CA_LOCATIONS) - SET(LOC "${OPENSSL_DIR}${SUFFIX}") - IF(NOT CERT_LOCATION AND EXISTS "${OPENSSL_DIR}${SUFFIX}") - SET(CERT_LOCATION ${LOC}) - ENDIF() - ENDFOREACH() - ELSE() - MESSAGE("Unable to find OpenSSL executable. Please provide default certificate location via CERT_LOCATION") - ENDIF() - ENDIF() - - IF(CERT_LOCATION) - IF(NOT EXISTS ${CERT_LOCATION}) - MESSAGE(FATAL_ERROR "Cannot use CERT_LOCATION=${CERT_LOCATION} as it doesn't exist") - ENDIF() - ADD_FEATURE_INFO(CERT_LOCATION ON "using certificates from ${CERT_LOCATION}") - ADD_DEFINITIONS(-DGIT_DEFAULT_CERT_LOCATION="${CERT_LOCATION}") - ENDIF() - - SET(GIT_MBEDTLS 1) - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR}) - LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES}) - # mbedTLS has no pkgconfig file, hence we can't require it - # https://github.com/ARMmbed/mbedtls/issues/228 - # For now, pass its link flags as our own - LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES}) - ELSEIF (HTTPS_BACKEND STREQUAL "WinHTTP") - # WinHTTP setup was handled in the WinHTTP-specific block above - ELSE() - MESSAGE(FATAL_ERROR "Asked for backend ${HTTPS_BACKEND} but it wasn't found") + SET(REGEX_BACKEND "builtin") ENDIF() +ENDIF() - ADD_FEATURE_INFO(HTTPS ON "using ${HTTPS_BACKEND}") - SET(GIT_HTTPS 1) +IF(REGEX_BACKEND STREQUAL "regcomp_l") + ADD_FEATURE_INFO(regex ON "using system regcomp_l") + SET(GIT_REGEX_REGCOMP_L 1) +ELSEIF(REGEX_BACKEND STREQUAL "pcre2") + FIND_PACKAGE(PCRE2) + + IF(NOT PCRE2_FOUND) + MESSAGE(FATAL_ERROR "PCRE2 support was requested but not found") + ENDIF() + + ADD_FEATURE_INFO(regex ON "using system PCRE2") + SET(GIT_REGEX_PCRE2 1) + + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE2_INCLUDE_DIRS}) + LIST(APPEND LIBGIT2_LIBS ${PCRE2_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre2-8") +ELSEIF(REGEX_BACKEND STREQUAL "pcre") + ADD_FEATURE_INFO(regex ON "using system PCRE") + SET(GIT_REGEX_PCRE 1) + + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE_INCLUDE_DIRS}) + LIST(APPEND LIBGIT2_LIBS ${PCRE_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_REQUIRES "libpcre") +ELSEIF(REGEX_BACKEND STREQUAL "regcomp") + ADD_FEATURE_INFO(regex ON "using system regcomp") + SET(GIT_REGEX_REGCOMP 1) +ELSEIF(REGEX_BACKEND STREQUAL "builtin") + ADD_FEATURE_INFO(regex ON "using bundled PCRE") + SET(GIT_REGEX_BUILTIN 1) + + ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/pcre" "${libgit2_BINARY_DIR}/deps/pcre") + LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/pcre") + LIST(APPEND LIBGIT2_OBJECTS $) ELSE() - ADD_FEATURE_INFO(HTTPS OFF "no support") + MESSAGE(FATAL_ERROR "The REGEX_BACKEND option provided is not supported") ENDIF() -# Specify sha1 implementation -IF(SHA1_BACKEND STREQUAL "OpenSSL") - IF(NOT OPENSSL_FOUND) - FIND_PACKAGE(OpenSSL) - IF(NOT OPENSSL_FOUND) - MESSAGE(FATAL_ERROR "Requested OpenSSL SHA1 backend, but OpenSSL could not be found") - ENDIF() - ENDIF() +# Optional external dependency: http-parser +IF(USE_HTTP_PARSER STREQUAL "system") + FIND_PACKAGE(HTTP_Parser) - ADD_FEATURE_INFO(SHA ON "using OpenSSL") - SET(GIT_SHA1_OPENSSL 1) - IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - LIST(APPEND LIBGIT2_PC_LIBS "-lssl") + IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS}) + LIST(APPEND LIBGIT2_LIBS ${HTTP_PARSER_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") + ADD_FEATURE_INFO(http-parser ON "http-parser support (system)") ELSE() - LIST(APPEND LIBGIT2_PC_REQUIRES "openssl") + MESSAGE(FATAL_ERROR "http-parser support was requested but not found") ENDIF() -ELSEIF(SHA1_BACKEND STREQUAL "CollisionDetection") - ADD_FEATURE_INFO(SHA ON "using CollisionDetection") - SET(GIT_SHA1_COLLISIONDETECT 1) - ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1) - ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\") - ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\") - FILE(GLOB SRC_SHA1 hash/hash_collisiondetect.c hash/sha1dc/*) -ELSEIF(SHA1_BACKEND STREQUAL "Generic") - ADD_FEATURE_INFO(SHA ON "using Generic") - FILE(GLOB SRC_SHA1 hash/hash_generic.c) -ELSEIF(SHA1_BACKEND STREQUAL "Win32") - ADD_FEATURE_INFO(SHA ON "using Win32") - SET(GIT_SHA1_WIN32 1) - FILE(GLOB SRC_SHA1 hash/hash_win32.c) -ELSEIF(SHA1_BACKEND STREQUAL "CommonCrypto") - ADD_FEATURE_INFO(SHA ON "using CommonCrypto") - SET(GIT_SHA1_COMMON_CRYPTO 1) -ELSEIF (SHA1_BACKEND STREQUAL "mbedTLS") - ADD_FEATURE_INFO(SHA ON "using mbedTLS") - SET(GIT_SHA1_MBEDTLS 1) - FILE(GLOB SRC_SHA1 hash/hash_mbedtls.c) - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${MBEDTLS_INCLUDE_DIR}) - LIST(APPEND LIBGIT2_LIBS ${MBEDTLS_LIBRARIES}) - # mbedTLS has no pkgconfig file, hence we can't require it - # https://github.com/ARMmbed/mbedtls/issues/228 - # For now, pass its link flags as our own - LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES}) -ELSE() - MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend ${SHA1_BACKEND}") -ENDIF() - -# Optional external dependency: http-parser -FIND_PACKAGE(HTTP_Parser) -IF (USE_EXT_HTTP_PARSER AND HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) - LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS}) - LIST(APPEND LIBGIT2_LIBS ${HTTP_PARSER_LIBRARIES}) - LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") - ADD_FEATURE_INFO(http-parser ON "http-parser support") ELSE() MESSAGE(STATUS "http-parser version 2 was not found or disabled; using bundled 3rd-party sources.") ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/http-parser" "${libgit2_BINARY_DIR}/deps/http-parser") @@ -328,7 +192,6 @@ LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${ZLIB_INCLUDE_DIRS}) LIST(APPEND LIBGIT2_LIBS ${ZLIB_LIBRARIES}) IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - LIST(APPEND LIBGIT2_LIBS "z") LIST(APPEND LIBGIT2_PC_LIBS "-lz") ELSE() LIST(APPEND LIBGIT2_PC_REQUIRES "zlib") @@ -364,15 +227,18 @@ ENDIF() ADD_FEATURE_INFO(SSH GIT_SSH "SSH transport support") -# Optional external dependency: libgssapi -IF (USE_GSSAPI) - FIND_PACKAGE(GSSAPI) -ENDIF() -IF (GSSAPI_FOUND) - SET(GIT_GSSAPI 1) - LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES}) +# Optional external dependency: ntlmclient +IF (USE_NTLMCLIENT) + SET(GIT_NTLM 1) + ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/ntlmclient" "${libgit2_BINARY_DIR}/deps/ntlmclient") + LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/ntlmclient") + LIST(APPEND LIBGIT2_OBJECTS "$") ENDIF() -ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support") +ADD_FEATURE_INFO(ntlmclient GIT_NTLM "NTLM authentication support for Unix") + +# Optional external dependency: GSSAPI + +INCLUDE(SelectGSSAPI) # Optional external dependency: iconv IF (USE_ICONV) @@ -407,35 +273,54 @@ SET(GIT_USE_STAT_MTIME_NSEC 1) ENDIF() -ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64) +target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64) # Collect sourcefiles -FILE(GLOB SRC_H +file(GLOB SRC_H "${libgit2_SOURCE_DIR}/include/git2.h" "${libgit2_SOURCE_DIR}/include/git2/*.h" "${libgit2_SOURCE_DIR}/include/git2/sys/*.h") +list(SORT SRC_H) +target_sources(git2internal PRIVATE ${SRC_H}) # On Windows use specific platform sources -IF (WIN32 AND NOT CYGWIN) - ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0600) +if(WIN32 AND NOT CYGWIN) + SET(WIN_RC "win32/git2.rc") - IF(MSVC) - SET(WIN_RC "win32/git2.rc") - ENDIF() + file(GLOB SRC_OS win32/*.c win32/*.h) + list(SORT SRC_OS) + target_sources(git2internal PRIVATE ${SRC_OS}) +elseif(AMIGA) + target_compile_definitions(git2internal PRIVATE NO_ADDRINFO NO_READDIR_R NO_MMAP) +else() + file(GLOB SRC_OS unix/*.c unix/*.h) + list(SORT SRC_OS) + target_sources(git2internal PRIVATE ${SRC_OS}) +endif() - FILE(GLOB SRC_OS win32/*.c win32/*.h) -ELSEIF (AMIGA) - ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP) -ELSE() - IF (VALGRIND) - ADD_DEFINITIONS(-DNO_MMAP) - ENDIF() - FILE(GLOB SRC_OS unix/*.c unix/*.h) +IF (USE_LEAK_CHECKER STREQUAL "valgrind") + target_compile_definitions(git2internal PRIVATE VALGRIND) ENDIF() -FILE(GLOB SRC_GIT2 *.c *.h + +file(GLOB SRC_GIT2 *.c *.h + allocators/*.c allocators/*.h streams/*.c streams/*.h transports/*.c transports/*.h xdiff/*.c xdiff/*.h) +list(SORT SRC_GIT2) +target_sources(git2internal PRIVATE ${SRC_GIT2}) + +IF(APPLE) + # The old Secure Transport API has been deprecated in macOS 10.15. + SET_SOURCE_FILES_PROPERTIES(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated) +ENDIF() + +# the xdiff dependency is not (yet) warning-free, disable warnings as +# errors for the xdiff sources until we've sorted them out +IF(MSVC) + SET_SOURCE_FILES_PROPERTIES(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-) + SET_SOURCE_FILES_PROPERTIES(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-) +ENDIF() # Determine architecture of the machine IF (CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -450,23 +335,11 @@ CONFIGURE_FILE(features.h.in git2/sys/features.h) -SET(LIBGIT2_SOURCES ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_SSH} ${SRC_SHA1}) - -ADD_LIBRARY(git2internal OBJECT ${LIBGIT2_SOURCES}) -SET_TARGET_PROPERTIES(git2internal PROPERTIES C_STANDARD 90) IDE_SPLIT_SOURCES(git2internal) LIST(APPEND LIBGIT2_OBJECTS $) -IF (${CMAKE_VERSION} VERSION_LESS 2.8.12) - INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES}) - INCLUDE_DIRECTORIES(SYSTEM ${LIBGIT2_SYSTEM_INCLUDES}) -ELSE() - TARGET_INCLUDE_DIRECTORIES(git2internal - PRIVATE ${LIBGIT2_INCLUDES} - PUBLIC ${libgit2_SOURCE_DIR}/include) - TARGET_INCLUDE_DIRECTORIES(git2internal - SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES}) -ENDIF() +TARGET_INCLUDE_DIRECTORIES(git2internal PRIVATE ${LIBGIT2_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include) +TARGET_INCLUDE_DIRECTORIES(git2internal SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES}) SET(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE) SET(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE) @@ -497,21 +370,24 @@ IDE_SPLIT_SOURCES(git2) -IF (SONAME) - SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING}) - SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION}) - IF (LIBGIT2_FILENAME) - ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\") - SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME}) - ELSEIF (DEFINED LIBGIT2_PREFIX) - SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}") - ENDIF() -ENDIF() - -LIST(REMOVE_DUPLICATES LIBGIT2_PC_REQUIRES) -STRING(REPLACE ";" " " LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES}") -STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}") -CONFIGURE_FILE(${libgit2_SOURCE_DIR}/libgit2.pc.in ${libgit2_BINARY_DIR}/libgit2.pc @ONLY) +if(SONAME) + set_target_properties(git2 PROPERTIES VERSION ${libgit2_VERSION}) + set_target_properties(git2 PROPERTIES SOVERSION "${libgit2_VERSION_MAJOR}.${libgit2_VERSION_MINOR}") + if(LIBGIT2_FILENAME) + target_compile_definitions(git2internal PRIVATE LIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\") + set_target_properties(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME}) + elseif(DEFINED LIBGIT2_PREFIX) + set_target_properties(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}") + endif() +endif() + +PKG_BUILD_CONFIG(NAME libgit2 + VERSION ${libgit2_VERSION} + DESCRIPTION "The git library, take 2" + LIBS_SELF git2 + PRIVATE_LIBS ${LIBGIT2_PC_LIBS} + REQUIRES ${LIBGIT2_PC_REQUIRES} +) IF (MSVC_IDE) # Precompiled headers @@ -521,10 +397,9 @@ # Install INSTALL(TARGETS git2 - RUNTIME DESTINATION ${BIN_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) -INSTALL(FILES ${libgit2_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) -INSTALL(DIRECTORY ${libgit2_SOURCE_DIR}/include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} ) -INSTALL(FILES ${libgit2_SOURCE_DIR}/include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) +INSTALL(DIRECTORY ${libgit2_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +INSTALL(FILES ${libgit2_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff -Nru libgit2-0.28.5+dfsg.1/src/commit.c libgit2-1.1.0+dfsg.1/src/commit.c --- libgit2-0.28.5+dfsg.1/src/commit.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/commit.c 2020-10-12 18:53:06.000000000 +0000 @@ -20,6 +20,7 @@ #include "message.h" #include "refs.h" #include "object.h" +#include "array.h" #include "oidarray.h" void git_commit__free(void *_commit) @@ -80,8 +81,8 @@ } static int validate_tree_and_parents(git_array_oid_t *parents, git_repository *repo, const git_oid *tree, - git_commit_parent_callback parent_cb, void *parent_payload, - const git_oid *current_id, bool validate) + git_commit_parent_callback parent_cb, void *parent_payload, + const git_oid *current_id, bool validate) { size_t i; int error; @@ -152,8 +153,8 @@ goto cleanup; error = git_commit__create_buffer_internal(&buf, author, committer, - message_encoding, message, tree, - &parents); + message_encoding, message, tree, + &parents); if (error < 0) goto cleanup; @@ -383,15 +384,16 @@ return error; } -int git_commit__parse_raw(void *_commit, const char *data, size_t size) +static int commit_parse(git_commit *commit, const char *data, size_t size, unsigned int flags) { - git_commit *commit = _commit; const char *buffer_start = data, *buffer; const char *buffer_end = buffer_start + size; git_oid parent_id; size_t header_len; git_signature dummy_sig; + assert(commit && data); + buffer = buffer_start; /* Allocate for one, which will allow not to realloc 90% of the time */ @@ -399,8 +401,15 @@ GIT_ERROR_CHECK_ARRAY(commit->parent_ids); /* The tree is always the first field */ - if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) - goto bad_buffer; + if (!(flags & GIT_COMMIT_PARSE_QUICK)) { + if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) + goto bad_buffer; + } else { + size_t tree_len = strlen("tree ") + GIT_OID_HEXSZ + 1; + if (buffer + tree_len > buffer_end) + goto bad_buffer; + buffer += tree_len; + } /* * TODO: commit grafts! @@ -413,11 +422,13 @@ git_oid_cpy(new_id, &parent_id); } - commit->author = git__malloc(sizeof(git_signature)); - GIT_ERROR_CHECK_ALLOC(commit->author); + if (!(flags & GIT_COMMIT_PARSE_QUICK)) { + commit->author = git__malloc(sizeof(git_signature)); + GIT_ERROR_CHECK_ALLOC(commit->author); - if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) - return -1; + if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) + return -1; + } /* Some tools create multiple author fields, ignore the extra ones */ while (!git__prefixncmp(buffer, buffer_end - buffer, "author ")) { @@ -435,6 +446,9 @@ if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0) return -1; + if (flags & GIT_COMMIT_PARSE_QUICK) + return 0; + /* Parse add'l header entries */ while (buffer < buffer_end) { const char *eoln = buffer; @@ -477,11 +491,19 @@ return -1; } +int git_commit__parse_raw(void *commit, const char *data, size_t size) +{ + return commit_parse(commit, data, size, 0); +} + +int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags) +{ + return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags); +} + int git_commit__parse(void *_commit, git_odb_object *odb_obj) { - return git_commit__parse_raw(_commit, - git_odb_object_data(odb_obj), - git_odb_object_size(odb_obj)); + return git_commit__parse_ext(_commit, odb_obj, 0); } #define GIT_COMMIT_GETTER(_rvalue, _name, _return) \ @@ -582,7 +604,7 @@ break; if (*msg) - commit->body = git__strndup(msg, end - msg + 1); + commit->body = git__strndup(msg, end - msg + 1); } return commit->body; @@ -731,7 +753,7 @@ return error; if (obj->cached.type != GIT_OBJECT_COMMIT) { - git_error_set(GIT_ERROR_INVALID, "the requested type does not match the type in ODB"); + git_error_set(GIT_ERROR_INVALID, "the requested type does not match the type in the ODB"); error = GIT_ENOTFOUND; goto cleanup; } @@ -856,6 +878,14 @@ git_buf_putc(out, '\n'); } +static const git_oid *commit_parent_from_commit(size_t n, void *payload) +{ + const git_commit *commit = (const git_commit *) payload; + + return git_array_get(commit->parent_ids, n); + +} + int git_commit_create_with_signature( git_oid *out, git_repository *repo, @@ -868,20 +898,37 @@ const char *field; const char *header_end; git_buf commit = GIT_BUF_INIT; + git_commit *parsed; + git_array_oid_t parents = GIT_ARRAY_INIT; + + /* The first step is to verify that all the tree and parents exist */ + parsed = git__calloc(1, sizeof(git_commit)); + GIT_ERROR_CHECK_ALLOC(parsed); + if ((error = commit_parse(parsed, commit_content, strlen(commit_content), 0)) < 0) + goto cleanup; + + if ((error = validate_tree_and_parents(&parents, repo, &parsed->tree_id, commit_parent_from_commit, parsed, NULL, true)) < 0) + goto cleanup; - /* We start by identifying the end of the commit header */ + git_array_clear(parents); + + /* Then we start appending by identifying the end of the commit header */ header_end = strstr(commit_content, "\n\n"); if (!header_end) { git_error_set(GIT_ERROR_INVALID, "malformed commit contents"); - return -1; + error = -1; + goto cleanup; } - field = signature_field ? signature_field : "gpgsig"; - /* The header ends after the first LF */ header_end++; git_buf_put(&commit, commit_content, header_end - commit_content); - format_header_field(&commit, field, signature); + + if (signature != NULL) { + field = signature_field ? signature_field : "gpgsig"; + format_header_field(&commit, field, signature); + } + git_buf_puts(&commit, header_end); if (git_buf_oom(&commit)) @@ -894,6 +941,7 @@ goto cleanup; cleanup: + git_commit__free(parsed); git_buf_dispose(&commit); return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/commit.h libgit2-1.1.0+dfsg.1/src/commit.h --- libgit2-0.28.5+dfsg.1/src/commit.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/commit.h 2020-10-12 18:53:06.000000000 +0000 @@ -37,4 +37,10 @@ int git_commit__parse(void *commit, git_odb_object *obj); int git_commit__parse_raw(void *commit, const char *data, size_t size); +typedef enum { + GIT_COMMIT_PARSE_QUICK = (1 << 0), /**< Only parse parents and committer info */ +} git_commit__parse_flags; + +int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags); + #endif diff -Nru libgit2-0.28.5+dfsg.1/src/commit_list.c libgit2-1.1.0+dfsg.1/src/commit_list.c --- libgit2-0.28.5+dfsg.1/src/commit_list.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/commit_list.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,6 +10,7 @@ #include "revwalk.h" #include "pool.h" #include "odb.h" +#include "commit.h" int git_commit_list_time_cmp(const void *a, const void *b) { @@ -55,17 +56,6 @@ return (git_commit_list_node *)git_pool_mallocz(&walk->commit_pool, 1); } -static int commit_error(git_commit_list_node *commit, const char *msg) -{ - char commit_oid[GIT_OID_HEXSZ + 1]; - git_oid_fmt(commit_oid, &commit->oid); - commit_oid[GIT_OID_HEXSZ] = '\0'; - - git_error_set(GIT_ERROR_ODB, "failed to parse commit %s - %s", commit_oid, msg); - - return -1; -} - static git_commit_list_node **alloc_parents( git_revwalk *walk, git_commit_list_node *commit, size_t n_parents) { @@ -111,77 +101,42 @@ static int commit_quick_parse( git_revwalk *walk, - git_commit_list_node *commit, - const uint8_t *buffer, - size_t buffer_len) + git_commit_list_node *node, + git_odb_object *obj) { - const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1; - const uint8_t *buffer_end = buffer + buffer_len; - const uint8_t *parents_start, *committer_start; - int i, parents = 0; - int64_t commit_time; + git_oid *parent_oid; + git_commit *commit; + int error; + size_t i; - buffer += strlen("tree ") + GIT_OID_HEXSZ + 1; + commit = git__calloc(1, sizeof(*commit)); + GIT_ERROR_CHECK_ALLOC(commit); + commit->object.repo = walk->repo; - parents_start = buffer; - while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) { - parents++; - buffer += parent_len; + if ((error = git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK)) < 0) { + git__free(commit); + return error; } - commit->parents = alloc_parents(walk, commit, parents); - GIT_ERROR_CHECK_ALLOC(commit->parents); - - buffer = parents_start; - for (i = 0; i < parents; ++i) { - git_oid oid; - - if (git_oid_fromstr(&oid, (const char *)buffer + strlen("parent ")) < 0) - return -1; - - commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); - if (commit->parents[i] == NULL) - return -1; - - buffer += parent_len; + if (!git__is_uint16(git_array_size(commit->parent_ids))) { + git__free(commit); + git_error_set(GIT_ERROR_INVALID, "commit has more than 2^16 parents"); + return -1; } - commit->out_degree = (unsigned short)parents; - - if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) - return commit_error(commit, "object is corrupted"); - - buffer++; - - if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) - return commit_error(commit, "object is corrupted"); + node->time = commit->committer->when.time; + node->out_degree = (uint16_t) git_array_size(commit->parent_ids); + node->parents = alloc_parents(walk, node, node->out_degree); + GIT_ERROR_CHECK_ALLOC(node->parents); - /* Skip trailing spaces */ - while (buffer > committer_start && git__isspace(*buffer)) - buffer--; - - /* Seek for the beginning of the pack of digits */ - while (buffer > committer_start && git__isdigit(*buffer)) - buffer--; - - /* Skip potential timezone offset */ - if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) { - buffer--; - - while (buffer > committer_start && git__isspace(*buffer)) - buffer--; - - while (buffer > committer_start && git__isdigit(*buffer)) - buffer--; + git_array_foreach(commit->parent_ids, i, parent_oid) { + node->parents[i] = git_revwalk__commit_lookup(walk, parent_oid); } - if ((buffer == committer_start) || - (git__strntol64(&commit_time, (char *)(buffer + 1), - buffer_end - buffer + 1, NULL, 10) < 0)) - return commit_error(commit, "cannot parse commit time"); + git_commit__free(commit); + + node->parsed = 1; - commit->time = commit_time; - commit->parsed = 1; return 0; } @@ -200,10 +155,7 @@ git_error_set(GIT_ERROR_INVALID, "object is no commit object"); error = -1; } else - error = commit_quick_parse( - walk, commit, - (const uint8_t *)git_odb_object_data(obj), - git_odb_object_size(obj)); + error = commit_quick_parse(walk, commit, obj); git_odb_object_free(obj); return error; diff -Nru libgit2-0.28.5+dfsg.1/src/commit_list.h libgit2-1.1.0+dfsg.1/src/commit_list.h --- libgit2-0.28.5+dfsg.1/src/commit_list.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/commit_list.h 2020-10-12 18:53:06.000000000 +0000 @@ -33,8 +33,8 @@ added:1, flags : FLAG_BITS; - unsigned short in_degree; - unsigned short out_degree; + uint16_t in_degree; + uint16_t out_degree; struct git_commit_list_node **parents; } git_commit_list_node; diff -Nru libgit2-0.28.5+dfsg.1/src/common.h libgit2-1.1.0+dfsg.1/src/common.h --- libgit2-0.28.5+dfsg.1/src/common.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/common.h 2020-10-12 18:53:06.000000000 +0000 @@ -47,6 +47,7 @@ # include # include "win32/msvc-compat.h" # include "win32/mingw-compat.h" +# include "win32/w32_common.h" # include "win32/win32-compat.h" # include "win32/error.h" # include "win32/version.h" @@ -76,8 +77,10 @@ #include "git2/types.h" #include "git2/errors.h" +#include "errors.h" #include "thread-utils.h" #include "integer.h" +#include "assert_safe.h" /* * Include the declarations for deprecated functions; this ensures @@ -85,7 +88,7 @@ */ #include "git2/deprecated.h" -#include +#include "posix.h" #define DEFAULT_BUFSIZE 65536 #define FILEIO_BUFSIZE DEFAULT_BUFSIZE @@ -109,80 +112,6 @@ do { int _err = (code); if (_err) return _err; } while (0) /** - * Set the error message for this thread, formatting as needed. - */ - -void git_error_set(int error_class, const char *string, ...) GIT_FORMAT_PRINTF(2, 3); - -/** - * Set the error message for a regex failure, using the internal regex - * error code lookup and return a libgit error code. - */ -int git_error_set_regex(const regex_t *regex, int error_code); - -/** - * Set error message for user callback if needed. - * - * If the error code in non-zero and no error message is set, this - * sets a generic error message. - * - * @return This always returns the `error_code` parameter. - */ -GIT_INLINE(int) git_error_set_after_callback_function( - int error_code, const char *action) -{ - if (error_code) { - const git_error *e = git_error_last(); - if (!e || !e->message) - git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, - "%s callback returned %d", action, error_code); - } - return error_code; -} - -#ifdef GIT_WIN32 -#define git_error_set_after_callback(code) \ - git_error_set_after_callback_function((code), __FUNCTION__) -#else -#define git_error_set_after_callback(code) \ - git_error_set_after_callback_function((code), __func__) -#endif - -/** - * Gets the system error code for this thread. - */ -int git_error_system_last(void); - -/** - * Sets the system error code for this thread. - */ -void git_error_system_set(int code); - -/** - * Structure to preserve libgit2 error state - */ -typedef struct { - int error_code; - unsigned int oom : 1; - git_error error_msg; -} git_error_state; - -/** - * Capture current error state to restore later, returning error code. - * If `error_code` is zero, this does not clear the current error state. - * You must either restore this error state, or free it. - */ -extern int git_error_state_capture(git_error_state *state, int error_code); - -/** - * Restore error state to a previous value, returning saved error code. - */ -extern int git_error_state_restore(git_error_state *state); - -/** Free an error state. */ -extern void git_error_state_free(git_error_state *state); - -/** * Check a versioned structure for validity */ GIT_INLINE(int) git_error__check_version(const void *structure, unsigned int expected_max, const char *name) diff -Nru libgit2-0.28.5+dfsg.1/src/config_backend.h libgit2-1.1.0+dfsg.1/src/config_backend.h --- libgit2-0.28.5+dfsg.1/src/config_backend.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_backend.h 2020-10-12 18:53:06.000000000 +0000 @@ -26,6 +26,18 @@ extern int git_config_backend_from_file(git_config_backend **out, const char *path); /** + * Create a readonly configuration file backend from another backend + * + * This copies the complete contents of the source backend to the + * new backend. The new backend will be completely read-only and + * cannot be modified. + * + * @param out the new snapshotted backend + * @param source the backend to copy + */ +extern int git_config_backend_snapshot(git_config_backend **out, git_config_backend *source); + +/** * Create an in-memory configuration file backend * * @param out the new backend diff -Nru libgit2-0.28.5+dfsg.1/src/config.c libgit2-1.1.0+dfsg.1/src/config.c --- libgit2-0.28.5+dfsg.1/src/config.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,13 +7,15 @@ #include "config.h" -#include "sysdir.h" #include "git2/config.h" #include "git2/sys/config.h" -#include "vector.h" + #include "buf_text.h" #include "config_backend.h" +#include "regexp.h" +#include "sysdir.h" #include "transaction.h" +#include "vector.h" #if GIT_WIN32 # include #endif @@ -345,7 +347,7 @@ git_config_iterator parent; git_config_iterator *current; const git_config *cfg; - regex_t regex; + git_regexp regex; size_t i; } all_iter; @@ -423,7 +425,7 @@ */ while ((error = all_iter_next(entry, _iter)) == 0) { /* skip non-matching keys if regexp was provided */ - if (regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0) + if (git_regexp_match(&iter->regex, (*entry)->name) != 0) continue; /* and simply return if we like the entry's name */ @@ -447,7 +449,7 @@ { all_iter *iter = (all_iter *) _iter; - regfree(&iter->regex); + git_regexp_dispose(&iter->regex); all_iter_free(_iter); } @@ -480,8 +482,7 @@ iter = git__calloc(1, sizeof(all_iter)); GIT_ERROR_CHECK_ALLOC(iter); - if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) { - git_error_set_regex(&iter->regex, result); + if ((result = git_regexp_compile(&iter->regex, regexp, 0)) < 0) { git__free(iter); return -1; } @@ -510,18 +511,13 @@ { git_config_entry *entry; git_config_iterator* iter; - regex_t regex; + git_regexp regex; int error = 0; assert(backend && cb); - if (regexp != NULL) { - if ((error = p_regcomp(®ex, regexp, REG_EXTENDED)) != 0) { - git_error_set_regex(®ex, error); - regfree(®ex); - return -1; - } - } + if (regexp && git_regexp_compile(®ex, regexp, 0) < 0) + return -1; if ((error = backend->iterator(&iter, backend)) < 0) { iter = NULL; @@ -530,7 +526,7 @@ while (!(iter->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ - if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0) + if (regexp && git_regexp_match(®ex, entry->name) != 0) continue; /* abort iterator on non-zero return value */ @@ -541,7 +537,7 @@ } if (regexp != NULL) - regfree(®ex); + git_regexp_dispose(®ex); iter->free(iter); @@ -661,7 +657,7 @@ error = backend->set(backend, name, value); if (!error && GIT_REFCOUNT_OWNER(cfg) != NULL) - git_repository__cvar_cache_clear(GIT_REFCOUNT_OWNER(cfg)); + git_repository__configmap_lookup_cache_clear(GIT_REFCOUNT_OWNER(cfg)); return error; } @@ -777,7 +773,7 @@ int *out, const git_config *cfg, const char *name, - const git_cvar_map *maps, + const git_configmap *maps, size_t map_n) { git_config_entry *entry; @@ -981,7 +977,7 @@ git_config_iterator parent; git_config_iterator *iter; char *name; - regex_t regex; + git_regexp regex; int have_regex; } multivar_iter; @@ -997,14 +993,14 @@ if (!iter->have_regex) return 0; - if (regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0) + if (git_regexp_match(&iter->regex, (*entry)->value) == 0) return 0; } return error; } -void multivar_iter_free(git_config_iterator *_iter) +static void multivar_iter_free(git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; @@ -1012,7 +1008,7 @@ git__free(iter->name); if (iter->have_regex) - regfree(&iter->regex); + git_regexp_dispose(&iter->regex); git__free(iter); } @@ -1032,13 +1028,8 @@ goto on_error; if (regexp != NULL) { - error = p_regcomp(&iter->regex, regexp, REG_EXTENDED); - if (error != 0) { - git_error_set_regex(&iter->regex, error); - error = -1; - regfree(&iter->regex); + if ((error = git_regexp_compile(&iter->regex, regexp, 0)) < 0) goto on_error; - } iter->have_regex = 1; } @@ -1230,38 +1221,35 @@ int git_config_lookup_map_value( int *out, - const git_cvar_map *maps, + const git_configmap *maps, size_t map_n, const char *value) { size_t i; - if (!value) - goto fail_parse; - for (i = 0; i < map_n; ++i) { - const git_cvar_map *m = maps + i; + const git_configmap *m = maps + i; - switch (m->cvar_type) { - case GIT_CVAR_FALSE: - case GIT_CVAR_TRUE: { + switch (m->type) { + case GIT_CONFIGMAP_FALSE: + case GIT_CONFIGMAP_TRUE: { int bool_val; - if (git__parse_bool(&bool_val, value) == 0 && - bool_val == (int)m->cvar_type) { + if (git_config_parse_bool(&bool_val, value) == 0 && + bool_val == (int)m->type) { *out = m->map_value; return 0; } break; } - case GIT_CVAR_INT32: + case GIT_CONFIGMAP_INT32: if (git_config_parse_int32(out, value) == 0) return 0; break; - case GIT_CVAR_STRING: - if (strcasecmp(value, m->str_match) == 0) { + case GIT_CONFIGMAP_STRING: + if (value && strcasecmp(value, m->str_match) == 0) { *out = m->map_value; return 0; } @@ -1269,23 +1257,22 @@ } } -fail_parse: git_error_set(GIT_ERROR_CONFIG, "failed to map '%s'", value); return -1; } -int git_config_lookup_map_enum(git_cvar_t *type_out, const char **str_out, - const git_cvar_map *maps, size_t map_n, int enum_val) +int git_config_lookup_map_enum(git_configmap_t *type_out, const char **str_out, + const git_configmap *maps, size_t map_n, int enum_val) { size_t i; for (i = 0; i < map_n; i++) { - const git_cvar_map *m = &maps[i]; + const git_configmap *m = &maps[i]; if (m->map_value != enum_val) continue; - *type_out = m->cvar_type; + *type_out = m->type; *str_out = m->str_match; return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/config_cache.c libgit2-1.1.0+dfsg.1/src/config_cache.c --- libgit2-0.28.5+dfsg.1/src/config_cache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_cache.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,7 +7,7 @@ #include "common.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" #include "config.h" #include "git2/config.h" @@ -15,8 +15,8 @@ #include "filter.h" struct map_data { - const char *cvar_name; - git_cvar_map *maps; + const char *name; + git_configmap *maps; size_t map_count; int default_value; }; @@ -29,11 +29,11 @@ * value is native. See gitattributes(5) for more information on * end-of-line conversion. */ -static git_cvar_map _cvar_map_eol[] = { - {GIT_CVAR_FALSE, NULL, GIT_EOL_UNSET}, - {GIT_CVAR_STRING, "lf", GIT_EOL_LF}, - {GIT_CVAR_STRING, "crlf", GIT_EOL_CRLF}, - {GIT_CVAR_STRING, "native", GIT_EOL_NATIVE} +static git_configmap _configmap_eol[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_EOL_UNSET}, + {GIT_CONFIGMAP_STRING, "lf", GIT_EOL_LF}, + {GIT_CONFIGMAP_STRING, "crlf", GIT_EOL_CRLF}, + {GIT_CONFIGMAP_STRING, "native", GIT_EOL_NATIVE} }; /* @@ -46,55 +46,55 @@ * does not have normalized line endings. This variable can be set to input, * in which case no output conversion is performed. */ -static git_cvar_map _cvar_map_autocrlf[] = { - {GIT_CVAR_FALSE, NULL, GIT_AUTO_CRLF_FALSE}, - {GIT_CVAR_TRUE, NULL, GIT_AUTO_CRLF_TRUE}, - {GIT_CVAR_STRING, "input", GIT_AUTO_CRLF_INPUT} -}; - -static git_cvar_map _cvar_map_safecrlf[] = { - {GIT_CVAR_FALSE, NULL, GIT_SAFE_CRLF_FALSE}, - {GIT_CVAR_TRUE, NULL, GIT_SAFE_CRLF_FAIL}, - {GIT_CVAR_STRING, "warn", GIT_SAFE_CRLF_WARN} -}; - -static git_cvar_map _cvar_map_logallrefupdates[] = { - {GIT_CVAR_FALSE, NULL, GIT_LOGALLREFUPDATES_FALSE}, - {GIT_CVAR_TRUE, NULL, GIT_LOGALLREFUPDATES_TRUE}, - {GIT_CVAR_STRING, "always", GIT_LOGALLREFUPDATES_ALWAYS}, +static git_configmap _configmap_autocrlf[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_AUTO_CRLF_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_AUTO_CRLF_TRUE}, + {GIT_CONFIGMAP_STRING, "input", GIT_AUTO_CRLF_INPUT} +}; + +static git_configmap _configmap_safecrlf[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_SAFE_CRLF_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_SAFE_CRLF_FAIL}, + {GIT_CONFIGMAP_STRING, "warn", GIT_SAFE_CRLF_WARN} +}; + +static git_configmap _configmap_logallrefupdates[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_LOGALLREFUPDATES_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_LOGALLREFUPDATES_TRUE}, + {GIT_CONFIGMAP_STRING, "always", GIT_LOGALLREFUPDATES_ALWAYS}, }; /* * Generic map for integer values */ -static git_cvar_map _cvar_map_int[] = { - {GIT_CVAR_INT32, NULL, 0}, +static git_configmap _configmap_int[] = { + {GIT_CONFIGMAP_INT32, NULL, 0}, }; -static struct map_data _cvar_maps[] = { - {"core.autocrlf", _cvar_map_autocrlf, ARRAY_SIZE(_cvar_map_autocrlf), GIT_AUTO_CRLF_DEFAULT}, - {"core.eol", _cvar_map_eol, ARRAY_SIZE(_cvar_map_eol), GIT_EOL_DEFAULT}, +static struct map_data _configmaps[] = { + {"core.autocrlf", _configmap_autocrlf, ARRAY_SIZE(_configmap_autocrlf), GIT_AUTO_CRLF_DEFAULT}, + {"core.eol", _configmap_eol, ARRAY_SIZE(_configmap_eol), GIT_EOL_DEFAULT}, {"core.symlinks", NULL, 0, GIT_SYMLINKS_DEFAULT }, {"core.ignorecase", NULL, 0, GIT_IGNORECASE_DEFAULT }, {"core.filemode", NULL, 0, GIT_FILEMODE_DEFAULT }, {"core.ignorestat", NULL, 0, GIT_IGNORESTAT_DEFAULT }, {"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT }, - {"core.abbrev", _cvar_map_int, 1, GIT_ABBREV_DEFAULT }, + {"core.abbrev", _configmap_int, 1, GIT_ABBREV_DEFAULT }, {"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT }, - {"core.safecrlf", _cvar_map_safecrlf, ARRAY_SIZE(_cvar_map_safecrlf), GIT_SAFE_CRLF_DEFAULT}, - {"core.logallrefupdates", _cvar_map_logallrefupdates, ARRAY_SIZE(_cvar_map_logallrefupdates), GIT_LOGALLREFUPDATES_DEFAULT}, + {"core.safecrlf", _configmap_safecrlf, ARRAY_SIZE(_configmap_safecrlf), GIT_SAFE_CRLF_DEFAULT}, + {"core.logallrefupdates", _configmap_logallrefupdates, ARRAY_SIZE(_configmap_logallrefupdates), GIT_LOGALLREFUPDATES_DEFAULT}, {"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT }, {"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT }, {"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT }, }; -int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar) +int git_config__configmap_lookup(int *out, git_config *config, git_configmap_item item) { int error = 0; - struct map_data *data = &_cvar_maps[(int)cvar]; + struct map_data *data = &_configmaps[(int)item]; git_config_entry *entry; - if ((error = git_config__lookup_entry(&entry, config, data->cvar_name, false)) < 0) + if ((error = git_config__lookup_entry(&entry, config, data->name, false)) < 0) return error; if (!entry) @@ -109,29 +109,29 @@ return error; } -int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar) +int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item) { - *out = repo->cvar_cache[(int)cvar]; + *out = repo->configmap_cache[(int)item]; - if (*out == GIT_CVAR_NOT_CACHED) { + if (*out == GIT_CONFIGMAP_NOT_CACHED) { int error; git_config *config; if ((error = git_repository_config__weakptr(&config, repo)) < 0 || - (error = git_config__cvar(out, config, cvar)) < 0) + (error = git_config__configmap_lookup(out, config, item)) < 0) return error; - repo->cvar_cache[(int)cvar] = *out; + repo->configmap_cache[(int)item] = *out; } return 0; } -void git_repository__cvar_cache_clear(git_repository *repo) +void git_repository__configmap_lookup_cache_clear(git_repository *repo) { int i; - for (i = 0; i < GIT_CVAR_CACHE_MAX; ++i) - repo->cvar_cache[i] = GIT_CVAR_NOT_CACHED; + for (i = 0; i < GIT_CONFIGMAP_CACHE_MAX; ++i) + repo->configmap_cache[i] = GIT_CONFIGMAP_NOT_CACHED; } diff -Nru libgit2-0.28.5+dfsg.1/src/config_entries.c libgit2-1.1.0+dfsg.1/src/config_entries.c --- libgit2-0.28.5+dfsg.1/src/config_entries.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_entries.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,6 +13,11 @@ git_config_entry *entry; } config_entry_list; +typedef struct { + git_config_entry *entry; + bool multivar; +} config_entry_map_head; + typedef struct config_entries_iterator { git_config_iterator parent; git_config_entries *entries; @@ -25,31 +30,6 @@ config_entry_list *list; }; -static void config_entry_list_free(config_entry_list *list) -{ - config_entry_list *next; - - while (list != NULL) { - next = list->next; - - git__free((char*) list->entry->name); - git__free((char *) list->entry->value); - git__free(list->entry); - git__free(list); - - list = next; - }; -} - -static void config_entry_list_append(config_entry_list **list, config_entry_list *entry) -{ - if (*list) - (*list)->last->next = entry; - else - *list = entry; - (*list)->last = entry; -} - int git_config_entries_new(git_config_entries **out) { git_config_entries *entries; @@ -59,7 +39,7 @@ GIT_ERROR_CHECK_ALLOC(entries); GIT_REFCOUNT_INC(entries); - if ((error = git_strmap_alloc(&entries->map)) < 0) + if ((error = git_strmap_new(&entries->map)) < 0) git__free(entries); else *out = entries; @@ -67,6 +47,36 @@ return error; } +int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry) +{ + git_config_entry *duplicated; + int error; + + duplicated = git__calloc(1, sizeof(git_config_entry)); + GIT_ERROR_CHECK_ALLOC(duplicated); + + duplicated->name = git__strdup(entry->name); + GIT_ERROR_CHECK_ALLOC(duplicated->name); + + if (entry->value) { + duplicated->value = git__strdup(entry->value); + GIT_ERROR_CHECK_ALLOC(duplicated->value); + } + duplicated->level = entry->level; + duplicated->include_depth = entry->include_depth; + + if ((error = git_config_entries_append(entries, duplicated)) < 0) + goto out; + +out: + if (error && duplicated) { + git__free((char *) duplicated->name); + git__free((char *) duplicated->value); + git__free(duplicated); + } + return error; +} + int git_config_entries_dup(git_config_entries **out, git_config_entries *entries) { git_config_entries *result = NULL; @@ -76,22 +86,9 @@ if ((error = git_config_entries_new(&result)) < 0) goto out; - for (head = entries->list; head; head = head->next) { - git_config_entry *dup; - - dup = git__calloc(1, sizeof(git_config_entry)); - dup->name = git__strdup(head->entry->name); - GIT_ERROR_CHECK_ALLOC(dup->name); - if (head->entry->value) { - dup->value = git__strdup(head->entry->value); - GIT_ERROR_CHECK_ALLOC(dup->value); - } - dup->level = head->entry->level; - dup->include_depth = head->entry->include_depth; - - if ((error = git_config_entries_append(result, dup)) < 0) + for (head = entries->list; head; head = head->next) + if ((git_config_entries_dup_entry(result, head->entry)) < 0) goto out; - } *out = result; result = NULL; @@ -109,13 +106,18 @@ static void config_entries_free(git_config_entries *entries) { config_entry_list *list = NULL, *next; + config_entry_map_head *head; - git_strmap_foreach_value(entries->map, list, config_entry_list_free(list)); + git_strmap_foreach_value(entries->map, head, + git__free((char *) head->entry->name); git__free(head) + ); git_strmap_free(entries->map); list = entries->list; while (list != NULL) { next = list->next; + git__free((char *) list->entry->value); + git__free(list->entry); git__free(list); list = next; } @@ -131,80 +133,56 @@ int git_config_entries_append(git_config_entries *entries, git_config_entry *entry) { - config_entry_list *existing, *var; - int error = 0; - size_t pos; - - var = git__calloc(1, sizeof(config_entry_list)); - GIT_ERROR_CHECK_ALLOC(var); - var->entry = entry; + config_entry_list *list_head; + config_entry_map_head *map_head; - pos = git_strmap_lookup_index(entries->map, entry->name); - if (!git_strmap_valid_index(entries->map, pos)) { + if ((map_head = git_strmap_get(entries->map, entry->name)) != NULL) { + map_head->multivar = true; /* - * We only ever inspect `last` from the first config - * entry in a multivar. In case where this new entry is - * the first one in the entry map, it will also be the - * last one at the time of adding it, which is - * why we set `last` here to itself. Otherwise we - * do not have to set `last` and leave it set to - * `NULL`. + * This is a micro-optimization for configuration files + * with a lot of same keys. As for multivars the entry's + * key will be the same for all entries, we can just free + * all except the first entry's name and just re-use it. */ - var->last = var; - - git_strmap_insert(entries->map, entry->name, var, &error); - - if (error > 0) - error = 0; + git__free((char *) entry->name); + entry->name = map_head->entry->name; } else { - existing = git_strmap_value_at(entries->map, pos); - config_entry_list_append(&existing, var); + map_head = git__calloc(1, sizeof(*map_head)); + if ((git_strmap_set(entries->map, entry->name, map_head)) < 0) + return -1; } + map_head->entry = entry; - var = git__calloc(1, sizeof(config_entry_list)); - GIT_ERROR_CHECK_ALLOC(var); - var->entry = entry; - config_entry_list_append(&entries->list, var); - - return error; -} + list_head = git__calloc(1, sizeof(config_entry_list)); + GIT_ERROR_CHECK_ALLOC(list_head); + list_head->entry = entry; -int config_entry_get(config_entry_list **out, git_config_entries *entries, const char *key) -{ - size_t pos; - - pos = git_strmap_lookup_index(entries->map, key); - - /* no error message; the config system will write one */ - if (!git_strmap_valid_index(entries->map, pos)) - return GIT_ENOTFOUND; - - *out = git_strmap_value_at(entries->map, pos); + if (entries->list) + entries->list->last->next = list_head; + else + entries->list = list_head; + entries->list->last = list_head; return 0; } int git_config_entries_get(git_config_entry **out, git_config_entries *entries, const char *key) { - config_entry_list *entry; - int error; - - if ((error = config_entry_get(&entry, entries, key)) < 0) - return error; - *out = entry->last->entry; - + config_entry_map_head *entry; + if ((entry = git_strmap_get(entries->map, key)) == NULL) + return GIT_ENOTFOUND; + *out = entry->entry; return 0; } int git_config_entries_get_unique(git_config_entry **out, git_config_entries *entries, const char *key) { - config_entry_list *entry; - int error; + config_entry_map_head *entry; - if ((error = config_entry_get(&entry, entries, key)) < 0) - return error; + if ((entry = git_strmap_get(entries->map, key)) == NULL) + return GIT_ENOTFOUND; - if (entry->next != NULL) { + if (entry->multivar) { git_error_set(GIT_ERROR_CONFIG, "entry is not unique due to being a multivar"); return -1; } @@ -219,14 +197,14 @@ return 0; } -void config_iterator_free(git_config_iterator *iter) +static void config_iterator_free(git_config_iterator *iter) { config_entries_iterator *it = (config_entries_iterator *) iter; git_config_entries_free(it->entries); git__free(it); } -int config_iterator_next( +static int config_iterator_next( git_config_entry **entry, git_config_iterator *iter) { diff -Nru libgit2-0.28.5+dfsg.1/src/config_entries.h libgit2-1.1.0+dfsg.1/src/config_entries.h --- libgit2-0.28.5+dfsg.1/src/config_entries.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_entries.h 2020-10-12 18:53:06.000000000 +0000 @@ -14,6 +14,7 @@ int git_config_entries_new(git_config_entries **out); int git_config_entries_dup(git_config_entries **out, git_config_entries *entries); +int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry); void git_config_entries_incref(git_config_entries *entries); void git_config_entries_free(git_config_entries *entries); /* Add or append the new config option */ diff -Nru libgit2-0.28.5+dfsg.1/src/config_file.c libgit2-1.1.0+dfsg.1/src/config_file.c --- libgit2-0.28.5+dfsg.1/src/config_file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_file.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,36 +7,35 @@ #include "config.h" -#include "filebuf.h" -#include "sysdir.h" -#include "buffer.h" -#include "buf_text.h" #include "git2/config.h" #include "git2/sys/config.h" -#include "git2/types.h" -#include "strmap.h" + #include "array.h" -#include "config_parse.h" +#include "buffer.h" +#include "config_backend.h" #include "config_entries.h" - -#include -#include -#include +#include "config_parse.h" +#include "filebuf.h" +#include "regexp.h" +#include "sysdir.h" +#include "wildmatch.h" /* Max depth for [include] directives */ #define MAX_INCLUDE_DEPTH 10 +typedef struct config_file { + git_futils_filestamp stamp; + git_oid checksum; + char *path; + git_array_t(struct config_file) includes; +} config_file; + typedef struct { git_config_backend parent; - /* mutex to coordinate accessing the values */ git_mutex values_mutex; git_config_entries *entries; const git_repository *repo; git_config_level_t level; -} diskfile_header; - -typedef struct { - diskfile_header header; git_array_t(git_config_parser) readers; @@ -44,60 +43,47 @@ git_filebuf locked_buf; git_buf locked_content; - struct config_file file; -} diskfile_backend; - -typedef struct { - diskfile_header header; - - diskfile_backend *snapshot_from; -} diskfile_readonly_backend; + config_file file; +} config_file_backend; typedef struct { const git_repository *repo; - const char *file_path; + config_file *file; git_config_entries *entries; git_config_level_t level; unsigned int depth; -} diskfile_parse_state; +} config_file_parse_data; -static int config_read(git_config_entries *entries, const git_repository *repo, git_config_file *file, git_config_level_t level, int depth); -static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char *value); +static int config_file_read(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth); +static int config_file_read_buffer(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth, const char *buf, size_t buflen); +static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char *value); static char *escape_value(const char *ptr); -static int config_snapshot(git_config_backend **out, git_config_backend *in); - -static int config_error_readonly(void) -{ - git_error_set(GIT_ERROR_CONFIG, "this backend is read-only"); - return -1; -} - /** * Take the current values map from the backend and increase its * refcount. This is its own function to make sure we use the mutex to * avoid the map pointer from changing under us. */ -static git_config_entries *diskfile_entries_take(diskfile_header *h) +static int config_file_entries_take(git_config_entries **out, config_file_backend *b) { - git_config_entries *entries; + int error; - if (git_mutex_lock(&h->values_mutex) < 0) { - git_error_set(GIT_ERROR_OS, "failed to lock config backend"); - return NULL; + if ((error = git_mutex_lock(&b->values_mutex)) < 0) { + git_error_set(GIT_ERROR_OS, "failed to lock config backend"); + return error; } - entries = h->entries; - git_config_entries_incref(entries); + git_config_entries_incref(b->entries); + *out = b->entries; - git_mutex_unlock(&h->values_mutex); + git_mutex_unlock(&b->values_mutex); - return entries; + return 0; } -static void config_file_clear(struct config_file *file) +static void config_file_clear(config_file *file) { - struct config_file *include; + config_file *include; uint32_t i; if (file == NULL) @@ -111,31 +97,40 @@ git__free(file->path); } -static int config_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo) +static int config_file_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo) { + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); int res; - diskfile_backend *b = (diskfile_backend *)cfg; - b->header.level = level; - b->header.repo = repo; + b->level = level; + b->repo = repo; - if ((res = git_config_entries_new(&b->header.entries)) < 0) + if ((res = git_config_entries_new(&b->entries)) < 0) return res; if (!git_path_exists(b->file.path)) return 0; - if (res < 0 || (res = config_read(b->header.entries, repo, &b->file, level, 0)) < 0) { - git_config_entries_free(b->header.entries); - b->header.entries = NULL; + /* + * git silently ignores configuration files that are not + * readable. We emulate that behavior. This is particularly + * important for sandboxed applications on macOS where the + * git configuration files may not be readable. + */ + if (p_access(b->file.path, R_OK) < 0) + return GIT_ENOTFOUND; + + if (res < 0 || (res = config_file_read(b->entries, repo, &b->file, level, 0)) < 0) { + git_config_entries_free(b->entries); + b->entries = NULL; } return res; } -static int config_is_modified(int *modified, struct config_file *file) +static int config_file_is_modified(int *modified, config_file *file) { - git_config_file *include; + config_file *include; git_buf buf = GIT_BUF_INIT; git_oid hash; uint32_t i; @@ -143,6 +138,9 @@ *modified = 0; + if (!git_futils_filestamp_check(&file->stamp, file->path)) + goto check_includes; + if ((error = git_futils_readbuffer(&buf, file->path)) < 0) goto out; @@ -154,8 +152,9 @@ goto out; } +check_includes: git_array_foreach(file->includes, i, include) { - if ((error = config_is_modified(modified, include)) < 0 || *modified) + if ((error = config_file_is_modified(modified, include)) < 0 || *modified) goto out; } @@ -165,89 +164,125 @@ return error; } -static int config_refresh(git_config_backend *cfg) +static int config_file_set_entries(git_config_backend *cfg, git_config_entries *entries) { - diskfile_backend *b = (diskfile_backend *)cfg; - git_config_entries *entries = NULL, *tmp; - git_config_file *include; - int error, modified; + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); + git_config_entries *old = NULL; + config_file *include; + int error; uint32_t i; - if (b->header.parent.readonly) - return config_error_readonly(); + if (b->parent.readonly) { + git_error_set(GIT_ERROR_CONFIG, "this backend is read-only"); + return -1; + } - error = config_is_modified(&modified, &b->file); - if (error < 0 && error != GIT_ENOTFOUND) + git_array_foreach(b->file.includes, i, include) + config_file_clear(include); + git_array_clear(b->file.includes); + + if ((error = git_mutex_lock(&b->values_mutex)) < 0) { + git_error_set(GIT_ERROR_OS, "failed to lock config backend"); goto out; + } - if (!modified) - return 0; + old = b->entries; + b->entries = entries; - if ((error = git_config_entries_new(&entries)) < 0) - goto out; + git_mutex_unlock(&b->values_mutex); - /* Reparse the current configuration */ - git_array_foreach(b->file.includes, i, include) { - config_file_clear(include); - } - git_array_clear(b->file.includes); +out: + git_config_entries_free(old); + return error; +} + +static int config_file_refresh_from_buffer(git_config_backend *cfg, const char *buf, size_t buflen) +{ + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); + git_config_entries *entries = NULL; + int error; - if ((error = config_read(entries, b->header.repo, &b->file, b->header.level, 0)) < 0) + if ((error = git_config_entries_new(&entries)) < 0 || + (error = config_file_read_buffer(entries, b->repo, &b->file, + b->level, 0, buf, buflen)) < 0 || + (error = config_file_set_entries(cfg, entries)) < 0) goto out; - if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) { - git_error_set(GIT_ERROR_OS, "failed to lock config backend"); + entries = NULL; +out: + git_config_entries_free(entries); + return error; +} + +static int config_file_refresh(git_config_backend *cfg) +{ + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); + git_config_entries *entries = NULL; + int error, modified; + + if (cfg->readonly) + return 0; + + if ((error = config_file_is_modified(&modified, &b->file)) < 0 && error != GIT_ENOTFOUND) goto out; - } - tmp = b->header.entries; - b->header.entries = entries; - entries = tmp; + if (!modified) + return 0; - git_mutex_unlock(&b->header.values_mutex); + if ((error = git_config_entries_new(&entries)) < 0 || + (error = config_file_read(entries, b->repo, &b->file, b->level, 0)) < 0 || + (error = config_file_set_entries(cfg, entries)) < 0) + goto out; + entries = NULL; out: git_config_entries_free(entries); return (error == GIT_ENOTFOUND) ? 0 : error; } -static void backend_free(git_config_backend *_backend) +static void config_file_free(git_config_backend *_backend) { - diskfile_backend *backend = (diskfile_backend *)_backend; + config_file_backend *backend = GIT_CONTAINER_OF(_backend, config_file_backend, parent); if (backend == NULL) return; config_file_clear(&backend->file); - git_config_entries_free(backend->header.entries); - git_mutex_free(&backend->header.values_mutex); + git_config_entries_free(backend->entries); + git_mutex_free(&backend->values_mutex); git__free(backend); } -static int config_iterator_new( +static int config_file_iterator( git_config_iterator **iter, - struct git_config_backend* backend) + struct git_config_backend *backend) { - diskfile_header *bh = (diskfile_header *) backend; - git_config_entries *entries; + config_file_backend *b = GIT_CONTAINER_OF(backend, config_file_backend, parent); + git_config_entries *dupped = NULL, *entries = NULL; int error; - if ((error = git_config_entries_dup(&entries, bh->entries)) < 0) - return error; - - if ((error = git_config_entries_iterator_new(iter, entries)) < 0) + if ((error = config_file_refresh(backend)) < 0 || + (error = config_file_entries_take(&entries, b)) < 0 || + (error = git_config_entries_dup(&dupped, entries)) < 0 || + (error = git_config_entries_iterator_new(iter, dupped)) < 0) goto out; out: /* Let iterator delete duplicated entries when it's done */ git_config_entries_free(entries); + git_config_entries_free(dupped); return error; } -static int config_set(git_config_backend *cfg, const char *name, const char *value) +static int config_file_snapshot(git_config_backend **out, git_config_backend *backend) { - diskfile_backend *b = (diskfile_backend *)cfg; + return git_config_backend_snapshot(out, backend); +} + +static int config_file_set(git_config_backend *cfg, const char *name, const char *value) +{ + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); git_config_entries *entries; git_config_entry *existing; char *key, *esc_value = NULL; @@ -256,8 +291,8 @@ if ((error = git_config__normalize_name(name, &key)) < 0) return error; - if ((entries = diskfile_entries_take(&b->header)) == NULL) - return -1; + if ((error = config_file_entries_take(&entries, b)) < 0) + return error; /* Check whether we'd be modifying an included or multivar key */ if ((error = git_config_entries_get_unique(&existing, entries, key)) < 0) { @@ -277,11 +312,9 @@ GIT_ERROR_CHECK_ALLOC(esc_value); } - if ((error = config_write(b, name, key, NULL, esc_value)) < 0) + if ((error = config_file_write(b, name, key, NULL, esc_value)) < 0) goto out; - error = config_refresh(cfg); - out: git_config_entries_free(entries); git__free(esc_value); @@ -290,7 +323,7 @@ } /* release the map containing the entry as an equivalent to freeing it */ -static void free_diskfile_entry(git_config_entry *entry) +static void config_file_entry_free(git_config_entry *entry) { git_config_entries *entries = (git_config_entries *) entry->payload; git_config_entries_free(entries); @@ -299,67 +332,61 @@ /* * Internal function that actually gets the value in string form */ -static int config_get(git_config_backend *cfg, const char *key, git_config_entry **out) +static int config_file_get(git_config_backend *cfg, const char *key, git_config_entry **out) { - diskfile_header *h = (diskfile_header *)cfg; + config_file_backend *h = GIT_CONTAINER_OF(cfg, config_file_backend, parent); git_config_entries *entries = NULL; git_config_entry *entry; int error = 0; - if (!h->parent.readonly && ((error = config_refresh(cfg)) < 0)) + if (!h->parent.readonly && ((error = config_file_refresh(cfg)) < 0)) return error; - if ((entries = diskfile_entries_take(h)) == NULL) - return -1; + if ((error = config_file_entries_take(&entries, h)) < 0) + return error; if ((error = (git_config_entries_get(&entry, entries, key))) < 0) { git_config_entries_free(entries); return error; } - entry->free = free_diskfile_entry; + entry->free = config_file_entry_free; entry->payload = entries; *out = entry; return 0; } -static int config_set_multivar( +static int config_file_set_multivar( git_config_backend *cfg, const char *name, const char *regexp, const char *value) { - diskfile_backend *b = (diskfile_backend *)cfg; - char *key; - regex_t preg; + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); + git_regexp preg; int result; + char *key; assert(regexp); if ((result = git_config__normalize_name(name, &key)) < 0) return result; - result = p_regcomp(&preg, regexp, REG_EXTENDED); - if (result != 0) { - git_error_set_regex(&preg, result); - result = -1; + if ((result = git_regexp_compile(&preg, regexp, 0)) < 0) goto out; - } - /* If we do have it, set call config_write() and reload */ - if ((result = config_write(b, name, key, &preg, value)) < 0) + /* If we do have it, set call config_file_write() and reload */ + if ((result = config_file_write(b, name, key, &preg, value)) < 0) goto out; - result = config_refresh(cfg); - out: git__free(key); - regfree(&preg); + git_regexp_dispose(&preg); return result; } -static int config_delete(git_config_backend *cfg, const char *name) +static int config_file_delete(git_config_backend *cfg, const char *name) { - diskfile_backend *b = (diskfile_backend *)cfg; + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); git_config_entries *entries = NULL; git_config_entry *entry; char *key = NULL; @@ -368,7 +395,7 @@ if ((error = git_config__normalize_name(name, &key)) < 0) goto out; - if ((entries = diskfile_entries_take(&b->header)) == NULL) + if ((error = config_file_entries_take(&entries, b)) < 0) goto out; /* Check whether we'd be modifying an included or multivar key */ @@ -378,10 +405,7 @@ goto out; } - if ((error = config_write(b, name, entry->name, NULL, NULL)) < 0) - goto out; - - if ((error = config_refresh(cfg)) < 0) + if ((error = config_file_write(b, name, entry->name, NULL, NULL)) < 0) goto out; out: @@ -390,22 +414,20 @@ return error; } -static int config_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp) +static int config_file_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp) { - diskfile_backend *b = (diskfile_backend *)cfg; + config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent); git_config_entries *entries = NULL; git_config_entry *entry = NULL; - regex_t preg = { 0 }; + git_regexp preg = GIT_REGEX_INIT; char *key = NULL; int result; if ((result = git_config__normalize_name(name, &key)) < 0) goto out; - if ((entries = diskfile_entries_take(&b->header)) == NULL) { - result = -1; + if ((result = config_file_entries_take(&entries, b)) < 0) goto out; - } if ((result = git_config_entries_get(&entry, entries, key)) < 0) { if (result == GIT_ENOTFOUND) @@ -413,28 +435,22 @@ goto out; } - if ((result = p_regcomp(&preg, regexp, REG_EXTENDED)) != 0) { - git_error_set_regex(&preg, result); - result = -1; + if ((result = git_regexp_compile(&preg, regexp, 0)) < 0) goto out; - } - if ((result = config_write(b, name, key, &preg, NULL)) < 0) - goto out; - - if ((result = config_refresh(cfg)) < 0) + if ((result = config_file_write(b, name, key, &preg, NULL)) < 0) goto out; out: git_config_entries_free(entries); git__free(key); - regfree(&preg); + git_regexp_dispose(&preg); return result; } -static int config_lock(git_config_backend *_cfg) +static int config_file_lock(git_config_backend *_cfg) { - diskfile_backend *cfg = (diskfile_backend *) _cfg; + config_file_backend *cfg = GIT_CONTAINER_OF(_cfg, config_file_backend, parent); int error; if ((error = git_filebuf_open(&cfg->locked_buf, cfg->file.path, 0, GIT_CONFIG_FILE_MODE)) < 0) @@ -451,9 +467,9 @@ } -static int config_unlock(git_config_backend *_cfg, int success) +static int config_file_unlock(git_config_backend *_cfg, int success) { - diskfile_backend *cfg = (diskfile_backend *) _cfg; + config_file_backend *cfg = GIT_CONTAINER_OF(_cfg, config_file_backend, parent); int error = 0; if (success) { @@ -470,145 +486,29 @@ int git_config_backend_from_file(git_config_backend **out, const char *path) { - diskfile_backend *backend; + config_file_backend *backend; - backend = git__calloc(1, sizeof(diskfile_backend)); + backend = git__calloc(1, sizeof(config_file_backend)); GIT_ERROR_CHECK_ALLOC(backend); - backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION; - git_mutex_init(&backend->header.values_mutex); + backend->parent.version = GIT_CONFIG_BACKEND_VERSION; + git_mutex_init(&backend->values_mutex); backend->file.path = git__strdup(path); GIT_ERROR_CHECK_ALLOC(backend->file.path); git_array_init(backend->file.includes); - backend->header.parent.open = config_open; - backend->header.parent.get = config_get; - backend->header.parent.set = config_set; - backend->header.parent.set_multivar = config_set_multivar; - backend->header.parent.del = config_delete; - backend->header.parent.del_multivar = config_delete_multivar; - backend->header.parent.iterator = config_iterator_new; - backend->header.parent.snapshot = config_snapshot; - backend->header.parent.lock = config_lock; - backend->header.parent.unlock = config_unlock; - backend->header.parent.free = backend_free; - - *out = (git_config_backend *)backend; - - return 0; -} - -static int config_set_readonly(git_config_backend *cfg, const char *name, const char *value) -{ - GIT_UNUSED(cfg); - GIT_UNUSED(name); - GIT_UNUSED(value); - - return config_error_readonly(); -} - -static int config_set_multivar_readonly( - git_config_backend *cfg, const char *name, const char *regexp, const char *value) -{ - GIT_UNUSED(cfg); - GIT_UNUSED(name); - GIT_UNUSED(regexp); - GIT_UNUSED(value); - - return config_error_readonly(); -} - -static int config_delete_multivar_readonly(git_config_backend *cfg, const char *name, const char *regexp) -{ - GIT_UNUSED(cfg); - GIT_UNUSED(name); - GIT_UNUSED(regexp); - - return config_error_readonly(); -} - -static int config_delete_readonly(git_config_backend *cfg, const char *name) -{ - GIT_UNUSED(cfg); - GIT_UNUSED(name); - - return config_error_readonly(); -} - -static int config_lock_readonly(git_config_backend *_cfg) -{ - GIT_UNUSED(_cfg); - - return config_error_readonly(); -} - -static int config_unlock_readonly(git_config_backend *_cfg, int success) -{ - GIT_UNUSED(_cfg); - GIT_UNUSED(success); - - return config_error_readonly(); -} - -static void backend_readonly_free(git_config_backend *_backend) -{ - diskfile_backend *backend = (diskfile_backend *)_backend; - - if (backend == NULL) - return; - - git_config_entries_free(backend->header.entries); - git_mutex_free(&backend->header.values_mutex); - git__free(backend); -} - -static int config_readonly_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo) -{ - diskfile_readonly_backend *b = (diskfile_readonly_backend *) cfg; - diskfile_backend *src = b->snapshot_from; - diskfile_header *src_header = &src->header; - git_config_entries *entries; - int error; - - if (!src_header->parent.readonly && (error = config_refresh(&src_header->parent)) < 0) - return error; - - /* We're just copying data, don't care about the level or repo*/ - GIT_UNUSED(level); - GIT_UNUSED(repo); - - if ((entries = diskfile_entries_take(src_header)) == NULL) - return -1; - b->header.entries = entries; - - return 0; -} - -static int config_snapshot(git_config_backend **out, git_config_backend *in) -{ - diskfile_readonly_backend *backend; - - backend = git__calloc(1, sizeof(diskfile_readonly_backend)); - GIT_ERROR_CHECK_ALLOC(backend); - - backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION; - git_mutex_init(&backend->header.values_mutex); - - backend->snapshot_from = (diskfile_backend *) in; - - backend->header.parent.readonly = 1; - backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION; - backend->header.parent.open = config_readonly_open; - backend->header.parent.get = config_get; - backend->header.parent.set = config_set_readonly; - backend->header.parent.set_multivar = config_set_multivar_readonly; - backend->header.parent.del = config_delete_readonly; - backend->header.parent.del_multivar = config_delete_multivar_readonly; - backend->header.parent.iterator = config_iterator_new; - backend->header.parent.lock = config_lock_readonly; - backend->header.parent.unlock = config_unlock_readonly; - backend->header.parent.free = backend_readonly_free; + backend->parent.open = config_file_open; + backend->parent.get = config_file_get; + backend->parent.set = config_file_set; + backend->parent.set_multivar = config_file_set_multivar; + backend->parent.del = config_file_delete; + backend->parent.del_multivar = config_file_delete_multivar; + backend->parent.iterator = config_file_iterator; + backend->parent.snapshot = config_file_snapshot; + backend->parent.lock = config_file_lock; + backend->parent.unlock = config_file_unlock; + backend->parent.free = config_file_free; *out = (git_config_backend *)backend; @@ -656,10 +556,9 @@ return git_buf_detach(&buf); } -static int parse_include(git_config_parser *reader, - diskfile_parse_state *parse_data, const char *file) +static int parse_include(config_file_parse_data *parse_data, const char *file) { - struct config_file *include; + config_file *include; git_buf path = GIT_BUF_INIT; char *dir; int result; @@ -667,7 +566,7 @@ if (!file) return 0; - if ((result = git_path_dirname_r(&path, reader->file->path)) < 0) + if ((result = git_path_dirname_r(&path, parse_data->file->path)) < 0) return result; dir = git_buf_detach(&path); @@ -677,14 +576,14 @@ if (result < 0) return result; - include = git_array_alloc(reader->file->includes); + include = git_array_alloc(parse_data->file->includes); GIT_ERROR_CHECK_ALLOC(include); memset(include, 0, sizeof(*include)); git_array_init(include->includes); include->path = git_buf_detach(&path); - result = config_read(parse_data->entries, parse_data->repo, - include, parse_data->level, parse_data->depth+1); + result = config_file_read(parse_data->entries, parse_data->repo, include, + parse_data->level, parse_data->depth+1); if (result == GIT_ENOTFOUND) { git_error_clear(); @@ -698,41 +597,41 @@ int *matches, const git_repository *repo, const char *cfg_file, - const char *value, + const char *condition, bool case_insensitive) { - git_buf path = GIT_BUF_INIT; - int error, fnmatch_flags; + git_buf pattern = GIT_BUF_INIT, gitdir = GIT_BUF_INIT; + int error; - if (value[0] == '.' && git_path_is_dirsep(value[1])) { - git_path_dirname_r(&path, cfg_file); - git_buf_joinpath(&path, path.ptr, value + 2); - } else if (value[0] == '~' && git_path_is_dirsep(value[1])) - git_sysdir_expand_global_file(&path, value + 1); - else if (!git_path_is_absolute(value)) - git_buf_joinpath(&path, "**", value); + if (condition[0] == '.' && git_path_is_dirsep(condition[1])) { + git_path_dirname_r(&pattern, cfg_file); + git_buf_joinpath(&pattern, pattern.ptr, condition + 2); + } else if (condition[0] == '~' && git_path_is_dirsep(condition[1])) + git_sysdir_expand_global_file(&pattern, condition + 1); + else if (!git_path_is_absolute(condition)) + git_buf_joinpath(&pattern, "**", condition); else - git_buf_sets(&path, value); + git_buf_sets(&pattern, condition); + + if (git_path_is_dirsep(condition[strlen(condition) - 1])) + git_buf_puts(&pattern, "**"); - if (git_buf_oom(&path)) { + if (git_buf_oom(&pattern)) { error = -1; goto out; } - if (git_path_is_dirsep(value[strlen(value) - 1])) - git_buf_puts(&path, "**"); - - fnmatch_flags = FNM_PATHNAME|FNM_LEADING_DIR; - if (case_insensitive) - fnmatch_flags |= FNM_IGNORECASE; - - if ((error = p_fnmatch(path.ptr, git_repository_path(repo), fnmatch_flags)) < 0) + if ((error = git_repository_item_path(&gitdir, repo, GIT_REPOSITORY_ITEM_GITDIR)) < 0) goto out; - *matches = (error == 0); + if (git_path_is_dirsep(gitdir.ptr[gitdir.size - 1])) + git_buf_truncate(&gitdir, gitdir.size - 1); + *matches = wildmatch(pattern.ptr, gitdir.ptr, + WM_PATHNAME | (case_insensitive ? WM_CASEFOLD : 0)) == WM_MATCH; out: - git_buf_dispose(&path); + git_buf_dispose(&pattern); + git_buf_dispose(&gitdir); return error; } @@ -754,16 +653,67 @@ return do_match_gitdir(matches, repo, cfg_file, value, true); } +static int conditional_match_onbranch( + int *matches, + const git_repository *repo, + const char *cfg_file, + const char *condition) +{ + git_buf reference = GIT_BUF_INIT, buf = GIT_BUF_INIT; + int error; + + GIT_UNUSED(cfg_file); + + /* + * NOTE: you cannot use `git_repository_head` here. Looking up the + * HEAD reference will create the ODB, which causes us to read the + * repo's config for keys like core.precomposeUnicode. As we're + * just parsing the config right now, though, this would result in + * an endless recursion. + */ + + if ((error = git_buf_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 || + (error = git_futils_readbuffer(&reference, buf.ptr)) < 0) + goto out; + git_buf_rtrim(&reference); + + if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF))) + goto out; + git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF)); + + if (git__strncmp(reference.ptr, GIT_REFS_HEADS_DIR, strlen(GIT_REFS_HEADS_DIR))) + goto out; + git_buf_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR)); + + /* + * If the condition ends with a '/', then we should treat it as if + * it had '**' appended. + */ + if ((error = git_buf_sets(&buf, condition)) < 0) + goto out; + if (git_path_is_dirsep(condition[strlen(condition) - 1]) && + (error = git_buf_puts(&buf, "**")) < 0) + goto out; + + *matches = wildmatch(buf.ptr, reference.ptr, WM_PATHNAME) == WM_MATCH; +out: + git_buf_dispose(&reference); + git_buf_dispose(&buf); + + return error; + +} + static const struct { const char *prefix; int (*matches)(int *matches, const git_repository *repo, const char *cfg, const char *value); } conditions[] = { { "gitdir:", conditional_match_gitdir }, - { "gitdir/i:", conditional_match_gitdir_i } + { "gitdir/i:", conditional_match_gitdir_i }, + { "onbranch:", conditional_match_onbranch } }; -static int parse_conditional_include(git_config_parser *reader, - diskfile_parse_state *parse_data, const char *section, const char *file) +static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file) { char *condition; size_t i; @@ -781,12 +731,12 @@ if ((error = conditions[i].matches(&matches, parse_data->repo, - parse_data->file_path, + parse_data->file->path, condition + strlen(conditions[i].prefix))) < 0) break; if (matches) - error = parse_include(reader, parse_data, file); + error = parse_include(parse_data, file); break; } @@ -804,12 +754,13 @@ size_t line_len, void *data) { - diskfile_parse_state *parse_data = (diskfile_parse_state *)data; + config_file_parse_data *parse_data = (config_file_parse_data *)data; git_buf buf = GIT_BUF_INIT; git_config_entry *entry; const char *c; int result = 0; + GIT_UNUSED(reader); GIT_UNUSED(line); GIT_UNUSED(line_len); @@ -842,25 +793,25 @@ /* Add or append the new config option */ if (!git__strcmp(entry->name, "include.path")) - result = parse_include(reader, parse_data, entry->value); + result = parse_include(parse_data, entry->value); else if (!git__prefixcmp(entry->name, "includeif.") && !git__suffixcmp(entry->name, ".path")) - result = parse_conditional_include(reader, parse_data, - entry->name, entry->value); + result = parse_conditional_include(parse_data, entry->name, entry->value); return result; } -static int config_read( +static int config_file_read_buffer( git_config_entries *entries, const git_repository *repo, - git_config_file *file, + config_file *file, git_config_level_t level, - int depth) + int depth, + const char *buf, + size_t buflen) { - diskfile_parse_state parse_data; + config_file_parse_data parse_data; git_config_parser reader; - git_buf contents = GIT_BUF_INIT; int error; if (depth >= MAX_INCLUDE_DEPTH) { @@ -868,24 +819,18 @@ return -1; } - if ((error = git_futils_readbuffer(&contents, file->path)) < 0) - goto out; - - git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size); - - if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0) - goto out; - /* Initialize the reading position */ - reader.file = file; - git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size); + reader.path = file->path; + git_parse_ctx_init(&reader.ctx, buf, buflen); /* If the file is empty, there's nothing for us to do */ - if (!reader.ctx.content || *reader.ctx.content == '\0') + if (!reader.ctx.content || *reader.ctx.content == '\0') { + error = 0; goto out; + } parse_data.repo = repo; - parse_data.file_path = file->path; + parse_data.file = file; parse_data.entries = entries; parse_data.level = level; parse_data.depth = depth; @@ -893,6 +838,37 @@ error = git_config_parse(&reader, NULL, read_on_variable, NULL, NULL, &parse_data); out: + return error; +} + +static int config_file_read( + git_config_entries *entries, + const git_repository *repo, + config_file *file, + git_config_level_t level, + int depth) +{ + git_buf contents = GIT_BUF_INIT; + struct stat st; + int error; + + if (p_stat(file->path, &st) < 0) { + error = git_path_set_error(errno, file->path, "stat"); + goto out; + } + + if ((error = git_futils_readbuffer(&contents, file->path)) < 0) + goto out; + + git_futils_filestamp_set_from_stat(&file->stamp, &st); + if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0) + goto out; + + if ((error = config_file_read_buffer(entries, repo, file, level, depth, + contents.ptr, contents.size)) < 0) + goto out; + +out: git_buf_dispose(&contents); return error; } @@ -954,7 +930,7 @@ const char *section; const char *orig_name; const char *name; - const regex_t *preg; + const git_regexp *preg; const char *value; }; @@ -1059,7 +1035,7 @@ /* If we have a regex to match the value, see if it matches */ if (has_matched && write_data->preg != NULL) - has_matched = (regexec(write_data->preg, var_value, 0, NULL, 0) == 0); + has_matched = (git_regexp_match(write_data->preg, var_value) == 0); /* If this isn't the name/value we're looking for, simply dump the * existing data back out and continue on. @@ -1120,39 +1096,33 @@ /* * This is pretty much the parsing, except we write out anything we don't have */ -static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *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) + { - int result; - char *orig_section, *section, *orig_name, *name, *ldot; - git_filebuf file = GIT_FILEBUF_INIT; + char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot; git_buf buf = GIT_BUF_INIT, contents = GIT_BUF_INIT; - git_config_parser reader; + git_config_parser parser = GIT_CONFIG_PARSER_INIT; + git_filebuf file = GIT_FILEBUF_INIT; struct write_data write_data; + int error; - memset(&reader, 0, sizeof(reader)); - reader.file = &cfg->file; + memset(&write_data, 0, sizeof(write_data)); if (cfg->locked) { - result = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content)); + error = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content)); } else { - /* Lock the file */ - if ((result = git_filebuf_open( - &file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) { - git_buf_dispose(&contents); - return result; - } + if ((error = git_filebuf_open(&file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS, + GIT_CONFIG_FILE_MODE)) < 0) + goto done; /* We need to read in our own config file */ - result = git_futils_readbuffer(&contents, cfg->file.path); + error = git_futils_readbuffer(&contents, cfg->file.path); } + if (error < 0 && error != GIT_ENOTFOUND) + goto done; - /* Initialise the reading position */ - if (result == 0 || result == GIT_ENOTFOUND) { - git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size); - } else { - git_filebuf_cleanup(&file); - return -1; /* OS error when reading the file */ - } + if ((git_config_parser_init(&parser, cfg->file.path, contents.ptr, contents.size)) < 0) + goto done; ldot = strrchr(key, '.'); name = ldot + 1; @@ -1165,30 +1135,16 @@ GIT_ERROR_CHECK_ALLOC(orig_section); write_data.buf = &buf; - git_buf_init(&write_data.buffered_comment, 0); write_data.orig_section = orig_section; write_data.section = section; - write_data.in_section = 0; - write_data.preg_replaced = 0; write_data.orig_name = orig_name; write_data.name = name; write_data.preg = preg; write_data.value = value; - result = git_config_parse(&reader, - write_on_section, - write_on_variable, - write_on_comment, - write_on_eof, - &write_data); - git__free(section); - git__free(orig_section); - git_buf_dispose(&write_data.buffered_comment); - - if (result < 0) { - git_filebuf_cleanup(&file); + if ((error = git_config_parse(&parser, write_on_section, write_on_variable, + write_on_comment, write_on_eof, &write_data)) < 0) goto done; - } if (cfg->locked) { size_t len = buf.asize; @@ -1197,12 +1153,22 @@ git_buf_attach(&cfg->locked_content, git_buf_detach(&buf), len); } else { git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf)); - result = git_filebuf_commit(&file); + + if ((error = git_filebuf_commit(&file)) < 0) + goto done; + + if ((error = config_file_refresh_from_buffer(&cfg->parent, buf.ptr, buf.size)) < 0) + goto done; } done: + git__free(section); + git__free(orig_section); + git_buf_dispose(&write_data.buffered_comment); git_buf_dispose(&buf); git_buf_dispose(&contents); - git_parse_ctx_clear(&reader.ctx); - return result; + git_filebuf_cleanup(&file); + git_config_parser_dispose(&parser); + + return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/config.h libgit2-1.1.0+dfsg.1/src/config.h --- libgit2-0.28.5+dfsg.1/src/config.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config.h 2020-10-12 18:53:06.000000000 +0000 @@ -66,18 +66,19 @@ extern int git_config__get_int_force( const git_config *cfg, const char *key, int fallback_value); -/* API for repository cvar-style lookups from config - not cached, but - * uses cvar value maps and fallbacks +/* API for repository configmap-style lookups from config - not cached, but + * uses configmap value maps and fallbacks */ -extern int git_config__cvar( - int *out, git_config *config, git_cvar_cached cvar); +extern int git_config__configmap_lookup( + int *out, git_config *config, git_configmap_item item); /** * The opposite of git_config_lookup_map_value, we take an enum value * and map it to the string or bool value on the config. */ -int git_config_lookup_map_enum(git_cvar_t *type_out, const char **str_out, - const git_cvar_map *maps, size_t map_n, int enum_val); +int git_config_lookup_map_enum(git_configmap_t *type_out, + const char **str_out, const git_configmap *maps, + size_t map_n, int enum_val); /** * Unlock the backend with the highest priority diff -Nru libgit2-0.28.5+dfsg.1/src/config_mem.c libgit2-1.1.0+dfsg.1/src/config_mem.c --- libgit2-0.28.5+dfsg.1/src/config_mem.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_mem.c 2020-10-12 18:53:06.000000000 +0000 @@ -78,20 +78,24 @@ static int config_memory_open(git_config_backend *backend, git_config_level_t level, const git_repository *repo) { config_memory_backend *memory_backend = (config_memory_backend *) backend; + git_config_parser parser = GIT_PARSE_CTX_INIT; config_memory_parse_data parse_data; - git_config_parser reader; + int error; GIT_UNUSED(repo); - if (memory_backend->cfg.size == 0) - return 0; - - git_parse_ctx_init(&reader.ctx, memory_backend->cfg.ptr, memory_backend->cfg.size); - reader.file = NULL; + if ((error = git_config_parser_init(&parser, "in-memory", memory_backend->cfg.ptr, + memory_backend->cfg.size)) < 0) + goto out; parse_data.entries = memory_backend->entries; parse_data.level = level; - return git_config_parse(&reader, NULL, read_variable_cb, NULL, NULL, &parse_data); + if ((error = git_config_parse(&parser, NULL, read_variable_cb, NULL, NULL, &parse_data)) < 0) + goto out; + +out: + git_config_parser_dispose(&parser); + return error; } static int config_memory_get(git_config_backend *backend, const char *key, git_config_entry **out) @@ -166,14 +170,6 @@ return config_error_readonly(); } -static int config_memory_snapshot(git_config_backend **out, git_config_backend *backend) -{ - GIT_UNUSED(out); - GIT_UNUSED(backend); - git_error_set(GIT_ERROR_CONFIG, "this backend does not support snapshots"); - return -1; -} - static void config_memory_free(git_config_backend *_backend) { config_memory_backend *backend = (config_memory_backend *)_backend; @@ -215,7 +211,7 @@ backend->parent.iterator = config_memory_iterator; backend->parent.lock = config_memory_lock; backend->parent.unlock = config_memory_unlock; - backend->parent.snapshot = config_memory_snapshot; + backend->parent.snapshot = git_config_backend_snapshot; backend->parent.free = config_memory_free; *out = (git_config_backend *)backend; diff -Nru libgit2-0.28.5+dfsg.1/src/config_parse.c libgit2-1.1.0+dfsg.1/src/config_parse.c --- libgit2-0.28.5+dfsg.1/src/config_parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,9 +16,14 @@ static void set_parse_error(git_config_parser *reader, int col, const char *error_str) { - const char *file = reader->file ? reader->file->path : "in-memory"; - git_error_set(GIT_ERROR_CONFIG, "failed to parse config file: %s (in %s:%"PRIuZ", column %d)", - error_str, file, reader->ctx.line_num, col); + if (col) + git_error_set(GIT_ERROR_CONFIG, + "failed to parse config file: %s (in %s:%"PRIuZ", column %d)", + error_str, reader->path, reader->ctx.line_num, col); + else + git_error_set(GIT_ERROR_CONFIG, + "failed to parse config file: %s (in %s:%"PRIuZ")", + error_str, reader->path, reader->ctx.line_num); } @@ -59,31 +64,35 @@ } -static int parse_section_header_ext(git_config_parser *reader, const char *line, const char *base_name, char **section_name) +static int parse_subsection_header(git_config_parser *reader, const char *line, size_t pos, const char *base_name, char **section_name) { int c, rpos; - char *first_quote, *last_quote; + const char *first_quote, *last_quote; const char *line_start = line; git_buf buf = GIT_BUF_INIT; size_t quoted_len, alloc_len, base_name_len = strlen(base_name); - /* - * base_name is what came before the space. We should be at the - * first quotation mark, except for now, line isn't being kept in - * sync so we only really use it to calculate the length. - */ - - first_quote = strchr(line, '"'); - if (first_quote == NULL) { - set_parse_error(reader, 0, "Missing quotation marks in section header"); + /* Skip any additional whitespace before our section name */ + while (git__isspace(line[pos])) + pos++; + + /* We should be at the first quotation mark. */ + if (line[pos] != '"') { + set_parse_error(reader, 0, "missing quotation marks in section header"); goto end_error; } + first_quote = &line[pos]; last_quote = strrchr(line, '"'); quoted_len = last_quote - first_quote; + if ((last_quote - line) > INT_MAX) { + set_parse_error(reader, 0, "invalid section header, line too long"); + goto end_error; + } + if (quoted_len == 0) { - set_parse_error(reader, 0, "Missing closing quotation mark in section header"); + set_parse_error(reader, 0, "missing closing quotation mark in section header"); goto end_error; } @@ -107,7 +116,7 @@ switch (c) { case 0: - set_parse_error(reader, 0, "Unexpected end-of-line in section header"); + set_parse_error(reader, 0, "unexpected end-of-line in section header"); goto end_error; case '"': @@ -117,7 +126,7 @@ c = line[++rpos]; if (c == 0) { - set_parse_error(reader, rpos, "Unexpected end-of-line in section header"); + set_parse_error(reader, rpos, "unexpected end-of-line in section header"); goto end_error; } @@ -134,13 +143,13 @@ goto end_error; if (line[rpos] != '"' || line[rpos + 1] != ']') { - set_parse_error(reader, rpos, "Unexpected text after closing quotes"); + set_parse_error(reader, rpos, "unexpected text after closing quotes"); git_buf_dispose(&buf); return -1; } *section_name = git_buf_detach(&buf); - return &line[rpos + 2] - line_start; /* rpos is at the closing quote */ + return (int)(&line[rpos + 2] - line_start); /* rpos is at the closing quote */ end_error: git_buf_dispose(&buf); @@ -165,7 +174,7 @@ name_end = strrchr(line, ']'); if (name_end == NULL) { git__free(line); - set_parse_error(reader, 0, "Missing ']' in section header"); + set_parse_error(reader, 0, "missing ']' in section header"); return -1; } @@ -185,14 +194,14 @@ do { if (git__isspace(c)){ name[name_length] = '\0'; - result = parse_section_header_ext(reader, line, name, section_out); + result = parse_subsection_header(reader, line, pos, name, section_out); git__free(line); git__free(name); return result; } if (!config_keychar(c) && c != '.') { - set_parse_error(reader, pos, "Unexpected character in header"); + set_parse_error(reader, pos, "unexpected character in header"); goto fail_parse; } @@ -201,7 +210,7 @@ } while ((c = line[pos++]) != ']'); if (line[pos - 1] != ']') { - set_parse_error(reader, pos, "Unexpected end of file"); + set_parse_error(reader, pos, "unexpected end of file"); goto fail_parse; } @@ -386,7 +395,7 @@ name_end++; if (line == name_end) { - set_parse_error(reader, 0, "Invalid configuration key"); + set_parse_error(reader, 0, "invalid configuration key"); return -1; } @@ -398,7 +407,7 @@ if (*value_start == '=') { *value = value_start + 1; } else if (*value_start) { - set_parse_error(reader, 0, "Invalid configuration key"); + set_parse_error(reader, 0, "invalid configuration key"); return -1; } @@ -442,7 +451,7 @@ git_buf_attach(&multi_value, value, 0); value = NULL; - if (parse_multiline_variable(reader, &multi_value, quote_count) < 0 || + if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 || git_buf_oom(&multi_value)) { error = -1; git_buf_dispose(&multi_value); @@ -465,13 +474,24 @@ return error; } +int git_config_parser_init(git_config_parser *out, const char *path, const char *data, size_t datalen) +{ + out->path = path; + return git_parse_ctx_init(&out->ctx, data, datalen); +} + +void git_config_parser_dispose(git_config_parser *parser) +{ + git_parse_ctx_clear(&parser->ctx); +} + int git_config_parse( git_config_parser *parser, git_config_parser_section_cb on_section, git_config_parser_variable_cb on_variable, git_config_parser_comment_cb on_comment, git_config_parser_eof_cb on_eof, - void *data) + void *payload) { git_parse_ctx *ctx; char *current_section = NULL, *var_name = NULL, *var_value = NULL; @@ -511,7 +531,7 @@ git_parse_advance_chars(ctx, result); if (on_section) - result = on_section(parser, current_section, line_start, line_len, data); + result = on_section(parser, current_section, line_start, line_len, payload); /* * After we've parsed the section header we may not be * done with the line. If there's still data in there, @@ -531,13 +551,13 @@ case ';': case '#': if (on_comment) { - result = on_comment(parser, line_start, line_len, data); + result = on_comment(parser, line_start, line_len, payload); } break; default: /* assume variable declaration */ if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) { - result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, data); + result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload); git__free(var_name); git__free(var_value); } @@ -550,7 +570,7 @@ } if (on_eof) - result = on_eof(parser, current_section, data); + result = on_eof(parser, current_section, payload); out: git__free(current_section); diff -Nru libgit2-0.28.5+dfsg.1/src/config_parse.h libgit2-1.1.0+dfsg.1/src/config_parse.h --- libgit2-0.28.5+dfsg.1/src/config_parse.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_parse.h 2020-10-12 18:53:06.000000000 +0000 @@ -8,30 +8,28 @@ #define INCLUDE_config_parse_h__ #include "common.h" + #include "array.h" +#include "futils.h" #include "oid.h" #include "parse.h" extern const char *git_config_escapes; extern const char *git_config_escaped; -typedef struct config_file { - git_oid checksum; - char *path; - git_array_t(struct config_file) includes; -} git_config_file; - typedef struct { - struct config_file *file; + const char *path; git_parse_ctx ctx; } git_config_parser; +#define GIT_CONFIG_PARSER_INIT { NULL, GIT_PARSE_CTX_INIT } + typedef int (*git_config_parser_section_cb)( git_config_parser *parser, const char *current_section, const char *line, size_t line_len, - void *data); + void *payload); typedef int (*git_config_parser_variable_cb)( git_config_parser *parser, @@ -40,18 +38,21 @@ const char *var_value, const char *line, size_t line_len, - void *data); + void *payload); typedef int (*git_config_parser_comment_cb)( git_config_parser *parser, const char *line, size_t line_len, - void *data); + void *payload); typedef int (*git_config_parser_eof_cb)( git_config_parser *parser, const char *current_section, - void *data); + void *payload); + +int git_config_parser_init(git_config_parser *out, const char *path, const char *data, size_t datalen); +void git_config_parser_dispose(git_config_parser *parser); int git_config_parse( git_config_parser *parser, @@ -59,6 +60,6 @@ git_config_parser_variable_cb on_variable, git_config_parser_comment_cb on_comment, git_config_parser_eof_cb on_eof, - void *data); + void *payload); #endif diff -Nru libgit2-0.28.5+dfsg.1/src/config_snapshot.c libgit2-1.1.0+dfsg.1/src/config_snapshot.c --- libgit2-0.28.5+dfsg.1/src/config_snapshot.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/config_snapshot.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * 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 "config_backend.h" + +#include "config.h" +#include "config_entries.h" + +typedef struct { + git_config_backend parent; + git_mutex values_mutex; + git_config_entries *entries; + git_config_backend *source; +} config_snapshot_backend; + +static int config_error_readonly(void) +{ + git_error_set(GIT_ERROR_CONFIG, "this backend is read-only"); + return -1; +} + +static int config_snapshot_iterator( + git_config_iterator **iter, + struct git_config_backend *backend) +{ + config_snapshot_backend *b = GIT_CONTAINER_OF(backend, config_snapshot_backend, parent); + git_config_entries *entries = NULL; + int error; + + if ((error = git_config_entries_dup(&entries, b->entries)) < 0 || + (error = git_config_entries_iterator_new(iter, entries)) < 0) + goto out; + +out: + /* Let iterator delete duplicated entries when it's done */ + git_config_entries_free(entries); + return error; +} + +/* release the map containing the entry as an equivalent to freeing it */ +static void config_snapshot_entry_free(git_config_entry *entry) +{ + git_config_entries *entries = (git_config_entries *) entry->payload; + git_config_entries_free(entries); +} + +static int config_snapshot_get(git_config_backend *cfg, const char *key, git_config_entry **out) +{ + config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent); + git_config_entries *entries = NULL; + git_config_entry *entry; + int error = 0; + + if (git_mutex_lock(&b->values_mutex) < 0) { + git_error_set(GIT_ERROR_OS, "failed to lock config backend"); + return -1; + } + + entries = b->entries; + git_config_entries_incref(entries); + git_mutex_unlock(&b->values_mutex); + + if ((error = (git_config_entries_get(&entry, entries, key))) < 0) { + git_config_entries_free(entries); + return error; + } + + entry->free = config_snapshot_entry_free; + entry->payload = entries; + *out = entry; + + return 0; +} + +static int config_snapshot_set(git_config_backend *cfg, const char *name, const char *value) +{ + GIT_UNUSED(cfg); + GIT_UNUSED(name); + GIT_UNUSED(value); + + return config_error_readonly(); +} + +static int config_snapshot_set_multivar( + git_config_backend *cfg, const char *name, const char *regexp, const char *value) +{ + GIT_UNUSED(cfg); + GIT_UNUSED(name); + GIT_UNUSED(regexp); + GIT_UNUSED(value); + + return config_error_readonly(); +} + +static int config_snapshot_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp) +{ + GIT_UNUSED(cfg); + GIT_UNUSED(name); + GIT_UNUSED(regexp); + + return config_error_readonly(); +} + +static int config_snapshot_delete(git_config_backend *cfg, const char *name) +{ + GIT_UNUSED(cfg); + GIT_UNUSED(name); + + return config_error_readonly(); +} + +static int config_snapshot_lock(git_config_backend *_cfg) +{ + GIT_UNUSED(_cfg); + + return config_error_readonly(); +} + +static int config_snapshot_unlock(git_config_backend *_cfg, int success) +{ + GIT_UNUSED(_cfg); + GIT_UNUSED(success); + + return config_error_readonly(); +} + +static void config_snapshot_free(git_config_backend *_backend) +{ + config_snapshot_backend *backend = GIT_CONTAINER_OF(_backend, config_snapshot_backend, parent); + + if (backend == NULL) + return; + + git_config_entries_free(backend->entries); + git_mutex_free(&backend->values_mutex); + git__free(backend); +} + +static int config_snapshot_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo) +{ + config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent); + git_config_entries *entries = NULL; + git_config_iterator *it = NULL; + git_config_entry *entry; + int error; + + /* We're just copying data, don't care about the level or repo*/ + GIT_UNUSED(level); + GIT_UNUSED(repo); + + if ((error = git_config_entries_new(&entries)) < 0 || + (error = b->source->iterator(&it, b->source)) < 0) + goto out; + + while ((error = git_config_next(&entry, it)) == 0) + if ((error = git_config_entries_dup_entry(entries, entry)) < 0) + goto out; + + if (error < 0) { + if (error != GIT_ITEROVER) + goto out; + error = 0; + } + + b->entries = entries; + +out: + git_config_iterator_free(it); + if (error) + git_config_entries_free(entries); + return error; +} + +int git_config_backend_snapshot(git_config_backend **out, git_config_backend *source) +{ + config_snapshot_backend *backend; + + backend = git__calloc(1, sizeof(config_snapshot_backend)); + GIT_ERROR_CHECK_ALLOC(backend); + + backend->parent.version = GIT_CONFIG_BACKEND_VERSION; + git_mutex_init(&backend->values_mutex); + + backend->source = source; + + backend->parent.readonly = 1; + backend->parent.version = GIT_CONFIG_BACKEND_VERSION; + backend->parent.open = config_snapshot_open; + backend->parent.get = config_snapshot_get; + backend->parent.set = config_snapshot_set; + backend->parent.set_multivar = config_snapshot_set_multivar; + backend->parent.snapshot = git_config_backend_snapshot; + backend->parent.del = config_snapshot_delete; + backend->parent.del_multivar = config_snapshot_delete_multivar; + backend->parent.iterator = config_snapshot_iterator; + backend->parent.lock = config_snapshot_lock; + backend->parent.unlock = config_snapshot_unlock; + backend->parent.free = config_snapshot_free; + + *out = &backend->parent; + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/crlf.c libgit2-1.1.0+dfsg.1/src/crlf.c --- libgit2-0.28.5+dfsg.1/src/crlf.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/crlf.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,7 +12,7 @@ #include "git2/index.h" #include "git2/sys/filter.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "filter.h" #include "buf_text.h" @@ -44,11 +44,11 @@ static git_crlf_t check_crlf(const char *value) { - if (GIT_ATTR_TRUE(value)) + if (GIT_ATTR_IS_TRUE(value)) return GIT_CRLF_TEXT; - else if (GIT_ATTR_FALSE(value)) + else if (GIT_ATTR_IS_FALSE(value)) return GIT_CRLF_BINARY; - else if (GIT_ATTR_UNSPECIFIED(value)) + else if (GIT_ATTR_IS_UNSPECIFIED(value)) ; else if (strcmp(value, "input") == 0) return GIT_CRLF_TEXT_INPUT; @@ -58,9 +58,9 @@ return GIT_CRLF_UNDEFINED; } -static git_cvar_value check_eol(const char *value) +static git_configmap_value check_eol(const char *value) { - if (GIT_ATTR_UNSPECIFIED(value)) + if (GIT_ATTR_IS_UNSPECIFIED(value)) ; else if (strcmp(value, "lf") == 0) return GIT_EOL_LF; @@ -78,7 +78,7 @@ const git_index_entry *entry; git_blob *blob; const void *blobcontent; - git_off_t blobsize; + git_object_size_t blobsize; bool found_cr; if (!path) @@ -127,7 +127,7 @@ return 0; } -static git_cvar_value output_eol(struct crlf_attrs *ca) +static git_configmap_value output_eol(struct crlf_attrs *ca) { switch (ca->crlf_action) { case GIT_CRLF_BINARY: @@ -293,12 +293,12 @@ memset(ca, 0, sizeof(struct crlf_attrs)); - if ((error = git_repository__cvar(&ca->auto_crlf, - git_filter_source_repo(src), GIT_CVAR_AUTO_CRLF)) < 0 || - (error = git_repository__cvar(&ca->safe_crlf, - git_filter_source_repo(src), GIT_CVAR_SAFE_CRLF)) < 0 || - (error = git_repository__cvar(&ca->core_eol, - git_filter_source_repo(src), GIT_CVAR_EOL)) < 0) + if ((error = git_repository__configmap_lookup(&ca->auto_crlf, + git_filter_source_repo(src), GIT_CONFIGMAP_AUTO_CRLF)) < 0 || + (error = git_repository__configmap_lookup(&ca->safe_crlf, + git_filter_source_repo(src), GIT_CONFIGMAP_SAFE_CRLF)) < 0 || + (error = git_repository__configmap_lookup(&ca->core_eol, + git_filter_source_repo(src), GIT_CONFIGMAP_EOL)) < 0) return error; /* downgrade FAIL to WARN if ALLOW_UNSAFE option is used */ diff -Nru libgit2-0.28.5+dfsg.1/src/describe.c libgit2-1.1.0+dfsg.1/src/describe.c --- libgit2-0.28.5+dfsg.1/src/describe.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/describe.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,10 +16,11 @@ #include "commit_list.h" #include "oidmap.h" #include "refs.h" +#include "repository.h" #include "revwalk.h" #include "tag.h" #include "vector.h" -#include "repository.h" +#include "wildmatch.h" /* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */ @@ -36,12 +37,7 @@ static void *oidmap_value_bykey(git_oidmap *map, const git_oid *key) { - size_t pos = git_oidmap_lookup_index(map, key); - - if (!git_oidmap_valid_index(map, pos)) - return NULL; - - return git_oidmap_value_at(map, pos); + return git_oidmap_get(map, key); } static struct commit_name *find_commit_name( @@ -124,13 +120,8 @@ e->path = git__strdup(path); git_oid_cpy(&e->peeled, peeled); - if (!found) { - int ret; - - git_oidmap_insert(names, &e->peeled, e, &ret); - if (ret < 0) - return -1; - } + if (!found && git_oidmap_set(names, &e->peeled, e) < 0) + return -1; } else git_tag_free(tag); @@ -224,7 +215,7 @@ return 0; /* Accept only tags that match the pattern, if given */ - if (data->opts->pattern && (!is_tag || p_fnmatch(data->opts->pattern, + if (data->opts->pattern && (!is_tag || wildmatch(data->opts->pattern, refname + strlen(GIT_REFS_TAGS_DIR), 0))) return 0; @@ -681,8 +672,8 @@ "git_describe_options"); data.opts = &normalized; - data.names = git_oidmap_alloc(); - GIT_ERROR_CHECK_ALLOC(data.names); + if ((error = git_oidmap_new(&data.names)) < 0) + return error; /** TODO: contains to be implemented */ @@ -694,7 +685,7 @@ get_name, &data)) < 0) goto cleanup; - if (git_oidmap_size(data.names) == 0 && !opts->show_commit_oid_as_fallback) { + if (git_oidmap_size(data.names) == 0 && !normalized.show_commit_oid_as_fallback) { git_error_set(GIT_ERROR_DESCRIBE, "cannot describe - " "no reference found, cannot describe anything."); error = -1; @@ -769,7 +760,7 @@ const git_describe_format_options *src) { if (!src) { - git_describe_init_format_options(dst, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION); + git_describe_format_options_init(dst, GIT_DESCRIBE_FORMAT_OPTIONS_VERSION); return 0; } @@ -878,16 +869,30 @@ git__free(result); } -int git_describe_init_options(git_describe_options *opts, unsigned int version) +int git_describe_options_init(git_describe_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_describe_options, GIT_DESCRIBE_OPTIONS_INIT); return 0; } -int git_describe_init_format_options(git_describe_format_options *opts, unsigned int version) +#ifndef GIT_DEPRECATE_HARD +int git_describe_init_options(git_describe_options *opts, unsigned int version) +{ + return git_describe_options_init(opts, version); +} +#endif + +int git_describe_format_options_init(git_describe_format_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_describe_format_options, GIT_DESCRIBE_FORMAT_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_describe_init_format_options(git_describe_format_options *opts, unsigned int version) +{ + return git_describe_format_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/diff.c libgit2-1.1.0+dfsg.1/src/diff.c --- libgit2-0.28.5+dfsg.1/src/diff.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,11 +32,6 @@ return str; } -const char *git_diff_delta__path(const git_diff_delta *delta) -{ - return diff_delta__path(delta); -} - int git_diff_delta__cmp(const void *a, const void *b) { const git_diff_delta *da = a, *db = b; @@ -155,7 +150,7 @@ return error; } -int git_diff_format_email__append_header_tobuf( +static int diff_format_email_append_header_tobuf( git_buf *out, const git_oid *id, const git_signature *author, @@ -212,7 +207,7 @@ return error; } -int git_diff_format_email__append_patches_tobuf( +static int diff_format_email_append_patches_tobuf( git_buf *out, git_diff *diff) { @@ -292,7 +287,7 @@ strncpy(summary, opts->summary, offset); } - error = git_diff_format_email__append_header_tobuf(out, + error = diff_format_email_append_header_tobuf(out, opts->id, opts->author, summary == NULL ? opts->summary : summary, opts->body, opts->patch_no, opts->total_patches, ignore_marker); @@ -305,7 +300,7 @@ (error = git_diff_get_stats(&stats, diff)) < 0 || (error = git_diff_stats_to_buf(out, stats, format_flags, 0)) < 0 || (error = git_buf_putc(out, '\n')) < 0 || - (error = git_diff_format_email__append_patches_tobuf(out, diff)) < 0) + (error = diff_format_email_append_patches_tobuf(out, diff)) < 0) goto on_error; error = git_buf_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n"); @@ -323,7 +318,7 @@ git_commit *commit, size_t patch_no, size_t total_patches, - git_diff_format_email_flags_t flags, + uint32_t flags, const git_diff_options *diff_opts) { git_diff *diff = NULL; @@ -350,14 +345,21 @@ return error; } -int git_diff_init_options(git_diff_options *opts, unsigned int version) +int git_diff_options_init(git_diff_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_diff_options, GIT_DIFF_OPTIONS_INIT); return 0; } -int git_diff_find_init_options( +#ifndef GIT_DEPRECATE_HARD +int git_diff_init_options(git_diff_options *opts, unsigned int version) +{ + return git_diff_options_init(opts, version); +} +#endif + +int git_diff_find_options_init( git_diff_find_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( @@ -365,7 +367,15 @@ return 0; } -int git_diff_format_email_init_options( +#ifndef GIT_DEPRECATE_HARD +int git_diff_find_init_options( + git_diff_find_options *opts, unsigned int version) +{ + return git_diff_find_options_init(opts, version); +} +#endif + +int git_diff_format_email_options_init( git_diff_format_email_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( @@ -374,6 +384,14 @@ return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_diff_format_email_init_options( + git_diff_format_email_options *opts, unsigned int version) +{ + return git_diff_format_email_options_init(opts, version); +} +#endif + static int flush_hunk(git_oid *result, git_hash_ctx *ctx) { git_oid hash; @@ -409,87 +427,44 @@ git_buf_truncate(buf, len); } -static int file_cb( +static int diff_patchid_print_callback_to_buf( const git_diff_delta *delta, - float progress, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { struct patch_id_args *args = (struct patch_id_args *) payload; git_buf buf = GIT_BUF_INIT; - int error; - - GIT_UNUSED(progress); + int error = 0; - if (!args->first_file && - (error = flush_hunk(&args->result, &args->ctx)) < 0) + if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL || + line->origin == GIT_DIFF_LINE_ADD_EOFNL || + line->origin == GIT_DIFF_LINE_DEL_EOFNL) goto out; - args->first_file = 0; - if ((error = git_buf_printf(&buf, - "diff--gita/%sb/%s---a/%s+++b/%s", - delta->old_file.path, - delta->new_file.path, - delta->old_file.path, - delta->new_file.path)) < 0) + if ((error = git_diff_print_callback__to_buf(delta, hunk, + line, &buf)) < 0) goto out; strip_spaces(&buf); - if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0) - goto out; - -out: - git_buf_dispose(&buf); - return error; -} - -static int patchid_line_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - struct patch_id_args *args = (struct patch_id_args *) payload; - git_buf buf = GIT_BUF_INIT; - int error; - - GIT_UNUSED(delta); - GIT_UNUSED(hunk); - - switch (line->origin) { - case GIT_DIFF_LINE_ADDITION: - git_buf_putc(&buf, '+'); - break; - case GIT_DIFF_LINE_DELETION: - git_buf_putc(&buf, '-'); - break; - case GIT_DIFF_LINE_CONTEXT: - break; - case GIT_DIFF_LINE_CONTEXT_EOFNL: - case GIT_DIFF_LINE_ADD_EOFNL: - case GIT_DIFF_LINE_DEL_EOFNL: - /* - * Ignore EOF without newlines for patch IDs as whitespace is - * not supposed to be significant. - */ - return 0; - default: - git_error_set(GIT_ERROR_PATCH, "invalid line origin for patch"); - return -1; - } - - git_buf_put(&buf, line->content, line->content_len); - strip_spaces(&buf); + if (line->origin == GIT_DIFF_LINE_FILE_HDR && + !args->first_file && + (error = flush_hunk(&args->result, &args->ctx) < 0)) + goto out; if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0) goto out; + if (line->origin == GIT_DIFF_LINE_FILE_HDR && args->first_file) + args->first_file = 0; + out: git_buf_dispose(&buf); return error; } -int git_diff_patchid_init_options(git_diff_patchid_options *opts, unsigned int version) +int git_diff_patchid_options_init(git_diff_patchid_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_diff_patchid_options, GIT_DIFF_PATCHID_OPTIONS_INIT); @@ -509,7 +484,10 @@ if ((error = git_hash_ctx_init(&args.ctx)) < 0) goto out; - if ((error = git_diff_foreach(diff, file_cb, NULL, NULL, patchid_line_cb, &args)) < 0) + if ((error = git_diff_print(diff, + GIT_DIFF_FORMAT_PATCH_ID, + diff_patchid_print_callback_to_buf, + &args)) < 0) goto out; if ((error = (flush_hunk(&args.result, &args.ctx))) < 0) diff -Nru libgit2-0.28.5+dfsg.1/src/diff_driver.c libgit2-1.1.0+dfsg.1/src/diff_driver.c --- libgit2-0.28.5+dfsg.1/src/diff_driver.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_driver.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,11 +9,13 @@ #include "git2/attr.h" +#include "common.h" #include "diff.h" #include "strmap.h" #include "map.h" #include "buf_text.h" #include "config.h" +#include "regexp.h" #include "repository.h" typedef enum { @@ -24,7 +26,7 @@ } git_diff_driver_t; typedef struct { - regex_t re; + git_regexp re; int flags; } git_diff_driver_pattern; @@ -38,7 +40,7 @@ uint32_t binary_flags; uint32_t other_flags; git_array_t(git_diff_driver_pattern) fn_patterns; - regex_t word_pattern; + git_regexp word_pattern; char name[GIT_FLEX_ARRAY]; }; @@ -63,7 +65,7 @@ if (!reg) return NULL; - if (git_strmap_alloc(®->drivers) < 0) { + if (git_strmap_new(®->drivers) < 0) { git_diff_driver_registry_free(reg); return NULL; } @@ -112,7 +114,7 @@ if (error < 0) break; - if ((error = p_regcomp(&pat->re, buf.ptr, regex_flags)) != 0) { + if ((error = git_regexp_compile(&pat->re, buf.ptr, regex_flags)) != 0) { /* * TODO: issue a warning */ @@ -129,7 +131,7 @@ static int diff_driver_xfuncname(const git_config_entry *entry, void *payload) { - return diff_driver_add_patterns(payload, entry->value, REG_EXTENDED); + return diff_driver_add_patterns(payload, entry->value, 0); } static int diff_driver_funcname(const git_config_entry *entry, void *payload) @@ -183,9 +185,9 @@ git_diff_driver_registry *reg, const char *driver_name) { - int error = 0; git_diff_driver_definition *ddef = NULL; git_diff_driver *drv = NULL; + int error = 0; size_t idx; for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) { @@ -204,20 +206,15 @@ if (ddef->fns && (error = diff_driver_add_patterns( - drv, ddef->fns, ddef->flags | REG_EXTENDED)) < 0) + drv, ddef->fns, ddef->flags)) < 0) goto done; if (ddef->words && - (error = p_regcomp( - &drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED))) - { - error = git_error_set_regex(&drv->word_pattern, error); + (error = git_regexp_compile(&drv->word_pattern, ddef->words, ddef->flags)) < 0) goto done; - } - git_strmap_insert(reg->drivers, drv->name, drv, &error); - if (error > 0) - error = 0; + if ((error = git_strmap_set(reg->drivers, drv->name, drv)) < 0) + goto done; done: if (error && drv) @@ -233,8 +230,8 @@ { int error = 0; git_diff_driver_registry *reg; - git_diff_driver *drv = NULL; - size_t namelen, pos; + git_diff_driver *drv; + size_t namelen; git_config *cfg = NULL; git_buf name = GIT_BUF_INIT; git_config_entry *ce = NULL; @@ -243,9 +240,8 @@ if ((reg = git_repository_driver_registry(repo)) == NULL) return -1; - pos = git_strmap_lookup_index(reg->drivers, driver_name); - if (git_strmap_valid_index(reg->drivers, pos)) { - *out = git_strmap_value_at(reg->drivers, pos); + if ((drv = git_strmap_get(reg->drivers, driver_name)) != NULL) { + *out = drv; return 0; } @@ -282,7 +278,9 @@ /* TODO: warn if diff..command or diff..textconv are set */ git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "xfuncname", strlen("xfuncname")); + if ((error = git_buf_PUTS(&name, "xfuncname")) < 0) + goto done; + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) { if (error != GIT_ENOTFOUND) @@ -291,7 +289,9 @@ } git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "funcname", strlen("funcname")); + if ((error = git_buf_PUTS(&name, "funcname")) < 0) + goto done; + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) { if (error != GIT_ENOTFOUND) @@ -306,16 +306,17 @@ } git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "wordregex", strlen("wordregex")); + if ((error = git_buf_PUTS(&name, "wordregex")) < 0) + goto done; + if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0) goto done; if (!ce || !ce->value) /* no diff..wordregex, so just continue */; - else if (!(error = p_regcomp(&drv->word_pattern, ce->value, REG_EXTENDED))) + else if (!(error = git_regexp_compile(&drv->word_pattern, ce->value, 0))) found_driver = true; else { /* TODO: warn about bad regex instead of failure */ - error = git_error_set_regex(&drv->word_pattern, error); goto done; } @@ -328,10 +329,8 @@ goto done; /* store driver in registry */ - git_strmap_insert(reg->drivers, drv->name, drv, &error); - if (error < 0) + if ((error = git_strmap_set(reg->drivers, drv->name, drv)) < 0) goto done; - error = 0; *out = drv; @@ -368,11 +367,11 @@ attrsession, 0, path, 1, attrs)) < 0) /* return error below */; - else if (GIT_ATTR_UNSPECIFIED(values[0])) + else if (GIT_ATTR_IS_UNSPECIFIED(values[0])) /* just use the auto value */; - else if (GIT_ATTR_FALSE(values[0])) + else if (GIT_ATTR_IS_FALSE(values[0])) *out = &global_drivers[DIFF_DRIVER_BINARY]; - else if (GIT_ATTR_TRUE(values[0])) + else if (GIT_ATTR_IS_TRUE(values[0])) *out = &global_drivers[DIFF_DRIVER_TEXT]; /* otherwise look for driver information in config and build driver */ @@ -397,10 +396,10 @@ return; for (i = 0; i < git_array_size(driver->fn_patterns); ++i) - regfree(& git_array_get(driver->fn_patterns, i)->re); + git_regexp_dispose(& git_array_get(driver->fn_patterns, i)->re); git_array_clear(driver->fn_patterns); - regfree(&driver->word_pattern); + git_regexp_dispose(&driver->word_pattern); git__free(driver); } @@ -448,19 +447,19 @@ git_diff_driver *driver, git_buf *line) { size_t i, maxi = git_array_size(driver->fn_patterns); - regmatch_t pmatch[2]; + git_regmatch pmatch[2]; for (i = 0; i < maxi; ++i) { git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i); - if (!regexec(&pat->re, line->ptr, 2, pmatch, 0)) { + if (!git_regexp_search(&pat->re, line->ptr, 2, pmatch)) { if (pat->flags & REG_NEGATE) return false; /* use pmatch data to trim line data */ - i = (pmatch[1].rm_so >= 0) ? 1 : 0; - git_buf_consume(line, git_buf_cstr(line) + pmatch[i].rm_so); - git_buf_truncate(line, pmatch[i].rm_eo - pmatch[i].rm_so); + i = (pmatch[1].start >= 0) ? 1 : 0; + git_buf_consume(line, git_buf_cstr(line) + pmatch[i].start); + git_buf_truncate(line, pmatch[i].end - pmatch[i].start); git_buf_rtrim(line); return true; diff -Nru libgit2-0.28.5+dfsg.1/src/diff_file.c libgit2-1.1.0+dfsg.1/src/diff_file.c --- libgit2-0.28.5+dfsg.1/src/diff_file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_file.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,7 +12,7 @@ #include "diff.h" #include "diff_generate.h" #include "odb.h" -#include "fileops.h" +#include "futils.h" #include "filter.h" #define DIFF_MAX_FILESIZE 0x20000000 @@ -50,8 +50,8 @@ fc->opts_max_size = opts->max_size ? opts->max_size : DIFF_MAX_FILESIZE; - if (fc->src == GIT_ITERATOR_TYPE_EMPTY) - fc->src = GIT_ITERATOR_TYPE_TREE; + if (fc->src == GIT_ITERATOR_EMPTY) + fc->src = GIT_ITERATOR_TREE; if (!fc->driver && git_diff_driver_lookup(&fc->driver, fc->repo, @@ -62,7 +62,7 @@ git_diff_driver_update_options(&fc->opts_flags, fc->driver); /* make sure file is conceivable mmap-able */ - if ((git_off_t)((size_t)fc->file->size) != fc->file->size) + if ((size_t)fc->file->size != fc->file->size) fc->file->flags |= GIT_DIFF_FLAG_BINARY; /* check if user is forcing text diff the file */ else if (fc->opts_flags & GIT_DIFF_FORCE_TEXT) { @@ -160,8 +160,10 @@ 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)) < 0) + return error; fc->file->size = src->buflen; - git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB); fc->file->id_abbrev = GIT_OID_HEXSZ; fc->map.len = src->buflen; @@ -232,7 +234,7 @@ int error = 0; git_odb_object *odb_obj = NULL; - if (git_oid_iszero(&fc->file->id)) + if (git_oid_is_zero(&fc->file->id)) return 0; if (fc->file->mode == GIT_FILEMODE_COMMIT) @@ -290,8 +292,8 @@ ssize_t alloc_len, read_len; int symlink_supported, error; - if ((error = git_repository__cvar( - &symlink_supported, fc->repo, GIT_CVAR_SYMLINKS)) < 0) + if ((error = git_repository__configmap_lookup( + &symlink_supported, fc->repo, GIT_CONFIGMAP_SYMLINKS)) < 0) return -1; if (!symlink_supported) @@ -330,8 +332,10 @@ if (fd < 0) return fd; - if (!fc->file->size && - !(fc->file->size = git_futils_filesize(fd))) + if (!fc->file->size) + error = git_futils_filesize(&fc->file->size, fd); + + if (error < 0 || !fc->file->size) goto cleanup; if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 && @@ -423,7 +427,7 @@ (diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0) return 0; - if (fc->src == GIT_ITERATOR_TYPE_WORKDIR) + if (fc->src == GIT_ITERATOR_WORKDIR) error = diff_file_content_load_workdir(fc, diff_opts); else error = diff_file_content_load_blob(fc, diff_opts); diff -Nru libgit2-0.28.5+dfsg.1/src/diff_file.h libgit2-1.1.0+dfsg.1/src/diff_file.h --- libgit2-0.28.5+dfsg.1/src/diff_file.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_file.h 2020-10-12 18:53:06.000000000 +0000 @@ -20,8 +20,8 @@ git_diff_driver *driver; uint32_t flags; uint32_t opts_flags; - git_off_t opts_max_size; - git_iterator_type_t src; + git_object_size_t opts_max_size; + git_iterator_t src; const git_blob *blob; git_map map; } git_diff_file_content; diff -Nru libgit2-0.28.5+dfsg.1/src/diff_generate.c libgit2-1.1.0+dfsg.1/src/diff_generate.c --- libgit2-0.28.5+dfsg.1/src/diff_generate.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_generate.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ #include "diff.h" #include "patch_generate.h" -#include "fileops.h" +#include "futils.h" #include "config.h" #include "attr_file.h" #include "filter.h" @@ -179,7 +179,7 @@ delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; - if (has_old || !git_oid_iszero(&delta->new_file.id)) + if (has_old || !git_oid_is_zero(&delta->new_file.id)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; return diff_insert_delta(diff, delta, matched_pathspec); @@ -240,7 +240,7 @@ delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS; delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS; - if (!git_oid_iszero(&new_entry->id)) + if (!git_oid_is_zero(&new_entry->id)) delta->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; } @@ -301,14 +301,14 @@ delta->old_file.path : delta->new_file.path; } -int git_diff_delta__i2w_cmp(const void *a, const void *b) +static int diff_delta_i2w_cmp(const void *a, const void *b) { const git_diff_delta *da = a, *db = b; int val = strcmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); return val ? val : ((int)da->status - (int)db->status); } -int git_diff_delta__i2w_casecmp(const void *a, const void *b) +static int diff_delta_i2w_casecmp(const void *a, const void *b) { const git_diff_delta *da = a, *db = b; int val = strcasecmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); @@ -341,16 +341,16 @@ static const char *diff_mnemonic_prefix( - git_iterator_type_t type, bool left_side) + git_iterator_t type, bool left_side) { const char *pfx = ""; switch (type) { - case GIT_ITERATOR_TYPE_EMPTY: pfx = "c"; break; - case GIT_ITERATOR_TYPE_TREE: pfx = "c"; break; - case GIT_ITERATOR_TYPE_INDEX: pfx = "i"; break; - case GIT_ITERATOR_TYPE_WORKDIR: pfx = "w"; break; - case GIT_ITERATOR_TYPE_FS: pfx = left_side ? "1" : "2"; break; + case GIT_ITERATOR_EMPTY: pfx = "c"; break; + case GIT_ITERATOR_TREE: pfx = "c"; break; + case GIT_ITERATOR_INDEX: pfx = "i"; break; + case GIT_ITERATOR_WORKDIR: pfx = "w"; break; + case GIT_ITERATOR_FS: pfx = left_side ? "1" : "2"; break; default: break; } @@ -361,7 +361,7 @@ return pfx; } -void git_diff__set_ignore_case(git_diff *diff, bool ignore_case) +static void diff_set_ignore_case(git_diff *diff, bool ignore_case) { if (!ignore_case) { diff->opts.flags &= ~GIT_DIFF_IGNORE_CASE; @@ -423,16 +423,15 @@ git_attr_session__init(&diff->base.attrsession, repo); memcpy(&diff->base.opts, &dflt, sizeof(git_diff_options)); - git_pool_init(&diff->base.pool, 1); - - if (git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) { + if (git_pool_init(&diff->base.pool, 1) < 0 || + git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) { git_diff_free(&diff->base); return NULL; } /* Use case-insensitive compare if either iterator has * the ignore_case bit set */ - git_diff__set_ignore_case( + diff_set_ignore_case( &diff->base, git_iterator_ignore_case(old_iter) || git_iterator_ignore_case(new_iter)); @@ -472,17 +471,17 @@ if ((val = git_repository_config_snapshot(&cfg, repo)) < 0) return val; - if (!git_config__cvar(&val, cfg, GIT_CVAR_SYMLINKS) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_SYMLINKS) && val) diff->diffcaps |= GIT_DIFFCAPS_HAS_SYMLINKS; - if (!git_config__cvar(&val, cfg, GIT_CVAR_IGNORESTAT) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_IGNORESTAT) && val) diff->diffcaps |= GIT_DIFFCAPS_IGNORE_STAT; if ((diff->base.opts.flags & GIT_DIFF_IGNORE_FILEMODE) == 0 && - !git_config__cvar(&val, cfg, GIT_CVAR_FILEMODE) && val) + !git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_FILEMODE) && val) diff->diffcaps |= GIT_DIFFCAPS_TRUST_MODE_BITS; - if (!git_config__cvar(&val, cfg, GIT_CVAR_TRUSTCTIME) && val) + if (!git_config__configmap_lookup(&val, cfg, GIT_CONFIGMAP_TRUSTCTIME) && val) diff->diffcaps |= GIT_DIFFCAPS_TRUST_CTIME; /* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */ @@ -497,17 +496,17 @@ /* Reverse src info if diff is reversed */ if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { - git_iterator_type_t tmp_src = diff->base.old_src; + git_iterator_t tmp_src = diff->base.old_src; diff->base.old_src = diff->base.new_src; diff->base.new_src = tmp_src; } /* Unset UPDATE_INDEX unless diffing workdir and index */ if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && - (!(diff->base.old_src == GIT_ITERATOR_TYPE_WORKDIR || - diff->base.new_src == GIT_ITERATOR_TYPE_WORKDIR) || - !(diff->base.old_src == GIT_ITERATOR_TYPE_INDEX || - diff->base.new_src == GIT_ITERATOR_TYPE_INDEX))) + (!(diff->base.old_src == GIT_ITERATOR_WORKDIR || + diff->base.new_src == GIT_ITERATOR_WORKDIR) || + !(diff->base.old_src == GIT_ITERATOR_INDEX || + diff->base.new_src == GIT_ITERATOR_INDEX))) diff->base.opts.flags &= ~GIT_DIFF_UPDATE_INDEX; /* if ignore_submodules not explicitly set, check diff config */ @@ -560,11 +559,11 @@ git_diff *diff, const char *path, uint16_t mode, - git_off_t size) + git_object_size_t size) { git_index_entry entry; - if (size < 0 || size > UINT32_MAX) { + if (size > UINT32_MAX) { git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'", path); return -1; } @@ -742,7 +741,7 @@ const git_index_entry *nitem = info->nitem; unsigned int omode = oitem->mode; unsigned int nmode = nitem->mode; - bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); + bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_WORKDIR); bool modified_uncertain = false; const char *matched_pathspec; int error = 0; @@ -797,13 +796,13 @@ /* if oids and modes match (and are valid), then file is unmodified */ } else if (git_oid_equal(&oitem->id, &nitem->id) && omode == nmode && - !git_oid_iszero(&oitem->id)) { + !git_oid_is_zero(&oitem->id)) { status = GIT_DELTA_UNMODIFIED; /* if we have an unknown OID and a workdir iterator, then check some * circumstances that can accelerate things or need special handling */ - } else if (git_oid_iszero(&nitem->id) && new_is_workdir) { + } else if (git_oid_is_zero(&nitem->id) && new_is_workdir) { bool use_ctime = ((diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) != 0); git_index *index = git_iterator_index(info->new_iter); @@ -843,7 +842,7 @@ /* if we got here and decided that the files are modified, but we * haven't calculated the OID of the new item, then calculate it now */ - if (modified_uncertain && git_oid_iszero(&nitem->id)) { + if (modified_uncertain && git_oid_is_zero(&nitem->id)) { const git_oid *update_check = DIFF_FLAG_IS_SET(diff, GIT_DIFF_UPDATE_INDEX) && omode == nmode ? &oitem->id : NULL; @@ -877,7 +876,7 @@ return diff_delta__from_two( diff, status, oitem, omode, nitem, nmode, - git_oid_iszero(&noid) ? NULL : &noid, matched_pathspec); + git_oid_is_zero(&noid) ? NULL : &noid, matched_pathspec); } static bool entry_is_prefixed( @@ -1079,7 +1078,7 @@ /* item contained in ignored directory, so skip over it */ return iterator_advance(&info->nitem, info->new_iter); - else if (info->new_iter->type != GIT_ITERATOR_TYPE_WORKDIR) { + else if (info->new_iter->type != GIT_ITERATOR_WORKDIR) { if (delta_type != GIT_DELTA_CONFLICTED) delta_type = GIT_DELTA_ADDED; } @@ -1376,7 +1375,7 @@ /* if index is in case-insensitive order, re-sort deltas to match */ if (index_ignore_case) - git_diff__set_ignore_case(diff, true); + diff_set_ignore_case(diff, true); *out = diff; diff = NULL; @@ -1527,7 +1526,7 @@ /* if index is in case-insensitive order, re-sort deltas to match */ if (old_index->ignore_case || new_index->ignore_case) - git_diff__set_ignore_case(diff, true); + diff_set_ignore_case(diff, true); *out = diff; diff = NULL; @@ -1584,10 +1583,10 @@ if (i2w_icase && !icase_mismatch) { strcomp = git__strcasecmp; - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_casecmp); + git_vector_set_cmp(&idx2wd->deltas, diff_delta_i2w_casecmp); git_vector_sort(&idx2wd->deltas); } else if (idx2wd != NULL) { - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_cmp); + git_vector_set_cmp(&idx2wd->deltas, diff_delta_i2w_cmp); git_vector_sort(&idx2wd->deltas); } diff -Nru libgit2-0.28.5+dfsg.1/src/diff_generate.h libgit2-1.1.0+dfsg.1/src/diff_generate.h --- libgit2-0.28.5+dfsg.1/src/diff_generate.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_generate.h 2020-10-12 18:53:06.000000000 +0000 @@ -88,7 +88,7 @@ git_diff *diff, const char *path, uint16_t mode, - git_off_t size); + git_object_size_t size); extern int git_diff__oid_for_entry( git_oid *out, @@ -120,7 +120,7 @@ git_odb_free(odb); if (!error) - file->size = (git_off_t)len; + file->size = (git_object_size_t)len; return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/diff.h libgit2-1.1.0+dfsg.1/src/diff.h --- libgit2-0.28.5+dfsg.1/src/diff.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff.h 2020-10-12 18:53:06.000000000 +0000 @@ -39,8 +39,8 @@ git_diff_options opts; git_vector deltas; /* vector of git_diff_delta */ git_pool pool; - git_iterator_type_t old_src; - git_iterator_type_t new_src; + git_iterator_t old_src; + git_iterator_t new_src; git_diff_perfdata perf; int (*strcomp)(const char *, const char *); @@ -57,7 +57,8 @@ const git_diff_delta *delta, const char *oldpfx, const char *newpfx, - int oid_strlen); + int oid_strlen, + bool print_index); extern int git_diff_delta__cmp(const void *a, const void *b); extern int git_diff_delta__casecmp(const void *a, const void *b); diff -Nru libgit2-0.28.5+dfsg.1/src/diff_parse.c libgit2-1.1.0+dfsg.1/src/diff_parse.c --- libgit2-0.28.5+dfsg.1/src/diff_parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -45,16 +45,15 @@ diff->base.patch_fn = git_patch_parsed_from_diff; diff->base.free_fn = diff_parsed_free; - if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) { + if (git_diff_options_init(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) { git__free(diff); return NULL; } diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE; - git_pool_init(&diff->base.pool, 1); - - if (git_vector_init(&diff->patches, 0, NULL) < 0 || + if (git_pool_init(&diff->base.pool, 1) < 0 || + git_vector_init(&diff->patches, 0, NULL) < 0 || git_vector_init(&diff->base.deltas, 0, git_diff_delta__cmp) < 0) { git_diff_free(&diff->base); return NULL; diff -Nru libgit2-0.28.5+dfsg.1/src/diff_print.c libgit2-1.1.0+dfsg.1/src/diff_print.c --- libgit2-0.28.5+dfsg.1/src/diff_print.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_print.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include "diff.h" #include "diff_file.h" #include "patch_generate.h" -#include "fileops.h" +#include "futils.h" #include "zstream.h" #include "blob.h" #include "delta.h" @@ -48,7 +48,7 @@ if (!pi->id_strlen) { if (!repo) pi->id_strlen = GIT_ABBREV_DEFAULT; - else if (git_repository__cvar(&pi->id_strlen, repo, GIT_CVAR_ABBREV) < 0) + else if (git_repository__configmap_lookup(&pi->id_strlen, repo, GIT_CONFIGMAP_ABBREV) < 0) return -1; } @@ -269,7 +269,8 @@ } static int diff_print_oid_range( - git_buf *out, const git_diff_delta *delta, int id_strlen) + git_buf *out, const git_diff_delta *delta, int id_strlen, + bool print_index) { char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1]; @@ -293,8 +294,9 @@ git_oid_tostr(end_oid, id_strlen + 1, &delta->new_file.id); if (delta->old_file.mode == delta->new_file.mode) { - git_buf_printf(out, "index %s..%s %o\n", - start_oid, end_oid, delta->old_file.mode); + if (print_index) + git_buf_printf(out, "index %s..%s %o\n", + start_oid, end_oid, delta->old_file.mode); } else { if (delta->old_file.mode == 0) git_buf_printf(out, "new file mode %o\n", delta->new_file.mode); @@ -303,7 +305,8 @@ else diff_print_modes(out, delta); - git_buf_printf(out, "index %s..%s\n", start_oid, end_oid); + if (print_index) + git_buf_printf(out, "index %s..%s\n", start_oid, end_oid); } return git_buf_oom(out) ? -1 : 0; @@ -325,16 +328,16 @@ const char *oldpath, const char *newpath) { - if (git_oid_iszero(&delta->old_file.id)) + if (git_oid_is_zero(&delta->old_file.id)) oldpath = "/dev/null"; - if (git_oid_iszero(&delta->new_file.id)) + if (git_oid_is_zero(&delta->new_file.id)) newpath = "/dev/null"; return git_buf_printf(out, template, oldpath, newpath); } -int diff_delta_format_similarity_header( +static int diff_delta_format_similarity_header( git_buf *out, const git_diff_delta *delta) { @@ -348,17 +351,16 @@ goto done; } + GIT_ASSERT(delta->status == GIT_DELTA_RENAMED || delta->status == GIT_DELTA_COPIED); if (delta->status == GIT_DELTA_RENAMED) type = "rename"; - else if (delta->status == GIT_DELTA_COPIED) - type = "copy"; else - abort(); + type = "copy"; if ((error = git_buf_puts(&old_path, delta->old_file.path)) < 0 || - (error = git_buf_puts(&new_path, delta->new_file.path)) < 0 || - (error = git_buf_quote(&old_path)) < 0 || - (error = git_buf_quote(&new_path)) < 0) + (error = git_buf_puts(&new_path, delta->new_file.path)) < 0 || + (error = git_buf_quote(&old_path)) < 0 || + (error = git_buf_quote(&new_path)) < 0) goto done; git_buf_printf(out, @@ -381,8 +383,8 @@ static bool delta_is_unchanged(const git_diff_delta *delta) { - if (git_oid_iszero(&delta->old_file.id) && - git_oid_iszero(&delta->new_file.id)) + if (git_oid_is_zero(&delta->old_file.id) && + git_oid_is_zero(&delta->new_file.id)) return true; if (delta->old_file.mode == GIT_FILEMODE_COMMIT || @@ -400,7 +402,8 @@ const git_diff_delta *delta, const char *oldpfx, const char *newpfx, - int id_strlen) + int id_strlen, + bool print_index) { git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT; bool unchanged = delta_is_unchanged(delta); @@ -424,14 +427,18 @@ git_buf_printf(out, "diff --git %s %s\n", old_path.ptr, new_path.ptr); + if (unchanged && delta->old_file.mode != delta->new_file.mode) + diff_print_modes(out, delta); + if (delta->status == GIT_DELTA_RENAMED || - (delta->status == GIT_DELTA_COPIED && unchanged)) { + (delta->status == GIT_DELTA_COPIED && unchanged)) { if ((error = diff_delta_format_similarity_header(out, delta)) < 0) goto done; } if (!unchanged) { - if ((error = diff_print_oid_range(out, delta, id_strlen)) < 0) + if ((error = diff_print_oid_range(out, delta, + id_strlen, print_index)) < 0) goto done; if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) @@ -439,9 +446,6 @@ "--- %s\n+++ %s\n", old_path.ptr, new_path.ptr); } - if (unchanged && delta->old_file.mode != delta->new_file.mode) - diff_print_modes(out, delta); - if (git_buf_oom(out)) error = -1; @@ -487,6 +491,9 @@ } git_buf_putc(pi->buf, '\n'); + if (git_buf_oom(pi->buf)) + return -1; + return 0; } @@ -497,21 +504,17 @@ git_buf old_path = GIT_BUF_INIT, new_path = GIT_BUF_INIT; int error; - if ((error = diff_delta_format_path( - &old_path, old_pfx, delta->old_file.path)) < 0 || - (error = diff_delta_format_path( - &new_path, new_pfx, delta->new_file.path)) < 0) + if ((error = diff_delta_format_path(&old_path, old_pfx, delta->old_file.path)) < 0 || + (error = diff_delta_format_path(&new_path, new_pfx, delta->new_file.path)) < 0 || + (error = diff_delta_format_with_paths(pi->buf, delta, "Binary files %s and %s differ\n", + old_path.ptr, new_path.ptr)) < 0) goto done; pi->line.num_lines = 1; - error = diff_delta_format_with_paths( - pi->buf, delta, "Binary files %s and %s differ\n", - old_path.ptr, new_path.ptr); done: git_buf_dispose(&old_path); git_buf_dispose(&new_path); - return error; } @@ -535,10 +538,9 @@ pi->line.num_lines++; if ((error = format_binary(pi, binary->new_file.type, binary->new_file.data, - binary->new_file.datalen, binary->new_file.inflatedlen)) < 0 || - (error = format_binary(pi, binary->old_file.type, binary->old_file.data, - binary->old_file.datalen, binary->old_file.inflatedlen)) < 0) { - + binary->new_file.datalen, binary->new_file.inflatedlen)) < 0 || + (error = format_binary(pi, binary->old_file.type, binary->old_file.data, + binary->old_file.datalen, binary->old_file.inflatedlen)) < 0) { if (error == GIT_EBUFS) { git_error_clear(); git_buf_truncate(pi->buf, pre_binary_size); @@ -566,6 +568,7 @@ (pi->flags & GIT_DIFF_FORCE_BINARY); bool show_binary = !!(pi->flags & GIT_DIFF_SHOW_BINARY); int id_strlen = pi->id_strlen; + bool print_index = (pi->format != GIT_DIFF_FORMAT_PATCH_ID); if (binary && show_binary) id_strlen = delta->old_file.id_abbrev ? delta->old_file.id_abbrev : @@ -574,15 +577,15 @@ GIT_UNUSED(progress); if (S_ISDIR(delta->new_file.mode) || - delta->status == GIT_DELTA_UNMODIFIED || - delta->status == GIT_DELTA_IGNORED || - delta->status == GIT_DELTA_UNREADABLE || - (delta->status == GIT_DELTA_UNTRACKED && + delta->status == GIT_DELTA_UNMODIFIED || + delta->status == GIT_DELTA_IGNORED || + delta->status == GIT_DELTA_UNREADABLE || + (delta->status == GIT_DELTA_UNTRACKED && (pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0)) return 0; - if ((error = git_diff_delta__format_file_header( - pi->buf, delta, oldpfx, newpfx, id_strlen)) < 0) + if ((error = git_diff_delta__format_file_header(pi->buf, delta, oldpfx, newpfx, + id_strlen, print_index)) < 0) return error; pi->line.origin = GIT_DIFF_LINE_FILE_HDR; @@ -670,6 +673,11 @@ print_hunk = diff_print_patch_hunk; print_line = diff_print_patch_line; break; + case GIT_DIFF_FORMAT_PATCH_ID: + print_file = diff_print_patch_file; + print_binary = diff_print_patch_binary; + print_line = diff_print_patch_line; + break; case GIT_DIFF_FORMAT_PATCH_HEADER: print_file = diff_print_patch_file; break; @@ -687,17 +695,16 @@ return -1; } - if (!(error = diff_print_info_init_fromdiff( - &pi, &buf, diff, format, print_cb, payload))) { - error = git_diff_foreach( - diff, print_file, print_binary, print_hunk, print_line, &pi); + if ((error = diff_print_info_init_fromdiff(&pi, &buf, diff, format, print_cb, payload)) < 0) + goto out; - if (error) /* make sure error message is set */ - git_error_set_after_callback_function(error, "git_diff_print"); + if ((error = git_diff_foreach(diff, print_file, print_binary, print_hunk, print_line, &pi)) != 0) { + git_error_set_after_callback_function(error, "git_diff_print"); + goto out; } +out: git_buf_dispose(&buf); - return error; } @@ -716,8 +723,8 @@ } if (line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION || - line->origin == GIT_DIFF_LINE_CONTEXT) + line->origin == GIT_DIFF_LINE_DELETION || + line->origin == GIT_DIFF_LINE_CONTEXT) git_buf_putc(output, line->origin); return git_buf_put(output, line->content, line->content_len); @@ -730,14 +737,27 @@ void *payload) { FILE *fp = payload ? payload : stdout; + int error; - GIT_UNUSED(delta); GIT_UNUSED(hunk); + GIT_UNUSED(delta); + GIT_UNUSED(hunk); if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, fp); - fwrite(line->content, 1, line->content_len, fp); + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) { + while ((error = fputc(line->origin, fp)) == EINTR) + continue; + if (error) { + git_error_set(GIT_ERROR_OS, "could not write status"); + return -1; + } + } + + if (fwrite(line->content, line->content_len, 1, fp) != 1) { + git_error_set(GIT_ERROR_OS, "could not write line"); + return -1; + } + return 0; } @@ -746,8 +766,7 @@ { assert(out && diff); git_buf_sanitize(out); - return git_diff_print( - diff, format, git_diff_print_callback__to_buf, out); + return git_diff_print(diff, format, git_diff_print_callback__to_buf, out); } /* print a git_patch to an output callback */ @@ -756,28 +775,24 @@ git_diff_line_cb print_cb, void *payload) { - int error; git_buf temp = GIT_BUF_INIT; diff_print_info pi; + int error; assert(patch && print_cb); - if (!(error = diff_print_info_init_frompatch( - &pi, &temp, patch, - GIT_DIFF_FORMAT_PATCH, print_cb, payload))) - { - error = git_patch__invoke_callbacks( - patch, - diff_print_patch_file, diff_print_patch_binary, - diff_print_patch_hunk, diff_print_patch_line, - &pi); + if ((error = diff_print_info_init_frompatch(&pi, &temp, patch, + GIT_DIFF_FORMAT_PATCH, print_cb, payload)) < 0) + goto out; - if (error) /* make sure error message is set */ - git_error_set_after_callback_function(error, "git_patch_print"); + if ((error = git_patch__invoke_callbacks(patch, diff_print_patch_file, diff_print_patch_binary, + diff_print_patch_hunk, diff_print_patch_line, &pi)) < 0) { + git_error_set_after_callback_function(error, "git_patch_print"); + goto out; } +out: git_buf_dispose(&temp); - return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/diff_stats.c libgit2-1.1.0+dfsg.1/src/diff_stats.c --- libgit2-0.28.5+dfsg.1/src/diff_stats.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_stats.c 2020-10-12 18:53:06.000000000 +0000 @@ -46,23 +46,23 @@ return count; } -int git_diff_file_stats__full_to_buf( +static int diff_file_stats_full_to_buf( git_buf *out, const git_diff_delta *delta, const diff_file_stats *filestat, const git_diff_stats *stats, size_t width) { - const char *old_path = NULL, *new_path = NULL; + const char *old_path = NULL, *new_path = NULL, *adddel_path = NULL; size_t padding; - git_off_t old_size, new_size; + git_object_size_t old_size, new_size; old_path = delta->old_file.path; new_path = delta->new_file.path; old_size = delta->old_file.size; new_size = delta->new_file.size; - if (strcmp(old_path, new_path) != 0) { + if (old_path && new_path && strcmp(old_path, new_path) != 0) { size_t common_dirlen; int error; @@ -82,10 +82,11 @@ if (error < 0) goto on_error; } else { - if (git_buf_printf(out, " %s", old_path) < 0) + adddel_path = new_path ? new_path : old_path; + if (git_buf_printf(out, " %s", adddel_path) < 0) goto on_error; - padding = stats->max_name - strlen(old_path); + padding = stats->max_name - strlen(adddel_path); if (stats->renames > 0) padding += strlen(DIFF_RENAME_FILE_SEPARATOR); @@ -134,7 +135,7 @@ return (git_buf_oom(out) ? -1 : 0); } -int git_diff_file_stats__number_to_buf( +static int diff_file_stats_number_to_buf( git_buf *out, const git_diff_delta *delta, const diff_file_stats *filestats) @@ -151,7 +152,7 @@ return error; } -int git_diff_file_stats__summary_to_buf( +static int diff_file_stats_summary_to_buf( git_buf *out, const git_diff_delta *delta) { @@ -211,7 +212,7 @@ /* TODO ugh */ namelen = strlen(delta->new_file.path); - if (strcmp(delta->old_file.path, delta->new_file.path) != 0) { + if (delta->old_file.path && strcmp(delta->old_file.path, delta->new_file.path) != 0) { namelen += strlen(delta->old_file.path); stats->renames++; } @@ -288,7 +289,7 @@ if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) continue; - error = git_diff_file_stats__number_to_buf( + error = diff_file_stats_number_to_buf( out, delta, &stats->filestats[i]); if (error < 0) return error; @@ -309,7 +310,7 @@ if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) continue; - error = git_diff_file_stats__full_to_buf( + error = diff_file_stats_full_to_buf( out, delta, &stats->filestats[i], stats, width); if (error < 0) return error; @@ -342,7 +343,7 @@ if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) continue; - error = git_diff_file_stats__summary_to_buf(out, delta); + error = diff_file_stats_summary_to_buf(out, delta); if (error < 0) return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/diff_tform.c libgit2-1.1.0+dfsg.1/src/diff_tform.c --- libgit2-0.28.5+dfsg.1/src/diff_tform.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/diff_tform.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,7 +14,7 @@ #include "diff.h" #include "diff_generate.h" #include "path.h" -#include "fileops.h" +#include "futils.h" #include "config.h" git_diff_delta *git_diff__delta_dup( @@ -136,11 +136,10 @@ return -1; } - if (git_vector_init(&onto_new, onto->deltas.length, git_diff_delta__cmp) < 0) + if (git_vector_init(&onto_new, onto->deltas.length, git_diff_delta__cmp) < 0 || + git_pool_init(&onto_pool, 1) < 0) return -1; - git_pool_init(&onto_pool, 1); - for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i); const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j); @@ -389,7 +388,7 @@ if (insert_delete_side_of_split(diff, &onto, delta) < 0) goto on_error; - if (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) + if (diff->new_src == GIT_ITERATOR_WORKDIR) delta->status = GIT_DELTA_UNTRACKED; else delta->status = GIT_DELTA_ADDED; @@ -441,7 +440,7 @@ typedef struct { size_t idx; - git_iterator_type_t src; + git_iterator_t src; git_repository *repo; git_diff_file *file; git_buf data; @@ -460,7 +459,7 @@ info->blob = NULL; git_buf_init(&info->data, 0); - if (info->file->size > 0 || info->src == GIT_ITERATOR_TYPE_WORKDIR) + if (info->file->size > 0 || info->src == GIT_ITERATOR_WORKDIR) return 0; return git_diff_file__resolve_zero_size( @@ -475,7 +474,7 @@ int error = 0; git_diff_file *file = info->file; - if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { + if (info->src == GIT_ITERATOR_WORKDIR) { if ((error = git_buf_joinpath( &info->data, git_repository_workdir(info->repo), file->path)) < 0) return error; @@ -510,7 +509,7 @@ if (file->size != git_blob_rawsize(info->blob)) file->size = git_blob_rawsize(info->blob); - sz = (size_t)(git__is_sizet(file->size) ? file->size : -1); + sz = git__is_sizet(file->size) ? (size_t)file->size : (size_t)-1; error = opts->metric->buffer_signature( &cache[info->idx], info->file, @@ -560,14 +559,14 @@ /* if exact match is requested, force calculation of missing OIDs now */ if (exact_match) { - if (git_oid_iszero(&a_file->id) && - diff->old_src == GIT_ITERATOR_TYPE_WORKDIR && + if (git_oid_is_zero(&a_file->id) && + diff->old_src == GIT_ITERATOR_WORKDIR && !git_diff__oid_for_file(&a_file->id, diff, a_file->path, a_file->mode, a_file->size)) a_file->flags |= GIT_DIFF_FLAG_VALID_ID; - if (git_oid_iszero(&b_file->id) && - diff->new_src == GIT_ITERATOR_TYPE_WORKDIR && + if (git_oid_is_zero(&b_file->id) && + diff->new_src == GIT_ITERATOR_WORKDIR && !git_diff__oid_for_file(&b_file->id, diff, b_file->path, b_file->mode, b_file->size)) b_file->flags |= GIT_DIFF_FLAG_VALID_ID; @@ -1013,7 +1012,7 @@ delta_make_rename(tgt, src, best_match->similarity); - src->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? + src->status = (diff->new_src == GIT_ITERATOR_WORKDIR) ? GIT_DELTA_UNTRACKED : GIT_DELTA_ADDED; src->nfiles = 1; memset(&src->old_file, 0, sizeof(src->old_file)); diff -Nru libgit2-0.28.5+dfsg.1/src/errors.c libgit2-1.1.0+dfsg.1/src/errors.c --- libgit2-0.28.5+dfsg.1/src/errors.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/errors.c 2020-10-12 18:53:06.000000000 +0000 @@ -49,9 +49,17 @@ GIT_GLOBAL->last_error = &g_git_oom_error; } -void git_error_set(int error_class, const char *string, ...) +void git_error_set(int error_class, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + git_error_vset(error_class, fmt, ap); + va_end(ap); +} + +void git_error_vset(int error_class, const char *fmt, va_list ap) { - va_list arglist; #ifdef GIT_WIN32 DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0; #endif @@ -59,11 +67,8 @@ git_buf *buf = &GIT_GLOBAL->error_buf; git_buf_clear(buf); - if (string) { - va_start(arglist, string); - git_buf_vprintf(buf, string, arglist); - va_end(arglist); - + if (fmt) { + git_buf_vprintf(buf, fmt, ap); if (error_class == GIT_ERROR_OS) git_buf_PUTS(buf, ": "); } @@ -90,34 +95,25 @@ set_error_from_buffer(error_class); } -void git_error_set_str(int error_class, const char *string) +int git_error_set_str(int error_class, const char *string) { git_buf *buf = &GIT_GLOBAL->error_buf; assert(string); - if (!string) - return; + if (!string) { + git_error_set(GIT_ERROR_INVALID, "unspecified caller error"); + return -1; + } git_buf_clear(buf); git_buf_puts(buf, string); - if (!git_buf_oom(buf)) - set_error_from_buffer(error_class); -} - -int git_error_set_regex(const regex_t *regex, int error_code) -{ - char error_buf[1024]; - assert(error_code); + if (git_buf_oom(buf)) + return -1; - regerror(error_code, regex, error_buf, sizeof(error_buf)); - git_error_set_str(GIT_ERROR_REGEX, error_buf); - - if (error_code == REG_NOMATCH) - return GIT_ENOTFOUND; - - return GIT_EINVALIDSPEC; + set_error_from_buffer(error_class); + return 0; } void git_error_clear(void) @@ -214,6 +210,7 @@ /* Deprecated error values and functions */ +#ifndef GIT_DEPRECATE_HARD const git_error *giterr_last(void) { return git_error_last(); @@ -233,3 +230,4 @@ { git_error_set_oom(); } +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/errors.h libgit2-1.1.0+dfsg.1/src/errors.h --- libgit2-0.28.5+dfsg.1/src/errors.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/errors.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * 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_errors_h__ +#define INCLUDE_errors_h__ + +#include "common.h" + +/* + * Set the error message for this thread, formatting as needed. + */ +void git_error_set(int error_class, const char *fmt, ...) GIT_FORMAT_PRINTF(2, 3); +void git_error_vset(int error_class, const char *fmt, va_list ap); + +/** + * Set error message for user callback if needed. + * + * If the error code in non-zero and no error message is set, this + * sets a generic error message. + * + * @return This always returns the `error_code` parameter. + */ +GIT_INLINE(int) git_error_set_after_callback_function( + int error_code, const char *action) +{ + if (error_code) { + const git_error *e = git_error_last(); + if (!e || !e->message) + git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, + "%s callback returned %d", action, error_code); + } + return error_code; +} + +#ifdef GIT_WIN32 +#define git_error_set_after_callback(code) \ + git_error_set_after_callback_function((code), __FUNCTION__) +#else +#define git_error_set_after_callback(code) \ + git_error_set_after_callback_function((code), __func__) +#endif + +/** + * Gets the system error code for this thread. + */ +int git_error_system_last(void); + +/** + * Sets the system error code for this thread. + */ +void git_error_system_set(int code); + +/** + * Structure to preserve libgit2 error state + */ +typedef struct { + int error_code; + unsigned int oom : 1; + git_error error_msg; +} git_error_state; + +/** + * Capture current error state to restore later, returning error code. + * If `error_code` is zero, this does not clear the current error state. + * You must either restore this error state, or free it. + */ +extern int git_error_state_capture(git_error_state *state, int error_code); + +/** + * Restore error state to a previous value, returning saved error code. + */ +extern int git_error_state_restore(git_error_state *state); + +/** Free an error state. */ +extern void git_error_state_free(git_error_state *state); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/features.h.in libgit2-1.1.0+dfsg.1/src/features.h.in --- libgit2-0.28.5+dfsg.1/src/features.h.in 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/features.h.in 2020-10-12 18:53:06.000000000 +0000 @@ -15,14 +15,21 @@ #cmakedefine GIT_USE_STAT_MTIMESPEC 1 #cmakedefine GIT_USE_STAT_MTIME_NSEC 1 #cmakedefine GIT_USE_FUTIMENS 1 -#cmakedefine GIT_USE_REGCOMP_L 1 + +#cmakedefine GIT_REGEX_REGCOMP_L +#cmakedefine GIT_REGEX_REGCOMP +#cmakedefine GIT_REGEX_PCRE +#cmakedefine GIT_REGEX_PCRE2 +#cmakedefine GIT_REGEX_BUILTIN 1 #cmakedefine GIT_SSH 1 #cmakedefine GIT_SSH_MEMORY_CREDENTIALS 1 +#cmakedefine GIT_NTLM 1 #cmakedefine GIT_GSSAPI 1 -#cmakedefine GIT_WINHTTP 1 +#cmakedefine GIT_GSSFRAMEWORK 1 +#cmakedefine GIT_WINHTTP 1 #cmakedefine GIT_HTTPS 1 #cmakedefine GIT_OPENSSL 1 #cmakedefine GIT_SECURE_TRANSPORT 1 diff -Nru libgit2-0.28.5+dfsg.1/src/fetch.c libgit2-1.1.0+dfsg.1/src/fetch.c --- libgit2-0.28.5+dfsg.1/src/fetch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fetch.c 2020-10-12 18:53:06.000000000 +0000 @@ -134,7 +134,7 @@ int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks) { git_transport *t = remote->transport; - git_transfer_progress_cb progress = NULL; + git_indexer_progress_cb progress = NULL; void *payload = NULL; if (!remote->need_pack) @@ -148,9 +148,16 @@ return t->download_pack(t, remote->repo, &remote->stats, progress, payload); } -int git_fetch_init_options(git_fetch_options *opts, unsigned int version) +int git_fetch_options_init(git_fetch_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_fetch_options, GIT_FETCH_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_fetch_init_options(git_fetch_options *opts, unsigned int version) +{ + return git_fetch_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/fetchhead.c libgit2-1.1.0+dfsg.1/src/fetchhead.c --- libgit2-0.28.5+dfsg.1/src/fetchhead.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fetchhead.c 2020-10-12 18:53:06.000000000 +0000 @@ -11,10 +11,10 @@ #include "git2/oid.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "filebuf.h" -#include "netops.h" #include "refs.h" +#include "net.h" #include "repository.h" int git_fetchhead_ref_cmp(const void *a, const void *b) @@ -39,18 +39,18 @@ static char *sanitized_remote_url(const char *remote_url) { - gitno_connection_data url = {0}; + git_net_url url = GIT_NET_URL_INIT; char *sanitized = NULL; int error; - if (gitno_connection_data_from_url(&url, remote_url, NULL) == 0) { + if (git_net_url_parse(&url, remote_url) == 0) { git_buf buf = GIT_BUF_INIT; - git__free(url.user); - git__free(url.pass); - url.user = url.pass = NULL; + git__free(url.username); + git__free(url.password); + url.username = url.password = NULL; - if ((error = gitno_connection_data_fmt(&buf, &url)) < 0) + if ((error = git_net_url_fmt(&buf, &url)) < 0) goto fallback; sanitized = git_buf_detach(&buf); @@ -60,7 +60,7 @@ if (!sanitized) sanitized = git__strdup(remote_url); - gitno_connection_data_free_ptrs(&url); + git_net_url_dispose(&url); return sanitized; } diff -Nru libgit2-0.28.5+dfsg.1/src/filebuf.c libgit2-1.1.0+dfsg.1/src/filebuf.c --- libgit2-0.28.5+dfsg.1/src/filebuf.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/filebuf.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,7 +7,7 @@ #include "filebuf.h" -#include "fileops.h" +#include "futils.h" static const size_t WRITE_BUFFER_SIZE = (4096 * 2); diff -Nru libgit2-0.28.5+dfsg.1/src/filebuf.h libgit2-1.1.0+dfsg.1/src/filebuf.h --- libgit2-0.28.5+dfsg.1/src/filebuf.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/filebuf.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ #include "common.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include diff -Nru libgit2-0.28.5+dfsg.1/src/fileops.c libgit2-1.1.0+dfsg.1/src/fileops.c --- libgit2-0.28.5+dfsg.1/src/fileops.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fileops.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1185 +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 "fileops.h" - -#include "global.h" -#include "strmap.h" -#include -#if GIT_WIN32 -#include "win32/findfile.h" -#endif - -int git_futils_mkpath2file(const char *file_path, const mode_t mode) -{ - return git_futils_mkdir( - file_path, mode, - GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR); -} - -int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode) -{ - int fd; - mode_t mask; - - p_umask(mask = p_umask(0)); - - git_buf_sets(path_out, filename); - git_buf_puts(path_out, "_git2_XXXXXX"); - - if (git_buf_oom(path_out)) - return -1; - - if ((fd = p_mkstemp(path_out->ptr)) < 0) { - git_error_set(GIT_ERROR_OS, - "failed to create temporary file '%s'", path_out->ptr); - return -1; - } - - if (p_chmod(path_out->ptr, (mode & ~mask))) { - git_error_set(GIT_ERROR_OS, - "failed to set permissions on file '%s'", path_out->ptr); - return -1; - } - - return fd; -} - -int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode) -{ - int fd; - - if (git_futils_mkpath2file(path, dirmode) < 0) - return -1; - - fd = p_creat(path, mode); - if (fd < 0) { - git_error_set(GIT_ERROR_OS, "failed to create file '%s'", path); - return -1; - } - - return fd; -} - -int git_futils_creat_locked(const char *path, const mode_t mode) -{ - int fd = p_open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, - mode); - - if (fd < 0) { - int error = errno; - git_error_set(GIT_ERROR_OS, "failed to create locked file '%s'", path); - switch (error) { - case EEXIST: - return GIT_ELOCKED; - case ENOENT: - return GIT_ENOTFOUND; - default: - return -1; - } - } - - return fd; -} - -int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode) -{ - if (git_futils_mkpath2file(path, dirmode) < 0) - return -1; - - return git_futils_creat_locked(path, mode); -} - -int git_futils_open_ro(const char *path) -{ - int fd = p_open(path, O_RDONLY); - if (fd < 0) - return git_path_set_error(errno, path, "open"); - return fd; -} - -int git_futils_truncate(const char *path, int mode) -{ - int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); - if (fd < 0) - return git_path_set_error(errno, path, "open"); - - close(fd); - return 0; -} - -git_off_t git_futils_filesize(git_file fd) -{ - struct stat sb; - - if (p_fstat(fd, &sb)) { - git_error_set(GIT_ERROR_OS, "failed to stat file descriptor"); - return -1; - } - - return sb.st_size; -} - -mode_t git_futils_canonical_mode(mode_t raw_mode) -{ - if (S_ISREG(raw_mode)) - return S_IFREG | GIT_PERMS_CANONICAL(raw_mode); - else if (S_ISLNK(raw_mode)) - return S_IFLNK; - else if (S_ISGITLINK(raw_mode)) - return S_IFGITLINK; - else if (S_ISDIR(raw_mode)) - return S_IFDIR; - else - return 0; -} - -int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) -{ - ssize_t read_size = 0; - size_t alloc_len; - - git_buf_clear(buf); - - if (!git__is_ssizet(len)) { - git_error_set(GIT_ERROR_INVALID, "read too large"); - return -1; - } - - GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, len, 1); - if (git_buf_grow(buf, alloc_len) < 0) - return -1; - - /* p_read loops internally to read len bytes */ - read_size = p_read(fd, buf->ptr, len); - - if (read_size != (ssize_t)len) { - git_error_set(GIT_ERROR_OS, "failed to read descriptor"); - git_buf_dispose(buf); - return -1; - } - - buf->ptr[read_size] = '\0'; - buf->size = read_size; - - return 0; -} - -int git_futils_readbuffer_updated( - git_buf *out, const char *path, git_oid *checksum, int *updated) -{ - int error; - git_file fd; - struct stat st; - git_buf buf = GIT_BUF_INIT; - git_oid checksum_new; - - assert(out && path && *path); - - if (updated != NULL) - *updated = 0; - - if (p_stat(path, &st) < 0) - return git_path_set_error(errno, path, "stat"); - - - if (S_ISDIR(st.st_mode)) { - git_error_set(GIT_ERROR_INVALID, "requested file is a directory"); - return GIT_ENOTFOUND; - } - - if (!git__is_sizet(st.st_size+1)) { - git_error_set(GIT_ERROR_OS, "invalid regular file stat for '%s'", path); - return -1; - } - - if ((fd = git_futils_open_ro(path)) < 0) - return fd; - - if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) { - p_close(fd); - return -1; - } - - p_close(fd); - - if (checksum) { - if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) { - git_buf_dispose(&buf); - return error; - } - - /* - * If we were given a checksum, we only want to use it if it's different - */ - if (!git_oid__cmp(checksum, &checksum_new)) { - git_buf_dispose(&buf); - if (updated) - *updated = 0; - - return 0; - } - - git_oid_cpy(checksum, &checksum_new); - } - - /* - * If we're here, the file did change, or the user didn't have an old version - */ - if (updated != NULL) - *updated = 1; - - git_buf_swap(out, &buf); - git_buf_dispose(&buf); - - return 0; -} - -int git_futils_readbuffer(git_buf *buf, const char *path) -{ - return git_futils_readbuffer_updated(buf, path, NULL, NULL); -} - -int git_futils_writebuffer( - const git_buf *buf, const char *path, int flags, mode_t mode) -{ - int fd, do_fsync = 0, error = 0; - - if (!flags) - flags = O_CREAT | O_TRUNC | O_WRONLY; - - if ((flags & O_FSYNC) != 0) - do_fsync = 1; - - flags &= ~O_FSYNC; - - if (!mode) - mode = GIT_FILEMODE_BLOB; - - if ((fd = p_open(path, flags, mode)) < 0) { - git_error_set(GIT_ERROR_OS, "could not open '%s' for writing", path); - return fd; - } - - if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) { - git_error_set(GIT_ERROR_OS, "could not write to '%s'", path); - (void)p_close(fd); - return error; - } - - if (do_fsync && (error = p_fsync(fd)) < 0) { - git_error_set(GIT_ERROR_OS, "could not fsync '%s'", path); - p_close(fd); - return error; - } - - if ((error = p_close(fd)) < 0) { - git_error_set(GIT_ERROR_OS, "error while closing '%s'", path); - return error; - } - - if (do_fsync && (flags & O_CREAT)) - error = git_futils_fsync_parent(path); - - return error; -} - -int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode) -{ - if (git_futils_mkpath2file(to, dirmode) < 0) - return -1; - - if (p_rename(from, to) < 0) { - git_error_set(GIT_ERROR_OS, "failed to rename '%s' to '%s'", from, to); - return -1; - } - - return 0; -} - -int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len) -{ - return p_mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin); -} - -int git_futils_mmap_ro_file(git_map *out, const char *path) -{ - git_file fd = git_futils_open_ro(path); - git_off_t len; - int result; - - if (fd < 0) - return fd; - - if ((len = git_futils_filesize(fd)) < 0) { - result = -1; - goto out; - } - - if (!git__is_sizet(len)) { - git_error_set(GIT_ERROR_OS, "file `%s` too large to mmap", path); - result = -1; - goto out; - } - - result = git_futils_mmap_ro(out, fd, 0, (size_t)len); -out: - p_close(fd); - return result; -} - -void git_futils_mmap_free(git_map *out) -{ - p_munmap(out); -} - -GIT_INLINE(int) mkdir_validate_dir( - const char *path, - struct stat *st, - mode_t mode, - uint32_t flags, - struct git_futils_mkdir_options *opts) -{ - /* with exclusive create, existing dir is an error */ - if ((flags & GIT_MKDIR_EXCL) != 0) { - git_error_set(GIT_ERROR_FILESYSTEM, - "failed to make directory '%s': directory exists", path); - return GIT_EEXISTS; - } - - if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) || - (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) { - if (p_unlink(path) < 0) { - git_error_set(GIT_ERROR_OS, "failed to remove %s '%s'", - S_ISLNK(st->st_mode) ? "symlink" : "file", path); - return GIT_EEXISTS; - } - - opts->perfdata.mkdir_calls++; - - if (p_mkdir(path, mode) < 0) { - git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path); - return GIT_EEXISTS; - } - } - - else if (S_ISLNK(st->st_mode)) { - /* Re-stat the target, make sure it's a directory */ - opts->perfdata.stat_calls++; - - if (p_stat(path, st) < 0) { - git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path); - return GIT_EEXISTS; - } - } - - else if (!S_ISDIR(st->st_mode)) { - git_error_set(GIT_ERROR_FILESYSTEM, - "failed to make directory '%s': directory exists", path); - return GIT_EEXISTS; - } - - return 0; -} - -GIT_INLINE(int) mkdir_validate_mode( - const char *path, - struct stat *st, - bool terminal_path, - mode_t mode, - uint32_t flags, - struct git_futils_mkdir_options *opts) -{ - if (((terminal_path && (flags & GIT_MKDIR_CHMOD) != 0) || - (flags & GIT_MKDIR_CHMOD_PATH) != 0) && st->st_mode != mode) { - - opts->perfdata.chmod_calls++; - - if (p_chmod(path, mode) < 0) { - git_error_set(GIT_ERROR_OS, "failed to set permissions on '%s'", path); - return -1; - } - } - - return 0; -} - -GIT_INLINE(int) mkdir_canonicalize( - git_buf *path, - uint32_t flags) -{ - ssize_t root_len; - - if (path->size == 0) { - git_error_set(GIT_ERROR_OS, "attempt to create empty path"); - return -1; - } - - /* Trim trailing slashes (except the root) */ - if ((root_len = git_path_root(path->ptr)) < 0) - root_len = 0; - else - root_len++; - - while (path->size > (size_t)root_len && path->ptr[path->size - 1] == '/') - path->ptr[--path->size] = '\0'; - - /* if we are not supposed to made the last element, truncate it */ - if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) { - git_path_dirname_r(path, path->ptr); - flags |= GIT_MKDIR_SKIP_LAST; - } - if ((flags & GIT_MKDIR_SKIP_LAST) != 0) { - git_path_dirname_r(path, path->ptr); - } - - /* We were either given the root path (or trimmed it to - * the root), we don't have anything to do. - */ - if (path->size <= (size_t)root_len) - git_buf_clear(path); - - return 0; -} - -int git_futils_mkdir( - const char *path, - mode_t mode, - uint32_t flags) -{ - git_buf make_path = GIT_BUF_INIT, parent_path = GIT_BUF_INIT; - const char *relative; - struct git_futils_mkdir_options opts = { 0 }; - struct stat st; - size_t depth = 0; - int len = 0, root_len, error; - - if ((error = git_buf_puts(&make_path, path)) < 0 || - (error = mkdir_canonicalize(&make_path, flags)) < 0 || - (error = git_buf_puts(&parent_path, make_path.ptr)) < 0 || - make_path.size == 0) - goto done; - - root_len = git_path_root(make_path.ptr); - - /* find the first parent directory that exists. this will be used - * as the base to dirname_relative. - */ - for (relative = make_path.ptr; parent_path.size; ) { - error = p_lstat(parent_path.ptr, &st); - - if (error == 0) { - break; - } else if (errno != ENOENT) { - git_error_set(GIT_ERROR_OS, "failed to stat '%s'", parent_path.ptr); - error = -1; - goto done; - } - - depth++; - - /* examine the parent of the current path */ - if ((len = git_path_dirname_r(&parent_path, parent_path.ptr)) < 0) { - error = len; - goto done; - } - - assert(len); - - /* - * We've walked all the given path's parents and it's either relative - * (the parent is simply '.') or rooted (the length is less than or - * equal to length of the root path). The path may be less than the - * root path length on Windows, where `C:` == `C:/`. - */ - if ((len == 1 && parent_path.ptr[0] == '.') || len <= root_len) { - relative = make_path.ptr; - break; - } - - relative = make_path.ptr + len + 1; - - /* not recursive? just make this directory relative to its parent. */ - if ((flags & GIT_MKDIR_PATH) == 0) - break; - } - - /* we found an item at the location we're trying to create, - * validate it. - */ - if (depth == 0) { - error = mkdir_validate_dir(make_path.ptr, &st, mode, flags, &opts); - - if (!error) - error = mkdir_validate_mode( - make_path.ptr, &st, true, mode, flags, &opts); - - goto done; - } - - /* we already took `SKIP_LAST` and `SKIP_LAST2` into account when - * canonicalizing `make_path`. - */ - flags &= ~(GIT_MKDIR_SKIP_LAST2 | GIT_MKDIR_SKIP_LAST); - - error = git_futils_mkdir_relative(relative, - parent_path.size ? parent_path.ptr : NULL, mode, flags, &opts); - -done: - git_buf_dispose(&make_path); - git_buf_dispose(&parent_path); - return error; -} - -int git_futils_mkdir_r(const char *path, const mode_t mode) -{ - return git_futils_mkdir(path, mode, GIT_MKDIR_PATH); -} - -int git_futils_mkdir_relative( - const char *relative_path, - const char *base, - mode_t mode, - uint32_t flags, - struct git_futils_mkdir_options *opts) -{ - git_buf make_path = GIT_BUF_INIT; - ssize_t root = 0, min_root_len; - char lastch = '/', *tail; - struct stat st; - struct git_futils_mkdir_options empty_opts = {0}; - int error; - - if (!opts) - opts = &empty_opts; - - /* build path and find "root" where we should start calling mkdir */ - if (git_path_join_unrooted(&make_path, relative_path, base, &root) < 0) - return -1; - - if ((error = mkdir_canonicalize(&make_path, flags)) < 0 || - make_path.size == 0) - goto done; - - /* if we are not supposed to make the whole path, reset root */ - if ((flags & GIT_MKDIR_PATH) == 0) - root = git_buf_rfind(&make_path, '/'); - - /* advance root past drive name or network mount prefix */ - min_root_len = git_path_root(make_path.ptr); - if (root < min_root_len) - root = min_root_len; - while (root >= 0 && make_path.ptr[root] == '/') - ++root; - - /* clip root to make_path length */ - if (root > (ssize_t)make_path.size) - root = (ssize_t)make_path.size; /* i.e. NUL byte of string */ - if (root < 0) - root = 0; - - /* walk down tail of path making each directory */ - for (tail = &make_path.ptr[root]; *tail; *tail = lastch) { - bool mkdir_attempted = false; - - /* advance tail to include next path component */ - while (*tail == '/') - tail++; - while (*tail && *tail != '/') - tail++; - - /* truncate path at next component */ - lastch = *tail; - *tail = '\0'; - st.st_mode = 0; - - if (opts->dir_map && git_strmap_exists(opts->dir_map, make_path.ptr)) - continue; - - /* See what's going on with this path component */ - opts->perfdata.stat_calls++; - -retry_lstat: - if (p_lstat(make_path.ptr, &st) < 0) { - if (mkdir_attempted || errno != ENOENT) { - git_error_set(GIT_ERROR_OS, "cannot access component in path '%s'", make_path.ptr); - error = -1; - goto done; - } - - git_error_clear(); - opts->perfdata.mkdir_calls++; - mkdir_attempted = true; - if (p_mkdir(make_path.ptr, mode) < 0) { - if (errno == EEXIST) - goto retry_lstat; - git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", make_path.ptr); - error = -1; - goto done; - } - } else { - if ((error = mkdir_validate_dir( - make_path.ptr, &st, mode, flags, opts)) < 0) - goto done; - } - - /* chmod if requested and necessary */ - if ((error = mkdir_validate_mode( - make_path.ptr, &st, (lastch == '\0'), mode, flags, opts)) < 0) - goto done; - - if (opts->dir_map && opts->pool) { - char *cache_path; - size_t alloc_size; - - GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, make_path.size, 1); - if (!git__is_uint32(alloc_size)) - return -1; - cache_path = git_pool_malloc(opts->pool, (uint32_t)alloc_size); - GIT_ERROR_CHECK_ALLOC(cache_path); - - memcpy(cache_path, make_path.ptr, make_path.size + 1); - - git_strmap_insert(opts->dir_map, cache_path, cache_path, &error); - if (error < 0) - goto done; - } - } - - error = 0; - - /* check that full path really is a directory if requested & needed */ - if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 && - lastch != '\0') { - opts->perfdata.stat_calls++; - - if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { - git_error_set(GIT_ERROR_OS, "path is not a directory '%s'", - make_path.ptr); - error = GIT_ENOTFOUND; - } - } - -done: - git_buf_dispose(&make_path); - return error; -} - -typedef struct { - const char *base; - size_t baselen; - uint32_t flags; - int depth; -} futils__rmdir_data; - -#define FUTILS_MAX_DEPTH 100 - -static int futils__error_cannot_rmdir(const char *path, const char *filemsg) -{ - if (filemsg) - git_error_set(GIT_ERROR_OS, "could not remove directory '%s': %s", - path, filemsg); - else - git_error_set(GIT_ERROR_OS, "could not remove directory '%s'", path); - - return -1; -} - -static int futils__rm_first_parent(git_buf *path, const char *ceiling) -{ - int error = GIT_ENOTFOUND; - struct stat st; - - while (error == GIT_ENOTFOUND) { - git_buf_rtruncate_at_char(path, '/'); - - if (!path->size || git__prefixcmp(path->ptr, ceiling) != 0) - error = 0; - else if (p_lstat_posixly(path->ptr, &st) == 0) { - if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) - error = p_unlink(path->ptr); - else if (!S_ISDIR(st.st_mode)) - error = -1; /* fail to remove non-regular file */ - } else if (errno != ENOTDIR) - error = -1; - } - - if (error) - futils__error_cannot_rmdir(path->ptr, "cannot remove parent"); - - return error; -} - -static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) -{ - int error = 0; - futils__rmdir_data *data = opaque; - struct stat st; - - if (data->depth > FUTILS_MAX_DEPTH) - error = futils__error_cannot_rmdir( - path->ptr, "directory nesting too deep"); - - else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) { - if (errno == ENOENT) - error = 0; - else if (errno == ENOTDIR) { - /* asked to remove a/b/c/d/e and a/b is a normal file */ - if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0) - error = futils__rm_first_parent(path, data->base); - else - futils__error_cannot_rmdir( - path->ptr, "parent is not directory"); - } - else - error = git_path_set_error(errno, path->ptr, "rmdir"); - } - - else if (S_ISDIR(st.st_mode)) { - data->depth++; - - error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); - - data->depth--; - - if (error < 0) - return error; - - if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) - return error; - - if ((error = p_rmdir(path->ptr)) < 0) { - if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 && - (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY)) - error = 0; - else - error = git_path_set_error(errno, path->ptr, "rmdir"); - } - } - - else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) { - if (p_unlink(path->ptr) < 0) - error = git_path_set_error(errno, path->ptr, "remove"); - } - - else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0) - error = futils__error_cannot_rmdir(path->ptr, "still present"); - - return error; -} - -static int futils__rmdir_empty_parent(void *opaque, const char *path) -{ - futils__rmdir_data *data = opaque; - int error = 0; - - if (strlen(path) <= data->baselen) - error = GIT_ITEROVER; - - else if (p_rmdir(path) < 0) { - int en = errno; - - if (en == ENOENT || en == ENOTDIR) { - /* do nothing */ - } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0 && - en == EBUSY) { - error = git_path_set_error(errno, path, "rmdir"); - } else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) { - error = GIT_ITEROVER; - } else { - error = git_path_set_error(errno, path, "rmdir"); - } - } - - return error; -} - -int git_futils_rmdir_r( - const char *path, const char *base, uint32_t flags) -{ - int error; - git_buf fullpath = GIT_BUF_INIT; - futils__rmdir_data data; - - /* build path and find "root" where we should start calling mkdir */ - if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0) - return -1; - - memset(&data, 0, sizeof(data)); - data.base = base ? base : ""; - data.baselen = base ? strlen(base) : 0; - data.flags = flags; - - error = futils__rmdir_recurs_foreach(&data, &fullpath); - - /* remove now-empty parents if requested */ - if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0) - error = git_path_walk_up( - &fullpath, base, futils__rmdir_empty_parent, &data); - - if (error == GIT_ITEROVER) { - git_error_clear(); - error = 0; - } - - git_buf_dispose(&fullpath); - - return error; -} - -int git_futils_fake_symlink(const char *old, const char *new) -{ - int retcode = GIT_ERROR; - int fd = git_futils_creat_withpath(new, 0755, 0644); - if (fd >= 0) { - retcode = p_write(fd, old, strlen(old)); - p_close(fd); - } - return retcode; -} - -static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done) -{ - int error = 0; - char buffer[FILEIO_BUFSIZE]; - ssize_t len = 0; - - while (!error && (len = p_read(ifd, buffer, sizeof(buffer))) > 0) - /* p_write() does not have the same semantics as write(). It loops - * internally and will return 0 when it has completed writing. - */ - error = p_write(ofd, buffer, len); - - if (len < 0) { - git_error_set(GIT_ERROR_OS, "read error while copying file"); - error = (int)len; - } - - if (error < 0) - git_error_set(GIT_ERROR_OS, "write error while copying file"); - - if (close_fd_when_done) { - p_close(ifd); - p_close(ofd); - } - - return error; -} - -int git_futils_cp(const char *from, const char *to, mode_t filemode) -{ - int ifd, ofd; - - if ((ifd = git_futils_open_ro(from)) < 0) - return ifd; - - if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) { - p_close(ifd); - return git_path_set_error(errno, to, "open for writing"); - } - - return cp_by_fd(ifd, ofd, true); -} - -int git_futils_touch(const char *path, time_t *when) -{ - struct p_timeval times[2]; - int ret; - - times[0].tv_sec = times[1].tv_sec = when ? *when : time(NULL); - times[0].tv_usec = times[1].tv_usec = 0; - - ret = p_utimes(path, times); - - return (ret < 0) ? git_path_set_error(errno, path, "touch") : 0; -} - -static int cp_link(const char *from, const char *to, size_t link_size) -{ - int error = 0; - ssize_t read_len; - char *link_data; - size_t alloc_size; - - GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, link_size, 1); - link_data = git__malloc(alloc_size); - GIT_ERROR_CHECK_ALLOC(link_data); - - read_len = p_readlink(from, link_data, link_size); - if (read_len != (ssize_t)link_size) { - git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", from); - error = -1; - } - else { - link_data[read_len] = '\0'; - - if (p_symlink(link_data, to) < 0) { - git_error_set(GIT_ERROR_OS, "could not symlink '%s' as '%s'", - link_data, to); - error = -1; - } - } - - git__free(link_data); - return error; -} - -typedef struct { - const char *to_root; - git_buf to; - ssize_t from_prefix; - uint32_t flags; - uint32_t mkdir_flags; - mode_t dirmode; -} cp_r_info; - -#define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10) - -static int _cp_r_mkdir(cp_r_info *info, git_buf *from) -{ - int error = 0; - - /* create root directory the first time we need to create a directory */ - if ((info->flags & GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT) == 0) { - error = git_futils_mkdir( - info->to_root, info->dirmode, - (info->flags & GIT_CPDIR_CHMOD_DIRS) ? GIT_MKDIR_CHMOD : 0); - - info->flags |= GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT; - } - - /* create directory with root as base to prevent excess chmods */ - if (!error) - error = git_futils_mkdir_relative( - from->ptr + info->from_prefix, info->to_root, - info->dirmode, info->mkdir_flags, NULL); - - return error; -} - -static int _cp_r_callback(void *ref, git_buf *from) -{ - int error = 0; - cp_r_info *info = ref; - struct stat from_st, to_st; - bool exists = false; - - if ((info->flags & GIT_CPDIR_COPY_DOTFILES) == 0 && - from->ptr[git_path_basename_offset(from)] == '.') - return 0; - - if ((error = git_buf_joinpath( - &info->to, info->to_root, from->ptr + info->from_prefix)) < 0) - return error; - - if (!(error = git_path_lstat(info->to.ptr, &to_st))) - exists = true; - else if (error != GIT_ENOTFOUND) - return error; - else { - git_error_clear(); - error = 0; - } - - if ((error = git_path_lstat(from->ptr, &from_st)) < 0) - return error; - - if (S_ISDIR(from_st.st_mode)) { - mode_t oldmode = info->dirmode; - - /* if we are not chmod'ing, then overwrite dirmode */ - if ((info->flags & GIT_CPDIR_CHMOD_DIRS) == 0) - info->dirmode = from_st.st_mode; - - /* make directory now if CREATE_EMPTY_DIRS is requested and needed */ - if (!exists && (info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) != 0) - error = _cp_r_mkdir(info, from); - - /* recurse onto target directory */ - if (!error && (!exists || S_ISDIR(to_st.st_mode))) - error = git_path_direach(from, 0, _cp_r_callback, info); - - if (oldmode != 0) - info->dirmode = oldmode; - - return error; - } - - if (exists) { - if ((info->flags & GIT_CPDIR_OVERWRITE) == 0) - return 0; - - if (p_unlink(info->to.ptr) < 0) { - git_error_set(GIT_ERROR_OS, "cannot overwrite existing file '%s'", - info->to.ptr); - return GIT_EEXISTS; - } - } - - /* Done if this isn't a regular file or a symlink */ - if (!S_ISREG(from_st.st_mode) && - (!S_ISLNK(from_st.st_mode) || - (info->flags & GIT_CPDIR_COPY_SYMLINKS) == 0)) - return 0; - - /* Make container directory on demand if needed */ - if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 && - (error = _cp_r_mkdir(info, from)) < 0) - return error; - - /* make symlink or regular file */ - if (info->flags & GIT_CPDIR_LINK_FILES) { - if ((error = p_link(from->ptr, info->to.ptr)) < 0) - git_error_set(GIT_ERROR_OS, "failed to link '%s'", from->ptr); - } else if (S_ISLNK(from_st.st_mode)) { - error = cp_link(from->ptr, info->to.ptr, (size_t)from_st.st_size); - } else { - mode_t usemode = from_st.st_mode; - - if ((info->flags & GIT_CPDIR_SIMPLE_TO_MODE) != 0) - usemode = GIT_PERMS_FOR_WRITE(usemode); - - error = git_futils_cp(from->ptr, info->to.ptr, usemode); - } - - return error; -} - -int git_futils_cp_r( - const char *from, - const char *to, - uint32_t flags, - mode_t dirmode) -{ - int error; - git_buf path = GIT_BUF_INIT; - cp_r_info info; - - if (git_buf_joinpath(&path, from, "") < 0) /* ensure trailing slash */ - return -1; - - memset(&info, 0, sizeof(info)); - info.to_root = to; - info.flags = flags; - info.dirmode = dirmode; - info.from_prefix = path.size; - git_buf_init(&info.to, 0); - - /* precalculate mkdir flags */ - if ((flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0) { - /* if not creating empty dirs, then use mkdir to create the path on - * demand right before files are copied. - */ - info.mkdir_flags = GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST; - if ((flags & GIT_CPDIR_CHMOD_DIRS) != 0) - info.mkdir_flags |= GIT_MKDIR_CHMOD_PATH; - } else { - /* otherwise, we will do simple mkdir as directories are encountered */ - info.mkdir_flags = - ((flags & GIT_CPDIR_CHMOD_DIRS) != 0) ? GIT_MKDIR_CHMOD : 0; - } - - error = _cp_r_callback(&info, &path); - - git_buf_dispose(&path); - git_buf_dispose(&info.to); - - return error; -} - -int git_futils_filestamp_check( - git_futils_filestamp *stamp, const char *path) -{ - struct stat st; - - /* if the stamp is NULL, then always reload */ - if (stamp == NULL) - return 1; - - if (p_stat(path, &st) < 0) - return GIT_ENOTFOUND; - - if (stamp->mtime.tv_sec == st.st_mtime && -#if defined(GIT_USE_NSEC) - stamp->mtime.tv_nsec == st.st_mtime_nsec && -#endif - stamp->size == (git_off_t)st.st_size && - stamp->ino == (unsigned int)st.st_ino) - return 0; - - stamp->mtime.tv_sec = st.st_mtime; -#if defined(GIT_USE_NSEC) - stamp->mtime.tv_nsec = st.st_mtime_nsec; -#endif - stamp->size = (git_off_t)st.st_size; - stamp->ino = (unsigned int)st.st_ino; - - return 1; -} - -void git_futils_filestamp_set( - git_futils_filestamp *target, const git_futils_filestamp *source) -{ - assert(target); - - if (source) - memcpy(target, source, sizeof(*target)); - else - memset(target, 0, sizeof(*target)); -} - - -void git_futils_filestamp_set_from_stat( - git_futils_filestamp *stamp, struct stat *st) -{ - if (st) { - stamp->mtime.tv_sec = st->st_mtime; -#if defined(GIT_USE_NSEC) - stamp->mtime.tv_nsec = st->st_mtime_nsec; -#else - stamp->mtime.tv_nsec = 0; -#endif - stamp->size = (git_off_t)st->st_size; - stamp->ino = (unsigned int)st->st_ino; - } else { - memset(stamp, 0, sizeof(*stamp)); - } -} - -int git_futils_fsync_dir(const char *path) -{ -#ifdef GIT_WIN32 - GIT_UNUSED(path); - return 0; -#else - int fd, error = -1; - - if ((fd = p_open(path, O_RDONLY)) < 0) { - git_error_set(GIT_ERROR_OS, "failed to open directory '%s' for fsync", path); - return -1; - } - - if ((error = p_fsync(fd)) < 0) - git_error_set(GIT_ERROR_OS, "failed to fsync directory '%s'", path); - - p_close(fd); - return error; -#endif -} - -int git_futils_fsync_parent(const char *path) -{ - char *parent; - int error; - - if ((parent = git_path_dirname(path)) == NULL) - return -1; - - error = git_futils_fsync_dir(parent); - git__free(parent); - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/src/fileops.h libgit2-1.1.0+dfsg.1/src/fileops.h --- libgit2-0.28.5+dfsg.1/src/fileops.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fileops.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,390 +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_fileops_h__ -#define INCLUDE_fileops_h__ - -#include "common.h" - -#include "map.h" -#include "posix.h" -#include "path.h" -#include "pool.h" -#include "strmap.h" -#include "oid.h" - -/** - * Filebuffer methods - * - * Read whole files into an in-memory buffer for processing - */ -extern int git_futils_readbuffer(git_buf *obj, const char *path); -extern int git_futils_readbuffer_updated( - git_buf *obj, const char *path, git_oid *checksum, int *updated); -extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len); - -/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We - * support these internally and they will be removed before the `open` call. - */ -#ifndef O_FSYNC -# define O_FSYNC (1 << 31) -#endif - -extern int git_futils_writebuffer( - const git_buf *buf, const char *path, int open_flags, mode_t mode); - -/** - * File utils - * - * These are custom filesystem-related helper methods. They are - * rather high level, and wrap the underlying POSIX methods - * - * All these methods return 0 on success, - * or an error code on failure and an error message is set. - */ - -/** - * Create and open a file, while also - * creating all the folders in its path - */ -extern int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode); - -/** - * Create and open a process-locked file - */ -extern int git_futils_creat_locked(const char *path, const mode_t mode); - -/** - * Create and open a process-locked file, while - * also creating all the folders in its path - */ -extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode); - -/** - * Create a path recursively. - */ -extern int git_futils_mkdir_r(const char *path, const mode_t mode); - -/** - * Flags to pass to `git_futils_mkdir`. - * - * * GIT_MKDIR_EXCL is "exclusive" - i.e. generate an error if dir exists. - * * GIT_MKDIR_PATH says to make all components in the path. - * * GIT_MKDIR_CHMOD says to chmod the final directory entry after creation - * * GIT_MKDIR_CHMOD_PATH says to chmod each directory component in the path - * * GIT_MKDIR_SKIP_LAST says to leave off the last element of the path - * * GIT_MKDIR_SKIP_LAST2 says to leave off the last 2 elements of the path - * * GIT_MKDIR_VERIFY_DIR says confirm final item is a dir, not just EEXIST - * * GIT_MKDIR_REMOVE_FILES says to remove files and recreate dirs - * * GIT_MKDIR_REMOVE_SYMLINKS says to remove symlinks and recreate dirs - * - * Note that the chmod options will be executed even if the directory already - * exists, unless GIT_MKDIR_EXCL is given. - */ -typedef enum { - GIT_MKDIR_EXCL = 1, - GIT_MKDIR_PATH = 2, - GIT_MKDIR_CHMOD = 4, - GIT_MKDIR_CHMOD_PATH = 8, - GIT_MKDIR_SKIP_LAST = 16, - GIT_MKDIR_SKIP_LAST2 = 32, - GIT_MKDIR_VERIFY_DIR = 64, - GIT_MKDIR_REMOVE_FILES = 128, - GIT_MKDIR_REMOVE_SYMLINKS = 256, -} git_futils_mkdir_flags; - -struct git_futils_mkdir_perfdata -{ - size_t stat_calls; - size_t mkdir_calls; - size_t chmod_calls; -}; - -struct git_futils_mkdir_options -{ - git_strmap *dir_map; - git_pool *pool; - struct git_futils_mkdir_perfdata perfdata; -}; - -/** - * Create a directory or entire path. - * - * This makes a directory (and the entire path leading up to it if requested), - * and optionally chmods the directory immediately after (or each part of the - * path if requested). - * - * @param path The path to create, relative to base. - * @param base Root for relative path. These directories will never be made. - * @param mode The mode to use for created directories. - * @param flags Combination of the mkdir flags above. - * @param opts Extended options, or null. - * @return 0 on success, else error code - */ -extern int git_futils_mkdir_relative(const char *path, const char *base, mode_t mode, uint32_t flags, struct git_futils_mkdir_options *opts); - -/** - * Create a directory or entire path. Similar to `git_futils_mkdir_relative` - * without performance data. - */ -extern int git_futils_mkdir(const char *path, mode_t mode, uint32_t flags); - -/** - * Create all the folders required to contain - * the full path of a file - */ -extern int git_futils_mkpath2file(const char *path, const mode_t mode); - -/** - * Flags to pass to `git_futils_rmdir_r`. - * - * * GIT_RMDIR_EMPTY_HIERARCHY - the default; remove hierarchy of empty - * dirs and generate error if any files are found. - * * GIT_RMDIR_REMOVE_FILES - attempt to remove files in the hierarchy. - * * GIT_RMDIR_SKIP_NONEMPTY - skip non-empty directories with no error. - * * GIT_RMDIR_EMPTY_PARENTS - remove containing directories up to base - * if removing this item leaves them empty - * * GIT_RMDIR_REMOVE_BLOCKERS - remove blocking file that causes ENOTDIR - * * GIT_RMDIR_SKIP_ROOT - don't remove root directory itself - */ -typedef enum { - GIT_RMDIR_EMPTY_HIERARCHY = 0, - GIT_RMDIR_REMOVE_FILES = (1 << 0), - GIT_RMDIR_SKIP_NONEMPTY = (1 << 1), - GIT_RMDIR_EMPTY_PARENTS = (1 << 2), - GIT_RMDIR_REMOVE_BLOCKERS = (1 << 3), - GIT_RMDIR_SKIP_ROOT = (1 << 4), -} git_futils_rmdir_flags; - -/** - * Remove path and any files and directories beneath it. - * - * @param path Path to the top level directory to process. - * @param base Root for relative path. - * @param flags Combination of git_futils_rmdir_flags values - * @return 0 on success; -1 on error. - */ -extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags); - -/** - * Create and open a temporary file with a `_git2_` suffix. - * Writes the filename into path_out. - * @return On success, an open file descriptor, else an error code < 0. - */ -extern int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode); - -/** - * Move a file on the filesystem, create the - * destination path if it doesn't exist - */ -extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode); - -/** - * Copy a file - * - * The filemode will be used for the newly created file. - */ -extern int git_futils_cp( - const char *from, - const char *to, - mode_t filemode); - -/** - * Set the files atime and mtime to the given time, or the current time - * if `ts` is NULL. - */ -extern int git_futils_touch(const char *path, time_t *when); - -/** - * Flags that can be passed to `git_futils_cp_r`. - * - * - GIT_CPDIR_CREATE_EMPTY_DIRS: create directories even if there are no - * files under them (otherwise directories will only be created lazily - * when a file inside them is copied). - * - GIT_CPDIR_COPY_SYMLINKS: copy symlinks, otherwise they are ignored. - * - GIT_CPDIR_COPY_DOTFILES: copy files with leading '.', otherwise ignored. - * - GIT_CPDIR_OVERWRITE: overwrite pre-existing files with source content, - * otherwise they are silently skipped. - * - GIT_CPDIR_CHMOD_DIRS: explicitly chmod directories to `dirmode` - * - GIT_CPDIR_SIMPLE_TO_MODE: default tries to replicate the mode of the - * source file to the target; with this flag, always use 0666 (or 0777 if - * source has exec bits set) for target. - * - GIT_CPDIR_LINK_FILES will try to use hardlinks for the files - */ -typedef enum { - GIT_CPDIR_CREATE_EMPTY_DIRS = (1u << 0), - GIT_CPDIR_COPY_SYMLINKS = (1u << 1), - GIT_CPDIR_COPY_DOTFILES = (1u << 2), - GIT_CPDIR_OVERWRITE = (1u << 3), - GIT_CPDIR_CHMOD_DIRS = (1u << 4), - GIT_CPDIR_SIMPLE_TO_MODE = (1u << 5), - GIT_CPDIR_LINK_FILES = (1u << 6), -} git_futils_cpdir_flags; - -/** - * Copy a directory tree. - * - * This copies directories and files from one root to another. You can - * pass a combinationof GIT_CPDIR flags as defined above. - * - * If you pass the CHMOD flag, then the dirmode will be applied to all - * directories that are created during the copy, overiding the natural - * permissions. If you do not pass the CHMOD flag, then the dirmode - * will actually be copied from the source files and the `dirmode` arg - * will be ignored. - */ -extern int git_futils_cp_r( - const char *from, - const char *to, - uint32_t flags, - mode_t dirmode); - -/** - * Open a file readonly and set error if needed. - */ -extern int git_futils_open_ro(const char *path); - -/** - * Truncate a file, creating it if it doesn't exist. - */ -extern int git_futils_truncate(const char *path, int mode); - -/** - * Get the filesize in bytes of a file - */ -extern git_off_t git_futils_filesize(git_file fd); - -#define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0111) != 0) -#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0755 : 0644) -#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0777 : 0666) - -#define GIT_MODE_PERMS_MASK 0777 -#define GIT_MODE_TYPE_MASK 0170000 -#define GIT_MODE_TYPE(MODE) ((MODE) & GIT_MODE_TYPE_MASK) -#define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB)) - -/** - * Convert a mode_t from the OS to a legal git mode_t value. - */ -extern mode_t git_futils_canonical_mode(mode_t raw_mode); - - -/** - * Read-only map all or part of a file into memory. - * When possible this function should favor a virtual memory - * style mapping over some form of malloc()+read(), as the - * data access will be random and is not likely to touch the - * majority of the region requested. - * - * @param out buffer to populate with the mapping information. - * @param fd open descriptor to configure the mapping from. - * @param begin first byte to map, this should be page aligned. - * @param len number of bytes to map. - * @return - * - 0 on success; - * - -1 on error. - */ -extern int git_futils_mmap_ro( - git_map *out, - git_file fd, - git_off_t begin, - size_t len); - -/** - * Read-only map an entire file. - * - * @param out buffer to populate with the mapping information. - * @param path path to file to be opened. - * @return - * - 0 on success; - * - GIT_ENOTFOUND if not found; - * - -1 on an unspecified OS related error. - */ -extern int git_futils_mmap_ro_file( - git_map *out, - const char *path); - -/** - * Release the memory associated with a previous memory mapping. - * @param map the mapping description previously configured. - */ -extern void git_futils_mmap_free(git_map *map); - -/** - * Create a "fake" symlink (text file containing the target path). - * - * @param new symlink file to be created - * @param old original symlink target - * @return 0 on success, -1 on error - */ -extern int git_futils_fake_symlink(const char *new, const char *old); - -/** - * A file stamp represents a snapshot of information about a file that can - * be used to test if the file changes. This portable implementation is - * based on stat data about that file, but it is possible that OS specific - * versions could be implemented in the future. - */ -typedef struct { - struct timespec mtime; - git_off_t size; - unsigned int ino; -} git_futils_filestamp; - -/** - * Compare stat information for file with reference info. - * - * This function updates the file stamp to current data for the given path - * and returns 0 if the file is up-to-date relative to the prior setting, - * 1 if the file has been changed, or GIT_ENOTFOUND if the file doesn't - * exist. This will not call git_error_set, so you must set the error if you - * plan to return an error. - * - * @param stamp File stamp to be checked - * @param path Path to stat and check if changed - * @return 0 if up-to-date, 1 if out-of-date, GIT_ENOTFOUND if cannot stat - */ -extern int git_futils_filestamp_check( - git_futils_filestamp *stamp, const char *path); - -/** - * Set or reset file stamp data - * - * This writes the target file stamp. If the source is NULL, this will set - * the target stamp to values that will definitely be out of date. If the - * source is not NULL, this copies the source values to the target. - * - * @param tgt File stamp to write to - * @param src File stamp to copy from or NULL to clear the target - */ -extern void git_futils_filestamp_set( - git_futils_filestamp *tgt, const git_futils_filestamp *src); - -/** - * Set file stamp data from stat structure - */ -extern void git_futils_filestamp_set_from_stat( - git_futils_filestamp *stamp, struct stat *st); - -/** - * `fsync` the parent directory of the given path, if `fsync` is - * supported for directories on this platform. - * - * @param path Path of the directory to sync. - * @return 0 on success, -1 on error - */ -extern int git_futils_fsync_dir(const char *path); - -/** - * `fsync` the parent directory of the given path, if `fsync` is - * supported for directories on this platform. - * - * @param path Path of the file whose parent directory should be synced. - * @return 0 on success, -1 on error - */ -extern int git_futils_fsync_parent(const char *path); - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/filter.c libgit2-1.1.0+dfsg.1/src/filter.c --- libgit2-0.28.5+dfsg.1/src/filter.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/filter.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ #include "filter.h" #include "common.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "repository.h" #include "global.h" @@ -385,7 +385,7 @@ const git_oid *git_filter_source_id(const git_filter_source *src) { - return git_oid_iszero(&src->oid) ? NULL : &src->oid; + return git_oid_is_zero(&src->oid) ? NULL : &src->oid; } git_filter_mode_t git_filter_source_mode(const git_filter_source *src) @@ -428,13 +428,21 @@ git_filter_def *fdef, const git_filter_source *src) { - int error; - size_t i; const char **strs = git__calloc(fdef->nattrs, sizeof(const char *)); + uint32_t flags = 0; + size_t i; + int error; + GIT_ERROR_CHECK_ALLOC(strs); + if ((src->flags & GIT_FILTER_NO_SYSTEM_ATTRIBUTES) != 0) + flags |= GIT_ATTR_CHECK_NO_SYSTEM; + + if ((src->flags & GIT_FILTER_ATTRIBUTES_FROM_HEAD) != 0) + flags |= GIT_ATTR_CHECK_INCLUDE_HEAD; + error = git_attr_get_many_with_session( - strs, repo, attr_session, 0, src->path, fdef->nattrs, fdef->attrs); + strs, repo, attr_session, flags, src->path, fdef->nattrs, fdef->attrs); /* if no values were found but no matches are needed, it's okay! */ if (error == GIT_ENOTFOUND && !fdef->nmatches) { @@ -445,7 +453,7 @@ for (i = 0; !error && i < fdef->nattrs; ++i) { const char *want = fdef->attrs[fdef->nattrs + i]; - git_attr_t want_type, found_type; + git_attr_value_t want_type, found_type; if (!want) continue; @@ -455,7 +463,7 @@ if (want_type != found_type) error = GIT_ENOTFOUND; - else if (want_type == GIT_ATTR_VALUE_T && + else if (want_type == GIT_ATTR_VALUE_STRING && strcmp(want, strs[i]) && strcmp(want, "*")) error = GIT_ENOTFOUND; @@ -756,7 +764,7 @@ static int buf_from_blob(git_buf *out, git_blob *blob) { - git_off_t rawsize = git_blob_rawsize(blob); + git_object_size_t rawsize = git_blob_rawsize(blob); if (!git__is_sizet(rawsize)) { git_error_set(GIT_ERROR_OS, "blob is too large to filter"); @@ -933,7 +941,7 @@ return error; } -void stream_list_free(git_vector *streams) +static void filter_streams_free(git_vector *streams) { git_writestream *stream; size_t i; @@ -982,7 +990,7 @@ if (fd >= 0) p_close(fd); - stream_list_free(&filter_streams); + filter_streams_free(&filter_streams); git_buf_dispose(&abspath); return error; } @@ -1010,7 +1018,7 @@ if (initialized) error |= stream_start->close(stream_start); - stream_list_free(&filter_streams); + filter_streams_free(&filter_streams); return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/fnmatch.c libgit2-1.1.0+dfsg.1/src/fnmatch.c --- libgit2-0.28.5+dfsg.1/src/fnmatch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fnmatch.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +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. - */ - -/* - * This file contains code originally derrived from OpenBSD fnmatch.c - * - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Guido van Rossum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. - * Compares a filename or pathname to a pattern. - */ - -#include "fnmatch.h" - -#include -#include -#include - -#define EOS '\0' - -#define RANGE_MATCH 1 -#define RANGE_NOMATCH 0 -#define RANGE_ERROR (-1) - -static int rangematch(const char *, char, int, char **); - -static int -p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs) -{ - const char *stringstart; - char *newp; - char c, test; - int recurs_flags = flags & ~FNM_PERIOD; - - if (recurs-- == 0) - return FNM_NORES; - - for (stringstart = string;;) - switch (c = *pattern++) { - case EOS: - if ((flags & FNM_LEADING_DIR) && *string == '/') - return (0); - return (*string == EOS ? 0 : FNM_NOMATCH); - case '?': - if (*string == EOS) - return (FNM_NOMATCH); - if (*string == '/' && (flags & FNM_PATHNAME)) - return (FNM_NOMATCH); - if (*string == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); - ++string; - break; - case '*': - c = *pattern; - - /* Let '**' override PATHNAME match for this segment. - * It will be restored if/when we recurse below. - */ - if (c == '*') { - c = *++pattern; - /* star-star-slash is at the end, match by default */ - if (c == EOS) - return 0; - /* Double-star must be at end or between slashes */ - if (c != '/') - return (FNM_NOMATCH); - - c = *++pattern; - do { - int e = p_fnmatchx(pattern, string, recurs_flags, recurs); - if (e != FNM_NOMATCH) - return e; - string = strchr(string, '/'); - } while (string++); - - /* If we get here, we didn't find a match */ - return FNM_NOMATCH; - } - - if (*string == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); - - /* Optimize for pattern with * at end or before /. */ - if (c == EOS) { - if (flags & FNM_PATHNAME) - return ((flags & FNM_LEADING_DIR) || - strchr(string, '/') == NULL ? - 0 : FNM_NOMATCH); - else - return (0); - } else if (c == '/' && (flags & FNM_PATHNAME)) { - if ((string = strchr(string, '/')) == NULL) - return (FNM_NOMATCH); - break; - } - - /* General case, use recursion. */ - while ((test = *string) != EOS) { - int e; - - e = p_fnmatchx(pattern, string, recurs_flags, recurs); - if (e != FNM_NOMATCH) - return e; - if (test == '/' && (flags & FNM_PATHNAME)) - break; - ++string; - } - return (FNM_NOMATCH); - case '[': - if (*string == EOS) - return (FNM_NOMATCH); - if (*string == '/' && (flags & FNM_PATHNAME)) - return (FNM_NOMATCH); - if (*string == '.' && (flags & FNM_PERIOD) && - (string == stringstart || - ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); - - switch (rangematch(pattern, *string, flags, &newp)) { - case RANGE_ERROR: - /* not a good range, treat as normal text */ - goto normal; - case RANGE_MATCH: - pattern = newp; - break; - case RANGE_NOMATCH: - return (FNM_NOMATCH); - } - ++string; - break; - case '\\': - if (!(flags & FNM_NOESCAPE)) { - if ((c = *pattern++) == EOS) { - c = '\\'; - --pattern; - } - } - /* FALLTHROUGH */ - default: - normal: - if (c != *string && !((flags & FNM_CASEFOLD) && - (git__tolower((unsigned char)c) == - git__tolower((unsigned char)*string)))) - return (FNM_NOMATCH); - ++string; - break; - } - /* NOTREACHED */ -} - -static int -rangematch(const char *pattern, char test, int flags, char **newp) -{ - int negate, ok; - char c, c2; - - /* - * A bracket expression starting with an unquoted circumflex - * character produces unspecified results (IEEE 1003.2-1992, - * 3.13.2). This implementation treats it like '!', for - * consistency with the regular expression syntax. - * J.T. Conklin (conklin@ngai.kaleida.com) - */ - if ((negate = (*pattern == '!' || *pattern == '^')) != 0) - ++pattern; - - if (flags & FNM_CASEFOLD) - test = (char)git__tolower((unsigned char)test); - - /* - * A right bracket shall lose its special meaning and represent - * itself in a bracket expression if it occurs first in the list. - * -- POSIX.2 2.8.3.2 - */ - ok = 0; - c = *pattern++; - do { - if (c == '\\' && !(flags & FNM_NOESCAPE)) - c = *pattern++; - if (c == EOS) - return (RANGE_ERROR); - if (c == '/' && (flags & FNM_PATHNAME)) - return (RANGE_NOMATCH); - if ((flags & FNM_CASEFOLD)) - c = (char)git__tolower((unsigned char)c); - if (*pattern == '-' - && (c2 = *(pattern+1)) != EOS && c2 != ']') { - pattern += 2; - if (c2 == '\\' && !(flags & FNM_NOESCAPE)) - c2 = *pattern++; - if (c2 == EOS) - return (RANGE_ERROR); - if (flags & FNM_CASEFOLD) - c2 = (char)git__tolower((unsigned char)c2); - if (c <= test && test <= c2) - ok = 1; - } else if (c == test) - ok = 1; - } while ((c = *pattern++) != ']'); - - *newp = (char *)pattern; - return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); -} - -int -p_fnmatch(const char *pattern, const char *string, int flags) -{ - return p_fnmatchx(pattern, string, flags, 64); -} - diff -Nru libgit2-0.28.5+dfsg.1/src/fnmatch.h libgit2-1.1.0+dfsg.1/src/fnmatch.h --- libgit2-0.28.5+dfsg.1/src/fnmatch.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/fnmatch.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifndef INCLUDE_fnmatch_h__ -#define INCLUDE_fnmatch_h__ - -#include "common.h" - -#define FNM_NOMATCH 1 /* Match failed. */ -#define FNM_NOSYS 2 /* Function not supported (unused). */ -#define FNM_NORES 3 /* Out of resources */ - -#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ -#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ -#define FNM_PERIOD 0x04 /* Period must be matched by period. */ -#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ -#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ - -#define FNM_IGNORECASE FNM_CASEFOLD -#define FNM_FILE_NAME FNM_PATHNAME - -extern int p_fnmatch(const char *pattern, const char *string, int flags); - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/futils.c libgit2-1.1.0+dfsg.1/src/futils.c --- libgit2-0.28.5+dfsg.1/src/futils.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/futils.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,1188 @@ +/* + * 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 "futils.h" + +#include "global.h" +#include "strmap.h" +#include +#if GIT_WIN32 +#include "win32/findfile.h" +#endif + +int git_futils_mkpath2file(const char *file_path, const mode_t mode) +{ + return git_futils_mkdir( + file_path, mode, + GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR); +} + +int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode) +{ + int fd; + mode_t mask; + + p_umask(mask = p_umask(0)); + + git_buf_sets(path_out, filename); + git_buf_puts(path_out, "_git2_XXXXXX"); + + if (git_buf_oom(path_out)) + return -1; + + if ((fd = p_mkstemp(path_out->ptr)) < 0) { + git_error_set(GIT_ERROR_OS, + "failed to create temporary file '%s'", path_out->ptr); + return -1; + } + + if (p_chmod(path_out->ptr, (mode & ~mask))) { + git_error_set(GIT_ERROR_OS, + "failed to set permissions on file '%s'", path_out->ptr); + return -1; + } + + return fd; +} + +int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode) +{ + int fd; + + if (git_futils_mkpath2file(path, dirmode) < 0) + return -1; + + fd = p_creat(path, mode); + if (fd < 0) { + git_error_set(GIT_ERROR_OS, "failed to create file '%s'", path); + return -1; + } + + return fd; +} + +int git_futils_creat_locked(const char *path, const mode_t mode) +{ + int fd = p_open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, + mode); + + if (fd < 0) { + int error = errno; + git_error_set(GIT_ERROR_OS, "failed to create locked file '%s'", path); + switch (error) { + case EEXIST: + return GIT_ELOCKED; + case ENOENT: + return GIT_ENOTFOUND; + default: + return -1; + } + } + + return fd; +} + +int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode) +{ + if (git_futils_mkpath2file(path, dirmode) < 0) + return -1; + + return git_futils_creat_locked(path, mode); +} + +int git_futils_open_ro(const char *path) +{ + int fd = p_open(path, O_RDONLY); + if (fd < 0) + return git_path_set_error(errno, path, "open"); + return fd; +} + +int git_futils_truncate(const char *path, int mode) +{ + int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); + if (fd < 0) + return git_path_set_error(errno, path, "open"); + + close(fd); + return 0; +} + +int git_futils_filesize(uint64_t *out, git_file fd) +{ + struct stat sb; + + if (p_fstat(fd, &sb)) { + git_error_set(GIT_ERROR_OS, "failed to stat file descriptor"); + return -1; + } + + if (sb.st_size < 0) { + git_error_set(GIT_ERROR_INVALID, "invalid file size"); + return -1; + } + + *out = sb.st_size; + return 0; +} + +mode_t git_futils_canonical_mode(mode_t raw_mode) +{ + if (S_ISREG(raw_mode)) + return S_IFREG | GIT_PERMS_CANONICAL(raw_mode); + else if (S_ISLNK(raw_mode)) + return S_IFLNK; + else if (S_ISGITLINK(raw_mode)) + return S_IFGITLINK; + else if (S_ISDIR(raw_mode)) + return S_IFDIR; + else + return 0; +} + +int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) +{ + ssize_t read_size = 0; + size_t alloc_len; + + git_buf_clear(buf); + + if (!git__is_ssizet(len)) { + git_error_set(GIT_ERROR_INVALID, "read too large"); + return -1; + } + + GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, len, 1); + if (git_buf_grow(buf, alloc_len) < 0) + return -1; + + /* p_read loops internally to read len bytes */ + read_size = p_read(fd, buf->ptr, len); + + if (read_size != (ssize_t)len) { + git_error_set(GIT_ERROR_OS, "failed to read descriptor"); + git_buf_dispose(buf); + return -1; + } + + buf->ptr[read_size] = '\0'; + buf->size = read_size; + + return 0; +} + +int git_futils_readbuffer_updated( + git_buf *out, const char *path, git_oid *checksum, int *updated) +{ + int error; + git_file fd; + struct stat st; + git_buf buf = GIT_BUF_INIT; + git_oid checksum_new; + + assert(out && path && *path); + + if (updated != NULL) + *updated = 0; + + if (p_stat(path, &st) < 0) + return git_path_set_error(errno, path, "stat"); + + + if (S_ISDIR(st.st_mode)) { + git_error_set(GIT_ERROR_INVALID, "requested file is a directory"); + return GIT_ENOTFOUND; + } + + if (!git__is_sizet(st.st_size+1)) { + git_error_set(GIT_ERROR_OS, "invalid regular file stat for '%s'", path); + return -1; + } + + if ((fd = git_futils_open_ro(path)) < 0) + return fd; + + if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) { + p_close(fd); + return -1; + } + + p_close(fd); + + if (checksum) { + if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) { + git_buf_dispose(&buf); + return error; + } + + /* + * If we were given a checksum, we only want to use it if it's different + */ + if (!git_oid__cmp(checksum, &checksum_new)) { + git_buf_dispose(&buf); + if (updated) + *updated = 0; + + return 0; + } + + git_oid_cpy(checksum, &checksum_new); + } + + /* + * If we're here, the file did change, or the user didn't have an old version + */ + if (updated != NULL) + *updated = 1; + + git_buf_swap(out, &buf); + git_buf_dispose(&buf); + + return 0; +} + +int git_futils_readbuffer(git_buf *buf, const char *path) +{ + return git_futils_readbuffer_updated(buf, path, NULL, NULL); +} + +int git_futils_writebuffer( + const git_buf *buf, const char *path, int flags, mode_t mode) +{ + int fd, do_fsync = 0, error = 0; + + if (!flags) + flags = O_CREAT | O_TRUNC | O_WRONLY; + + if ((flags & O_FSYNC) != 0) + do_fsync = 1; + + flags &= ~O_FSYNC; + + if (!mode) + mode = GIT_FILEMODE_BLOB; + + if ((fd = p_open(path, flags, mode)) < 0) { + git_error_set(GIT_ERROR_OS, "could not open '%s' for writing", path); + return fd; + } + + if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) { + git_error_set(GIT_ERROR_OS, "could not write to '%s'", path); + (void)p_close(fd); + return error; + } + + if (do_fsync && (error = p_fsync(fd)) < 0) { + git_error_set(GIT_ERROR_OS, "could not fsync '%s'", path); + p_close(fd); + return error; + } + + if ((error = p_close(fd)) < 0) { + git_error_set(GIT_ERROR_OS, "error while closing '%s'", path); + return error; + } + + if (do_fsync && (flags & O_CREAT)) + error = git_futils_fsync_parent(path); + + return error; +} + +int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode) +{ + if (git_futils_mkpath2file(to, dirmode) < 0) + return -1; + + if (p_rename(from, to) < 0) { + git_error_set(GIT_ERROR_OS, "failed to rename '%s' to '%s'", from, to); + return -1; + } + + return 0; +} + +int git_futils_mmap_ro(git_map *out, git_file fd, off64_t begin, size_t len) +{ + return p_mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin); +} + +int git_futils_mmap_ro_file(git_map *out, const char *path) +{ + git_file fd = git_futils_open_ro(path); + uint64_t len; + int result; + + if (fd < 0) + return fd; + + if ((result = git_futils_filesize(&len, fd)) < 0) + goto out; + + if (!git__is_sizet(len)) { + git_error_set(GIT_ERROR_OS, "file `%s` too large to mmap", path); + result = -1; + goto out; + } + + result = git_futils_mmap_ro(out, fd, 0, (size_t)len); +out: + p_close(fd); + return result; +} + +void git_futils_mmap_free(git_map *out) +{ + p_munmap(out); +} + +GIT_INLINE(int) mkdir_validate_dir( + const char *path, + struct stat *st, + mode_t mode, + uint32_t flags, + struct git_futils_mkdir_options *opts) +{ + /* with exclusive create, existing dir is an error */ + if ((flags & GIT_MKDIR_EXCL) != 0) { + git_error_set(GIT_ERROR_FILESYSTEM, + "failed to make directory '%s': directory exists", path); + return GIT_EEXISTS; + } + + if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) || + (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) { + if (p_unlink(path) < 0) { + git_error_set(GIT_ERROR_OS, "failed to remove %s '%s'", + S_ISLNK(st->st_mode) ? "symlink" : "file", path); + return GIT_EEXISTS; + } + + opts->perfdata.mkdir_calls++; + + if (p_mkdir(path, mode) < 0) { + git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path); + return GIT_EEXISTS; + } + } + + else if (S_ISLNK(st->st_mode)) { + /* Re-stat the target, make sure it's a directory */ + opts->perfdata.stat_calls++; + + if (p_stat(path, st) < 0) { + git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", path); + return GIT_EEXISTS; + } + } + + else if (!S_ISDIR(st->st_mode)) { + git_error_set(GIT_ERROR_FILESYSTEM, + "failed to make directory '%s': directory exists", path); + return GIT_EEXISTS; + } + + return 0; +} + +GIT_INLINE(int) mkdir_validate_mode( + const char *path, + struct stat *st, + bool terminal_path, + mode_t mode, + uint32_t flags, + struct git_futils_mkdir_options *opts) +{ + if (((terminal_path && (flags & GIT_MKDIR_CHMOD) != 0) || + (flags & GIT_MKDIR_CHMOD_PATH) != 0) && st->st_mode != mode) { + + opts->perfdata.chmod_calls++; + + if (p_chmod(path, mode) < 0) { + git_error_set(GIT_ERROR_OS, "failed to set permissions on '%s'", path); + return -1; + } + } + + return 0; +} + +GIT_INLINE(int) mkdir_canonicalize( + git_buf *path, + uint32_t flags) +{ + ssize_t root_len; + + if (path->size == 0) { + git_error_set(GIT_ERROR_OS, "attempt to create empty path"); + return -1; + } + + /* Trim trailing slashes (except the root) */ + if ((root_len = git_path_root(path->ptr)) < 0) + root_len = 0; + else + root_len++; + + while (path->size > (size_t)root_len && path->ptr[path->size - 1] == '/') + path->ptr[--path->size] = '\0'; + + /* if we are not supposed to made the last element, truncate it */ + if ((flags & GIT_MKDIR_SKIP_LAST2) != 0) { + git_path_dirname_r(path, path->ptr); + flags |= GIT_MKDIR_SKIP_LAST; + } + if ((flags & GIT_MKDIR_SKIP_LAST) != 0) { + git_path_dirname_r(path, path->ptr); + } + + /* We were either given the root path (or trimmed it to + * the root), we don't have anything to do. + */ + if (path->size <= (size_t)root_len) + git_buf_clear(path); + + return 0; +} + +int git_futils_mkdir( + const char *path, + mode_t mode, + uint32_t flags) +{ + git_buf make_path = GIT_BUF_INIT, parent_path = GIT_BUF_INIT; + const char *relative; + struct git_futils_mkdir_options opts = { 0 }; + struct stat st; + size_t depth = 0; + int len = 0, root_len, error; + + if ((error = git_buf_puts(&make_path, path)) < 0 || + (error = mkdir_canonicalize(&make_path, flags)) < 0 || + (error = git_buf_puts(&parent_path, make_path.ptr)) < 0 || + make_path.size == 0) + goto done; + + root_len = git_path_root(make_path.ptr); + + /* find the first parent directory that exists. this will be used + * as the base to dirname_relative. + */ + for (relative = make_path.ptr; parent_path.size; ) { + error = p_lstat(parent_path.ptr, &st); + + if (error == 0) { + break; + } else if (errno != ENOENT) { + git_error_set(GIT_ERROR_OS, "failed to stat '%s'", parent_path.ptr); + error = -1; + goto done; + } + + depth++; + + /* examine the parent of the current path */ + if ((len = git_path_dirname_r(&parent_path, parent_path.ptr)) < 0) { + error = len; + goto done; + } + + assert(len); + + /* + * We've walked all the given path's parents and it's either relative + * (the parent is simply '.') or rooted (the length is less than or + * equal to length of the root path). The path may be less than the + * root path length on Windows, where `C:` == `C:/`. + */ + if ((len == 1 && parent_path.ptr[0] == '.') || + (len == 1 && parent_path.ptr[0] == '/') || + len <= root_len) { + relative = make_path.ptr; + break; + } + + relative = make_path.ptr + len + 1; + + /* not recursive? just make this directory relative to its parent. */ + if ((flags & GIT_MKDIR_PATH) == 0) + break; + } + + /* we found an item at the location we're trying to create, + * validate it. + */ + if (depth == 0) { + error = mkdir_validate_dir(make_path.ptr, &st, mode, flags, &opts); + + if (!error) + error = mkdir_validate_mode( + make_path.ptr, &st, true, mode, flags, &opts); + + goto done; + } + + /* we already took `SKIP_LAST` and `SKIP_LAST2` into account when + * canonicalizing `make_path`. + */ + flags &= ~(GIT_MKDIR_SKIP_LAST2 | GIT_MKDIR_SKIP_LAST); + + error = git_futils_mkdir_relative(relative, + parent_path.size ? parent_path.ptr : NULL, mode, flags, &opts); + +done: + git_buf_dispose(&make_path); + git_buf_dispose(&parent_path); + return error; +} + +int git_futils_mkdir_r(const char *path, const mode_t mode) +{ + return git_futils_mkdir(path, mode, GIT_MKDIR_PATH); +} + +int git_futils_mkdir_relative( + const char *relative_path, + const char *base, + mode_t mode, + uint32_t flags, + struct git_futils_mkdir_options *opts) +{ + git_buf make_path = GIT_BUF_INIT; + ssize_t root = 0, min_root_len; + char lastch = '/', *tail; + struct stat st; + struct git_futils_mkdir_options empty_opts = {0}; + int error; + + if (!opts) + opts = &empty_opts; + + /* build path and find "root" where we should start calling mkdir */ + if (git_path_join_unrooted(&make_path, relative_path, base, &root) < 0) + return -1; + + if ((error = mkdir_canonicalize(&make_path, flags)) < 0 || + make_path.size == 0) + goto done; + + /* if we are not supposed to make the whole path, reset root */ + if ((flags & GIT_MKDIR_PATH) == 0) + root = git_buf_rfind(&make_path, '/'); + + /* advance root past drive name or network mount prefix */ + min_root_len = git_path_root(make_path.ptr); + if (root < min_root_len) + root = min_root_len; + while (root >= 0 && make_path.ptr[root] == '/') + ++root; + + /* clip root to make_path length */ + if (root > (ssize_t)make_path.size) + root = (ssize_t)make_path.size; /* i.e. NUL byte of string */ + if (root < 0) + root = 0; + + /* walk down tail of path making each directory */ + for (tail = &make_path.ptr[root]; *tail; *tail = lastch) { + bool mkdir_attempted = false; + + /* advance tail to include next path component */ + while (*tail == '/') + tail++; + while (*tail && *tail != '/') + tail++; + + /* truncate path at next component */ + lastch = *tail; + *tail = '\0'; + st.st_mode = 0; + + if (opts->dir_map && git_strmap_exists(opts->dir_map, make_path.ptr)) + continue; + + /* See what's going on with this path component */ + opts->perfdata.stat_calls++; + +retry_lstat: + if (p_lstat(make_path.ptr, &st) < 0) { + if (mkdir_attempted || errno != ENOENT) { + git_error_set(GIT_ERROR_OS, "cannot access component in path '%s'", make_path.ptr); + error = -1; + goto done; + } + + git_error_clear(); + opts->perfdata.mkdir_calls++; + mkdir_attempted = true; + if (p_mkdir(make_path.ptr, mode) < 0) { + if (errno == EEXIST) + goto retry_lstat; + git_error_set(GIT_ERROR_OS, "failed to make directory '%s'", make_path.ptr); + error = -1; + goto done; + } + } else { + if ((error = mkdir_validate_dir( + make_path.ptr, &st, mode, flags, opts)) < 0) + goto done; + } + + /* chmod if requested and necessary */ + if ((error = mkdir_validate_mode( + make_path.ptr, &st, (lastch == '\0'), mode, flags, opts)) < 0) + goto done; + + if (opts->dir_map && opts->pool) { + char *cache_path; + size_t alloc_size; + + GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, make_path.size, 1); + cache_path = git_pool_malloc(opts->pool, alloc_size); + GIT_ERROR_CHECK_ALLOC(cache_path); + + memcpy(cache_path, make_path.ptr, make_path.size + 1); + + if ((error = git_strmap_set(opts->dir_map, cache_path, cache_path)) < 0) + goto done; + } + } + + error = 0; + + /* check that full path really is a directory if requested & needed */ + if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 && + lastch != '\0') { + opts->perfdata.stat_calls++; + + if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { + git_error_set(GIT_ERROR_OS, "path is not a directory '%s'", + make_path.ptr); + error = GIT_ENOTFOUND; + } + } + +done: + git_buf_dispose(&make_path); + return error; +} + +typedef struct { + const char *base; + size_t baselen; + uint32_t flags; + int depth; +} futils__rmdir_data; + +#define FUTILS_MAX_DEPTH 100 + +static int futils__error_cannot_rmdir(const char *path, const char *filemsg) +{ + if (filemsg) + git_error_set(GIT_ERROR_OS, "could not remove directory '%s': %s", + path, filemsg); + else + git_error_set(GIT_ERROR_OS, "could not remove directory '%s'", path); + + return -1; +} + +static int futils__rm_first_parent(git_buf *path, const char *ceiling) +{ + int error = GIT_ENOTFOUND; + struct stat st; + + while (error == GIT_ENOTFOUND) { + git_buf_rtruncate_at_char(path, '/'); + + if (!path->size || git__prefixcmp(path->ptr, ceiling) != 0) + error = 0; + else if (p_lstat_posixly(path->ptr, &st) == 0) { + if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) + error = p_unlink(path->ptr); + else if (!S_ISDIR(st.st_mode)) + error = -1; /* fail to remove non-regular file */ + } else if (errno != ENOTDIR) + error = -1; + } + + if (error) + futils__error_cannot_rmdir(path->ptr, "cannot remove parent"); + + return error; +} + +static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) +{ + int error = 0; + futils__rmdir_data *data = opaque; + struct stat st; + + if (data->depth > FUTILS_MAX_DEPTH) + error = futils__error_cannot_rmdir( + path->ptr, "directory nesting too deep"); + + else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) { + if (errno == ENOENT) + error = 0; + else if (errno == ENOTDIR) { + /* asked to remove a/b/c/d/e and a/b is a normal file */ + if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0) + error = futils__rm_first_parent(path, data->base); + else + futils__error_cannot_rmdir( + path->ptr, "parent is not directory"); + } + else + error = git_path_set_error(errno, path->ptr, "rmdir"); + } + + else if (S_ISDIR(st.st_mode)) { + data->depth++; + + error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); + + data->depth--; + + if (error < 0) + return error; + + if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) + return error; + + if ((error = p_rmdir(path->ptr)) < 0) { + if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 && + (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY)) + error = 0; + else + error = git_path_set_error(errno, path->ptr, "rmdir"); + } + } + + else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) { + if (p_unlink(path->ptr) < 0) + error = git_path_set_error(errno, path->ptr, "remove"); + } + + else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0) + error = futils__error_cannot_rmdir(path->ptr, "still present"); + + return error; +} + +static int futils__rmdir_empty_parent(void *opaque, const char *path) +{ + futils__rmdir_data *data = opaque; + int error = 0; + + if (strlen(path) <= data->baselen) + error = GIT_ITEROVER; + + else if (p_rmdir(path) < 0) { + int en = errno; + + if (en == ENOENT || en == ENOTDIR) { + /* do nothing */ + } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0 && + en == EBUSY) { + error = git_path_set_error(errno, path, "rmdir"); + } else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) { + error = GIT_ITEROVER; + } else { + error = git_path_set_error(errno, path, "rmdir"); + } + } + + return error; +} + +int git_futils_rmdir_r( + const char *path, const char *base, uint32_t flags) +{ + int error; + git_buf fullpath = GIT_BUF_INIT; + futils__rmdir_data data; + + /* build path and find "root" where we should start calling mkdir */ + if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0) + return -1; + + memset(&data, 0, sizeof(data)); + data.base = base ? base : ""; + data.baselen = base ? strlen(base) : 0; + data.flags = flags; + + error = futils__rmdir_recurs_foreach(&data, &fullpath); + + /* remove now-empty parents if requested */ + if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0) + error = git_path_walk_up( + &fullpath, base, futils__rmdir_empty_parent, &data); + + if (error == GIT_ITEROVER) { + git_error_clear(); + error = 0; + } + + git_buf_dispose(&fullpath); + + return error; +} + +int git_futils_fake_symlink(const char *target, const char *path) +{ + int retcode = GIT_ERROR; + int fd = git_futils_creat_withpath(path, 0755, 0644); + if (fd >= 0) { + retcode = p_write(fd, target, strlen(target)); + p_close(fd); + } + return retcode; +} + +static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done) +{ + int error = 0; + char buffer[FILEIO_BUFSIZE]; + ssize_t len = 0; + + while (!error && (len = p_read(ifd, buffer, sizeof(buffer))) > 0) + /* p_write() does not have the same semantics as write(). It loops + * internally and will return 0 when it has completed writing. + */ + error = p_write(ofd, buffer, len); + + if (len < 0) { + git_error_set(GIT_ERROR_OS, "read error while copying file"); + error = (int)len; + } + + if (error < 0) + git_error_set(GIT_ERROR_OS, "write error while copying file"); + + if (close_fd_when_done) { + p_close(ifd); + p_close(ofd); + } + + return error; +} + +int git_futils_cp(const char *from, const char *to, mode_t filemode) +{ + int ifd, ofd; + + if ((ifd = git_futils_open_ro(from)) < 0) + return ifd; + + if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) { + p_close(ifd); + return git_path_set_error(errno, to, "open for writing"); + } + + return cp_by_fd(ifd, ofd, true); +} + +int git_futils_touch(const char *path, time_t *when) +{ + struct p_timeval times[2]; + int ret; + + times[0].tv_sec = times[1].tv_sec = when ? *when : time(NULL); + times[0].tv_usec = times[1].tv_usec = 0; + + ret = p_utimes(path, times); + + return (ret < 0) ? git_path_set_error(errno, path, "touch") : 0; +} + +static int cp_link(const char *from, const char *to, size_t link_size) +{ + int error = 0; + ssize_t read_len; + char *link_data; + size_t alloc_size; + + GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, link_size, 1); + link_data = git__malloc(alloc_size); + GIT_ERROR_CHECK_ALLOC(link_data); + + read_len = p_readlink(from, link_data, link_size); + if (read_len != (ssize_t)link_size) { + git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", from); + error = -1; + } + else { + link_data[read_len] = '\0'; + + if (p_symlink(link_data, to) < 0) { + git_error_set(GIT_ERROR_OS, "could not symlink '%s' as '%s'", + link_data, to); + error = -1; + } + } + + git__free(link_data); + return error; +} + +typedef struct { + const char *to_root; + git_buf to; + ssize_t from_prefix; + uint32_t flags; + uint32_t mkdir_flags; + mode_t dirmode; +} cp_r_info; + +#define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10) + +static int _cp_r_mkdir(cp_r_info *info, git_buf *from) +{ + int error = 0; + + /* create root directory the first time we need to create a directory */ + if ((info->flags & GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT) == 0) { + error = git_futils_mkdir( + info->to_root, info->dirmode, + (info->flags & GIT_CPDIR_CHMOD_DIRS) ? GIT_MKDIR_CHMOD : 0); + + info->flags |= GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT; + } + + /* create directory with root as base to prevent excess chmods */ + if (!error) + error = git_futils_mkdir_relative( + from->ptr + info->from_prefix, info->to_root, + info->dirmode, info->mkdir_flags, NULL); + + return error; +} + +static int _cp_r_callback(void *ref, git_buf *from) +{ + int error = 0; + cp_r_info *info = ref; + struct stat from_st, to_st; + bool exists = false; + + if ((info->flags & GIT_CPDIR_COPY_DOTFILES) == 0 && + from->ptr[git_path_basename_offset(from)] == '.') + return 0; + + if ((error = git_buf_joinpath( + &info->to, info->to_root, from->ptr + info->from_prefix)) < 0) + return error; + + if (!(error = git_path_lstat(info->to.ptr, &to_st))) + exists = true; + else if (error != GIT_ENOTFOUND) + return error; + else { + git_error_clear(); + error = 0; + } + + if ((error = git_path_lstat(from->ptr, &from_st)) < 0) + return error; + + if (S_ISDIR(from_st.st_mode)) { + mode_t oldmode = info->dirmode; + + /* if we are not chmod'ing, then overwrite dirmode */ + if ((info->flags & GIT_CPDIR_CHMOD_DIRS) == 0) + info->dirmode = from_st.st_mode; + + /* make directory now if CREATE_EMPTY_DIRS is requested and needed */ + if (!exists && (info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) != 0) + error = _cp_r_mkdir(info, from); + + /* recurse onto target directory */ + if (!error && (!exists || S_ISDIR(to_st.st_mode))) + error = git_path_direach(from, 0, _cp_r_callback, info); + + if (oldmode != 0) + info->dirmode = oldmode; + + return error; + } + + if (exists) { + if ((info->flags & GIT_CPDIR_OVERWRITE) == 0) + return 0; + + if (p_unlink(info->to.ptr) < 0) { + git_error_set(GIT_ERROR_OS, "cannot overwrite existing file '%s'", + info->to.ptr); + return GIT_EEXISTS; + } + } + + /* Done if this isn't a regular file or a symlink */ + if (!S_ISREG(from_st.st_mode) && + (!S_ISLNK(from_st.st_mode) || + (info->flags & GIT_CPDIR_COPY_SYMLINKS) == 0)) + return 0; + + /* Make container directory on demand if needed */ + if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 && + (error = _cp_r_mkdir(info, from)) < 0) + return error; + + /* make symlink or regular file */ + if (info->flags & GIT_CPDIR_LINK_FILES) { + if ((error = p_link(from->ptr, info->to.ptr)) < 0) + git_error_set(GIT_ERROR_OS, "failed to link '%s'", from->ptr); + } else if (S_ISLNK(from_st.st_mode)) { + error = cp_link(from->ptr, info->to.ptr, (size_t)from_st.st_size); + } else { + mode_t usemode = from_st.st_mode; + + if ((info->flags & GIT_CPDIR_SIMPLE_TO_MODE) != 0) + usemode = GIT_PERMS_FOR_WRITE(usemode); + + error = git_futils_cp(from->ptr, info->to.ptr, usemode); + } + + return error; +} + +int git_futils_cp_r( + const char *from, + const char *to, + uint32_t flags, + mode_t dirmode) +{ + int error; + git_buf path = GIT_BUF_INIT; + cp_r_info info; + + if (git_buf_joinpath(&path, from, "") < 0) /* ensure trailing slash */ + return -1; + + memset(&info, 0, sizeof(info)); + info.to_root = to; + info.flags = flags; + info.dirmode = dirmode; + info.from_prefix = path.size; + git_buf_init(&info.to, 0); + + /* precalculate mkdir flags */ + if ((flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0) { + /* if not creating empty dirs, then use mkdir to create the path on + * demand right before files are copied. + */ + info.mkdir_flags = GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST; + if ((flags & GIT_CPDIR_CHMOD_DIRS) != 0) + info.mkdir_flags |= GIT_MKDIR_CHMOD_PATH; + } else { + /* otherwise, we will do simple mkdir as directories are encountered */ + info.mkdir_flags = + ((flags & GIT_CPDIR_CHMOD_DIRS) != 0) ? GIT_MKDIR_CHMOD : 0; + } + + error = _cp_r_callback(&info, &path); + + git_buf_dispose(&path); + git_buf_dispose(&info.to); + + return error; +} + +int git_futils_filestamp_check( + git_futils_filestamp *stamp, const char *path) +{ + struct stat st; + + /* if the stamp is NULL, then always reload */ + if (stamp == NULL) + return 1; + + if (p_stat(path, &st) < 0) + return GIT_ENOTFOUND; + + if (stamp->mtime.tv_sec == st.st_mtime && +#if defined(GIT_USE_NSEC) + stamp->mtime.tv_nsec == st.st_mtime_nsec && +#endif + stamp->size == (uint64_t)st.st_size && + stamp->ino == (unsigned int)st.st_ino) + return 0; + + stamp->mtime.tv_sec = st.st_mtime; +#if defined(GIT_USE_NSEC) + stamp->mtime.tv_nsec = st.st_mtime_nsec; +#endif + stamp->size = (uint64_t)st.st_size; + stamp->ino = (unsigned int)st.st_ino; + + return 1; +} + +void git_futils_filestamp_set( + git_futils_filestamp *target, const git_futils_filestamp *source) +{ + assert(target); + + if (source) + memcpy(target, source, sizeof(*target)); + else + memset(target, 0, sizeof(*target)); +} + + +void git_futils_filestamp_set_from_stat( + git_futils_filestamp *stamp, struct stat *st) +{ + if (st) { + stamp->mtime.tv_sec = st->st_mtime; +#if defined(GIT_USE_NSEC) + stamp->mtime.tv_nsec = st->st_mtime_nsec; +#else + stamp->mtime.tv_nsec = 0; +#endif + stamp->size = (uint64_t)st->st_size; + stamp->ino = (unsigned int)st->st_ino; + } else { + memset(stamp, 0, sizeof(*stamp)); + } +} + +int git_futils_fsync_dir(const char *path) +{ +#ifdef GIT_WIN32 + GIT_UNUSED(path); + return 0; +#else + int fd, error = -1; + + if ((fd = p_open(path, O_RDONLY)) < 0) { + git_error_set(GIT_ERROR_OS, "failed to open directory '%s' for fsync", path); + return -1; + } + + if ((error = p_fsync(fd)) < 0) + git_error_set(GIT_ERROR_OS, "failed to fsync directory '%s'", path); + + p_close(fd); + return error; +#endif +} + +int git_futils_fsync_parent(const char *path) +{ + char *parent; + int error; + + if ((parent = git_path_dirname(path)) == NULL) + return -1; + + error = git_futils_fsync_dir(parent); + git__free(parent); + return error; +} diff -Nru libgit2-0.28.5+dfsg.1/src/futils.h libgit2-1.1.0+dfsg.1/src/futils.h --- libgit2-0.28.5+dfsg.1/src/futils.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/futils.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,390 @@ +/* + * 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_futils_h__ +#define INCLUDE_futils_h__ + +#include "common.h" + +#include "map.h" +#include "posix.h" +#include "path.h" +#include "pool.h" +#include "strmap.h" +#include "oid.h" + +/** + * Filebuffer methods + * + * Read whole files into an in-memory buffer for processing + */ +extern int git_futils_readbuffer(git_buf *obj, const char *path); +extern int git_futils_readbuffer_updated( + git_buf *obj, const char *path, git_oid *checksum, int *updated); +extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len); + +/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We + * support these internally and they will be removed before the `open` call. + */ +#ifndef O_FSYNC +# define O_FSYNC (1 << 31) +#endif + +extern int git_futils_writebuffer( + const git_buf *buf, const char *path, int open_flags, mode_t mode); + +/** + * File utils + * + * These are custom filesystem-related helper methods. They are + * rather high level, and wrap the underlying POSIX methods + * + * All these methods return 0 on success, + * or an error code on failure and an error message is set. + */ + +/** + * Create and open a file, while also + * creating all the folders in its path + */ +extern int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode); + +/** + * Create and open a process-locked file + */ +extern int git_futils_creat_locked(const char *path, const mode_t mode); + +/** + * Create and open a process-locked file, while + * also creating all the folders in its path + */ +extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode); + +/** + * Create a path recursively. + */ +extern int git_futils_mkdir_r(const char *path, const mode_t mode); + +/** + * Flags to pass to `git_futils_mkdir`. + * + * * GIT_MKDIR_EXCL is "exclusive" - i.e. generate an error if dir exists. + * * GIT_MKDIR_PATH says to make all components in the path. + * * GIT_MKDIR_CHMOD says to chmod the final directory entry after creation + * * GIT_MKDIR_CHMOD_PATH says to chmod each directory component in the path + * * GIT_MKDIR_SKIP_LAST says to leave off the last element of the path + * * GIT_MKDIR_SKIP_LAST2 says to leave off the last 2 elements of the path + * * GIT_MKDIR_VERIFY_DIR says confirm final item is a dir, not just EEXIST + * * GIT_MKDIR_REMOVE_FILES says to remove files and recreate dirs + * * GIT_MKDIR_REMOVE_SYMLINKS says to remove symlinks and recreate dirs + * + * Note that the chmod options will be executed even if the directory already + * exists, unless GIT_MKDIR_EXCL is given. + */ +typedef enum { + GIT_MKDIR_EXCL = 1, + GIT_MKDIR_PATH = 2, + GIT_MKDIR_CHMOD = 4, + GIT_MKDIR_CHMOD_PATH = 8, + GIT_MKDIR_SKIP_LAST = 16, + GIT_MKDIR_SKIP_LAST2 = 32, + GIT_MKDIR_VERIFY_DIR = 64, + GIT_MKDIR_REMOVE_FILES = 128, + GIT_MKDIR_REMOVE_SYMLINKS = 256, +} git_futils_mkdir_flags; + +struct git_futils_mkdir_perfdata +{ + size_t stat_calls; + size_t mkdir_calls; + size_t chmod_calls; +}; + +struct git_futils_mkdir_options +{ + git_strmap *dir_map; + git_pool *pool; + struct git_futils_mkdir_perfdata perfdata; +}; + +/** + * Create a directory or entire path. + * + * This makes a directory (and the entire path leading up to it if requested), + * and optionally chmods the directory immediately after (or each part of the + * path if requested). + * + * @param path The path to create, relative to base. + * @param base Root for relative path. These directories will never be made. + * @param mode The mode to use for created directories. + * @param flags Combination of the mkdir flags above. + * @param opts Extended options, or null. + * @return 0 on success, else error code + */ +extern int git_futils_mkdir_relative(const char *path, const char *base, mode_t mode, uint32_t flags, struct git_futils_mkdir_options *opts); + +/** + * Create a directory or entire path. Similar to `git_futils_mkdir_relative` + * without performance data. + */ +extern int git_futils_mkdir(const char *path, mode_t mode, uint32_t flags); + +/** + * Create all the folders required to contain + * the full path of a file + */ +extern int git_futils_mkpath2file(const char *path, const mode_t mode); + +/** + * Flags to pass to `git_futils_rmdir_r`. + * + * * GIT_RMDIR_EMPTY_HIERARCHY - the default; remove hierarchy of empty + * dirs and generate error if any files are found. + * * GIT_RMDIR_REMOVE_FILES - attempt to remove files in the hierarchy. + * * GIT_RMDIR_SKIP_NONEMPTY - skip non-empty directories with no error. + * * GIT_RMDIR_EMPTY_PARENTS - remove containing directories up to base + * if removing this item leaves them empty + * * GIT_RMDIR_REMOVE_BLOCKERS - remove blocking file that causes ENOTDIR + * * GIT_RMDIR_SKIP_ROOT - don't remove root directory itself + */ +typedef enum { + GIT_RMDIR_EMPTY_HIERARCHY = 0, + GIT_RMDIR_REMOVE_FILES = (1 << 0), + GIT_RMDIR_SKIP_NONEMPTY = (1 << 1), + GIT_RMDIR_EMPTY_PARENTS = (1 << 2), + GIT_RMDIR_REMOVE_BLOCKERS = (1 << 3), + GIT_RMDIR_SKIP_ROOT = (1 << 4), +} git_futils_rmdir_flags; + +/** + * Remove path and any files and directories beneath it. + * + * @param path Path to the top level directory to process. + * @param base Root for relative path. + * @param flags Combination of git_futils_rmdir_flags values + * @return 0 on success; -1 on error. + */ +extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags); + +/** + * Create and open a temporary file with a `_git2_` suffix. + * Writes the filename into path_out. + * @return On success, an open file descriptor, else an error code < 0. + */ +extern int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode); + +/** + * Move a file on the filesystem, create the + * destination path if it doesn't exist + */ +extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode); + +/** + * Copy a file + * + * The filemode will be used for the newly created file. + */ +extern int git_futils_cp( + const char *from, + const char *to, + mode_t filemode); + +/** + * Set the files atime and mtime to the given time, or the current time + * if `ts` is NULL. + */ +extern int git_futils_touch(const char *path, time_t *when); + +/** + * Flags that can be passed to `git_futils_cp_r`. + * + * - GIT_CPDIR_CREATE_EMPTY_DIRS: create directories even if there are no + * files under them (otherwise directories will only be created lazily + * when a file inside them is copied). + * - GIT_CPDIR_COPY_SYMLINKS: copy symlinks, otherwise they are ignored. + * - GIT_CPDIR_COPY_DOTFILES: copy files with leading '.', otherwise ignored. + * - GIT_CPDIR_OVERWRITE: overwrite pre-existing files with source content, + * otherwise they are silently skipped. + * - GIT_CPDIR_CHMOD_DIRS: explicitly chmod directories to `dirmode` + * - GIT_CPDIR_SIMPLE_TO_MODE: default tries to replicate the mode of the + * source file to the target; with this flag, always use 0666 (or 0777 if + * source has exec bits set) for target. + * - GIT_CPDIR_LINK_FILES will try to use hardlinks for the files + */ +typedef enum { + GIT_CPDIR_CREATE_EMPTY_DIRS = (1u << 0), + GIT_CPDIR_COPY_SYMLINKS = (1u << 1), + GIT_CPDIR_COPY_DOTFILES = (1u << 2), + GIT_CPDIR_OVERWRITE = (1u << 3), + GIT_CPDIR_CHMOD_DIRS = (1u << 4), + GIT_CPDIR_SIMPLE_TO_MODE = (1u << 5), + GIT_CPDIR_LINK_FILES = (1u << 6), +} git_futils_cpdir_flags; + +/** + * Copy a directory tree. + * + * This copies directories and files from one root to another. You can + * pass a combinationof GIT_CPDIR flags as defined above. + * + * If you pass the CHMOD flag, then the dirmode will be applied to all + * directories that are created during the copy, overiding the natural + * permissions. If you do not pass the CHMOD flag, then the dirmode + * will actually be copied from the source files and the `dirmode` arg + * will be ignored. + */ +extern int git_futils_cp_r( + const char *from, + const char *to, + uint32_t flags, + mode_t dirmode); + +/** + * Open a file readonly and set error if needed. + */ +extern int git_futils_open_ro(const char *path); + +/** + * Truncate a file, creating it if it doesn't exist. + */ +extern int git_futils_truncate(const char *path, int mode); + +/** + * Get the filesize in bytes of a file + */ +extern int git_futils_filesize(uint64_t *out, git_file fd); + +#define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0111) != 0) +#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0755 : 0644) +#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0777 : 0666) + +#define GIT_MODE_PERMS_MASK 0777 +#define GIT_MODE_TYPE_MASK 0170000 +#define GIT_MODE_TYPE(MODE) ((MODE) & GIT_MODE_TYPE_MASK) +#define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB)) + +/** + * Convert a mode_t from the OS to a legal git mode_t value. + */ +extern mode_t git_futils_canonical_mode(mode_t raw_mode); + + +/** + * Read-only map all or part of a file into memory. + * When possible this function should favor a virtual memory + * style mapping over some form of malloc()+read(), as the + * data access will be random and is not likely to touch the + * majority of the region requested. + * + * @param out buffer to populate with the mapping information. + * @param fd open descriptor to configure the mapping from. + * @param begin first byte to map, this should be page aligned. + * @param len number of bytes to map. + * @return + * - 0 on success; + * - -1 on error. + */ +extern int git_futils_mmap_ro( + git_map *out, + git_file fd, + off64_t begin, + size_t len); + +/** + * Read-only map an entire file. + * + * @param out buffer to populate with the mapping information. + * @param path path to file to be opened. + * @return + * - 0 on success; + * - GIT_ENOTFOUND if not found; + * - -1 on an unspecified OS related error. + */ +extern int git_futils_mmap_ro_file( + git_map *out, + const char *path); + +/** + * Release the memory associated with a previous memory mapping. + * @param map the mapping description previously configured. + */ +extern void git_futils_mmap_free(git_map *map); + +/** + * Create a "fake" symlink (text file containing the target path). + * + * @param target original symlink target + * @param path symlink file to be created + * @return 0 on success, -1 on error + */ +extern int git_futils_fake_symlink(const char *target, const char *path); + +/** + * A file stamp represents a snapshot of information about a file that can + * be used to test if the file changes. This portable implementation is + * based on stat data about that file, but it is possible that OS specific + * versions could be implemented in the future. + */ +typedef struct { + struct timespec mtime; + uint64_t size; + unsigned int ino; +} git_futils_filestamp; + +/** + * Compare stat information for file with reference info. + * + * This function updates the file stamp to current data for the given path + * and returns 0 if the file is up-to-date relative to the prior setting, + * 1 if the file has been changed, or GIT_ENOTFOUND if the file doesn't + * exist. This will not call git_error_set, so you must set the error if you + * plan to return an error. + * + * @param stamp File stamp to be checked + * @param path Path to stat and check if changed + * @return 0 if up-to-date, 1 if out-of-date, GIT_ENOTFOUND if cannot stat + */ +extern int git_futils_filestamp_check( + git_futils_filestamp *stamp, const char *path); + +/** + * Set or reset file stamp data + * + * This writes the target file stamp. If the source is NULL, this will set + * the target stamp to values that will definitely be out of date. If the + * source is not NULL, this copies the source values to the target. + * + * @param tgt File stamp to write to + * @param src File stamp to copy from or NULL to clear the target + */ +extern void git_futils_filestamp_set( + git_futils_filestamp *tgt, const git_futils_filestamp *src); + +/** + * Set file stamp data from stat structure + */ +extern void git_futils_filestamp_set_from_stat( + git_futils_filestamp *stamp, struct stat *st); + +/** + * `fsync` the parent directory of the given path, if `fsync` is + * supported for directories on this platform. + * + * @param path Path of the directory to sync. + * @return 0 on success, -1 on error + */ +extern int git_futils_fsync_dir(const char *path); + +/** + * `fsync` the parent directory of the given path, if `fsync` is + * supported for directories on this platform. + * + * @param path Path of the file whose parent directory should be synced. + * @return 0 on success, -1 on error + */ +extern int git_futils_fsync_parent(const char *path); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/global.c libgit2-1.1.0+dfsg.1/src/global.c --- libgit2-0.28.5+dfsg.1/src/global.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/global.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,6 +12,7 @@ #include "sysdir.h" #include "filter.h" #include "merge_driver.h" +#include "pool.h" #include "streams/registry.h" #include "streams/mbedtls.h" #include "streams/openssl.h" @@ -38,7 +39,8 @@ git_stream_registry_global_init, git_openssl_stream_global_init, git_mbedtls_stream_global_init, - git_mwindow_global_init + git_mwindow_global_init, + git_pool_global_init }; static git_global_shutdown_fn git__shutdown_callbacks[ARRAY_SIZE(git__init_callbacks)]; diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_collisiondetect.h libgit2-1.1.0+dfsg.1/src/hash/hash_collisiondetect.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_collisiondetect.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_collisiondetect.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_hash_collisiondetect_h__ -#define INCLUDE_hash_hash_collisiondetect_h__ - -#include "hash.h" -#include "sha1dc/sha1.h" - -struct git_hash_ctx { - SHA1_CTX c; -}; - -#define git_hash_ctx_init(ctx) git_hash_init(ctx) -#define git_hash_ctx_cleanup(ctx) - -GIT_INLINE(int) git_hash_global_init(void) -{ - return 0; -} - -GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - SHA1DCInit(&ctx->c); - return 0; -} - -GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx); - SHA1DCUpdate(&ctx->c, data, len); - return 0; -} - -GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - if (SHA1DCFinal(out->id, &ctx->c)) { - git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected"); - return -1; - } - - return 0; -} - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_common_crypto.h libgit2-1.1.0+dfsg.1/src/hash/hash_common_crypto.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_common_crypto.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_common_crypto.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_hash_common_crypto_h__ -#define INCLUDE_hash_hash_common_crypto_h__ - -#include "hash.h" - -#include - -struct git_hash_ctx { - CC_SHA1_CTX c; -}; - -#define CC_LONG_MAX ((CC_LONG)-1) - -#define git_hash_ctx_init(ctx) git_hash_init(ctx) -#define git_hash_ctx_cleanup(ctx) - -GIT_INLINE(int) git_hash_global_init(void) -{ - return 0; -} - -GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - CC_SHA1_Init(&ctx->c); - return 0; -} - -GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *_data, size_t len) -{ - const unsigned char *data = _data; - - assert(ctx); - - while (len > 0) { - CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len; - - CC_SHA1_Update(&ctx->c, data, chunk); - - data += chunk; - len -= chunk; - } - - return 0; -} - -GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - CC_SHA1_Final(out->id, &ctx->c); - return 0; -} - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_generic.c libgit2-1.1.0+dfsg.1/src/hash/hash_generic.c --- libgit2-0.28.5+dfsg.1/src/hash/hash_generic.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_generic.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,288 +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 "hash_generic.h" - -#include "hash.h" - -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - -/* - * Force usage of rol or ror by selecting the one with the smaller constant. - * It _can_ generate slightly smaller code (a constant of 1 is special), but - * perhaps more importantly it's possibly faster on any uarch that does a - * rotate with a loop. - */ - -#define SHA_ASM(op, x, n) (__extension__ ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })) -#define SHA_ROL(x,n) SHA_ASM("rol", x, n) -#define SHA_ROR(x,n) SHA_ASM("ror", x, n) - -#else - -#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) -#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) -#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) - -#endif - -/* - * If you have 32 registers or more, the compiler can (and should) - * try to change the array[] accesses into registers. However, on - * machines with less than ~25 registers, that won't really work, - * and at least gcc will make an unholy mess of it. - * - * So to avoid that mess which just slows things down, we force - * the stores to memory to actually happen (we might be better off - * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as - * suggested by Artur Skawina - that will also make gcc unable to - * try to do the silly "optimize away loads" part because it won't - * see what the value will be). - * - * Ben Herrenschmidt reports that on PPC, the C version comes close - * to the optimized asm with this (ie on PPC you don't want that - * 'volatile', since there are lots of registers). - * - * On ARM we get the best code generation by forcing a full memory barrier - * between each SHA_ROUND, otherwise gcc happily get wild with spilling and - * the stack frame size simply explode and performance goes down the drain. - */ - -#if defined(__i386__) || defined(__x86_64__) - #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) -#elif defined(__GNUC__) && defined(__arm__) - #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) -#else - #define setW(x, val) (W(x) = (val)) -#endif - -/* - * Performance might be improved if the CPU architecture is OK with - * unaligned 32-bit loads and a fast ntohl() is available. - * Otherwise fall back to byte loads and shifts which is portable, - * and is faster on architectures with memory alignment issues. - */ - -#if defined(__i386__) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(_M_X64) || \ - defined(__ppc__) || defined(__ppc64__) || \ - defined(__powerpc__) || defined(__powerpc64__) || \ - defined(__s390__) || defined(__s390x__) - -#define get_be32(p) ntohl(*(const unsigned int *)(p)) -#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) - -#else - -#define get_be32(p) ( \ - (*((const unsigned char *)(p) + 0) << 24) | \ - (*((const unsigned char *)(p) + 1) << 16) | \ - (*((const unsigned char *)(p) + 2) << 8) | \ - (*((const unsigned char *)(p) + 3) << 0) ) -#define put_be32(p, v) do { \ - unsigned int __v = (v); \ - *((unsigned char *)(p) + 0) = __v >> 24; \ - *((unsigned char *)(p) + 1) = __v >> 16; \ - *((unsigned char *)(p) + 2) = __v >> 8; \ - *((unsigned char *)(p) + 3) = __v >> 0; } while (0) - -#endif - -/* This "rolls" over the 512-bit array */ -#define W(x) (array[(x)&15]) - -/* - * Where do we get the source from? The first 16 iterations get it from - * the input data, the next mix it from the 512-bit array. - */ -#define SHA_SRC(t) get_be32(data + t) -#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1) - -#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ - unsigned int TEMP = input(t); setW(t, TEMP); \ - E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ - B = SHA_ROR(B, 2); } while (0) - -#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) -#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) -#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) -#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) -#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) - -static void hash__block(git_hash_ctx *ctx, const unsigned int *data) -{ - unsigned int A,B,C,D,E; - unsigned int array[16]; - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - /* Round 1 - iterations 0-16 take their input from 'data' */ - T_0_15( 0, A, B, C, D, E); - T_0_15( 1, E, A, B, C, D); - T_0_15( 2, D, E, A, B, C); - T_0_15( 3, C, D, E, A, B); - T_0_15( 4, B, C, D, E, A); - T_0_15( 5, A, B, C, D, E); - T_0_15( 6, E, A, B, C, D); - T_0_15( 7, D, E, A, B, C); - T_0_15( 8, C, D, E, A, B); - T_0_15( 9, B, C, D, E, A); - T_0_15(10, A, B, C, D, E); - T_0_15(11, E, A, B, C, D); - T_0_15(12, D, E, A, B, C); - T_0_15(13, C, D, E, A, B); - T_0_15(14, B, C, D, E, A); - T_0_15(15, A, B, C, D, E); - - /* Round 1 - tail. Input from 512-bit mixing array */ - T_16_19(16, E, A, B, C, D); - T_16_19(17, D, E, A, B, C); - T_16_19(18, C, D, E, A, B); - T_16_19(19, B, C, D, E, A); - - /* Round 2 */ - T_20_39(20, A, B, C, D, E); - T_20_39(21, E, A, B, C, D); - T_20_39(22, D, E, A, B, C); - T_20_39(23, C, D, E, A, B); - T_20_39(24, B, C, D, E, A); - T_20_39(25, A, B, C, D, E); - T_20_39(26, E, A, B, C, D); - T_20_39(27, D, E, A, B, C); - T_20_39(28, C, D, E, A, B); - T_20_39(29, B, C, D, E, A); - T_20_39(30, A, B, C, D, E); - T_20_39(31, E, A, B, C, D); - T_20_39(32, D, E, A, B, C); - T_20_39(33, C, D, E, A, B); - T_20_39(34, B, C, D, E, A); - T_20_39(35, A, B, C, D, E); - T_20_39(36, E, A, B, C, D); - T_20_39(37, D, E, A, B, C); - T_20_39(38, C, D, E, A, B); - T_20_39(39, B, C, D, E, A); - - /* Round 3 */ - T_40_59(40, A, B, C, D, E); - T_40_59(41, E, A, B, C, D); - T_40_59(42, D, E, A, B, C); - T_40_59(43, C, D, E, A, B); - T_40_59(44, B, C, D, E, A); - T_40_59(45, A, B, C, D, E); - T_40_59(46, E, A, B, C, D); - T_40_59(47, D, E, A, B, C); - T_40_59(48, C, D, E, A, B); - T_40_59(49, B, C, D, E, A); - T_40_59(50, A, B, C, D, E); - T_40_59(51, E, A, B, C, D); - T_40_59(52, D, E, A, B, C); - T_40_59(53, C, D, E, A, B); - T_40_59(54, B, C, D, E, A); - T_40_59(55, A, B, C, D, E); - T_40_59(56, E, A, B, C, D); - T_40_59(57, D, E, A, B, C); - T_40_59(58, C, D, E, A, B); - T_40_59(59, B, C, D, E, A); - - /* Round 4 */ - T_60_79(60, A, B, C, D, E); - T_60_79(61, E, A, B, C, D); - T_60_79(62, D, E, A, B, C); - T_60_79(63, C, D, E, A, B); - T_60_79(64, B, C, D, E, A); - T_60_79(65, A, B, C, D, E); - T_60_79(66, E, A, B, C, D); - T_60_79(67, D, E, A, B, C); - T_60_79(68, C, D, E, A, B); - T_60_79(69, B, C, D, E, A); - T_60_79(70, A, B, C, D, E); - T_60_79(71, E, A, B, C, D); - T_60_79(72, D, E, A, B, C); - T_60_79(73, C, D, E, A, B); - T_60_79(74, B, C, D, E, A); - T_60_79(75, A, B, C, D, E); - T_60_79(76, E, A, B, C, D); - T_60_79(77, D, E, A, B, C); - T_60_79(78, C, D, E, A, B); - T_60_79(79, B, C, D, E, A); - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -int git_hash_init(git_hash_ctx *ctx) -{ - ctx->size = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) */ - ctx->H[0] = 0x67452301; - ctx->H[1] = 0xefcdab89; - ctx->H[2] = 0x98badcfe; - ctx->H[3] = 0x10325476; - ctx->H[4] = 0xc3d2e1f0; - - return 0; -} - -int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - unsigned int lenW = ctx->size & 63; - - ctx->size += len; - - /* Read the data into W and process blocks as they get full */ - if (lenW) { - unsigned int left = 64 - lenW; - if (len < left) - left = (unsigned int)len; - memcpy(lenW + (char *)ctx->W, data, left); - lenW = (lenW + left) & 63; - len -= left; - data = ((const char *)data + left); - if (lenW) - return 0; - hash__block(ctx, ctx->W); - } - while (len >= 64) { - hash__block(ctx, data); - data = ((const char *)data + 64); - len -= 64; - } - if (len) - memcpy(ctx->W, data, len); - - return 0; -} - -int git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - static const unsigned char pad[64] = { 0x80 }; - unsigned int padlen[2]; - int i; - - /* Pad with a binary 1 (ie 0x80), then zeroes, then length */ - padlen[0] = htonl((uint32_t)(ctx->size >> 29)); - padlen[1] = htonl((uint32_t)(ctx->size << 3)); - - i = ctx->size & 63; - git_hash_update(ctx, pad, 1+ (63 & (55 - i))); - git_hash_update(ctx, padlen, 8); - - /* Output hash */ - for (i = 0; i < 5; i++) - put_be32(out->id + i*4, ctx->H[i]); - - return 0; -} - diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_generic.h libgit2-1.1.0+dfsg.1/src/hash/hash_generic.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_generic.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_generic.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_hash_generic_h__ -#define INCLUDE_hash_hash_generic_h__ - -#include "common.h" - -#include "hash.h" - -struct git_hash_ctx { - unsigned long long size; - unsigned int H[5]; - unsigned int W[16]; -}; - -#define git_hash_ctx_init(ctx) git_hash_init(ctx) -#define git_hash_ctx_cleanup(ctx) - -GIT_INLINE(int) git_hash_global_init(void) -{ - return 0; -} - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_mbedtls.c libgit2-1.1.0+dfsg.1/src/hash/hash_mbedtls.c --- libgit2-0.28.5+dfsg.1/src/hash/hash_mbedtls.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_mbedtls.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +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 "common.h" -#include "hash.h" -#include "hash/hash_mbedtls.h" - -void git_hash_ctx_cleanup(git_hash_ctx *ctx) -{ - assert(ctx); - mbedtls_sha1_free(&ctx->c); -} - -int git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - mbedtls_sha1_init(&ctx->c); - mbedtls_sha1_starts(&ctx->c); - return 0; -} - -int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx); - mbedtls_sha1_update(&ctx->c, data, len); - return 0; -} - -int git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - mbedtls_sha1_finish(&ctx->c, out->id); - return 0; -} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_mbedtls.h libgit2-1.1.0+dfsg.1/src/hash/hash_mbedtls.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_mbedtls.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_mbedtls.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_mbedtld_h__ -#define INCLUDE_hash_mbedtld_h__ - -#include - -struct git_hash_ctx { - mbedtls_sha1_context c; -}; - -#define git_hash_ctx_init(ctx) git_hash_init(ctx) - -GIT_INLINE(int) git_hash_global_init(void) -{ - return 0; -} - -#endif /* INCLUDE_hash_mbedtld_h__ */ diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_openssl.h libgit2-1.1.0+dfsg.1/src/hash/hash_openssl.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_openssl.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_openssl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_hash_openssl_h__ -#define INCLUDE_hash_hash_openssl_h__ - -#include "hash.h" - -#include - -struct git_hash_ctx { - SHA_CTX c; -}; - -#define git_hash_ctx_init(ctx) git_hash_init(ctx) -#define git_hash_ctx_cleanup(ctx) - -GIT_INLINE(int) git_hash_global_init(void) -{ - return 0; -} - -GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - - if (SHA1_Init(&ctx->c) != 1) { - git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context"); - return -1; - } - - return 0; -} - -GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx); - - if (SHA1_Update(&ctx->c, data, len) != 1) { - git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash"); - return -1; - } - - return 0; -} - -GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - - if (SHA1_Final(out->id, &ctx->c) != 1) { - git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash"); - return -1; - } - - return 0; -} - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_win32.c libgit2-1.1.0+dfsg.1/src/hash/hash_win32.c --- libgit2-0.28.5+dfsg.1/src/hash/hash_win32.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_win32.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,319 +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 "hash_win32.h" - -#include "global.h" -#include "hash.h" - -#include -#include - -static struct git_hash_prov hash_prov = {0}; - -/* Hash initialization */ - -/* Initialize CNG, if available */ -GIT_INLINE(int) hash_cng_prov_init(void) -{ - char dll_path[MAX_PATH]; - DWORD dll_path_len, size_len; - - /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */ - if (!git_has_win32_version(6, 0, 1)) { - git_error_set(GIT_ERROR_SHA1, "CryptoNG is not supported on this platform"); - return -1; - } - - /* Load bcrypt.dll explicitly from the system directory */ - if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 || - dll_path_len > MAX_PATH || - StringCchCat(dll_path, MAX_PATH, "\\") < 0 || - StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 || - (hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) { - git_error_set(GIT_ERROR_SHA1, "CryptoNG library could not be loaded"); - return -1; - } - - /* Load the function addresses */ - if ((hash_prov.prov.cng.open_algorithm_provider = (hash_win32_cng_open_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptOpenAlgorithmProvider")) == NULL || - (hash_prov.prov.cng.get_property = (hash_win32_cng_get_property_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptGetProperty")) == NULL || - (hash_prov.prov.cng.create_hash = (hash_win32_cng_create_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCreateHash")) == NULL || - (hash_prov.prov.cng.finish_hash = (hash_win32_cng_finish_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptFinishHash")) == NULL || - (hash_prov.prov.cng.hash_data = (hash_win32_cng_hash_data_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptHashData")) == NULL || - (hash_prov.prov.cng.destroy_hash = (hash_win32_cng_destroy_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptDestroyHash")) == NULL || - (hash_prov.prov.cng.close_algorithm_provider = (hash_win32_cng_close_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCloseAlgorithmProvider")) == NULL) { - FreeLibrary(hash_prov.prov.cng.dll); - - git_error_set(GIT_ERROR_OS, "CryptoNG functions could not be loaded"); - return -1; - } - - /* Load the SHA1 algorithm */ - if (hash_prov.prov.cng.open_algorithm_provider(&hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0) { - FreeLibrary(hash_prov.prov.cng.dll); - - git_error_set(GIT_ERROR_OS, "algorithm provider could not be initialized"); - return -1; - } - - /* Get storage space for the hash object */ - if (hash_prov.prov.cng.get_property(hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_prov.prov.cng.hash_object_size, sizeof(DWORD), &size_len, 0) < 0) { - hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0); - FreeLibrary(hash_prov.prov.cng.dll); - - git_error_set(GIT_ERROR_OS, "algorithm handle could not be found"); - return -1; - } - - hash_prov.type = CNG; - return 0; -} - -GIT_INLINE(void) hash_cng_prov_shutdown(void) -{ - hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0); - FreeLibrary(hash_prov.prov.cng.dll); - - hash_prov.type = INVALID; -} - -/* Initialize CryptoAPI */ -GIT_INLINE(int) hash_cryptoapi_prov_init() -{ - if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - git_error_set(GIT_ERROR_OS, "legacy hash context could not be started"); - return -1; - } - - hash_prov.type = CRYPTOAPI; - return 0; -} - -GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void) -{ - CryptReleaseContext(hash_prov.prov.cryptoapi.handle, 0); - - hash_prov.type = INVALID; -} - -static void git_hash_global_shutdown(void) -{ - if (hash_prov.type == CNG) - hash_cng_prov_shutdown(); - else if(hash_prov.type == CRYPTOAPI) - hash_cryptoapi_prov_shutdown(); -} - -int git_hash_global_init(void) -{ - int error = 0; - - if (hash_prov.type != INVALID) - return 0; - - if ((error = hash_cng_prov_init()) < 0) - error = hash_cryptoapi_prov_init(); - - git__on_shutdown(git_hash_global_shutdown); - - return error; -} - -/* CryptoAPI: available in Windows XP and newer */ - -GIT_INLINE(int) hash_ctx_cryptoapi_init(git_hash_ctx *ctx) -{ - ctx->type = CRYPTOAPI; - ctx->prov = &hash_prov; - - return git_hash_init(ctx); -} - -GIT_INLINE(int) hash_cryptoapi_init(git_hash_ctx *ctx) -{ - if (ctx->ctx.cryptoapi.valid) - CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); - - if (!CryptCreateHash(ctx->prov->prov.cryptoapi.handle, CALG_SHA1, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) { - ctx->ctx.cryptoapi.valid = 0; - git_error_set(GIT_ERROR_OS, "legacy hash implementation could not be created"); - return -1; - } - - ctx->ctx.cryptoapi.valid = 1; - return 0; -} - -GIT_INLINE(int) hash_cryptoapi_update(git_hash_ctx *ctx, const void *_data, size_t len) -{ - const BYTE *data = (BYTE *)_data; - - assert(ctx->ctx.cryptoapi.valid); - - while (len > 0) { - DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len; - - if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0)) { - git_error_set(GIT_ERROR_OS, "legacy hash data could not be updated"); - return -1; - } - - data += chunk; - len -= chunk; - } - - return 0; -} - -GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_ctx *ctx) -{ - DWORD len = 20; - int error = 0; - - assert(ctx->ctx.cryptoapi.valid); - - if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) { - git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished"); - error = -1; - } - - CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); - ctx->ctx.cryptoapi.valid = 0; - - return error; -} - -GIT_INLINE(void) hash_ctx_cryptoapi_cleanup(git_hash_ctx *ctx) -{ - if (ctx->ctx.cryptoapi.valid) - CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); -} - -/* CNG: Available in Windows Server 2008 and newer */ - -GIT_INLINE(int) hash_ctx_cng_init(git_hash_ctx *ctx) -{ - if ((ctx->ctx.cng.hash_object = git__malloc(hash_prov.prov.cng.hash_object_size)) == NULL) - return -1; - - if (hash_prov.prov.cng.create_hash(hash_prov.prov.cng.handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_prov.prov.cng.hash_object_size, NULL, 0, 0) < 0) { - git__free(ctx->ctx.cng.hash_object); - - git_error_set(GIT_ERROR_OS, "hash implementation could not be created"); - return -1; - } - - ctx->type = CNG; - ctx->prov = &hash_prov; - - return 0; -} - -GIT_INLINE(int) hash_cng_init(git_hash_ctx *ctx) -{ - BYTE hash[GIT_OID_RAWSZ]; - - if (!ctx->ctx.cng.updated) - return 0; - - /* CNG needs to be finished to restart */ - if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, GIT_OID_RAWSZ, 0) < 0) { - git_error_set(GIT_ERROR_OS, "hash implementation could not be finished"); - return -1; - } - - ctx->ctx.cng.updated = 0; - - return 0; -} - -GIT_INLINE(int) hash_cng_update(git_hash_ctx *ctx, const void *_data, size_t len) -{ - PBYTE data = (PBYTE)_data; - - while (len > 0) { - ULONG chunk = (len > ULONG_MAX) ? ULONG_MAX : (ULONG)len; - - if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0) { - git_error_set(GIT_ERROR_OS, "hash could not be updated"); - return -1; - } - - data += chunk; - len -= chunk; - } - - return 0; -} - -GIT_INLINE(int) hash_cng_final(git_oid *out, git_hash_ctx *ctx) -{ - if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out->id, GIT_OID_RAWSZ, 0) < 0) { - git_error_set(GIT_ERROR_OS, "hash could not be finished"); - return -1; - } - - ctx->ctx.cng.updated = 0; - - return 0; -} - -GIT_INLINE(void) hash_ctx_cng_cleanup(git_hash_ctx *ctx) -{ - ctx->prov->prov.cng.destroy_hash(ctx->ctx.cng.hash_handle); - git__free(ctx->ctx.cng.hash_object); -} - -/* Indirection between CryptoAPI and CNG */ - -int git_hash_ctx_init(git_hash_ctx *ctx) -{ - int error = 0; - - assert(ctx); - - /* - * When compiled with GIT_THREADS, the global hash_prov data is - * initialized with git_libgit2_init. Otherwise, it must be initialized - * at first use. - */ - if (hash_prov.type == INVALID && (error = git_hash_global_init()) < 0) - return error; - - memset(ctx, 0x0, sizeof(git_hash_ctx)); - - return (hash_prov.type == CNG) ? hash_ctx_cng_init(ctx) : hash_ctx_cryptoapi_init(ctx); -} - -int git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx && ctx->type); - return (ctx->type == CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx); -} - -int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx && ctx->type); - return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len); -} - -int git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx && ctx->type); - return (ctx->type == CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx); -} - -void git_hash_ctx_cleanup(git_hash_ctx *ctx) -{ - assert(ctx); - - if (ctx->type == CNG) - hash_ctx_cng_cleanup(ctx); - else if(ctx->type == CRYPTOAPI) - hash_ctx_cryptoapi_cleanup(ctx); -} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/hash_win32.h libgit2-1.1.0+dfsg.1/src/hash/hash_win32.h --- libgit2-0.28.5+dfsg.1/src/hash/hash_win32.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/hash_win32.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,141 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_hash_hash_win32_h__ -#define INCLUDE_hash_hash_win32_h__ - -#include "common.h" - -#include "hash.h" - -#include -#include - -enum hash_win32_prov_type { - INVALID = 0, - CRYPTOAPI, - CNG -}; - -/* - * CryptoAPI is available for hashing on Windows XP and newer. - */ - -struct hash_cryptoapi_prov { - HCRYPTPROV handle; -}; - -/* - * CNG (bcrypt.dll) is significantly more performant than CryptoAPI and is - * preferred, however it is only available on Windows 2008 and newer and - * must therefore be dynamically loaded, and we must inline constants that - * would not exist when building in pre-Windows 2008 environments. - */ - -#define GIT_HASH_CNG_DLL_NAME "bcrypt.dll" - -/* BCRYPT_SHA1_ALGORITHM */ -#define GIT_HASH_CNG_HASH_TYPE L"SHA1" - -/* BCRYPT_OBJECT_LENGTH */ -#define GIT_HASH_CNG_HASH_OBJECT_LEN L"ObjectLength" - -/* BCRYPT_HASH_REUSEABLE_FLAGS */ -#define GIT_HASH_CNG_HASH_REUSABLE 0x00000020 - -/* Function declarations for CNG */ -typedef NTSTATUS (WINAPI *hash_win32_cng_open_algorithm_provider_fn)( - HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm, - LPCWSTR pszAlgId, - LPCWSTR pszImplementation, - DWORD dwFlags); - -typedef NTSTATUS (WINAPI *hash_win32_cng_get_property_fn)( - HANDLE /* BCRYPT_HANDLE */ hObject, - LPCWSTR pszProperty, - PUCHAR pbOutput, - ULONG cbOutput, - ULONG *pcbResult, - ULONG dwFlags); - -typedef NTSTATUS (WINAPI *hash_win32_cng_create_hash_fn)( - HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, - HANDLE /* BCRYPT_HASH_HANDLE */ *phHash, - PUCHAR pbHashObject, ULONG cbHashObject, - PUCHAR pbSecret, - ULONG cbSecret, - ULONG dwFlags); - -typedef NTSTATUS (WINAPI *hash_win32_cng_finish_hash_fn)( - HANDLE /* BCRYPT_HASH_HANDLE */ hHash, - PUCHAR pbOutput, - ULONG cbOutput, - ULONG dwFlags); - -typedef NTSTATUS (WINAPI *hash_win32_cng_hash_data_fn)( - HANDLE /* BCRYPT_HASH_HANDLE */ hHash, - PUCHAR pbInput, - ULONG cbInput, - ULONG dwFlags); - -typedef NTSTATUS (WINAPI *hash_win32_cng_destroy_hash_fn)( - HANDLE /* BCRYPT_HASH_HANDLE */ hHash); - -typedef NTSTATUS (WINAPI *hash_win32_cng_close_algorithm_provider_fn)( - HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, - ULONG dwFlags); - -struct hash_cng_prov { - /* DLL for CNG */ - HINSTANCE dll; - - /* Function pointers for CNG */ - hash_win32_cng_open_algorithm_provider_fn open_algorithm_provider; - hash_win32_cng_get_property_fn get_property; - hash_win32_cng_create_hash_fn create_hash; - hash_win32_cng_finish_hash_fn finish_hash; - hash_win32_cng_hash_data_fn hash_data; - hash_win32_cng_destroy_hash_fn destroy_hash; - hash_win32_cng_close_algorithm_provider_fn close_algorithm_provider; - - HANDLE /* BCRYPT_ALG_HANDLE */ handle; - DWORD hash_object_size; -}; - -struct git_hash_prov { - enum hash_win32_prov_type type; - - union { - struct hash_cryptoapi_prov cryptoapi; - struct hash_cng_prov cng; - } prov; -}; - -/* Hash contexts */ - -struct hash_cryptoapi_ctx { - bool valid; - HCRYPTHASH hash_handle; -}; - -struct hash_cng_ctx { - bool updated; - HANDLE /* BCRYPT_HASH_HANDLE */ hash_handle; - PBYTE hash_object; -}; - -struct git_hash_ctx { - enum hash_win32_prov_type type; - git_hash_prov *prov; - - union { - struct hash_cryptoapi_ctx cryptoapi; - struct hash_cng_ctx cng; - } ctx; -}; - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/collisiondetect.c libgit2-1.1.0+dfsg.1/src/hash/sha1/collisiondetect.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/collisiondetect.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/collisiondetect.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * 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 "collisiondetect.h" + +int git_hash_sha1_global_init(void) +{ + return 0; +} + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + return git_hash_sha1_init(ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + GIT_UNUSED(ctx); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + SHA1DCInit(&ctx->c); + return 0; +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + SHA1DCUpdate(&ctx->c, data, len); + return 0; +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + assert(ctx); + if (SHA1DCFinal(out->id, &ctx->c)) { + git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected"); + return -1; + } + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/collisiondetect.h libgit2-1.1.0+dfsg.1/src/hash/sha1/collisiondetect.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/collisiondetect.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/collisiondetect.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_collisiondetect_h__ +#define INCLUDE_hash_sha1_collisiondetect_h__ + +#include "hash/sha1.h" + +#include "sha1dc/sha1.h" + +struct git_hash_sha1_ctx { + SHA1_CTX c; +}; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/common_crypto.c libgit2-1.1.0+dfsg.1/src/hash/sha1/common_crypto.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/common_crypto.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/common_crypto.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * 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 "common_crypto.h" + +#define CC_LONG_MAX ((CC_LONG)-1) + +int git_hash_sha1_global_init(void) +{ + return 0; +} + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + return git_hash_sha1_init(ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + GIT_UNUSED(ctx); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + CC_SHA1_Init(&ctx->c); + return 0; +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len) +{ + const unsigned char *data = _data; + + assert(ctx); + + while (len > 0) { + CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len; + + CC_SHA1_Update(&ctx->c, data, chunk); + + data += chunk; + len -= chunk; + } + + return 0; +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + assert(ctx); + CC_SHA1_Final(out->id, &ctx->c); + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/common_crypto.h libgit2-1.1.0+dfsg.1/src/hash/sha1/common_crypto.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/common_crypto.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/common_crypto.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_common_crypto_h__ +#define INCLUDE_hash_sha1_common_crypto_h__ + +#include "hash/sha1.h" + +#include + +struct git_hash_sha1_ctx { + CC_SHA1_CTX c; +}; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/generic.c libgit2-1.1.0+dfsg.1/src/hash/sha1/generic.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/generic.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/generic.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,300 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "generic.h" + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +/* + * Force usage of rol or ror by selecting the one with the smaller constant. + * It _can_ generate slightly smaller code (a constant of 1 is special), but + * perhaps more importantly it's possibly faster on any uarch that does a + * rotate with a loop. + */ + +#define SHA_ASM(op, x, n) (__extension__ ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })) +#define SHA_ROL(x,n) SHA_ASM("rol", x, n) +#define SHA_ROR(x,n) SHA_ASM("ror", x, n) + +#else + +#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) +#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) +#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) + +#endif + +/* + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * + * Ben Herrenschmidt reports that on PPC, the C version comes close + * to the optimized asm with this (ie on PPC you don't want that + * 'volatile', since there are lots of registers). + * + * On ARM we get the best code generation by forcing a full memory barrier + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and + * the stack frame size simply explode and performance goes down the drain. + */ + +#if defined(__i386__) || defined(__x86_64__) + #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) +#elif defined(__GNUC__) && defined(__arm__) + #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) +#else + #define setW(x, val) (W(x) = (val)) +#endif + +/* + * Performance might be improved if the CPU architecture is OK with + * unaligned 32-bit loads and a fast ntohl() is available. + * Otherwise fall back to byte loads and shifts which is portable, + * and is faster on architectures with memory alignment issues. + */ + +#if defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64) || \ + defined(__ppc__) || defined(__ppc64__) || \ + defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__s390__) || defined(__s390x__) + +#define get_be32(p) ntohl(*(const unsigned int *)(p)) +#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) + +#else + +#define get_be32(p) ( \ + (*((const unsigned char *)(p) + 0) << 24) | \ + (*((const unsigned char *)(p) + 1) << 16) | \ + (*((const unsigned char *)(p) + 2) << 8) | \ + (*((const unsigned char *)(p) + 3) << 0) ) +#define put_be32(p, v) do { \ + unsigned int __v = (v); \ + *((unsigned char *)(p) + 0) = __v >> 24; \ + *((unsigned char *)(p) + 1) = __v >> 16; \ + *((unsigned char *)(p) + 2) = __v >> 8; \ + *((unsigned char *)(p) + 3) = __v >> 0; } while (0) + +#endif + +/* This "rolls" over the 512-bit array */ +#define W(x) (array[(x)&15]) + +/* + * Where do we get the source from? The first 16 iterations get it from + * the input data, the next mix it from the 512-bit array. + */ +#define SHA_SRC(t) get_be32(data + t) +#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1) + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + unsigned int TEMP = input(t); setW(t, TEMP); \ + E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ + B = SHA_ROR(B, 2); } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +static void hash__block(git_hash_sha1_ctx *ctx, const unsigned int *data) +{ + unsigned int A,B,C,D,E; + unsigned int array[16]; + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + /* Round 1 - iterations 0-16 take their input from 'data' */ + T_0_15( 0, A, B, C, D, E); + T_0_15( 1, E, A, B, C, D); + T_0_15( 2, D, E, A, B, C); + T_0_15( 3, C, D, E, A, B); + T_0_15( 4, B, C, D, E, A); + T_0_15( 5, A, B, C, D, E); + T_0_15( 6, E, A, B, C, D); + T_0_15( 7, D, E, A, B, C); + T_0_15( 8, C, D, E, A, B); + T_0_15( 9, B, C, D, E, A); + T_0_15(10, A, B, C, D, E); + T_0_15(11, E, A, B, C, D); + T_0_15(12, D, E, A, B, C); + T_0_15(13, C, D, E, A, B); + T_0_15(14, B, C, D, E, A); + T_0_15(15, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + T_16_19(16, E, A, B, C, D); + T_16_19(17, D, E, A, B, C); + T_16_19(18, C, D, E, A, B); + T_16_19(19, B, C, D, E, A); + + /* Round 2 */ + T_20_39(20, A, B, C, D, E); + T_20_39(21, E, A, B, C, D); + T_20_39(22, D, E, A, B, C); + T_20_39(23, C, D, E, A, B); + T_20_39(24, B, C, D, E, A); + T_20_39(25, A, B, C, D, E); + T_20_39(26, E, A, B, C, D); + T_20_39(27, D, E, A, B, C); + T_20_39(28, C, D, E, A, B); + T_20_39(29, B, C, D, E, A); + T_20_39(30, A, B, C, D, E); + T_20_39(31, E, A, B, C, D); + T_20_39(32, D, E, A, B, C); + T_20_39(33, C, D, E, A, B); + T_20_39(34, B, C, D, E, A); + T_20_39(35, A, B, C, D, E); + T_20_39(36, E, A, B, C, D); + T_20_39(37, D, E, A, B, C); + T_20_39(38, C, D, E, A, B); + T_20_39(39, B, C, D, E, A); + + /* Round 3 */ + T_40_59(40, A, B, C, D, E); + T_40_59(41, E, A, B, C, D); + T_40_59(42, D, E, A, B, C); + T_40_59(43, C, D, E, A, B); + T_40_59(44, B, C, D, E, A); + T_40_59(45, A, B, C, D, E); + T_40_59(46, E, A, B, C, D); + T_40_59(47, D, E, A, B, C); + T_40_59(48, C, D, E, A, B); + T_40_59(49, B, C, D, E, A); + T_40_59(50, A, B, C, D, E); + T_40_59(51, E, A, B, C, D); + T_40_59(52, D, E, A, B, C); + T_40_59(53, C, D, E, A, B); + T_40_59(54, B, C, D, E, A); + T_40_59(55, A, B, C, D, E); + T_40_59(56, E, A, B, C, D); + T_40_59(57, D, E, A, B, C); + T_40_59(58, C, D, E, A, B); + T_40_59(59, B, C, D, E, A); + + /* Round 4 */ + T_60_79(60, A, B, C, D, E); + T_60_79(61, E, A, B, C, D); + T_60_79(62, D, E, A, B, C); + T_60_79(63, C, D, E, A, B); + T_60_79(64, B, C, D, E, A); + T_60_79(65, A, B, C, D, E); + T_60_79(66, E, A, B, C, D); + T_60_79(67, D, E, A, B, C); + T_60_79(68, C, D, E, A, B); + T_60_79(69, B, C, D, E, A); + T_60_79(70, A, B, C, D, E); + T_60_79(71, E, A, B, C, D); + T_60_79(72, D, E, A, B, C); + T_60_79(73, C, D, E, A, B); + T_60_79(74, B, C, D, E, A); + T_60_79(75, A, B, C, D, E); + T_60_79(76, E, A, B, C, D); + T_60_79(77, D, E, A, B, C); + T_60_79(78, C, D, E, A, B); + T_60_79(79, B, C, D, E, A); + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + +int git_hash_sha1_global_init(void) +{ + return 0; +} + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + return git_hash_sha1_init(ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + GIT_UNUSED(ctx); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + ctx->size = 0; + + /* Initialize H with the magic constants (see FIPS180 for constants) */ + ctx->H[0] = 0x67452301; + ctx->H[1] = 0xefcdab89; + ctx->H[2] = 0x98badcfe; + ctx->H[3] = 0x10325476; + ctx->H[4] = 0xc3d2e1f0; + + return 0; +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len) +{ + unsigned int lenW = ctx->size & 63; + + ctx->size += len; + + /* Read the data into W and process blocks as they get full */ + if (lenW) { + unsigned int left = 64 - lenW; + if (len < left) + left = (unsigned int)len; + memcpy(lenW + (char *)ctx->W, data, left); + lenW = (lenW + left) & 63; + len -= left; + data = ((const char *)data + left); + if (lenW) + return 0; + hash__block(ctx, ctx->W); + } + while (len >= 64) { + hash__block(ctx, data); + data = ((const char *)data + 64); + len -= 64; + } + if (len) + memcpy(ctx->W, data, len); + + return 0; +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + static const unsigned char pad[64] = { 0x80 }; + unsigned int padlen[2]; + int i; + + /* Pad with a binary 1 (ie 0x80), then zeroes, then length */ + padlen[0] = htonl((uint32_t)(ctx->size >> 29)); + padlen[1] = htonl((uint32_t)(ctx->size << 3)); + + i = ctx->size & 63; + git_hash_sha1_update(ctx, pad, 1+ (63 & (55 - i))); + git_hash_sha1_update(ctx, padlen, 8); + + /* Output hash */ + for (i = 0; i < 5; i++) + put_be32(out->id + i*4, ctx->H[i]); + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/generic.h libgit2-1.1.0+dfsg.1/src/hash/sha1/generic.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/generic.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/generic.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_generic_h__ +#define INCLUDE_hash_sha1_generic_h__ + +#include "hash/sha1.h" + +struct git_hash_sha1_ctx { + unsigned long long size; + unsigned int H[5]; + unsigned int W[16]; +}; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/mbedtls.c libgit2-1.1.0+dfsg.1/src/hash/sha1/mbedtls.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/mbedtls.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/mbedtls.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * 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 "mbedtls.h" + +int git_hash_sha1_global_init(void) +{ + return 0; +} + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + return git_hash_sha1_init(ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_free(&ctx->c); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_init(&ctx->c); + mbedtls_sha1_starts(&ctx->c); + return 0; +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + mbedtls_sha1_update(&ctx->c, data, len); + return 0; +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_finish(&ctx->c, out->id); + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/mbedtls.h libgit2-1.1.0+dfsg.1/src/hash/sha1/mbedtls.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/mbedtls.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/mbedtls.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_mbedtls_h__ +#define INCLUDE_hash_sha1_mbedtls_h__ + +#include "hash/sha1.h" + +#include + +struct git_hash_sha1_ctx { + mbedtls_sha1_context c; +}; + +#endif /* INCLUDE_hash_sha1_mbedtls_h__ */ diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/openssl.c libgit2-1.1.0+dfsg.1/src/hash/sha1/openssl.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/openssl.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/openssl.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "openssl.h" + +int git_hash_sha1_global_init(void) +{ + return 0; +} + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + return git_hash_sha1_init(ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + GIT_UNUSED(ctx); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + + if (SHA1_Init(&ctx->c) != 1) { + git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context"); + return -1; + } + + return 0; +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + + if (SHA1_Update(&ctx->c, data, len) != 1) { + git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash"); + return -1; + } + + return 0; +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + assert(ctx); + + if (SHA1_Final(out->id, &ctx->c) != 1) { + git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash"); + return -1; + } + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/openssl.h libgit2-1.1.0+dfsg.1/src/hash/sha1/openssl.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/openssl.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/openssl.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_openssl_h__ +#define INCLUDE_hash_sha1_openssl_h__ + +#include "hash/sha1.h" + +#include + +struct git_hash_sha1_ctx { + SHA_CTX c; +}; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/sha1.c libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/sha1.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/sha1.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/sha1.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,1911 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow (danshu@microsoft.com) +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#include +#include +#include +#ifdef __unix__ +#include /* make sure macros like _BIG_ENDIAN visible */ +#endif +#endif + +#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C +#include SHA1DC_CUSTOM_INCLUDE_SHA1_C +#endif + +#ifndef SHA1DC_INIT_SAFE_HASH_DEFAULT +#define SHA1DC_INIT_SAFE_HASH_DEFAULT 1 +#endif + +#include "sha1.h" +#include "ubc_check.h" + +#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \ + defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \ + defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \ + defined(__386) || defined(_M_X64) || defined(_M_AMD64)) +#define SHA1DC_ON_INTEL_LIKE_PROCESSOR +#endif + +/* + Because Little-Endian architectures are most common, + we only set SHA1DC_BIGENDIAN if one of these conditions is met. + Note that all MSFT platforms are little endian, + so none of these will be defined under the MSC compiler. + If you are compiling on a big endian platform and your compiler does not define one of these, + you will have to add whatever macros your tool chain defines to indicate Big-Endianness. + */ + +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) +/* + * Should detect Big Endian under GCC since at least 4.6.0 (gcc svn + * rev #165881). See + * https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html + * + * This also works under clang since 3.2, it copied the GCC-ism. See + * clang.git's 3b198a97d2 ("Preprocessor: add __BYTE_ORDER__ + * predefined macro", 2012-07-27) + */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike */ +#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +/* + * Should detect Big Endian under glibc.git since 14245eb70e ("entered + * into RCS", 1992-11-25). Defined in which will have been + * brought in by standard headers. See glibc.git and + * https://sourceforge.net/p/predef/wiki/Endianness/ + */ +#if __BYTE_ORDER == __BIG_ENDIAN +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike or glibc */ +#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) +/* + * *BSD and newlib (embeded linux, cygwin, etc). + * the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents + * this condition from matching with Solaris/sparc. + * (Solaris defines only one endian macro) + */ +#if _BYTE_ORDER == _BIG_ENDIAN +#define SHA1DC_BIGENDIAN +#endif + +/* Not under GCC-alike or glibc or *BSD or newlib */ +#elif (defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \ + defined(__sparc)) +/* + * Should define Big Endian for a whitelist of known processors. See + * https://sourceforge.net/p/predef/wiki/Endianness/ and + * http://www.oracle.com/technetwork/server-storage/solaris/portingtosolaris-138514.html + */ +#define SHA1DC_BIGENDIAN + +/* Not under GCC-alike or glibc or *BSD or newlib or */ +#elif (defined(_AIX) || defined(__hpux)) + +/* + * Defines Big Endian on a whitelist of OSs that are known to be Big + * Endian-only. See + * https://public-inbox.org/git/93056823-2740-d072-1ebd-46b440b33d7e@felt.demon.nl/ + */ +#define SHA1DC_BIGENDIAN + +/* Not under GCC-alike or glibc or *BSD or newlib or or */ +#elif defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) +/* + * As a last resort before we do anything else we're not 100% sure + * about below, we blacklist specific processors here. We could add + * more, see e.g. https://wiki.debian.org/ArchitectureSpecificsMemo + */ +#else /* Not under GCC-alike or glibc or *BSD or newlib or or or */ + +/* We do nothing more here for now */ +/*#error "Uncomment this to see if you fall through all the detection"*/ + +#endif /* Big Endian detection */ + +#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN)) +#undef SHA1DC_BIGENDIAN +#endif +#if (defined(SHA1DC_FORCE_BIGENDIAN) && !defined(SHA1DC_BIGENDIAN)) +#define SHA1DC_BIGENDIAN +#endif +/*ENDIANNESS SELECTION*/ + +#ifndef SHA1DC_FORCE_ALIGNED_ACCESS +#if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) +#define SHA1DC_ALLOW_UNALIGNED_ACCESS +#endif /*UNALIGNED ACCESS DETECTION*/ +#endif /*FORCE ALIGNED ACCESS*/ + +#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n)))) + +#define sha1_bswap32(x) \ + {x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = (x << 16) | (x >> 16);} + +#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1)) + +#ifdef SHA1DC_BIGENDIAN + #define sha1_load(m, t, temp) { temp = m[t]; } +#else + #define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); } +#endif + +#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x + +#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d)))) +#define sha1_f2(b,c,d) ((b)^(c)^(d)) +#define sha1_f3(b,c,d) (((b)&(c))+((d)&((b)^(c)))) +#define sha1_f4(b,c,d) ((b)^(c)^(d)) + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; b = rotate_left(b, 30); } + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; } + +#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \ + {sha1_load(m, t, temp); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30);} + +#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \ + {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30); } + +#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \ + {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1; b = rotate_left(b, 30); } + +#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \ + {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC; b = rotate_left(b, 30); } + +#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \ + {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6; b = rotate_left(b, 30); } + + +#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e; + +#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION +void sha1_compression(uint32_t ihv[5], const uint32_t m[16]) +{ + uint32_t W[80]; + uint32_t a,b,c,d,e; + unsigned i; + + memcpy(W, m, 16 * 4); + for (i = 16; i < 80; ++i) + W[i] = sha1_mix(W, i); + + a = ihv[0]; b = ihv[1]; c = ihv[2]; d = ihv[3]; e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} +#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/ + + +static void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} + + + +void sha1_compression_states(uint32_t ihv[5], const uint32_t m[16], uint32_t W[80], uint32_t states[80][5]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + uint32_t temp; + +#ifdef DOSTORESTATE00 + SHA1_STORE_STATE(0) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp); + +#ifdef DOSTORESTATE01 + SHA1_STORE_STATE(1) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp); + +#ifdef DOSTORESTATE02 + SHA1_STORE_STATE(2) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp); + +#ifdef DOSTORESTATE03 + SHA1_STORE_STATE(3) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp); + +#ifdef DOSTORESTATE04 + SHA1_STORE_STATE(4) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp); + +#ifdef DOSTORESTATE05 + SHA1_STORE_STATE(5) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp); + +#ifdef DOSTORESTATE06 + SHA1_STORE_STATE(6) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp); + +#ifdef DOSTORESTATE07 + SHA1_STORE_STATE(7) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp); + +#ifdef DOSTORESTATE08 + SHA1_STORE_STATE(8) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp); + +#ifdef DOSTORESTATE09 + SHA1_STORE_STATE(9) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp); + +#ifdef DOSTORESTATE10 + SHA1_STORE_STATE(10) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp); + +#ifdef DOSTORESTATE11 + SHA1_STORE_STATE(11) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp); + +#ifdef DOSTORESTATE12 + SHA1_STORE_STATE(12) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp); + +#ifdef DOSTORESTATE13 + SHA1_STORE_STATE(13) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp); + +#ifdef DOSTORESTATE14 + SHA1_STORE_STATE(14) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp); + +#ifdef DOSTORESTATE15 + SHA1_STORE_STATE(15) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp); + +#ifdef DOSTORESTATE16 + SHA1_STORE_STATE(16) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp); + +#ifdef DOSTORESTATE17 + SHA1_STORE_STATE(17) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp); + +#ifdef DOSTORESTATE18 + SHA1_STORE_STATE(18) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp); + +#ifdef DOSTORESTATE19 + SHA1_STORE_STATE(19) +#endif + SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp); + + + +#ifdef DOSTORESTATE20 + SHA1_STORE_STATE(20) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp); + +#ifdef DOSTORESTATE21 + SHA1_STORE_STATE(21) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp); + +#ifdef DOSTORESTATE22 + SHA1_STORE_STATE(22) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp); + +#ifdef DOSTORESTATE23 + SHA1_STORE_STATE(23) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp); + +#ifdef DOSTORESTATE24 + SHA1_STORE_STATE(24) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp); + +#ifdef DOSTORESTATE25 + SHA1_STORE_STATE(25) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp); + +#ifdef DOSTORESTATE26 + SHA1_STORE_STATE(26) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp); + +#ifdef DOSTORESTATE27 + SHA1_STORE_STATE(27) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp); + +#ifdef DOSTORESTATE28 + SHA1_STORE_STATE(28) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp); + +#ifdef DOSTORESTATE29 + SHA1_STORE_STATE(29) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp); + +#ifdef DOSTORESTATE30 + SHA1_STORE_STATE(30) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp); + +#ifdef DOSTORESTATE31 + SHA1_STORE_STATE(31) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp); + +#ifdef DOSTORESTATE32 + SHA1_STORE_STATE(32) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp); + +#ifdef DOSTORESTATE33 + SHA1_STORE_STATE(33) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp); + +#ifdef DOSTORESTATE34 + SHA1_STORE_STATE(34) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp); + +#ifdef DOSTORESTATE35 + SHA1_STORE_STATE(35) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp); + +#ifdef DOSTORESTATE36 + SHA1_STORE_STATE(36) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp); + +#ifdef DOSTORESTATE37 + SHA1_STORE_STATE(37) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp); + +#ifdef DOSTORESTATE38 + SHA1_STORE_STATE(38) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp); + +#ifdef DOSTORESTATE39 + SHA1_STORE_STATE(39) +#endif + SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp); + + + +#ifdef DOSTORESTATE40 + SHA1_STORE_STATE(40) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp); + +#ifdef DOSTORESTATE41 + SHA1_STORE_STATE(41) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp); + +#ifdef DOSTORESTATE42 + SHA1_STORE_STATE(42) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp); + +#ifdef DOSTORESTATE43 + SHA1_STORE_STATE(43) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp); + +#ifdef DOSTORESTATE44 + SHA1_STORE_STATE(44) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp); + +#ifdef DOSTORESTATE45 + SHA1_STORE_STATE(45) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp); + +#ifdef DOSTORESTATE46 + SHA1_STORE_STATE(46) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp); + +#ifdef DOSTORESTATE47 + SHA1_STORE_STATE(47) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp); + +#ifdef DOSTORESTATE48 + SHA1_STORE_STATE(48) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp); + +#ifdef DOSTORESTATE49 + SHA1_STORE_STATE(49) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp); + +#ifdef DOSTORESTATE50 + SHA1_STORE_STATE(50) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp); + +#ifdef DOSTORESTATE51 + SHA1_STORE_STATE(51) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp); + +#ifdef DOSTORESTATE52 + SHA1_STORE_STATE(52) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp); + +#ifdef DOSTORESTATE53 + SHA1_STORE_STATE(53) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp); + +#ifdef DOSTORESTATE54 + SHA1_STORE_STATE(54) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp); + +#ifdef DOSTORESTATE55 + SHA1_STORE_STATE(55) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp); + +#ifdef DOSTORESTATE56 + SHA1_STORE_STATE(56) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp); + +#ifdef DOSTORESTATE57 + SHA1_STORE_STATE(57) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp); + +#ifdef DOSTORESTATE58 + SHA1_STORE_STATE(58) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp); + +#ifdef DOSTORESTATE59 + SHA1_STORE_STATE(59) +#endif + SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp); + + + + +#ifdef DOSTORESTATE60 + SHA1_STORE_STATE(60) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp); + +#ifdef DOSTORESTATE61 + SHA1_STORE_STATE(61) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp); + +#ifdef DOSTORESTATE62 + SHA1_STORE_STATE(62) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp); + +#ifdef DOSTORESTATE63 + SHA1_STORE_STATE(63) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp); + +#ifdef DOSTORESTATE64 + SHA1_STORE_STATE(64) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp); + +#ifdef DOSTORESTATE65 + SHA1_STORE_STATE(65) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp); + +#ifdef DOSTORESTATE66 + SHA1_STORE_STATE(66) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp); + +#ifdef DOSTORESTATE67 + SHA1_STORE_STATE(67) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp); + +#ifdef DOSTORESTATE68 + SHA1_STORE_STATE(68) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp); + +#ifdef DOSTORESTATE69 + SHA1_STORE_STATE(69) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp); + +#ifdef DOSTORESTATE70 + SHA1_STORE_STATE(70) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp); + +#ifdef DOSTORESTATE71 + SHA1_STORE_STATE(71) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp); + +#ifdef DOSTORESTATE72 + SHA1_STORE_STATE(72) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp); + +#ifdef DOSTORESTATE73 + SHA1_STORE_STATE(73) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp); + +#ifdef DOSTORESTATE74 + SHA1_STORE_STATE(74) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp); + +#ifdef DOSTORESTATE75 + SHA1_STORE_STATE(75) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp); + +#ifdef DOSTORESTATE76 + SHA1_STORE_STATE(76) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp); + +#ifdef DOSTORESTATE77 + SHA1_STORE_STATE(77) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp); + +#ifdef DOSTORESTATE78 + SHA1_STORE_STATE(78) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp); + +#ifdef DOSTORESTATE79 + SHA1_STORE_STATE(79) +#endif + SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp); + + + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} + + + + +#define SHA1_RECOMPRESS(t) \ +static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \ +{ \ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \ + if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \ + if (t > 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 78); \ + if (t > 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 77); \ + if (t > 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 76); \ + if (t > 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 75); \ + if (t > 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 74); \ + if (t > 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 73); \ + if (t > 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 72); \ + if (t > 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 71); \ + if (t > 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 70); \ + if (t > 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 69); \ + if (t > 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 68); \ + if (t > 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 67); \ + if (t > 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 66); \ + if (t > 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 65); \ + if (t > 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 64); \ + if (t > 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 63); \ + if (t > 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 62); \ + if (t > 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 61); \ + if (t > 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 60); \ + if (t > 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 59); \ + if (t > 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 58); \ + if (t > 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 57); \ + if (t > 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 56); \ + if (t > 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 55); \ + if (t > 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 54); \ + if (t > 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 53); \ + if (t > 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 52); \ + if (t > 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 51); \ + if (t > 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 50); \ + if (t > 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 49); \ + if (t > 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 48); \ + if (t > 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 47); \ + if (t > 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 46); \ + if (t > 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 45); \ + if (t > 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 44); \ + if (t > 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 43); \ + if (t > 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 42); \ + if (t > 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 41); \ + if (t > 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 40); \ + if (t > 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 39); \ + if (t > 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 38); \ + if (t > 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 37); \ + if (t > 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 36); \ + if (t > 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 35); \ + if (t > 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 34); \ + if (t > 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 33); \ + if (t > 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 32); \ + if (t > 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 31); \ + if (t > 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 30); \ + if (t > 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 29); \ + if (t > 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 28); \ + if (t > 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 27); \ + if (t > 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 26); \ + if (t > 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 25); \ + if (t > 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 24); \ + if (t > 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 23); \ + if (t > 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 22); \ + if (t > 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 21); \ + if (t > 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 20); \ + if (t > 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 19); \ + if (t > 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 18); \ + if (t > 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 17); \ + if (t > 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 16); \ + if (t > 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 15); \ + if (t > 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 14); \ + if (t > 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 13); \ + if (t > 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 12); \ + if (t > 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 11); \ + if (t > 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 10); \ + if (t > 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 9); \ + if (t > 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 8); \ + if (t > 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 7); \ + if (t > 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 6); \ + if (t > 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 5); \ + if (t > 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 4); \ + if (t > 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 3); \ + if (t > 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 2); \ + if (t > 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 1); \ + if (t > 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 0); \ + ihvin[0] = a; ihvin[1] = b; ihvin[2] = c; ihvin[3] = d; ihvin[4] = e; \ + a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; \ + if (t <= 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 0); \ + if (t <= 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 1); \ + if (t <= 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 2); \ + if (t <= 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 3); \ + if (t <= 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 4); \ + if (t <= 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 5); \ + if (t <= 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 6); \ + if (t <= 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 7); \ + if (t <= 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 8); \ + if (t <= 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 9); \ + if (t <= 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 10); \ + if (t <= 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 11); \ + if (t <= 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 12); \ + if (t <= 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 13); \ + if (t <= 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 14); \ + if (t <= 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 15); \ + if (t <= 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 16); \ + if (t <= 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 17); \ + if (t <= 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 18); \ + if (t <= 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 19); \ + if (t <= 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 20); \ + if (t <= 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 21); \ + if (t <= 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 22); \ + if (t <= 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 23); \ + if (t <= 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 24); \ + if (t <= 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 25); \ + if (t <= 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 26); \ + if (t <= 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 27); \ + if (t <= 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 28); \ + if (t <= 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 29); \ + if (t <= 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 30); \ + if (t <= 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 31); \ + if (t <= 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 32); \ + if (t <= 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 33); \ + if (t <= 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 34); \ + if (t <= 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 35); \ + if (t <= 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 36); \ + if (t <= 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 37); \ + if (t <= 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 38); \ + if (t <= 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 39); \ + if (t <= 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 40); \ + if (t <= 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 41); \ + if (t <= 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 42); \ + if (t <= 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 43); \ + if (t <= 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 44); \ + if (t <= 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 45); \ + if (t <= 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 46); \ + if (t <= 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 47); \ + if (t <= 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 48); \ + if (t <= 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 49); \ + if (t <= 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 50); \ + if (t <= 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 51); \ + if (t <= 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 52); \ + if (t <= 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 53); \ + if (t <= 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 54); \ + if (t <= 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 55); \ + if (t <= 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 56); \ + if (t <= 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 57); \ + if (t <= 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 58); \ + if (t <= 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 59); \ + if (t <= 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 60); \ + if (t <= 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 61); \ + if (t <= 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 62); \ + if (t <= 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 63); \ + if (t <= 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 64); \ + if (t <= 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 65); \ + if (t <= 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 66); \ + if (t <= 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 67); \ + if (t <= 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 68); \ + if (t <= 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 69); \ + if (t <= 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 70); \ + if (t <= 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 71); \ + if (t <= 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 72); \ + if (t <= 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 73); \ + if (t <= 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 74); \ + if (t <= 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 75); \ + if (t <= 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 76); \ + if (t <= 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 77); \ + if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \ + if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \ + ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \ +} + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) /* Compiler complains about the checks in the above macro being constant. */ +#endif + +#ifdef DOSTORESTATE0 +SHA1_RECOMPRESS(0) +#endif + +#ifdef DOSTORESTATE1 +SHA1_RECOMPRESS(1) +#endif + +#ifdef DOSTORESTATE2 +SHA1_RECOMPRESS(2) +#endif + +#ifdef DOSTORESTATE3 +SHA1_RECOMPRESS(3) +#endif + +#ifdef DOSTORESTATE4 +SHA1_RECOMPRESS(4) +#endif + +#ifdef DOSTORESTATE5 +SHA1_RECOMPRESS(5) +#endif + +#ifdef DOSTORESTATE6 +SHA1_RECOMPRESS(6) +#endif + +#ifdef DOSTORESTATE7 +SHA1_RECOMPRESS(7) +#endif + +#ifdef DOSTORESTATE8 +SHA1_RECOMPRESS(8) +#endif + +#ifdef DOSTORESTATE9 +SHA1_RECOMPRESS(9) +#endif + +#ifdef DOSTORESTATE10 +SHA1_RECOMPRESS(10) +#endif + +#ifdef DOSTORESTATE11 +SHA1_RECOMPRESS(11) +#endif + +#ifdef DOSTORESTATE12 +SHA1_RECOMPRESS(12) +#endif + +#ifdef DOSTORESTATE13 +SHA1_RECOMPRESS(13) +#endif + +#ifdef DOSTORESTATE14 +SHA1_RECOMPRESS(14) +#endif + +#ifdef DOSTORESTATE15 +SHA1_RECOMPRESS(15) +#endif + +#ifdef DOSTORESTATE16 +SHA1_RECOMPRESS(16) +#endif + +#ifdef DOSTORESTATE17 +SHA1_RECOMPRESS(17) +#endif + +#ifdef DOSTORESTATE18 +SHA1_RECOMPRESS(18) +#endif + +#ifdef DOSTORESTATE19 +SHA1_RECOMPRESS(19) +#endif + +#ifdef DOSTORESTATE20 +SHA1_RECOMPRESS(20) +#endif + +#ifdef DOSTORESTATE21 +SHA1_RECOMPRESS(21) +#endif + +#ifdef DOSTORESTATE22 +SHA1_RECOMPRESS(22) +#endif + +#ifdef DOSTORESTATE23 +SHA1_RECOMPRESS(23) +#endif + +#ifdef DOSTORESTATE24 +SHA1_RECOMPRESS(24) +#endif + +#ifdef DOSTORESTATE25 +SHA1_RECOMPRESS(25) +#endif + +#ifdef DOSTORESTATE26 +SHA1_RECOMPRESS(26) +#endif + +#ifdef DOSTORESTATE27 +SHA1_RECOMPRESS(27) +#endif + +#ifdef DOSTORESTATE28 +SHA1_RECOMPRESS(28) +#endif + +#ifdef DOSTORESTATE29 +SHA1_RECOMPRESS(29) +#endif + +#ifdef DOSTORESTATE30 +SHA1_RECOMPRESS(30) +#endif + +#ifdef DOSTORESTATE31 +SHA1_RECOMPRESS(31) +#endif + +#ifdef DOSTORESTATE32 +SHA1_RECOMPRESS(32) +#endif + +#ifdef DOSTORESTATE33 +SHA1_RECOMPRESS(33) +#endif + +#ifdef DOSTORESTATE34 +SHA1_RECOMPRESS(34) +#endif + +#ifdef DOSTORESTATE35 +SHA1_RECOMPRESS(35) +#endif + +#ifdef DOSTORESTATE36 +SHA1_RECOMPRESS(36) +#endif + +#ifdef DOSTORESTATE37 +SHA1_RECOMPRESS(37) +#endif + +#ifdef DOSTORESTATE38 +SHA1_RECOMPRESS(38) +#endif + +#ifdef DOSTORESTATE39 +SHA1_RECOMPRESS(39) +#endif + +#ifdef DOSTORESTATE40 +SHA1_RECOMPRESS(40) +#endif + +#ifdef DOSTORESTATE41 +SHA1_RECOMPRESS(41) +#endif + +#ifdef DOSTORESTATE42 +SHA1_RECOMPRESS(42) +#endif + +#ifdef DOSTORESTATE43 +SHA1_RECOMPRESS(43) +#endif + +#ifdef DOSTORESTATE44 +SHA1_RECOMPRESS(44) +#endif + +#ifdef DOSTORESTATE45 +SHA1_RECOMPRESS(45) +#endif + +#ifdef DOSTORESTATE46 +SHA1_RECOMPRESS(46) +#endif + +#ifdef DOSTORESTATE47 +SHA1_RECOMPRESS(47) +#endif + +#ifdef DOSTORESTATE48 +SHA1_RECOMPRESS(48) +#endif + +#ifdef DOSTORESTATE49 +SHA1_RECOMPRESS(49) +#endif + +#ifdef DOSTORESTATE50 +SHA1_RECOMPRESS(50) +#endif + +#ifdef DOSTORESTATE51 +SHA1_RECOMPRESS(51) +#endif + +#ifdef DOSTORESTATE52 +SHA1_RECOMPRESS(52) +#endif + +#ifdef DOSTORESTATE53 +SHA1_RECOMPRESS(53) +#endif + +#ifdef DOSTORESTATE54 +SHA1_RECOMPRESS(54) +#endif + +#ifdef DOSTORESTATE55 +SHA1_RECOMPRESS(55) +#endif + +#ifdef DOSTORESTATE56 +SHA1_RECOMPRESS(56) +#endif + +#ifdef DOSTORESTATE57 +SHA1_RECOMPRESS(57) +#endif + +#ifdef DOSTORESTATE58 +SHA1_RECOMPRESS(58) +#endif + +#ifdef DOSTORESTATE59 +SHA1_RECOMPRESS(59) +#endif + +#ifdef DOSTORESTATE60 +SHA1_RECOMPRESS(60) +#endif + +#ifdef DOSTORESTATE61 +SHA1_RECOMPRESS(61) +#endif + +#ifdef DOSTORESTATE62 +SHA1_RECOMPRESS(62) +#endif + +#ifdef DOSTORESTATE63 +SHA1_RECOMPRESS(63) +#endif + +#ifdef DOSTORESTATE64 +SHA1_RECOMPRESS(64) +#endif + +#ifdef DOSTORESTATE65 +SHA1_RECOMPRESS(65) +#endif + +#ifdef DOSTORESTATE66 +SHA1_RECOMPRESS(66) +#endif + +#ifdef DOSTORESTATE67 +SHA1_RECOMPRESS(67) +#endif + +#ifdef DOSTORESTATE68 +SHA1_RECOMPRESS(68) +#endif + +#ifdef DOSTORESTATE69 +SHA1_RECOMPRESS(69) +#endif + +#ifdef DOSTORESTATE70 +SHA1_RECOMPRESS(70) +#endif + +#ifdef DOSTORESTATE71 +SHA1_RECOMPRESS(71) +#endif + +#ifdef DOSTORESTATE72 +SHA1_RECOMPRESS(72) +#endif + +#ifdef DOSTORESTATE73 +SHA1_RECOMPRESS(73) +#endif + +#ifdef DOSTORESTATE74 +SHA1_RECOMPRESS(74) +#endif + +#ifdef DOSTORESTATE75 +SHA1_RECOMPRESS(75) +#endif + +#ifdef DOSTORESTATE76 +SHA1_RECOMPRESS(76) +#endif + +#ifdef DOSTORESTATE77 +SHA1_RECOMPRESS(77) +#endif + +#ifdef DOSTORESTATE78 +SHA1_RECOMPRESS(78) +#endif + +#ifdef DOSTORESTATE79 +SHA1_RECOMPRESS(79) +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) +{ + switch (step) + { +#ifdef DOSTORESTATE0 + case 0: + sha1recompress_fast_0(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE1 + case 1: + sha1recompress_fast_1(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE2 + case 2: + sha1recompress_fast_2(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE3 + case 3: + sha1recompress_fast_3(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE4 + case 4: + sha1recompress_fast_4(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE5 + case 5: + sha1recompress_fast_5(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE6 + case 6: + sha1recompress_fast_6(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE7 + case 7: + sha1recompress_fast_7(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE8 + case 8: + sha1recompress_fast_8(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE9 + case 9: + sha1recompress_fast_9(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE10 + case 10: + sha1recompress_fast_10(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE11 + case 11: + sha1recompress_fast_11(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE12 + case 12: + sha1recompress_fast_12(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE13 + case 13: + sha1recompress_fast_13(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE14 + case 14: + sha1recompress_fast_14(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE15 + case 15: + sha1recompress_fast_15(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE16 + case 16: + sha1recompress_fast_16(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE17 + case 17: + sha1recompress_fast_17(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE18 + case 18: + sha1recompress_fast_18(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE19 + case 19: + sha1recompress_fast_19(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE20 + case 20: + sha1recompress_fast_20(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE21 + case 21: + sha1recompress_fast_21(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE22 + case 22: + sha1recompress_fast_22(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE23 + case 23: + sha1recompress_fast_23(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE24 + case 24: + sha1recompress_fast_24(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE25 + case 25: + sha1recompress_fast_25(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE26 + case 26: + sha1recompress_fast_26(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE27 + case 27: + sha1recompress_fast_27(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE28 + case 28: + sha1recompress_fast_28(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE29 + case 29: + sha1recompress_fast_29(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE30 + case 30: + sha1recompress_fast_30(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE31 + case 31: + sha1recompress_fast_31(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE32 + case 32: + sha1recompress_fast_32(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE33 + case 33: + sha1recompress_fast_33(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE34 + case 34: + sha1recompress_fast_34(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE35 + case 35: + sha1recompress_fast_35(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE36 + case 36: + sha1recompress_fast_36(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE37 + case 37: + sha1recompress_fast_37(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE38 + case 38: + sha1recompress_fast_38(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE39 + case 39: + sha1recompress_fast_39(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE40 + case 40: + sha1recompress_fast_40(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE41 + case 41: + sha1recompress_fast_41(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE42 + case 42: + sha1recompress_fast_42(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE43 + case 43: + sha1recompress_fast_43(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE44 + case 44: + sha1recompress_fast_44(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE45 + case 45: + sha1recompress_fast_45(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE46 + case 46: + sha1recompress_fast_46(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE47 + case 47: + sha1recompress_fast_47(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE48 + case 48: + sha1recompress_fast_48(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE49 + case 49: + sha1recompress_fast_49(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE50 + case 50: + sha1recompress_fast_50(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE51 + case 51: + sha1recompress_fast_51(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE52 + case 52: + sha1recompress_fast_52(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE53 + case 53: + sha1recompress_fast_53(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE54 + case 54: + sha1recompress_fast_54(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE55 + case 55: + sha1recompress_fast_55(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE56 + case 56: + sha1recompress_fast_56(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE57 + case 57: + sha1recompress_fast_57(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE58 + case 58: + sha1recompress_fast_58(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE59 + case 59: + sha1recompress_fast_59(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE60 + case 60: + sha1recompress_fast_60(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE61 + case 61: + sha1recompress_fast_61(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE62 + case 62: + sha1recompress_fast_62(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE63 + case 63: + sha1recompress_fast_63(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE64 + case 64: + sha1recompress_fast_64(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE65 + case 65: + sha1recompress_fast_65(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE66 + case 66: + sha1recompress_fast_66(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE67 + case 67: + sha1recompress_fast_67(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE68 + case 68: + sha1recompress_fast_68(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE69 + case 69: + sha1recompress_fast_69(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE70 + case 70: + sha1recompress_fast_70(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE71 + case 71: + sha1recompress_fast_71(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE72 + case 72: + sha1recompress_fast_72(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE73 + case 73: + sha1recompress_fast_73(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE74 + case 74: + sha1recompress_fast_74(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE75 + case 75: + sha1recompress_fast_75(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE76 + case 76: + sha1recompress_fast_76(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE77 + case 77: + sha1recompress_fast_77(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE78 + case 78: + sha1recompress_fast_78(ihvin, ihvout, me2, state); + break; +#endif +#ifdef DOSTORESTATE79 + case 79: + sha1recompress_fast_79(ihvin, ihvout, me2, state); + break; +#endif + default: + abort(); + } + +} + + + +static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16]) +{ + unsigned i, j; + uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF }; + uint32_t ihvtmp[5]; + + ctx->ihv1[0] = ctx->ihv[0]; + ctx->ihv1[1] = ctx->ihv[1]; + ctx->ihv1[2] = ctx->ihv[2]; + ctx->ihv1[3] = ctx->ihv[3]; + ctx->ihv1[4] = ctx->ihv[4]; + + sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states); + + if (ctx->detect_coll) + { + if (ctx->ubc_check) + { + ubc_check(ctx->m1, ubc_dv_mask); + } + + if (ubc_dv_mask[0] != 0) + { + for (i = 0; sha1_dvs[i].dvType != 0; ++i) + { + if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb)) + { + for (j = 0; j < 80; ++j) + ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j]; + + sha1_recompression_step(sha1_dvs[i].testt, ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]); + + /* to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 */ + if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | (ihvtmp[4] ^ ctx->ihv[4]))) + || (ctx->reduced_round_coll && 0==((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | (ctx->ihv1[4] ^ ctx->ihv2[4])))) + { + ctx->found_collision = 1; + + if (ctx->safe_hash) + { + sha1_compression_W(ctx->ihv, ctx->m1); + sha1_compression_W(ctx->ihv, ctx->m1); + } + + break; + } + } + } + } + } +} + +void SHA1DCInit(SHA1_CTX* ctx) +{ + ctx->total = 0; + ctx->ihv[0] = 0x67452301; + ctx->ihv[1] = 0xEFCDAB89; + ctx->ihv[2] = 0x98BADCFE; + ctx->ihv[3] = 0x10325476; + ctx->ihv[4] = 0xC3D2E1F0; + ctx->found_collision = 0; + ctx->safe_hash = SHA1DC_INIT_SAFE_HASH_DEFAULT; + ctx->ubc_check = 1; + ctx->detect_coll = 1; + ctx->reduced_round_coll = 0; + ctx->callback = NULL; +} + +void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash) +{ + if (safehash) + ctx->safe_hash = 1; + else + ctx->safe_hash = 0; +} + + +void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check) +{ + if (ubc_check) + ctx->ubc_check = 1; + else + ctx->ubc_check = 0; +} + +void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll) +{ + if (detect_coll) + ctx->detect_coll = 1; + else + ctx->detect_coll = 0; +} + +void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll) +{ + if (reduced_round_coll) + ctx->reduced_round_coll = 1; + else + ctx->reduced_round_coll = 0; +} + +void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback) +{ + ctx->callback = callback; +} + +void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len) +{ + unsigned left, fill; + + if (len == 0) + return; + + left = ctx->total & 63; + fill = 64 - left; + + if (left && len >= fill) + { + ctx->total += fill; + memcpy(ctx->buffer + left, buf, fill); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); + buf += fill; + len -= fill; + left = 0; + } + while (len >= 64) + { + ctx->total += 64; + +#if defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) + sha1_process(ctx, (uint32_t*)(buf)); +#else + memcpy(ctx->buffer, buf, 64); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); +#endif /* defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) */ + buf += 64; + len -= 64; + } + if (len > 0) + { + ctx->total += len; + memcpy(ctx->buffer + left, buf, len); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx) +{ + uint32_t last = ctx->total & 63; + uint32_t padn = (last < 56) ? (56 - last) : (120 - last); + uint64_t total; + SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn); + + total = ctx->total - padn; + total <<= 3; + ctx->buffer[56] = (unsigned char)(total >> 56); + ctx->buffer[57] = (unsigned char)(total >> 48); + ctx->buffer[58] = (unsigned char)(total >> 40); + ctx->buffer[59] = (unsigned char)(total >> 32); + ctx->buffer[60] = (unsigned char)(total >> 24); + ctx->buffer[61] = (unsigned char)(total >> 16); + ctx->buffer[62] = (unsigned char)(total >> 8); + ctx->buffer[63] = (unsigned char)(total); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); + output[0] = (unsigned char)(ctx->ihv[0] >> 24); + output[1] = (unsigned char)(ctx->ihv[0] >> 16); + output[2] = (unsigned char)(ctx->ihv[0] >> 8); + output[3] = (unsigned char)(ctx->ihv[0]); + output[4] = (unsigned char)(ctx->ihv[1] >> 24); + output[5] = (unsigned char)(ctx->ihv[1] >> 16); + output[6] = (unsigned char)(ctx->ihv[1] >> 8); + output[7] = (unsigned char)(ctx->ihv[1]); + output[8] = (unsigned char)(ctx->ihv[2] >> 24); + output[9] = (unsigned char)(ctx->ihv[2] >> 16); + output[10] = (unsigned char)(ctx->ihv[2] >> 8); + output[11] = (unsigned char)(ctx->ihv[2]); + output[12] = (unsigned char)(ctx->ihv[3] >> 24); + output[13] = (unsigned char)(ctx->ihv[3] >> 16); + output[14] = (unsigned char)(ctx->ihv[3] >> 8); + output[15] = (unsigned char)(ctx->ihv[3]); + output[16] = (unsigned char)(ctx->ihv[4] >> 24); + output[17] = (unsigned char)(ctx->ihv[4] >> 16); + output[18] = (unsigned char)(ctx->ihv[4] >> 8); + output[19] = (unsigned char)(ctx->ihv[4]); + return ctx->found_collision; +} + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/sha1.h libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/sha1.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/sha1.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/sha1.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,110 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +#ifndef SHA1DC_SHA1_H +#define SHA1DC_SHA1_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif + +/* sha-1 compression function that takes an already expanded message, and additionally store intermediate states */ +/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */ +void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]); + +/* +// Function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]). +// Where 0 <= T < 80 +// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference.) +// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block. +// The function will return: +// ihvin: The reconstructed input chaining value. +// ihvout: The reconstructed output chaining value. +*/ +typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*); + +/* A callback function type that can be set to be called when a collision block has been found: */ +/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */ +typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*); + +/* The SHA-1 context. */ +typedef struct { + uint64_t total; + uint32_t ihv[5]; + unsigned char buffer[64]; + int found_collision; + int safe_hash; + int detect_coll; + int ubc_check; + int reduced_round_coll; + collision_block_callback callback; + + uint32_t ihv1[5]; + uint32_t ihv2[5]; + uint32_t m1[80]; + uint32_t m2[80]; + uint32_t states[80][5]; +} SHA1_CTX; + +/* Initialize SHA-1 context. */ +void SHA1DCInit(SHA1_CTX*); + +/* + Function to enable safe SHA-1 hashing: + Collision attacks are thwarted by hashing a detected near-collision block 3 times. + Think of it as extending SHA-1 from 80-steps to 240-steps for such blocks: + The best collision attacks against SHA-1 have complexity about 2^60, + thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would be 2^180. + An attacker would be better off using a generic birthday search of complexity 2^80. + + Enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected, + but it will result in a different SHA-1 hash for messages where a collision attack was detected. + This will automatically invalidate SHA-1 based digital signature forgeries. + Enabled by default. +*/ +void SHA1DCSetSafeHash(SHA1_CTX*, int); + +/* + Function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up). + Enabled by default + */ +void SHA1DCSetUseUBC(SHA1_CTX*, int); + +/* + Function to disable or enable the use of Collision Detection. + Enabled by default. + */ +void SHA1DCSetUseDetectColl(SHA1_CTX*, int); + +/* function to disable or enable the detection of reduced-round SHA-1 collisions */ +/* disabled by default */ +void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int); + +/* function to set a callback function, pass NULL to disable */ +/* by default no callback set */ +void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback); + +/* update SHA-1 context with buffer contents */ +void SHA1DCUpdate(SHA1_CTX*, const char*, size_t); + +/* obtain SHA-1 hash from SHA-1 context */ +/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */ +int SHA1DCFinal(unsigned char[20], SHA1_CTX*); + +#if defined(__cplusplus) +} +#endif + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H +#endif + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/ubc_check.c libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/ubc_check.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/ubc_check.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/ubc_check.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,372 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +/* +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set +// +// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded +// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c +// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section +*/ + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif +#ifdef SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C +#include SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C +#endif +#include "ubc_check.h" + +static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0; +static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1; +static const uint32_t DV_I_45_0_bit = (uint32_t)(1) << 2; +static const uint32_t DV_I_46_0_bit = (uint32_t)(1) << 3; +static const uint32_t DV_I_46_2_bit = (uint32_t)(1) << 4; +static const uint32_t DV_I_47_0_bit = (uint32_t)(1) << 5; +static const uint32_t DV_I_47_2_bit = (uint32_t)(1) << 6; +static const uint32_t DV_I_48_0_bit = (uint32_t)(1) << 7; +static const uint32_t DV_I_48_2_bit = (uint32_t)(1) << 8; +static const uint32_t DV_I_49_0_bit = (uint32_t)(1) << 9; +static const uint32_t DV_I_49_2_bit = (uint32_t)(1) << 10; +static const uint32_t DV_I_50_0_bit = (uint32_t)(1) << 11; +static const uint32_t DV_I_50_2_bit = (uint32_t)(1) << 12; +static const uint32_t DV_I_51_0_bit = (uint32_t)(1) << 13; +static const uint32_t DV_I_51_2_bit = (uint32_t)(1) << 14; +static const uint32_t DV_I_52_0_bit = (uint32_t)(1) << 15; +static const uint32_t DV_II_45_0_bit = (uint32_t)(1) << 16; +static const uint32_t DV_II_46_0_bit = (uint32_t)(1) << 17; +static const uint32_t DV_II_46_2_bit = (uint32_t)(1) << 18; +static const uint32_t DV_II_47_0_bit = (uint32_t)(1) << 19; +static const uint32_t DV_II_48_0_bit = (uint32_t)(1) << 20; +static const uint32_t DV_II_49_0_bit = (uint32_t)(1) << 21; +static const uint32_t DV_II_49_2_bit = (uint32_t)(1) << 22; +static const uint32_t DV_II_50_0_bit = (uint32_t)(1) << 23; +static const uint32_t DV_II_50_2_bit = (uint32_t)(1) << 24; +static const uint32_t DV_II_51_0_bit = (uint32_t)(1) << 25; +static const uint32_t DV_II_51_2_bit = (uint32_t)(1) << 26; +static const uint32_t DV_II_52_0_bit = (uint32_t)(1) << 27; +static const uint32_t DV_II_53_0_bit = (uint32_t)(1) << 28; +static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29; +static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30; +static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31; + +dv_info_t sha1_dvs[] = +{ + {1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } } +, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } } +, {1,45,0,58,0,2, { 0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803 } } +, {1,46,0,58,0,3, { 0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c } } +, {1,46,2,58,0,4, { 0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a,0x00000132 } } +, {1,47,0,58,0,5, { 0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6 } } +, {1,47,2,58,0,6, { 0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a } } +, {1,48,0,58,0,7, { 0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408 } } +, {1,48,2,58,0,8, { 0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020 } } +, {1,49,0,58,0,9, { 0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164 } } +, {1,49,2,58,0,10, { 0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590 } } +, {1,50,0,65,0,11, { 0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018 } } +, {1,50,2,65,0,12, { 0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060 } } +, {1,51,0,65,0,13, { 0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202 } } +, {1,51,2,65,0,14, { 0xa0000003,0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a } } +, {1,52,0,65,0,15, { 0x04000010,0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012 } } +, {2,45,0,58,0,16, { 0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054,0x00000967 } } +, {2,46,0,58,0,17, { 0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054 } } +, {2,46,2,58,0,18, { 0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6,0x0000106a,0x00000b90,0x00000152 } } +, {2,47,0,58,0,19, { 0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4 } } +, {2,48,0,58,0,20, { 0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a } } +, {2,49,0,58,0,21, { 0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d } } +, {2,49,2,58,0,22, { 0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6 } } +, {2,50,0,65,0,23, { 0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b } } +, {2,50,2,65,0,24, { 0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c } } +, {2,51,0,65,0,25, { 0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b } } +, {2,51,2,65,0,26, { 0x00000043,0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e } } +, {2,52,0,65,0,27, { 0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014 } } +, {2,53,0,65,0,28, { 0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089 } } +, {2,54,0,65,0,29, { 0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107 } } +, {2,55,0,65,0,30, { 0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b } } +, {2,56,0,65,0,31, { 0x2600001a,0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046 } } +, {0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} +}; +void ubc_check(const uint32_t W[80], uint32_t dvmask[1]) +{ + uint32_t mask = ~((uint32_t)(0)); + mask &= (((((W[44]^W[45])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_I_51_0_bit|DV_I_52_0_bit|DV_II_45_0_bit|DV_II_46_0_bit|DV_II_50_0_bit|DV_II_51_0_bit)); + mask &= (((((W[49]^W[50])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_II_45_0_bit|DV_II_50_0_bit|DV_II_51_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); + mask &= (((((W[48]^W[49])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_52_0_bit|DV_II_49_0_bit|DV_II_50_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); + mask &= ((((W[47]^(W[50]>>25))&(1<<4))-(1<<4)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); + mask &= (((((W[47]^W[48])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_51_0_bit|DV_II_48_0_bit|DV_II_49_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); + mask &= (((((W[46]>>4)^(W[49]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_50_0_bit|DV_II_55_0_bit)); + mask &= (((((W[46]^W[47])>>29)&1)-1) | ~(DV_I_43_0_bit|DV_I_50_0_bit|DV_II_47_0_bit|DV_II_48_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); + mask &= (((((W[45]>>4)^(W[48]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_49_0_bit|DV_II_54_0_bit)); + mask &= (((((W[45]^W[46])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_51_0_bit|DV_II_52_0_bit)); + mask &= (((((W[44]>>4)^(W[47]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_53_0_bit)); + mask &= (((((W[43]>>4)^(W[46]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_52_0_bit)); + mask &= (((((W[43]^W[44])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_I_50_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_49_0_bit|DV_II_50_0_bit)); + mask &= (((((W[42]>>4)^(W[45]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_51_0_bit)); + mask &= (((((W[41]>>4)^(W[44]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_50_0_bit)); + mask &= (((((W[40]^W[41])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_47_0_bit|DV_I_48_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_56_0_bit)); + mask &= (((((W[54]^W[55])>>29)&1)-1) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_50_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); + mask &= (((((W[53]^W[54])>>29)&1)-1) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_49_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); + mask &= (((((W[52]^W[53])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); + mask &= ((((W[50]^(W[53]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_48_0_bit|DV_II_54_0_bit)); + mask &= (((((W[50]^W[51])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_II_46_0_bit|DV_II_51_0_bit|DV_II_52_0_bit|DV_II_56_0_bit)); + mask &= ((((W[49]^(W[52]>>25))&(1<<4))-(1<<4)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_47_0_bit|DV_II_53_0_bit)); + mask &= ((((W[48]^(W[51]>>25))&(1<<4))-(1<<4)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_52_0_bit)); + mask &= (((((W[42]^W[43])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); + mask &= (((((W[41]^W[42])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_48_0_bit)); + mask &= (((((W[40]>>4)^(W[43]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_50_0_bit|DV_II_49_0_bit|DV_II_56_0_bit)); + mask &= (((((W[39]>>4)^(W[42]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_49_0_bit|DV_II_48_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) + mask &= (((((W[38]>>4)^(W[41]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); + mask &= (((((W[37]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_47_0_bit|DV_II_46_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)) + mask &= (((((W[55]^W[56])>>29)&1)-1) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)) + mask &= ((((W[52]^(W[55]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)) + mask &= ((((W[51]^(W[54]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)) + mask &= (((((W[51]^W[52])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); + if (mask & (DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)) + mask &= (((((W[36]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)) + mask &= ((0-(((W[53]^W[56])>>29)&1)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); + if (mask & (DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)) + mask &= ((0-(((W[51]^W[54])>>29)&1)) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)) + mask &= ((0-(((W[50]^W[52])>>29)&1)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)); + if (mask & (DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)) + mask &= ((0-(((W[49]^W[51])>>29)&1)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)); + if (mask & (DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)) + mask &= ((0-(((W[48]^W[50])>>29)&1)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)); + if (mask & (DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)) + mask &= ((0-(((W[47]^W[49])>>29)&1)) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)); + if (mask & (DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)) + mask &= ((0-(((W[46]^W[48])>>29)&1)) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)); + mask &= ((((W[45]^W[47])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit|DV_I_51_2_bit)); + if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)) + mask &= ((0-(((W[45]^W[47])>>29)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)); + mask &= (((((W[44]^W[46])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit|DV_I_50_2_bit)); + if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)) + mask &= ((0-(((W[44]^W[46])>>29)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)); + mask &= ((0-((W[41]^(W[42]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_II_46_2_bit|DV_II_51_2_bit)); + mask &= ((0-((W[40]^(W[41]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_51_2_bit|DV_II_50_2_bit)); + if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)) + mask &= ((0-(((W[40]^W[42])>>4)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)); + mask &= ((0-((W[39]^(W[40]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_50_2_bit|DV_II_49_2_bit)); + if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)) + mask &= ((0-(((W[39]^W[41])>>4)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) + mask &= ((0-(((W[38]^W[40])>>4)&1)) | ~(DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)) + mask &= ((0-(((W[37]^W[39])>>4)&1)) | ~(DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); + mask &= ((0-((W[36]^(W[37]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_50_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)) + mask &= (((((W[35]>>4)^(W[39]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_48_0_bit|DV_II_48_0_bit)) + mask &= ((0-((W[63]^(W[64]>>5))&(1<<0))) | ~(DV_I_48_0_bit|DV_II_48_0_bit)); + if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) + mask &= ((0-((W[63]^(W[64]>>5))&(1<<1))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); + if (mask & (DV_I_47_0_bit|DV_II_47_0_bit)) + mask &= ((0-((W[62]^(W[63]>>5))&(1<<0))) | ~(DV_I_47_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_46_0_bit|DV_II_46_0_bit)) + mask &= ((0-((W[61]^(W[62]>>5))&(1<<0))) | ~(DV_I_46_0_bit|DV_II_46_0_bit)); + mask &= ((0-((W[61]^(W[62]>>5))&(1<<2))) | ~(DV_I_46_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) + mask &= ((0-((W[60]^(W[61]>>5))&(1<<0))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_54_0_bit)) + mask &= (((((W[58]^W[59])>>29)&1)-1) | ~(DV_II_51_0_bit|DV_II_54_0_bit)); + if (mask & (DV_II_50_0_bit|DV_II_53_0_bit)) + mask &= (((((W[57]^W[58])>>29)&1)-1) | ~(DV_II_50_0_bit|DV_II_53_0_bit)); + if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) + mask &= ((((W[56]^(W[59]>>25))&(1<<4))-(1<<4)) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_52_0_bit)) + mask &= ((0-(((W[56]^W[59])>>29)&1)) | ~(DV_II_51_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit|DV_II_52_0_bit)) + mask &= (((((W[56]^W[57])>>29)&1)-1) | ~(DV_II_49_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_53_0_bit)) + mask &= ((((W[55]^(W[58]>>25))&(1<<4))-(1<<4)) | ~(DV_II_51_0_bit|DV_II_53_0_bit)); + if (mask & (DV_II_50_0_bit|DV_II_52_0_bit)) + mask &= ((((W[54]^(W[57]>>25))&(1<<4))-(1<<4)) | ~(DV_II_50_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit|DV_II_51_0_bit)) + mask &= ((((W[53]^(W[56]>>25))&(1<<4))-(1<<4)) | ~(DV_II_49_0_bit|DV_II_51_0_bit)); + mask &= ((((W[51]^(W[50]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); + mask &= ((((W[48]^W[50])&(1<<6))-(1<<6)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_51_0_bit|DV_I_52_0_bit)) + mask &= ((0-(((W[48]^W[55])>>29)&1)) | ~(DV_I_51_0_bit|DV_I_52_0_bit)); + mask &= ((((W[47]^W[49])&(1<<6))-(1<<6)) | ~(DV_I_49_2_bit|DV_I_51_2_bit)); + mask &= ((((W[48]^(W[47]>>5))&(1<<1))-(1<<1)) | ~(DV_I_47_2_bit|DV_II_51_2_bit)); + mask &= ((((W[46]^W[48])&(1<<6))-(1<<6)) | ~(DV_I_48_2_bit|DV_I_50_2_bit)); + mask &= ((((W[47]^(W[46]>>5))&(1<<1))-(1<<1)) | ~(DV_I_46_2_bit|DV_II_50_2_bit)); + mask &= ((0-((W[44]^(W[45]>>5))&(1<<1))) | ~(DV_I_51_2_bit|DV_II_49_2_bit)); + mask &= ((((W[43]^W[45])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit)); + mask &= (((((W[42]^W[44])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit)); + mask &= ((((W[43]^(W[42]>>5))&(1<<1))-(1<<1)) | ~(DV_II_46_2_bit|DV_II_51_2_bit)); + mask &= ((((W[42]^(W[41]>>5))&(1<<1))-(1<<1)) | ~(DV_I_51_2_bit|DV_II_50_2_bit)); + mask &= ((((W[41]^(W[40]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_49_2_bit)); + if (mask & (DV_I_52_0_bit|DV_II_51_0_bit)) + mask &= ((((W[39]^(W[43]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_51_0_bit)); + if (mask & (DV_I_51_0_bit|DV_II_50_0_bit)) + mask &= ((((W[38]^(W[42]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_50_0_bit)); + if (mask & (DV_I_48_2_bit|DV_I_51_2_bit)) + mask &= ((0-((W[37]^(W[38]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_I_51_2_bit)); + if (mask & (DV_I_50_0_bit|DV_II_49_0_bit)) + mask &= ((((W[37]^(W[41]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_II_49_0_bit)); + if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) + mask &= ((0-((W[36]^W[38])&(1<<4))) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); + mask &= ((0-((W[35]^(W[36]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_49_2_bit)); + if (mask & (DV_I_51_0_bit|DV_II_47_0_bit)) + mask &= ((((W[35]^(W[39]>>25))&(1<<3))-(1<<3)) | ~(DV_I_51_0_bit|DV_II_47_0_bit)); +if (mask) { + + if (mask & DV_I_43_0_bit) + if ( + !((W[61]^(W[62]>>5)) & (1<<1)) + || !(!((W[59]^(W[63]>>25)) & (1<<5))) + || !((W[58]^(W[63]>>30)) & (1<<0)) + ) mask &= ~DV_I_43_0_bit; + if (mask & DV_I_44_0_bit) + if ( + !((W[62]^(W[63]>>5)) & (1<<1)) + || !(!((W[60]^(W[64]>>25)) & (1<<5))) + || !((W[59]^(W[64]>>30)) & (1<<0)) + ) mask &= ~DV_I_44_0_bit; + if (mask & DV_I_46_2_bit) + mask &= ((~((W[40]^W[42])>>2)) | ~DV_I_46_2_bit); + if (mask & DV_I_47_2_bit) + if ( + !((W[62]^(W[63]>>5)) & (1<<2)) + || !(!((W[41]^W[43]) & (1<<6))) + ) mask &= ~DV_I_47_2_bit; + if (mask & DV_I_48_2_bit) + if ( + !((W[63]^(W[64]>>5)) & (1<<2)) + || !(!((W[48]^(W[49]<<5)) & (1<<6))) + ) mask &= ~DV_I_48_2_bit; + if (mask & DV_I_49_2_bit) + if ( + !(!((W[49]^(W[50]<<5)) & (1<<6))) + || !((W[42]^W[50]) & (1<<1)) + || !(!((W[39]^(W[40]<<5)) & (1<<6))) + || !((W[38]^W[40]) & (1<<1)) + ) mask &= ~DV_I_49_2_bit; + if (mask & DV_I_50_0_bit) + mask &= ((((W[36]^W[37])<<7)) | ~DV_I_50_0_bit); + if (mask & DV_I_50_2_bit) + mask &= ((((W[43]^W[51])<<11)) | ~DV_I_50_2_bit); + if (mask & DV_I_51_0_bit) + mask &= ((((W[37]^W[38])<<9)) | ~DV_I_51_0_bit); + if (mask & DV_I_51_2_bit) + if ( + !(!((W[51]^(W[52]<<5)) & (1<<6))) + || !(!((W[49]^W[51]) & (1<<6))) + || !(!((W[37]^(W[37]>>5)) & (1<<1))) + || !(!((W[35]^(W[39]>>25)) & (1<<5))) + ) mask &= ~DV_I_51_2_bit; + if (mask & DV_I_52_0_bit) + mask &= ((((W[38]^W[39])<<11)) | ~DV_I_52_0_bit); + if (mask & DV_II_46_2_bit) + mask &= ((((W[47]^W[51])<<17)) | ~DV_II_46_2_bit); + if (mask & DV_II_48_0_bit) + if ( + !(!((W[36]^(W[40]>>25)) & (1<<3))) + || !((W[35]^(W[40]<<2)) & (1<<30)) + ) mask &= ~DV_II_48_0_bit; + if (mask & DV_II_49_0_bit) + if ( + !(!((W[37]^(W[41]>>25)) & (1<<3))) + || !((W[36]^(W[41]<<2)) & (1<<30)) + ) mask &= ~DV_II_49_0_bit; + if (mask & DV_II_49_2_bit) + if ( + !(!((W[53]^(W[54]<<5)) & (1<<6))) + || !(!((W[51]^W[53]) & (1<<6))) + || !((W[50]^W[54]) & (1<<1)) + || !(!((W[45]^(W[46]<<5)) & (1<<6))) + || !(!((W[37]^(W[41]>>25)) & (1<<5))) + || !((W[36]^(W[41]>>30)) & (1<<0)) + ) mask &= ~DV_II_49_2_bit; + if (mask & DV_II_50_0_bit) + if ( + !((W[55]^W[58]) & (1<<29)) + || !(!((W[38]^(W[42]>>25)) & (1<<3))) + || !((W[37]^(W[42]<<2)) & (1<<30)) + ) mask &= ~DV_II_50_0_bit; + if (mask & DV_II_50_2_bit) + if ( + !(!((W[54]^(W[55]<<5)) & (1<<6))) + || !(!((W[52]^W[54]) & (1<<6))) + || !((W[51]^W[55]) & (1<<1)) + || !((W[45]^W[47]) & (1<<1)) + || !(!((W[38]^(W[42]>>25)) & (1<<5))) + || !((W[37]^(W[42]>>30)) & (1<<0)) + ) mask &= ~DV_II_50_2_bit; + if (mask & DV_II_51_0_bit) + if ( + !(!((W[39]^(W[43]>>25)) & (1<<3))) + || !((W[38]^(W[43]<<2)) & (1<<30)) + ) mask &= ~DV_II_51_0_bit; + if (mask & DV_II_51_2_bit) + if ( + !(!((W[55]^(W[56]<<5)) & (1<<6))) + || !(!((W[53]^W[55]) & (1<<6))) + || !((W[52]^W[56]) & (1<<1)) + || !((W[46]^W[48]) & (1<<1)) + || !(!((W[39]^(W[43]>>25)) & (1<<5))) + || !((W[38]^(W[43]>>30)) & (1<<0)) + ) mask &= ~DV_II_51_2_bit; + if (mask & DV_II_52_0_bit) + if ( + !(!((W[59]^W[60]) & (1<<29))) + || !(!((W[40]^(W[44]>>25)) & (1<<3))) + || !(!((W[40]^(W[44]>>25)) & (1<<4))) + || !((W[39]^(W[44]<<2)) & (1<<30)) + ) mask &= ~DV_II_52_0_bit; + if (mask & DV_II_53_0_bit) + if ( + !((W[58]^W[61]) & (1<<29)) + || !(!((W[57]^(W[61]>>25)) & (1<<4))) + || !(!((W[41]^(W[45]>>25)) & (1<<3))) + || !(!((W[41]^(W[45]>>25)) & (1<<4))) + ) mask &= ~DV_II_53_0_bit; + if (mask & DV_II_54_0_bit) + if ( + !(!((W[58]^(W[62]>>25)) & (1<<4))) + || !(!((W[42]^(W[46]>>25)) & (1<<3))) + || !(!((W[42]^(W[46]>>25)) & (1<<4))) + ) mask &= ~DV_II_54_0_bit; + if (mask & DV_II_55_0_bit) + if ( + !(!((W[59]^(W[63]>>25)) & (1<<4))) + || !(!((W[57]^(W[59]>>25)) & (1<<4))) + || !(!((W[43]^(W[47]>>25)) & (1<<3))) + || !(!((W[43]^(W[47]>>25)) & (1<<4))) + ) mask &= ~DV_II_55_0_bit; + if (mask & DV_II_56_0_bit) + if ( + !(!((W[60]^(W[64]>>25)) & (1<<4))) + || !(!((W[44]^(W[48]>>25)) & (1<<3))) + || !(!((W[44]^(W[48]>>25)) & (1<<4))) + ) mask &= ~DV_II_56_0_bit; +} + + dvmask[0]=mask; +} + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/ubc_check.h libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/ubc_check.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/sha1dc/ubc_check.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/sha1dc/ubc_check.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,52 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +/* +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set +*/ + +#ifndef SHA1DC_UBC_CHECK_H +#define SHA1DC_UBC_CHECK_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef SHA1DC_NO_STANDARD_INCLUDES +#include +#endif + +#define DVMASKSIZE 1 +typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t; +extern dv_info_t sha1_dvs[]; +void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]); + +#define DOSTORESTATE58 +#define DOSTORESTATE65 + +#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0]) + +#if defined(__cplusplus) +} +#endif + +#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H +#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H +#endif + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/win32.c libgit2-1.1.0+dfsg.1/src/hash/sha1/win32.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1/win32.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/win32.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,329 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "win32.h" + +#include "global.h" + +#include +#include + +#define GIT_HASH_CNG_DLL_NAME "bcrypt.dll" + +/* BCRYPT_SHA1_ALGORITHM */ +#define GIT_HASH_CNG_HASH_TYPE L"SHA1" + +/* BCRYPT_OBJECT_LENGTH */ +#define GIT_HASH_CNG_HASH_OBJECT_LEN L"ObjectLength" + +/* BCRYPT_HASH_REUSEABLE_FLAGS */ +#define GIT_HASH_CNG_HASH_REUSABLE 0x00000020 + +static git_hash_prov hash_prov = {0}; + +/* Hash initialization */ + +/* Initialize CNG, if available */ +GIT_INLINE(int) hash_cng_prov_init(void) +{ + char dll_path[MAX_PATH]; + DWORD dll_path_len, size_len; + + /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */ + if (!git_has_win32_version(6, 0, 1)) { + git_error_set(GIT_ERROR_SHA1, "CryptoNG is not supported on this platform"); + return -1; + } + + /* Load bcrypt.dll explicitly from the system directory */ + if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 || + dll_path_len > MAX_PATH || + StringCchCat(dll_path, MAX_PATH, "\\") < 0 || + StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 || + (hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) { + git_error_set(GIT_ERROR_SHA1, "CryptoNG library could not be loaded"); + return -1; + } + + /* Load the function addresses */ + if ((hash_prov.prov.cng.open_algorithm_provider = (hash_win32_cng_open_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptOpenAlgorithmProvider")) == NULL || + (hash_prov.prov.cng.get_property = (hash_win32_cng_get_property_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptGetProperty")) == NULL || + (hash_prov.prov.cng.create_hash = (hash_win32_cng_create_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCreateHash")) == NULL || + (hash_prov.prov.cng.finish_hash = (hash_win32_cng_finish_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptFinishHash")) == NULL || + (hash_prov.prov.cng.hash_data = (hash_win32_cng_hash_data_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptHashData")) == NULL || + (hash_prov.prov.cng.destroy_hash = (hash_win32_cng_destroy_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptDestroyHash")) == NULL || + (hash_prov.prov.cng.close_algorithm_provider = (hash_win32_cng_close_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCloseAlgorithmProvider")) == NULL) { + FreeLibrary(hash_prov.prov.cng.dll); + + git_error_set(GIT_ERROR_OS, "CryptoNG functions could not be loaded"); + return -1; + } + + /* Load the SHA1 algorithm */ + if (hash_prov.prov.cng.open_algorithm_provider(&hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0) { + FreeLibrary(hash_prov.prov.cng.dll); + + git_error_set(GIT_ERROR_OS, "algorithm provider could not be initialized"); + return -1; + } + + /* Get storage space for the hash object */ + if (hash_prov.prov.cng.get_property(hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_prov.prov.cng.hash_object_size, sizeof(DWORD), &size_len, 0) < 0) { + hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0); + FreeLibrary(hash_prov.prov.cng.dll); + + git_error_set(GIT_ERROR_OS, "algorithm handle could not be found"); + return -1; + } + + hash_prov.type = CNG; + return 0; +} + +GIT_INLINE(void) hash_cng_prov_shutdown(void) +{ + hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0); + FreeLibrary(hash_prov.prov.cng.dll); + + hash_prov.type = INVALID; +} + +/* Initialize CryptoAPI */ +GIT_INLINE(int) hash_cryptoapi_prov_init() +{ + if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + git_error_set(GIT_ERROR_OS, "legacy hash context could not be started"); + return -1; + } + + hash_prov.type = CRYPTOAPI; + return 0; +} + +GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void) +{ + CryptReleaseContext(hash_prov.prov.cryptoapi.handle, 0); + + hash_prov.type = INVALID; +} + +static void sha1_shutdown(void) +{ + if (hash_prov.type == CNG) + hash_cng_prov_shutdown(); + else if(hash_prov.type == CRYPTOAPI) + hash_cryptoapi_prov_shutdown(); +} + +int git_hash_sha1_global_init(void) +{ + int error = 0; + + if (hash_prov.type != INVALID) + return 0; + + if ((error = hash_cng_prov_init()) < 0) + error = hash_cryptoapi_prov_init(); + + git__on_shutdown(sha1_shutdown); + + return error; +} + +/* CryptoAPI: available in Windows XP and newer */ + +GIT_INLINE(int) hash_ctx_cryptoapi_init(git_hash_sha1_ctx *ctx) +{ + ctx->type = CRYPTOAPI; + ctx->prov = &hash_prov; + + return git_hash_sha1_init(ctx); +} + +GIT_INLINE(int) hash_cryptoapi_init(git_hash_sha1_ctx *ctx) +{ + if (ctx->ctx.cryptoapi.valid) + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); + + if (!CryptCreateHash(ctx->prov->prov.cryptoapi.handle, CALG_SHA1, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) { + ctx->ctx.cryptoapi.valid = 0; + git_error_set(GIT_ERROR_OS, "legacy hash implementation could not be created"); + return -1; + } + + ctx->ctx.cryptoapi.valid = 1; + return 0; +} + +GIT_INLINE(int) hash_cryptoapi_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len) +{ + const BYTE *data = (BYTE *)_data; + + assert(ctx->ctx.cryptoapi.valid); + + while (len > 0) { + DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len; + + if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0)) { + git_error_set(GIT_ERROR_OS, "legacy hash data could not be updated"); + return -1; + } + + data += chunk; + len -= chunk; + } + + return 0; +} + +GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + DWORD len = 20; + int error = 0; + + assert(ctx->ctx.cryptoapi.valid); + + if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) { + git_error_set(GIT_ERROR_OS, "legacy hash data could not be finished"); + error = -1; + } + + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); + ctx->ctx.cryptoapi.valid = 0; + + return error; +} + +GIT_INLINE(void) hash_ctx_cryptoapi_cleanup(git_hash_sha1_ctx *ctx) +{ + if (ctx->ctx.cryptoapi.valid) + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); +} + +/* CNG: Available in Windows Server 2008 and newer */ + +GIT_INLINE(int) hash_ctx_cng_init(git_hash_sha1_ctx *ctx) +{ + if ((ctx->ctx.cng.hash_object = git__malloc(hash_prov.prov.cng.hash_object_size)) == NULL) + return -1; + + if (hash_prov.prov.cng.create_hash(hash_prov.prov.cng.handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_prov.prov.cng.hash_object_size, NULL, 0, 0) < 0) { + git__free(ctx->ctx.cng.hash_object); + + git_error_set(GIT_ERROR_OS, "hash implementation could not be created"); + return -1; + } + + ctx->type = CNG; + ctx->prov = &hash_prov; + + return 0; +} + +GIT_INLINE(int) hash_cng_init(git_hash_sha1_ctx *ctx) +{ + BYTE hash[GIT_OID_RAWSZ]; + + if (!ctx->ctx.cng.updated) + return 0; + + /* CNG needs to be finished to restart */ + if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, GIT_OID_RAWSZ, 0) < 0) { + git_error_set(GIT_ERROR_OS, "hash implementation could not be finished"); + return -1; + } + + ctx->ctx.cng.updated = 0; + + return 0; +} + +GIT_INLINE(int) hash_cng_update(git_hash_sha1_ctx *ctx, const void *_data, size_t len) +{ + PBYTE data = (PBYTE)_data; + + while (len > 0) { + ULONG chunk = (len > ULONG_MAX) ? ULONG_MAX : (ULONG)len; + + if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0) { + git_error_set(GIT_ERROR_OS, "hash could not be updated"); + return -1; + } + + data += chunk; + len -= chunk; + } + + return 0; +} + +GIT_INLINE(int) hash_cng_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out->id, GIT_OID_RAWSZ, 0) < 0) { + git_error_set(GIT_ERROR_OS, "hash could not be finished"); + return -1; + } + + ctx->ctx.cng.updated = 0; + + return 0; +} + +GIT_INLINE(void) hash_ctx_cng_cleanup(git_hash_sha1_ctx *ctx) +{ + ctx->prov->prov.cng.destroy_hash(ctx->ctx.cng.hash_handle); + git__free(ctx->ctx.cng.hash_object); +} + +/* Indirection between CryptoAPI and CNG */ + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx) +{ + int error = 0; + + assert(ctx); + + /* + * When compiled with GIT_THREADS, the global hash_prov data is + * initialized with git_libgit2_init. Otherwise, it must be initialized + * at first use. + */ + if (hash_prov.type == INVALID && (error = git_hash_sha1_global_init()) < 0) + return error; + + memset(ctx, 0x0, sizeof(git_hash_sha1_ctx)); + + return (hash_prov.type == CNG) ? hash_ctx_cng_init(ctx) : hash_ctx_cryptoapi_init(ctx); +} + +int git_hash_sha1_init(git_hash_sha1_ctx *ctx) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx); +} + +int git_hash_sha1_update(git_hash_sha1_ctx *ctx, const void *data, size_t len) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len); +} + +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *ctx) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx); +} + +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx) +{ + assert(ctx); + + if (ctx->type == CNG) + hash_ctx_cng_cleanup(ctx); + else if(ctx->type == CRYPTOAPI) + hash_ctx_cryptoapi_cleanup(ctx); +} diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1/win32.h libgit2-1.1.0+dfsg.1/src/hash/sha1/win32.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1/win32.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1/win32.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,128 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_win32_h__ +#define INCLUDE_hash_sha1_win32_h__ + +#include "hash/sha1.h" + +#include +#include + +enum hash_win32_prov_type { + INVALID = 0, + CRYPTOAPI, + CNG +}; + +/* + * CryptoAPI is available for hashing on Windows XP and newer. + */ + +struct hash_cryptoapi_prov { + HCRYPTPROV handle; +}; + +/* + * CNG (bcrypt.dll) is significantly more performant than CryptoAPI and is + * preferred, however it is only available on Windows 2008 and newer and + * must therefore be dynamically loaded, and we must inline constants that + * would not exist when building in pre-Windows 2008 environments. + */ + +/* Function declarations for CNG */ +typedef NTSTATUS (WINAPI *hash_win32_cng_open_algorithm_provider_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm, + LPCWSTR pszAlgId, + LPCWSTR pszImplementation, + DWORD dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_get_property_fn)( + HANDLE /* BCRYPT_HANDLE */ hObject, + LPCWSTR pszProperty, + PUCHAR pbOutput, + ULONG cbOutput, + ULONG *pcbResult, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_create_hash_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, + HANDLE /* BCRYPT_HASH_HANDLE */ *phHash, + PUCHAR pbHashObject, ULONG cbHashObject, + PUCHAR pbSecret, + ULONG cbSecret, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_finish_hash_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash, + PUCHAR pbOutput, + ULONG cbOutput, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_hash_data_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash, + PUCHAR pbInput, + ULONG cbInput, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_destroy_hash_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash); + +typedef NTSTATUS (WINAPI *hash_win32_cng_close_algorithm_provider_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, + ULONG dwFlags); + +struct hash_cng_prov { + /* DLL for CNG */ + HINSTANCE dll; + + /* Function pointers for CNG */ + hash_win32_cng_open_algorithm_provider_fn open_algorithm_provider; + hash_win32_cng_get_property_fn get_property; + hash_win32_cng_create_hash_fn create_hash; + hash_win32_cng_finish_hash_fn finish_hash; + hash_win32_cng_hash_data_fn hash_data; + hash_win32_cng_destroy_hash_fn destroy_hash; + hash_win32_cng_close_algorithm_provider_fn close_algorithm_provider; + + HANDLE /* BCRYPT_ALG_HANDLE */ handle; + DWORD hash_object_size; +}; + +typedef struct { + enum hash_win32_prov_type type; + + union { + struct hash_cryptoapi_prov cryptoapi; + struct hash_cng_prov cng; + } prov; +} git_hash_prov; + +/* Hash contexts */ + +struct hash_cryptoapi_ctx { + bool valid; + HCRYPTHASH hash_handle; +}; + +struct hash_cng_ctx { + bool updated; + HANDLE /* BCRYPT_HASH_HANDLE */ hash_handle; + PBYTE hash_object; +}; + +struct git_hash_sha1_ctx { + enum hash_win32_prov_type type; + git_hash_prov *prov; + + union { + struct hash_cryptoapi_ctx cryptoapi; + struct hash_cng_ctx cng; + } ctx; +}; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1dc/sha1.c libgit2-1.1.0+dfsg.1/src/hash/sha1dc/sha1.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1dc/sha1.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1dc/sha1.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1900 +0,0 @@ -/*** -* Copyright 2017 Marc Stevens , Dan Shumow (danshu@microsoft.com) -* Distributed under the MIT Software License. -* See accompanying file LICENSE.txt or copy at -* https://opensource.org/licenses/MIT -***/ - -#ifndef SHA1DC_NO_STANDARD_INCLUDES -#include -#include -#include -#include -#ifdef __unix__ -#include /* make sure macros like _BIG_ENDIAN visible */ -#endif -#endif - -#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C -#include SHA1DC_CUSTOM_INCLUDE_SHA1_C -#endif - -#ifndef SHA1DC_INIT_SAFE_HASH_DEFAULT -#define SHA1DC_INIT_SAFE_HASH_DEFAULT 1 -#endif - -#include "sha1.h" -#include "ubc_check.h" - -#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \ - defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \ - defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \ - defined(__386) || defined(_M_X64) || defined(_M_AMD64)) -#define SHA1DC_ON_INTEL_LIKE_PROCESSOR -#endif - -/* - Because Little-Endian architectures are most common, - we only set SHA1DC_BIGENDIAN if one of these conditions is met. - Note that all MSFT platforms are little endian, - so none of these will be defined under the MSC compiler. - If you are compiling on a big endian platform and your compiler does not define one of these, - you will have to add whatever macros your tool chain defines to indicate Big-Endianness. - */ - -#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) -/* - * Should detect Big Endian under GCC since at least 4.6.0 (gcc svn - * rev #165881). See - * https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html - * - * This also works under clang since 3.2, it copied the GCC-ism. See - * clang.git's 3b198a97d2 ("Preprocessor: add __BYTE_ORDER__ - * predefined macro", 2012-07-27) - */ -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define SHA1DC_BIGENDIAN -#endif - -/* Not under GCC-alike */ -#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) -/* - * Should detect Big Endian under glibc.git since 14245eb70e ("entered - * into RCS", 1992-11-25). Defined in which will have been - * brought in by standard headers. See glibc.git and - * https://sourceforge.net/p/predef/wiki/Endianness/ - */ -#if __BYTE_ORDER == __BIG_ENDIAN -#define SHA1DC_BIGENDIAN -#endif - -/* Not under GCC-alike or glibc */ -#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) -/* - * *BSD and newlib (embeded linux, cygwin, etc). - * the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents - * this condition from matching with Solaris/sparc. - * (Solaris defines only one endian macro) - */ -#if _BYTE_ORDER == _BIG_ENDIAN -#define SHA1DC_BIGENDIAN -#endif - -/* Not under GCC-alike or glibc or *BSD or newlib */ -#elif (defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ - defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \ - defined(__sparc)) -/* - * Should define Big Endian for a whitelist of known processors. See - * https://sourceforge.net/p/predef/wiki/Endianness/ and - * http://www.oracle.com/technetwork/server-storage/solaris/portingtosolaris-138514.html - */ -#define SHA1DC_BIGENDIAN - -/* Not under GCC-alike or glibc or *BSD or newlib or */ -#elif defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) -/* - * As a last resort before we do anything else we're not 100% sure - * about below, we blacklist specific processors here. We could add - * more, see e.g. https://wiki.debian.org/ArchitectureSpecificsMemo - */ -#else /* Not under GCC-alike or glibc or *BSD or newlib or or */ - -/* We do nothing more here for now */ -/*#error "Uncomment this to see if you fall through all the detection"*/ - -#endif /* Big Endian detection */ - -#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN)) -#undef SHA1DC_BIGENDIAN -#endif -#if (defined(SHA1DC_FORCE_BIGENDIAN) && !defined(SHA1DC_BIGENDIAN)) -#define SHA1DC_BIGENDIAN -#endif -/*ENDIANNESS SELECTION*/ - -#if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR) -#define SHA1DC_ALLOW_UNALIGNED_ACCESS -#endif /*UNALIGNMENT DETECTION*/ - - -#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n)))) -#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n)))) - -#define sha1_bswap32(x) \ - {x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = (x << 16) | (x >> 16);} - -#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1)) - -#ifdef SHA1DC_BIGENDIAN - #define sha1_load(m, t, temp) { temp = m[t]; } -#else - #define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); } -#endif - -#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x - -#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d)))) -#define sha1_f2(b,c,d) ((b)^(c)^(d)) -#define sha1_f3(b,c,d) (((b)&(c))+((d)&((b)^(c)))) -#define sha1_f4(b,c,d) ((b)^(c)^(d)) - -#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \ - { e += rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; b = rotate_left(b, 30); } -#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, m, t) \ - { e += rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; b = rotate_left(b, 30); } -#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, m, t) \ - { e += rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; b = rotate_left(b, 30); } -#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, m, t) \ - { e += rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; b = rotate_left(b, 30); } - -#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, m, t) \ - { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; } -#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, m, t) \ - { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; } -#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, m, t) \ - { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; } -#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \ - { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; } - -#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \ - {sha1_load(m, t, temp); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30);} - -#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \ - {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30); } - -#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \ - {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1; b = rotate_left(b, 30); } - -#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \ - {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC; b = rotate_left(b, 30); } - -#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \ - {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6; b = rotate_left(b, 30); } - - -#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e; - -#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION -void sha1_compression(uint32_t ihv[5], const uint32_t m[16]) -{ - uint32_t W[80]; - uint32_t a,b,c,d,e; - unsigned i; - - memcpy(W, m, 16 * 4); - for (i = 16; i < 80; ++i) - W[i] = sha1_mix(W, i); - - a = ihv[0]; b = ihv[1]; c = ihv[2]; d = ihv[3]; e = ihv[4]; - - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); - - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); - - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); - - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); - - ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; -} -#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/ - - -static void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]) -{ - uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; - - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); - HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); - - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); - HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); - - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); - HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); - - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); - HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); - - ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; -} - - - -void sha1_compression_states(uint32_t ihv[5], const uint32_t m[16], uint32_t W[80], uint32_t states[80][5]) -{ - uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; - uint32_t temp; - -#ifdef DOSTORESTATE00 - SHA1_STORE_STATE(0) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp); - -#ifdef DOSTORESTATE01 - SHA1_STORE_STATE(1) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp); - -#ifdef DOSTORESTATE02 - SHA1_STORE_STATE(2) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp); - -#ifdef DOSTORESTATE03 - SHA1_STORE_STATE(3) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp); - -#ifdef DOSTORESTATE04 - SHA1_STORE_STATE(4) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp); - -#ifdef DOSTORESTATE05 - SHA1_STORE_STATE(5) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp); - -#ifdef DOSTORESTATE06 - SHA1_STORE_STATE(6) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp); - -#ifdef DOSTORESTATE07 - SHA1_STORE_STATE(7) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp); - -#ifdef DOSTORESTATE08 - SHA1_STORE_STATE(8) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp); - -#ifdef DOSTORESTATE09 - SHA1_STORE_STATE(9) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp); - -#ifdef DOSTORESTATE10 - SHA1_STORE_STATE(10) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp); - -#ifdef DOSTORESTATE11 - SHA1_STORE_STATE(11) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp); - -#ifdef DOSTORESTATE12 - SHA1_STORE_STATE(12) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp); - -#ifdef DOSTORESTATE13 - SHA1_STORE_STATE(13) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp); - -#ifdef DOSTORESTATE14 - SHA1_STORE_STATE(14) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp); - -#ifdef DOSTORESTATE15 - SHA1_STORE_STATE(15) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp); - -#ifdef DOSTORESTATE16 - SHA1_STORE_STATE(16) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp); - -#ifdef DOSTORESTATE17 - SHA1_STORE_STATE(17) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp); - -#ifdef DOSTORESTATE18 - SHA1_STORE_STATE(18) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp); - -#ifdef DOSTORESTATE19 - SHA1_STORE_STATE(19) -#endif - SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp); - - - -#ifdef DOSTORESTATE20 - SHA1_STORE_STATE(20) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp); - -#ifdef DOSTORESTATE21 - SHA1_STORE_STATE(21) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp); - -#ifdef DOSTORESTATE22 - SHA1_STORE_STATE(22) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp); - -#ifdef DOSTORESTATE23 - SHA1_STORE_STATE(23) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp); - -#ifdef DOSTORESTATE24 - SHA1_STORE_STATE(24) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp); - -#ifdef DOSTORESTATE25 - SHA1_STORE_STATE(25) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp); - -#ifdef DOSTORESTATE26 - SHA1_STORE_STATE(26) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp); - -#ifdef DOSTORESTATE27 - SHA1_STORE_STATE(27) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp); - -#ifdef DOSTORESTATE28 - SHA1_STORE_STATE(28) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp); - -#ifdef DOSTORESTATE29 - SHA1_STORE_STATE(29) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp); - -#ifdef DOSTORESTATE30 - SHA1_STORE_STATE(30) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp); - -#ifdef DOSTORESTATE31 - SHA1_STORE_STATE(31) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp); - -#ifdef DOSTORESTATE32 - SHA1_STORE_STATE(32) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp); - -#ifdef DOSTORESTATE33 - SHA1_STORE_STATE(33) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp); - -#ifdef DOSTORESTATE34 - SHA1_STORE_STATE(34) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp); - -#ifdef DOSTORESTATE35 - SHA1_STORE_STATE(35) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp); - -#ifdef DOSTORESTATE36 - SHA1_STORE_STATE(36) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp); - -#ifdef DOSTORESTATE37 - SHA1_STORE_STATE(37) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp); - -#ifdef DOSTORESTATE38 - SHA1_STORE_STATE(38) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp); - -#ifdef DOSTORESTATE39 - SHA1_STORE_STATE(39) -#endif - SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp); - - - -#ifdef DOSTORESTATE40 - SHA1_STORE_STATE(40) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp); - -#ifdef DOSTORESTATE41 - SHA1_STORE_STATE(41) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp); - -#ifdef DOSTORESTATE42 - SHA1_STORE_STATE(42) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp); - -#ifdef DOSTORESTATE43 - SHA1_STORE_STATE(43) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp); - -#ifdef DOSTORESTATE44 - SHA1_STORE_STATE(44) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp); - -#ifdef DOSTORESTATE45 - SHA1_STORE_STATE(45) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp); - -#ifdef DOSTORESTATE46 - SHA1_STORE_STATE(46) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp); - -#ifdef DOSTORESTATE47 - SHA1_STORE_STATE(47) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp); - -#ifdef DOSTORESTATE48 - SHA1_STORE_STATE(48) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp); - -#ifdef DOSTORESTATE49 - SHA1_STORE_STATE(49) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp); - -#ifdef DOSTORESTATE50 - SHA1_STORE_STATE(50) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp); - -#ifdef DOSTORESTATE51 - SHA1_STORE_STATE(51) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp); - -#ifdef DOSTORESTATE52 - SHA1_STORE_STATE(52) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp); - -#ifdef DOSTORESTATE53 - SHA1_STORE_STATE(53) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp); - -#ifdef DOSTORESTATE54 - SHA1_STORE_STATE(54) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp); - -#ifdef DOSTORESTATE55 - SHA1_STORE_STATE(55) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp); - -#ifdef DOSTORESTATE56 - SHA1_STORE_STATE(56) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp); - -#ifdef DOSTORESTATE57 - SHA1_STORE_STATE(57) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp); - -#ifdef DOSTORESTATE58 - SHA1_STORE_STATE(58) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp); - -#ifdef DOSTORESTATE59 - SHA1_STORE_STATE(59) -#endif - SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp); - - - - -#ifdef DOSTORESTATE60 - SHA1_STORE_STATE(60) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp); - -#ifdef DOSTORESTATE61 - SHA1_STORE_STATE(61) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp); - -#ifdef DOSTORESTATE62 - SHA1_STORE_STATE(62) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp); - -#ifdef DOSTORESTATE63 - SHA1_STORE_STATE(63) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp); - -#ifdef DOSTORESTATE64 - SHA1_STORE_STATE(64) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp); - -#ifdef DOSTORESTATE65 - SHA1_STORE_STATE(65) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp); - -#ifdef DOSTORESTATE66 - SHA1_STORE_STATE(66) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp); - -#ifdef DOSTORESTATE67 - SHA1_STORE_STATE(67) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp); - -#ifdef DOSTORESTATE68 - SHA1_STORE_STATE(68) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp); - -#ifdef DOSTORESTATE69 - SHA1_STORE_STATE(69) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp); - -#ifdef DOSTORESTATE70 - SHA1_STORE_STATE(70) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp); - -#ifdef DOSTORESTATE71 - SHA1_STORE_STATE(71) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp); - -#ifdef DOSTORESTATE72 - SHA1_STORE_STATE(72) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp); - -#ifdef DOSTORESTATE73 - SHA1_STORE_STATE(73) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp); - -#ifdef DOSTORESTATE74 - SHA1_STORE_STATE(74) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp); - -#ifdef DOSTORESTATE75 - SHA1_STORE_STATE(75) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp); - -#ifdef DOSTORESTATE76 - SHA1_STORE_STATE(76) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp); - -#ifdef DOSTORESTATE77 - SHA1_STORE_STATE(77) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp); - -#ifdef DOSTORESTATE78 - SHA1_STORE_STATE(78) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp); - -#ifdef DOSTORESTATE79 - SHA1_STORE_STATE(79) -#endif - SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp); - - - - ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; -} - - - - -#define SHA1_RECOMPRESS(t) \ -static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \ -{ \ - uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \ - if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \ - if (t > 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 78); \ - if (t > 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 77); \ - if (t > 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 76); \ - if (t > 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 75); \ - if (t > 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 74); \ - if (t > 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 73); \ - if (t > 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 72); \ - if (t > 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 71); \ - if (t > 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 70); \ - if (t > 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 69); \ - if (t > 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 68); \ - if (t > 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 67); \ - if (t > 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 66); \ - if (t > 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 65); \ - if (t > 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 64); \ - if (t > 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 63); \ - if (t > 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 62); \ - if (t > 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 61); \ - if (t > 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 60); \ - if (t > 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 59); \ - if (t > 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 58); \ - if (t > 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 57); \ - if (t > 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 56); \ - if (t > 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 55); \ - if (t > 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 54); \ - if (t > 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 53); \ - if (t > 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 52); \ - if (t > 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 51); \ - if (t > 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 50); \ - if (t > 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 49); \ - if (t > 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 48); \ - if (t > 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 47); \ - if (t > 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 46); \ - if (t > 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 45); \ - if (t > 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 44); \ - if (t > 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 43); \ - if (t > 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 42); \ - if (t > 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 41); \ - if (t > 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 40); \ - if (t > 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 39); \ - if (t > 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 38); \ - if (t > 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 37); \ - if (t > 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 36); \ - if (t > 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 35); \ - if (t > 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 34); \ - if (t > 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 33); \ - if (t > 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 32); \ - if (t > 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 31); \ - if (t > 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 30); \ - if (t > 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 29); \ - if (t > 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 28); \ - if (t > 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 27); \ - if (t > 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 26); \ - if (t > 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 25); \ - if (t > 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 24); \ - if (t > 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 23); \ - if (t > 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 22); \ - if (t > 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 21); \ - if (t > 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 20); \ - if (t > 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 19); \ - if (t > 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 18); \ - if (t > 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 17); \ - if (t > 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 16); \ - if (t > 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 15); \ - if (t > 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 14); \ - if (t > 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 13); \ - if (t > 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 12); \ - if (t > 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 11); \ - if (t > 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 10); \ - if (t > 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 9); \ - if (t > 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 8); \ - if (t > 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 7); \ - if (t > 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 6); \ - if (t > 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 5); \ - if (t > 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 4); \ - if (t > 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 3); \ - if (t > 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 2); \ - if (t > 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 1); \ - if (t > 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 0); \ - ihvin[0] = a; ihvin[1] = b; ihvin[2] = c; ihvin[3] = d; ihvin[4] = e; \ - a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; \ - if (t <= 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 0); \ - if (t <= 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 1); \ - if (t <= 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 2); \ - if (t <= 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 3); \ - if (t <= 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 4); \ - if (t <= 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 5); \ - if (t <= 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 6); \ - if (t <= 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 7); \ - if (t <= 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 8); \ - if (t <= 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 9); \ - if (t <= 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 10); \ - if (t <= 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 11); \ - if (t <= 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 12); \ - if (t <= 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 13); \ - if (t <= 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 14); \ - if (t <= 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 15); \ - if (t <= 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 16); \ - if (t <= 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 17); \ - if (t <= 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 18); \ - if (t <= 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 19); \ - if (t <= 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 20); \ - if (t <= 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 21); \ - if (t <= 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 22); \ - if (t <= 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 23); \ - if (t <= 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 24); \ - if (t <= 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 25); \ - if (t <= 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 26); \ - if (t <= 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 27); \ - if (t <= 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 28); \ - if (t <= 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 29); \ - if (t <= 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 30); \ - if (t <= 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 31); \ - if (t <= 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 32); \ - if (t <= 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 33); \ - if (t <= 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 34); \ - if (t <= 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 35); \ - if (t <= 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 36); \ - if (t <= 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 37); \ - if (t <= 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 38); \ - if (t <= 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 39); \ - if (t <= 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 40); \ - if (t <= 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 41); \ - if (t <= 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 42); \ - if (t <= 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 43); \ - if (t <= 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 44); \ - if (t <= 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 45); \ - if (t <= 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 46); \ - if (t <= 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 47); \ - if (t <= 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 48); \ - if (t <= 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 49); \ - if (t <= 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 50); \ - if (t <= 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 51); \ - if (t <= 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 52); \ - if (t <= 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 53); \ - if (t <= 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 54); \ - if (t <= 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 55); \ - if (t <= 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 56); \ - if (t <= 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 57); \ - if (t <= 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 58); \ - if (t <= 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 59); \ - if (t <= 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 60); \ - if (t <= 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 61); \ - if (t <= 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 62); \ - if (t <= 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 63); \ - if (t <= 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 64); \ - if (t <= 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 65); \ - if (t <= 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 66); \ - if (t <= 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 67); \ - if (t <= 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 68); \ - if (t <= 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 69); \ - if (t <= 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 70); \ - if (t <= 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 71); \ - if (t <= 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 72); \ - if (t <= 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 73); \ - if (t <= 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 74); \ - if (t <= 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 75); \ - if (t <= 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 76); \ - if (t <= 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 77); \ - if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \ - if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \ - ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \ -} - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4127) /* Compiler complains about the checks in the above macro being constant. */ -#endif - -#ifdef DOSTORESTATE0 -SHA1_RECOMPRESS(0) -#endif - -#ifdef DOSTORESTATE1 -SHA1_RECOMPRESS(1) -#endif - -#ifdef DOSTORESTATE2 -SHA1_RECOMPRESS(2) -#endif - -#ifdef DOSTORESTATE3 -SHA1_RECOMPRESS(3) -#endif - -#ifdef DOSTORESTATE4 -SHA1_RECOMPRESS(4) -#endif - -#ifdef DOSTORESTATE5 -SHA1_RECOMPRESS(5) -#endif - -#ifdef DOSTORESTATE6 -SHA1_RECOMPRESS(6) -#endif - -#ifdef DOSTORESTATE7 -SHA1_RECOMPRESS(7) -#endif - -#ifdef DOSTORESTATE8 -SHA1_RECOMPRESS(8) -#endif - -#ifdef DOSTORESTATE9 -SHA1_RECOMPRESS(9) -#endif - -#ifdef DOSTORESTATE10 -SHA1_RECOMPRESS(10) -#endif - -#ifdef DOSTORESTATE11 -SHA1_RECOMPRESS(11) -#endif - -#ifdef DOSTORESTATE12 -SHA1_RECOMPRESS(12) -#endif - -#ifdef DOSTORESTATE13 -SHA1_RECOMPRESS(13) -#endif - -#ifdef DOSTORESTATE14 -SHA1_RECOMPRESS(14) -#endif - -#ifdef DOSTORESTATE15 -SHA1_RECOMPRESS(15) -#endif - -#ifdef DOSTORESTATE16 -SHA1_RECOMPRESS(16) -#endif - -#ifdef DOSTORESTATE17 -SHA1_RECOMPRESS(17) -#endif - -#ifdef DOSTORESTATE18 -SHA1_RECOMPRESS(18) -#endif - -#ifdef DOSTORESTATE19 -SHA1_RECOMPRESS(19) -#endif - -#ifdef DOSTORESTATE20 -SHA1_RECOMPRESS(20) -#endif - -#ifdef DOSTORESTATE21 -SHA1_RECOMPRESS(21) -#endif - -#ifdef DOSTORESTATE22 -SHA1_RECOMPRESS(22) -#endif - -#ifdef DOSTORESTATE23 -SHA1_RECOMPRESS(23) -#endif - -#ifdef DOSTORESTATE24 -SHA1_RECOMPRESS(24) -#endif - -#ifdef DOSTORESTATE25 -SHA1_RECOMPRESS(25) -#endif - -#ifdef DOSTORESTATE26 -SHA1_RECOMPRESS(26) -#endif - -#ifdef DOSTORESTATE27 -SHA1_RECOMPRESS(27) -#endif - -#ifdef DOSTORESTATE28 -SHA1_RECOMPRESS(28) -#endif - -#ifdef DOSTORESTATE29 -SHA1_RECOMPRESS(29) -#endif - -#ifdef DOSTORESTATE30 -SHA1_RECOMPRESS(30) -#endif - -#ifdef DOSTORESTATE31 -SHA1_RECOMPRESS(31) -#endif - -#ifdef DOSTORESTATE32 -SHA1_RECOMPRESS(32) -#endif - -#ifdef DOSTORESTATE33 -SHA1_RECOMPRESS(33) -#endif - -#ifdef DOSTORESTATE34 -SHA1_RECOMPRESS(34) -#endif - -#ifdef DOSTORESTATE35 -SHA1_RECOMPRESS(35) -#endif - -#ifdef DOSTORESTATE36 -SHA1_RECOMPRESS(36) -#endif - -#ifdef DOSTORESTATE37 -SHA1_RECOMPRESS(37) -#endif - -#ifdef DOSTORESTATE38 -SHA1_RECOMPRESS(38) -#endif - -#ifdef DOSTORESTATE39 -SHA1_RECOMPRESS(39) -#endif - -#ifdef DOSTORESTATE40 -SHA1_RECOMPRESS(40) -#endif - -#ifdef DOSTORESTATE41 -SHA1_RECOMPRESS(41) -#endif - -#ifdef DOSTORESTATE42 -SHA1_RECOMPRESS(42) -#endif - -#ifdef DOSTORESTATE43 -SHA1_RECOMPRESS(43) -#endif - -#ifdef DOSTORESTATE44 -SHA1_RECOMPRESS(44) -#endif - -#ifdef DOSTORESTATE45 -SHA1_RECOMPRESS(45) -#endif - -#ifdef DOSTORESTATE46 -SHA1_RECOMPRESS(46) -#endif - -#ifdef DOSTORESTATE47 -SHA1_RECOMPRESS(47) -#endif - -#ifdef DOSTORESTATE48 -SHA1_RECOMPRESS(48) -#endif - -#ifdef DOSTORESTATE49 -SHA1_RECOMPRESS(49) -#endif - -#ifdef DOSTORESTATE50 -SHA1_RECOMPRESS(50) -#endif - -#ifdef DOSTORESTATE51 -SHA1_RECOMPRESS(51) -#endif - -#ifdef DOSTORESTATE52 -SHA1_RECOMPRESS(52) -#endif - -#ifdef DOSTORESTATE53 -SHA1_RECOMPRESS(53) -#endif - -#ifdef DOSTORESTATE54 -SHA1_RECOMPRESS(54) -#endif - -#ifdef DOSTORESTATE55 -SHA1_RECOMPRESS(55) -#endif - -#ifdef DOSTORESTATE56 -SHA1_RECOMPRESS(56) -#endif - -#ifdef DOSTORESTATE57 -SHA1_RECOMPRESS(57) -#endif - -#ifdef DOSTORESTATE58 -SHA1_RECOMPRESS(58) -#endif - -#ifdef DOSTORESTATE59 -SHA1_RECOMPRESS(59) -#endif - -#ifdef DOSTORESTATE60 -SHA1_RECOMPRESS(60) -#endif - -#ifdef DOSTORESTATE61 -SHA1_RECOMPRESS(61) -#endif - -#ifdef DOSTORESTATE62 -SHA1_RECOMPRESS(62) -#endif - -#ifdef DOSTORESTATE63 -SHA1_RECOMPRESS(63) -#endif - -#ifdef DOSTORESTATE64 -SHA1_RECOMPRESS(64) -#endif - -#ifdef DOSTORESTATE65 -SHA1_RECOMPRESS(65) -#endif - -#ifdef DOSTORESTATE66 -SHA1_RECOMPRESS(66) -#endif - -#ifdef DOSTORESTATE67 -SHA1_RECOMPRESS(67) -#endif - -#ifdef DOSTORESTATE68 -SHA1_RECOMPRESS(68) -#endif - -#ifdef DOSTORESTATE69 -SHA1_RECOMPRESS(69) -#endif - -#ifdef DOSTORESTATE70 -SHA1_RECOMPRESS(70) -#endif - -#ifdef DOSTORESTATE71 -SHA1_RECOMPRESS(71) -#endif - -#ifdef DOSTORESTATE72 -SHA1_RECOMPRESS(72) -#endif - -#ifdef DOSTORESTATE73 -SHA1_RECOMPRESS(73) -#endif - -#ifdef DOSTORESTATE74 -SHA1_RECOMPRESS(74) -#endif - -#ifdef DOSTORESTATE75 -SHA1_RECOMPRESS(75) -#endif - -#ifdef DOSTORESTATE76 -SHA1_RECOMPRESS(76) -#endif - -#ifdef DOSTORESTATE77 -SHA1_RECOMPRESS(77) -#endif - -#ifdef DOSTORESTATE78 -SHA1_RECOMPRESS(78) -#endif - -#ifdef DOSTORESTATE79 -SHA1_RECOMPRESS(79) -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) -{ - switch (step) - { -#ifdef DOSTORESTATE0 - case 0: - sha1recompress_fast_0(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE1 - case 1: - sha1recompress_fast_1(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE2 - case 2: - sha1recompress_fast_2(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE3 - case 3: - sha1recompress_fast_3(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE4 - case 4: - sha1recompress_fast_4(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE5 - case 5: - sha1recompress_fast_5(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE6 - case 6: - sha1recompress_fast_6(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE7 - case 7: - sha1recompress_fast_7(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE8 - case 8: - sha1recompress_fast_8(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE9 - case 9: - sha1recompress_fast_9(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE10 - case 10: - sha1recompress_fast_10(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE11 - case 11: - sha1recompress_fast_11(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE12 - case 12: - sha1recompress_fast_12(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE13 - case 13: - sha1recompress_fast_13(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE14 - case 14: - sha1recompress_fast_14(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE15 - case 15: - sha1recompress_fast_15(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE16 - case 16: - sha1recompress_fast_16(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE17 - case 17: - sha1recompress_fast_17(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE18 - case 18: - sha1recompress_fast_18(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE19 - case 19: - sha1recompress_fast_19(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE20 - case 20: - sha1recompress_fast_20(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE21 - case 21: - sha1recompress_fast_21(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE22 - case 22: - sha1recompress_fast_22(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE23 - case 23: - sha1recompress_fast_23(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE24 - case 24: - sha1recompress_fast_24(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE25 - case 25: - sha1recompress_fast_25(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE26 - case 26: - sha1recompress_fast_26(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE27 - case 27: - sha1recompress_fast_27(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE28 - case 28: - sha1recompress_fast_28(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE29 - case 29: - sha1recompress_fast_29(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE30 - case 30: - sha1recompress_fast_30(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE31 - case 31: - sha1recompress_fast_31(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE32 - case 32: - sha1recompress_fast_32(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE33 - case 33: - sha1recompress_fast_33(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE34 - case 34: - sha1recompress_fast_34(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE35 - case 35: - sha1recompress_fast_35(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE36 - case 36: - sha1recompress_fast_36(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE37 - case 37: - sha1recompress_fast_37(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE38 - case 38: - sha1recompress_fast_38(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE39 - case 39: - sha1recompress_fast_39(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE40 - case 40: - sha1recompress_fast_40(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE41 - case 41: - sha1recompress_fast_41(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE42 - case 42: - sha1recompress_fast_42(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE43 - case 43: - sha1recompress_fast_43(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE44 - case 44: - sha1recompress_fast_44(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE45 - case 45: - sha1recompress_fast_45(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE46 - case 46: - sha1recompress_fast_46(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE47 - case 47: - sha1recompress_fast_47(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE48 - case 48: - sha1recompress_fast_48(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE49 - case 49: - sha1recompress_fast_49(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE50 - case 50: - sha1recompress_fast_50(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE51 - case 51: - sha1recompress_fast_51(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE52 - case 52: - sha1recompress_fast_52(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE53 - case 53: - sha1recompress_fast_53(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE54 - case 54: - sha1recompress_fast_54(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE55 - case 55: - sha1recompress_fast_55(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE56 - case 56: - sha1recompress_fast_56(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE57 - case 57: - sha1recompress_fast_57(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE58 - case 58: - sha1recompress_fast_58(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE59 - case 59: - sha1recompress_fast_59(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE60 - case 60: - sha1recompress_fast_60(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE61 - case 61: - sha1recompress_fast_61(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE62 - case 62: - sha1recompress_fast_62(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE63 - case 63: - sha1recompress_fast_63(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE64 - case 64: - sha1recompress_fast_64(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE65 - case 65: - sha1recompress_fast_65(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE66 - case 66: - sha1recompress_fast_66(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE67 - case 67: - sha1recompress_fast_67(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE68 - case 68: - sha1recompress_fast_68(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE69 - case 69: - sha1recompress_fast_69(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE70 - case 70: - sha1recompress_fast_70(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE71 - case 71: - sha1recompress_fast_71(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE72 - case 72: - sha1recompress_fast_72(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE73 - case 73: - sha1recompress_fast_73(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE74 - case 74: - sha1recompress_fast_74(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE75 - case 75: - sha1recompress_fast_75(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE76 - case 76: - sha1recompress_fast_76(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE77 - case 77: - sha1recompress_fast_77(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE78 - case 78: - sha1recompress_fast_78(ihvin, ihvout, me2, state); - break; -#endif -#ifdef DOSTORESTATE79 - case 79: - sha1recompress_fast_79(ihvin, ihvout, me2, state); - break; -#endif - default: - abort(); - } - -} - - - -static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16]) -{ - unsigned i, j; - uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF }; - uint32_t ihvtmp[5]; - - ctx->ihv1[0] = ctx->ihv[0]; - ctx->ihv1[1] = ctx->ihv[1]; - ctx->ihv1[2] = ctx->ihv[2]; - ctx->ihv1[3] = ctx->ihv[3]; - ctx->ihv1[4] = ctx->ihv[4]; - - sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states); - - if (ctx->detect_coll) - { - if (ctx->ubc_check) - { - ubc_check(ctx->m1, ubc_dv_mask); - } - - if (ubc_dv_mask[0] != 0) - { - for (i = 0; sha1_dvs[i].dvType != 0; ++i) - { - if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb)) - { - for (j = 0; j < 80; ++j) - ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j]; - - sha1_recompression_step(sha1_dvs[i].testt, ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]); - - /* to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 */ - if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | (ihvtmp[4] ^ ctx->ihv[4]))) - || (ctx->reduced_round_coll && 0==((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | (ctx->ihv1[4] ^ ctx->ihv2[4])))) - { - ctx->found_collision = 1; - - if (ctx->safe_hash) - { - sha1_compression_W(ctx->ihv, ctx->m1); - sha1_compression_W(ctx->ihv, ctx->m1); - } - - break; - } - } - } - } - } -} - -void SHA1DCInit(SHA1_CTX* ctx) -{ - ctx->total = 0; - ctx->ihv[0] = 0x67452301; - ctx->ihv[1] = 0xEFCDAB89; - ctx->ihv[2] = 0x98BADCFE; - ctx->ihv[3] = 0x10325476; - ctx->ihv[4] = 0xC3D2E1F0; - ctx->found_collision = 0; - ctx->safe_hash = SHA1DC_INIT_SAFE_HASH_DEFAULT; - ctx->ubc_check = 1; - ctx->detect_coll = 1; - ctx->reduced_round_coll = 0; - ctx->callback = NULL; -} - -void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash) -{ - if (safehash) - ctx->safe_hash = 1; - else - ctx->safe_hash = 0; -} - - -void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check) -{ - if (ubc_check) - ctx->ubc_check = 1; - else - ctx->ubc_check = 0; -} - -void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll) -{ - if (detect_coll) - ctx->detect_coll = 1; - else - ctx->detect_coll = 0; -} - -void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll) -{ - if (reduced_round_coll) - ctx->reduced_round_coll = 1; - else - ctx->reduced_round_coll = 0; -} - -void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback) -{ - ctx->callback = callback; -} - -void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len) -{ - unsigned left, fill; - - if (len == 0) - return; - - left = ctx->total & 63; - fill = 64 - left; - - if (left && len >= fill) - { - ctx->total += fill; - memcpy(ctx->buffer + left, buf, fill); - sha1_process(ctx, (uint32_t*)(ctx->buffer)); - buf += fill; - len -= fill; - left = 0; - } - while (len >= 64) - { - ctx->total += 64; - -#if defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) - sha1_process(ctx, (uint32_t*)(buf)); -#else - memcpy(ctx->buffer, buf, 64); - sha1_process(ctx, (uint32_t*)(ctx->buffer)); -#endif /* defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) */ - buf += 64; - len -= 64; - } - if (len > 0) - { - ctx->total += len; - memcpy(ctx->buffer + left, buf, len); - } -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx) -{ - uint32_t last = ctx->total & 63; - uint32_t padn = (last < 56) ? (56 - last) : (120 - last); - uint64_t total; - SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn); - - total = ctx->total - padn; - total <<= 3; - ctx->buffer[56] = (unsigned char)(total >> 56); - ctx->buffer[57] = (unsigned char)(total >> 48); - ctx->buffer[58] = (unsigned char)(total >> 40); - ctx->buffer[59] = (unsigned char)(total >> 32); - ctx->buffer[60] = (unsigned char)(total >> 24); - ctx->buffer[61] = (unsigned char)(total >> 16); - ctx->buffer[62] = (unsigned char)(total >> 8); - ctx->buffer[63] = (unsigned char)(total); - sha1_process(ctx, (uint32_t*)(ctx->buffer)); - output[0] = (unsigned char)(ctx->ihv[0] >> 24); - output[1] = (unsigned char)(ctx->ihv[0] >> 16); - output[2] = (unsigned char)(ctx->ihv[0] >> 8); - output[3] = (unsigned char)(ctx->ihv[0]); - output[4] = (unsigned char)(ctx->ihv[1] >> 24); - output[5] = (unsigned char)(ctx->ihv[1] >> 16); - output[6] = (unsigned char)(ctx->ihv[1] >> 8); - output[7] = (unsigned char)(ctx->ihv[1]); - output[8] = (unsigned char)(ctx->ihv[2] >> 24); - output[9] = (unsigned char)(ctx->ihv[2] >> 16); - output[10] = (unsigned char)(ctx->ihv[2] >> 8); - output[11] = (unsigned char)(ctx->ihv[2]); - output[12] = (unsigned char)(ctx->ihv[3] >> 24); - output[13] = (unsigned char)(ctx->ihv[3] >> 16); - output[14] = (unsigned char)(ctx->ihv[3] >> 8); - output[15] = (unsigned char)(ctx->ihv[3]); - output[16] = (unsigned char)(ctx->ihv[4] >> 24); - output[17] = (unsigned char)(ctx->ihv[4] >> 16); - output[18] = (unsigned char)(ctx->ihv[4] >> 8); - output[19] = (unsigned char)(ctx->ihv[4]); - return ctx->found_collision; -} - -#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C -#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1dc/sha1.h libgit2-1.1.0+dfsg.1/src/hash/sha1dc/sha1.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1dc/sha1.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1dc/sha1.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/*** -* Copyright 2017 Marc Stevens , Dan Shumow -* Distributed under the MIT Software License. -* See accompanying file LICENSE.txt or copy at -* https://opensource.org/licenses/MIT -***/ - -#ifndef SHA1DC_SHA1_H -#define SHA1DC_SHA1_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef SHA1DC_NO_STANDARD_INCLUDES -#include -#endif - -/* sha-1 compression function that takes an already expanded message, and additionally store intermediate states */ -/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */ -void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]); - -/* -// Function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]). -// Where 0 <= T < 80 -// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference.) -// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block. -// The function will return: -// ihvin: The reconstructed input chaining value. -// ihvout: The reconstructed output chaining value. -*/ -typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*); - -/* A callback function type that can be set to be called when a collision block has been found: */ -/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */ -typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*); - -/* The SHA-1 context. */ -typedef struct { - uint64_t total; - uint32_t ihv[5]; - unsigned char buffer[64]; - int found_collision; - int safe_hash; - int detect_coll; - int ubc_check; - int reduced_round_coll; - collision_block_callback callback; - - uint32_t ihv1[5]; - uint32_t ihv2[5]; - uint32_t m1[80]; - uint32_t m2[80]; - uint32_t states[80][5]; -} SHA1_CTX; - -/* Initialize SHA-1 context. */ -void SHA1DCInit(SHA1_CTX*); - -/* - Function to enable safe SHA-1 hashing: - Collision attacks are thwarted by hashing a detected near-collision block 3 times. - Think of it as extending SHA-1 from 80-steps to 240-steps for such blocks: - The best collision attacks against SHA-1 have complexity about 2^60, - thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would be 2^180. - An attacker would be better off using a generic birthday search of complexity 2^80. - - Enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected, - but it will result in a different SHA-1 hash for messages where a collision attack was detected. - This will automatically invalidate SHA-1 based digital signature forgeries. - Enabled by default. -*/ -void SHA1DCSetSafeHash(SHA1_CTX*, int); - -/* - Function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up). - Enabled by default - */ -void SHA1DCSetUseUBC(SHA1_CTX*, int); - -/* - Function to disable or enable the use of Collision Detection. - Enabled by default. - */ -void SHA1DCSetUseDetectColl(SHA1_CTX*, int); - -/* function to disable or enable the detection of reduced-round SHA-1 collisions */ -/* disabled by default */ -void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int); - -/* function to set a callback function, pass NULL to disable */ -/* by default no callback set */ -void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback); - -/* update SHA-1 context with buffer contents */ -void SHA1DCUpdate(SHA1_CTX*, const char*, size_t); - -/* obtain SHA-1 hash from SHA-1 context */ -/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */ -int SHA1DCFinal(unsigned char[20], SHA1_CTX*); - -#if defined(__cplusplus) -} -#endif - -#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H -#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H -#endif - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1dc/ubc_check.c libgit2-1.1.0+dfsg.1/src/hash/sha1dc/ubc_check.c --- libgit2-0.28.5+dfsg.1/src/hash/sha1dc/ubc_check.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1dc/ubc_check.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,372 +0,0 @@ -/*** -* Copyright 2017 Marc Stevens , Dan Shumow -* Distributed under the MIT Software License. -* See accompanying file LICENSE.txt or copy at -* https://opensource.org/licenses/MIT -***/ - -/* -// this file was generated by the 'parse_bitrel' program in the tools section -// using the data files from directory 'tools/data/3565' -// -// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check -// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) -// dm[80] is the expanded message block XOR-difference defined by the DV -// testt is the step to do the recompression from for collision detection -// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check -// -// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs -// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met -// thus one needs to do the recompression check for each DV that has its bit set -// -// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded -// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c -// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section -*/ - -#ifndef SHA1DC_NO_STANDARD_INCLUDES -#include -#endif -#ifdef SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C -#include SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C -#endif -#include "ubc_check.h" - -static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0; -static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1; -static const uint32_t DV_I_45_0_bit = (uint32_t)(1) << 2; -static const uint32_t DV_I_46_0_bit = (uint32_t)(1) << 3; -static const uint32_t DV_I_46_2_bit = (uint32_t)(1) << 4; -static const uint32_t DV_I_47_0_bit = (uint32_t)(1) << 5; -static const uint32_t DV_I_47_2_bit = (uint32_t)(1) << 6; -static const uint32_t DV_I_48_0_bit = (uint32_t)(1) << 7; -static const uint32_t DV_I_48_2_bit = (uint32_t)(1) << 8; -static const uint32_t DV_I_49_0_bit = (uint32_t)(1) << 9; -static const uint32_t DV_I_49_2_bit = (uint32_t)(1) << 10; -static const uint32_t DV_I_50_0_bit = (uint32_t)(1) << 11; -static const uint32_t DV_I_50_2_bit = (uint32_t)(1) << 12; -static const uint32_t DV_I_51_0_bit = (uint32_t)(1) << 13; -static const uint32_t DV_I_51_2_bit = (uint32_t)(1) << 14; -static const uint32_t DV_I_52_0_bit = (uint32_t)(1) << 15; -static const uint32_t DV_II_45_0_bit = (uint32_t)(1) << 16; -static const uint32_t DV_II_46_0_bit = (uint32_t)(1) << 17; -static const uint32_t DV_II_46_2_bit = (uint32_t)(1) << 18; -static const uint32_t DV_II_47_0_bit = (uint32_t)(1) << 19; -static const uint32_t DV_II_48_0_bit = (uint32_t)(1) << 20; -static const uint32_t DV_II_49_0_bit = (uint32_t)(1) << 21; -static const uint32_t DV_II_49_2_bit = (uint32_t)(1) << 22; -static const uint32_t DV_II_50_0_bit = (uint32_t)(1) << 23; -static const uint32_t DV_II_50_2_bit = (uint32_t)(1) << 24; -static const uint32_t DV_II_51_0_bit = (uint32_t)(1) << 25; -static const uint32_t DV_II_51_2_bit = (uint32_t)(1) << 26; -static const uint32_t DV_II_52_0_bit = (uint32_t)(1) << 27; -static const uint32_t DV_II_53_0_bit = (uint32_t)(1) << 28; -static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29; -static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30; -static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31; - -dv_info_t sha1_dvs[] = -{ - {1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } } -, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } } -, {1,45,0,58,0,2, { 0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803 } } -, {1,46,0,58,0,3, { 0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c } } -, {1,46,2,58,0,4, { 0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a,0x00000132 } } -, {1,47,0,58,0,5, { 0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6 } } -, {1,47,2,58,0,6, { 0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a } } -, {1,48,0,58,0,7, { 0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408 } } -, {1,48,2,58,0,8, { 0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020 } } -, {1,49,0,58,0,9, { 0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164 } } -, {1,49,2,58,0,10, { 0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590 } } -, {1,50,0,65,0,11, { 0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018 } } -, {1,50,2,65,0,12, { 0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060 } } -, {1,51,0,65,0,13, { 0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202 } } -, {1,51,2,65,0,14, { 0xa0000003,0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a } } -, {1,52,0,65,0,15, { 0x04000010,0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012 } } -, {2,45,0,58,0,16, { 0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054,0x00000967 } } -, {2,46,0,58,0,17, { 0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054 } } -, {2,46,2,58,0,18, { 0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6,0x0000106a,0x00000b90,0x00000152 } } -, {2,47,0,58,0,19, { 0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4 } } -, {2,48,0,58,0,20, { 0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a } } -, {2,49,0,58,0,21, { 0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d } } -, {2,49,2,58,0,22, { 0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6 } } -, {2,50,0,65,0,23, { 0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b } } -, {2,50,2,65,0,24, { 0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c } } -, {2,51,0,65,0,25, { 0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b } } -, {2,51,2,65,0,26, { 0x00000043,0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e } } -, {2,52,0,65,0,27, { 0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014 } } -, {2,53,0,65,0,28, { 0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089 } } -, {2,54,0,65,0,29, { 0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107 } } -, {2,55,0,65,0,30, { 0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b } } -, {2,56,0,65,0,31, { 0x2600001a,0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046 } } -, {0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} -}; -void ubc_check(const uint32_t W[80], uint32_t dvmask[1]) -{ - uint32_t mask = ~((uint32_t)(0)); - mask &= (((((W[44]^W[45])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_I_51_0_bit|DV_I_52_0_bit|DV_II_45_0_bit|DV_II_46_0_bit|DV_II_50_0_bit|DV_II_51_0_bit)); - mask &= (((((W[49]^W[50])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_II_45_0_bit|DV_II_50_0_bit|DV_II_51_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); - mask &= (((((W[48]^W[49])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_52_0_bit|DV_II_49_0_bit|DV_II_50_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); - mask &= ((((W[47]^(W[50]>>25))&(1<<4))-(1<<4)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); - mask &= (((((W[47]^W[48])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_51_0_bit|DV_II_48_0_bit|DV_II_49_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); - mask &= (((((W[46]>>4)^(W[49]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_50_0_bit|DV_II_55_0_bit)); - mask &= (((((W[46]^W[47])>>29)&1)-1) | ~(DV_I_43_0_bit|DV_I_50_0_bit|DV_II_47_0_bit|DV_II_48_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); - mask &= (((((W[45]>>4)^(W[48]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_49_0_bit|DV_II_54_0_bit)); - mask &= (((((W[45]^W[46])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_51_0_bit|DV_II_52_0_bit)); - mask &= (((((W[44]>>4)^(W[47]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_53_0_bit)); - mask &= (((((W[43]>>4)^(W[46]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_52_0_bit)); - mask &= (((((W[43]^W[44])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_I_50_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_49_0_bit|DV_II_50_0_bit)); - mask &= (((((W[42]>>4)^(W[45]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_51_0_bit)); - mask &= (((((W[41]>>4)^(W[44]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_50_0_bit)); - mask &= (((((W[40]^W[41])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_47_0_bit|DV_I_48_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_56_0_bit)); - mask &= (((((W[54]^W[55])>>29)&1)-1) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_50_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); - mask &= (((((W[53]^W[54])>>29)&1)-1) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_49_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); - mask &= (((((W[52]^W[53])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); - mask &= ((((W[50]^(W[53]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_48_0_bit|DV_II_54_0_bit)); - mask &= (((((W[50]^W[51])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_II_46_0_bit|DV_II_51_0_bit|DV_II_52_0_bit|DV_II_56_0_bit)); - mask &= ((((W[49]^(W[52]>>25))&(1<<4))-(1<<4)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_47_0_bit|DV_II_53_0_bit)); - mask &= ((((W[48]^(W[51]>>25))&(1<<4))-(1<<4)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_52_0_bit)); - mask &= (((((W[42]^W[43])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); - mask &= (((((W[41]^W[42])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_48_0_bit)); - mask &= (((((W[40]>>4)^(W[43]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_50_0_bit|DV_II_49_0_bit|DV_II_56_0_bit)); - mask &= (((((W[39]>>4)^(W[42]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_49_0_bit|DV_II_48_0_bit|DV_II_55_0_bit)); - if (mask & (DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) - mask &= (((((W[38]>>4)^(W[41]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); - mask &= (((((W[37]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_47_0_bit|DV_II_46_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); - if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)) - mask &= (((((W[55]^W[56])>>29)&1)-1) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); - if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)) - mask &= ((((W[52]^(W[55]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)); - if (mask & (DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)) - mask &= ((((W[51]^(W[54]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)); - if (mask & (DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)) - mask &= (((((W[51]^W[52])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); - if (mask & (DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)) - mask &= (((((W[36]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)); - if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)) - mask &= ((0-(((W[53]^W[56])>>29)&1)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); - if (mask & (DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)) - mask &= ((0-(((W[51]^W[54])>>29)&1)) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)); - if (mask & (DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)) - mask &= ((0-(((W[50]^W[52])>>29)&1)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)); - if (mask & (DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)) - mask &= ((0-(((W[49]^W[51])>>29)&1)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)); - if (mask & (DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)) - mask &= ((0-(((W[48]^W[50])>>29)&1)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)); - if (mask & (DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)) - mask &= ((0-(((W[47]^W[49])>>29)&1)) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)); - if (mask & (DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)) - mask &= ((0-(((W[46]^W[48])>>29)&1)) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)); - mask &= ((((W[45]^W[47])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit|DV_I_51_2_bit)); - if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)) - mask &= ((0-(((W[45]^W[47])>>29)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)); - mask &= (((((W[44]^W[46])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit|DV_I_50_2_bit)); - if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)) - mask &= ((0-(((W[44]^W[46])>>29)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)); - mask &= ((0-((W[41]^(W[42]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_II_46_2_bit|DV_II_51_2_bit)); - mask &= ((0-((W[40]^(W[41]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_51_2_bit|DV_II_50_2_bit)); - if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)) - mask &= ((0-(((W[40]^W[42])>>4)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)); - mask &= ((0-((W[39]^(W[40]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_50_2_bit|DV_II_49_2_bit)); - if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)) - mask &= ((0-(((W[39]^W[41])>>4)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)); - if (mask & (DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) - mask &= ((0-(((W[38]^W[40])>>4)&1)) | ~(DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); - if (mask & (DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)) - mask &= ((0-(((W[37]^W[39])>>4)&1)) | ~(DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); - mask &= ((0-((W[36]^(W[37]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_50_2_bit|DV_II_46_2_bit)); - if (mask & (DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)) - mask &= (((((W[35]>>4)^(W[39]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)); - if (mask & (DV_I_48_0_bit|DV_II_48_0_bit)) - mask &= ((0-((W[63]^(W[64]>>5))&(1<<0))) | ~(DV_I_48_0_bit|DV_II_48_0_bit)); - if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) - mask &= ((0-((W[63]^(W[64]>>5))&(1<<1))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); - if (mask & (DV_I_47_0_bit|DV_II_47_0_bit)) - mask &= ((0-((W[62]^(W[63]>>5))&(1<<0))) | ~(DV_I_47_0_bit|DV_II_47_0_bit)); - if (mask & (DV_I_46_0_bit|DV_II_46_0_bit)) - mask &= ((0-((W[61]^(W[62]>>5))&(1<<0))) | ~(DV_I_46_0_bit|DV_II_46_0_bit)); - mask &= ((0-((W[61]^(W[62]>>5))&(1<<2))) | ~(DV_I_46_2_bit|DV_II_46_2_bit)); - if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) - mask &= ((0-((W[60]^(W[61]>>5))&(1<<0))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); - if (mask & (DV_II_51_0_bit|DV_II_54_0_bit)) - mask &= (((((W[58]^W[59])>>29)&1)-1) | ~(DV_II_51_0_bit|DV_II_54_0_bit)); - if (mask & (DV_II_50_0_bit|DV_II_53_0_bit)) - mask &= (((((W[57]^W[58])>>29)&1)-1) | ~(DV_II_50_0_bit|DV_II_53_0_bit)); - if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) - mask &= ((((W[56]^(W[59]>>25))&(1<<4))-(1<<4)) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); - if (mask & (DV_II_51_0_bit|DV_II_52_0_bit)) - mask &= ((0-(((W[56]^W[59])>>29)&1)) | ~(DV_II_51_0_bit|DV_II_52_0_bit)); - if (mask & (DV_II_49_0_bit|DV_II_52_0_bit)) - mask &= (((((W[56]^W[57])>>29)&1)-1) | ~(DV_II_49_0_bit|DV_II_52_0_bit)); - if (mask & (DV_II_51_0_bit|DV_II_53_0_bit)) - mask &= ((((W[55]^(W[58]>>25))&(1<<4))-(1<<4)) | ~(DV_II_51_0_bit|DV_II_53_0_bit)); - if (mask & (DV_II_50_0_bit|DV_II_52_0_bit)) - mask &= ((((W[54]^(W[57]>>25))&(1<<4))-(1<<4)) | ~(DV_II_50_0_bit|DV_II_52_0_bit)); - if (mask & (DV_II_49_0_bit|DV_II_51_0_bit)) - mask &= ((((W[53]^(W[56]>>25))&(1<<4))-(1<<4)) | ~(DV_II_49_0_bit|DV_II_51_0_bit)); - mask &= ((((W[51]^(W[50]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); - mask &= ((((W[48]^W[50])&(1<<6))-(1<<6)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); - if (mask & (DV_I_51_0_bit|DV_I_52_0_bit)) - mask &= ((0-(((W[48]^W[55])>>29)&1)) | ~(DV_I_51_0_bit|DV_I_52_0_bit)); - mask &= ((((W[47]^W[49])&(1<<6))-(1<<6)) | ~(DV_I_49_2_bit|DV_I_51_2_bit)); - mask &= ((((W[48]^(W[47]>>5))&(1<<1))-(1<<1)) | ~(DV_I_47_2_bit|DV_II_51_2_bit)); - mask &= ((((W[46]^W[48])&(1<<6))-(1<<6)) | ~(DV_I_48_2_bit|DV_I_50_2_bit)); - mask &= ((((W[47]^(W[46]>>5))&(1<<1))-(1<<1)) | ~(DV_I_46_2_bit|DV_II_50_2_bit)); - mask &= ((0-((W[44]^(W[45]>>5))&(1<<1))) | ~(DV_I_51_2_bit|DV_II_49_2_bit)); - mask &= ((((W[43]^W[45])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit)); - mask &= (((((W[42]^W[44])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit)); - mask &= ((((W[43]^(W[42]>>5))&(1<<1))-(1<<1)) | ~(DV_II_46_2_bit|DV_II_51_2_bit)); - mask &= ((((W[42]^(W[41]>>5))&(1<<1))-(1<<1)) | ~(DV_I_51_2_bit|DV_II_50_2_bit)); - mask &= ((((W[41]^(W[40]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_49_2_bit)); - if (mask & (DV_I_52_0_bit|DV_II_51_0_bit)) - mask &= ((((W[39]^(W[43]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_51_0_bit)); - if (mask & (DV_I_51_0_bit|DV_II_50_0_bit)) - mask &= ((((W[38]^(W[42]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_50_0_bit)); - if (mask & (DV_I_48_2_bit|DV_I_51_2_bit)) - mask &= ((0-((W[37]^(W[38]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_I_51_2_bit)); - if (mask & (DV_I_50_0_bit|DV_II_49_0_bit)) - mask &= ((((W[37]^(W[41]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_II_49_0_bit)); - if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) - mask &= ((0-((W[36]^W[38])&(1<<4))) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); - mask &= ((0-((W[35]^(W[36]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_49_2_bit)); - if (mask & (DV_I_51_0_bit|DV_II_47_0_bit)) - mask &= ((((W[35]^(W[39]>>25))&(1<<3))-(1<<3)) | ~(DV_I_51_0_bit|DV_II_47_0_bit)); -if (mask) { - - if (mask & DV_I_43_0_bit) - if ( - !((W[61]^(W[62]>>5)) & (1<<1)) - || !(!((W[59]^(W[63]>>25)) & (1<<5))) - || !((W[58]^(W[63]>>30)) & (1<<0)) - ) mask &= ~DV_I_43_0_bit; - if (mask & DV_I_44_0_bit) - if ( - !((W[62]^(W[63]>>5)) & (1<<1)) - || !(!((W[60]^(W[64]>>25)) & (1<<5))) - || !((W[59]^(W[64]>>30)) & (1<<0)) - ) mask &= ~DV_I_44_0_bit; - if (mask & DV_I_46_2_bit) - mask &= ((~((W[40]^W[42])>>2)) | ~DV_I_46_2_bit); - if (mask & DV_I_47_2_bit) - if ( - !((W[62]^(W[63]>>5)) & (1<<2)) - || !(!((W[41]^W[43]) & (1<<6))) - ) mask &= ~DV_I_47_2_bit; - if (mask & DV_I_48_2_bit) - if ( - !((W[63]^(W[64]>>5)) & (1<<2)) - || !(!((W[48]^(W[49]<<5)) & (1<<6))) - ) mask &= ~DV_I_48_2_bit; - if (mask & DV_I_49_2_bit) - if ( - !(!((W[49]^(W[50]<<5)) & (1<<6))) - || !((W[42]^W[50]) & (1<<1)) - || !(!((W[39]^(W[40]<<5)) & (1<<6))) - || !((W[38]^W[40]) & (1<<1)) - ) mask &= ~DV_I_49_2_bit; - if (mask & DV_I_50_0_bit) - mask &= ((((W[36]^W[37])<<7)) | ~DV_I_50_0_bit); - if (mask & DV_I_50_2_bit) - mask &= ((((W[43]^W[51])<<11)) | ~DV_I_50_2_bit); - if (mask & DV_I_51_0_bit) - mask &= ((((W[37]^W[38])<<9)) | ~DV_I_51_0_bit); - if (mask & DV_I_51_2_bit) - if ( - !(!((W[51]^(W[52]<<5)) & (1<<6))) - || !(!((W[49]^W[51]) & (1<<6))) - || !(!((W[37]^(W[37]>>5)) & (1<<1))) - || !(!((W[35]^(W[39]>>25)) & (1<<5))) - ) mask &= ~DV_I_51_2_bit; - if (mask & DV_I_52_0_bit) - mask &= ((((W[38]^W[39])<<11)) | ~DV_I_52_0_bit); - if (mask & DV_II_46_2_bit) - mask &= ((((W[47]^W[51])<<17)) | ~DV_II_46_2_bit); - if (mask & DV_II_48_0_bit) - if ( - !(!((W[36]^(W[40]>>25)) & (1<<3))) - || !((W[35]^(W[40]<<2)) & (1<<30)) - ) mask &= ~DV_II_48_0_bit; - if (mask & DV_II_49_0_bit) - if ( - !(!((W[37]^(W[41]>>25)) & (1<<3))) - || !((W[36]^(W[41]<<2)) & (1<<30)) - ) mask &= ~DV_II_49_0_bit; - if (mask & DV_II_49_2_bit) - if ( - !(!((W[53]^(W[54]<<5)) & (1<<6))) - || !(!((W[51]^W[53]) & (1<<6))) - || !((W[50]^W[54]) & (1<<1)) - || !(!((W[45]^(W[46]<<5)) & (1<<6))) - || !(!((W[37]^(W[41]>>25)) & (1<<5))) - || !((W[36]^(W[41]>>30)) & (1<<0)) - ) mask &= ~DV_II_49_2_bit; - if (mask & DV_II_50_0_bit) - if ( - !((W[55]^W[58]) & (1<<29)) - || !(!((W[38]^(W[42]>>25)) & (1<<3))) - || !((W[37]^(W[42]<<2)) & (1<<30)) - ) mask &= ~DV_II_50_0_bit; - if (mask & DV_II_50_2_bit) - if ( - !(!((W[54]^(W[55]<<5)) & (1<<6))) - || !(!((W[52]^W[54]) & (1<<6))) - || !((W[51]^W[55]) & (1<<1)) - || !((W[45]^W[47]) & (1<<1)) - || !(!((W[38]^(W[42]>>25)) & (1<<5))) - || !((W[37]^(W[42]>>30)) & (1<<0)) - ) mask &= ~DV_II_50_2_bit; - if (mask & DV_II_51_0_bit) - if ( - !(!((W[39]^(W[43]>>25)) & (1<<3))) - || !((W[38]^(W[43]<<2)) & (1<<30)) - ) mask &= ~DV_II_51_0_bit; - if (mask & DV_II_51_2_bit) - if ( - !(!((W[55]^(W[56]<<5)) & (1<<6))) - || !(!((W[53]^W[55]) & (1<<6))) - || !((W[52]^W[56]) & (1<<1)) - || !((W[46]^W[48]) & (1<<1)) - || !(!((W[39]^(W[43]>>25)) & (1<<5))) - || !((W[38]^(W[43]>>30)) & (1<<0)) - ) mask &= ~DV_II_51_2_bit; - if (mask & DV_II_52_0_bit) - if ( - !(!((W[59]^W[60]) & (1<<29))) - || !(!((W[40]^(W[44]>>25)) & (1<<3))) - || !(!((W[40]^(W[44]>>25)) & (1<<4))) - || !((W[39]^(W[44]<<2)) & (1<<30)) - ) mask &= ~DV_II_52_0_bit; - if (mask & DV_II_53_0_bit) - if ( - !((W[58]^W[61]) & (1<<29)) - || !(!((W[57]^(W[61]>>25)) & (1<<4))) - || !(!((W[41]^(W[45]>>25)) & (1<<3))) - || !(!((W[41]^(W[45]>>25)) & (1<<4))) - ) mask &= ~DV_II_53_0_bit; - if (mask & DV_II_54_0_bit) - if ( - !(!((W[58]^(W[62]>>25)) & (1<<4))) - || !(!((W[42]^(W[46]>>25)) & (1<<3))) - || !(!((W[42]^(W[46]>>25)) & (1<<4))) - ) mask &= ~DV_II_54_0_bit; - if (mask & DV_II_55_0_bit) - if ( - !(!((W[59]^(W[63]>>25)) & (1<<4))) - || !(!((W[57]^(W[59]>>25)) & (1<<4))) - || !(!((W[43]^(W[47]>>25)) & (1<<3))) - || !(!((W[43]^(W[47]>>25)) & (1<<4))) - ) mask &= ~DV_II_55_0_bit; - if (mask & DV_II_56_0_bit) - if ( - !(!((W[60]^(W[64]>>25)) & (1<<4))) - || !(!((W[44]^(W[48]>>25)) & (1<<3))) - || !(!((W[44]^(W[48]>>25)) & (1<<4))) - ) mask &= ~DV_II_56_0_bit; -} - - dvmask[0]=mask; -} - -#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C -#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1dc/ubc_check.h libgit2-1.1.0+dfsg.1/src/hash/sha1dc/ubc_check.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1dc/ubc_check.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1dc/ubc_check.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/*** -* Copyright 2017 Marc Stevens , Dan Shumow -* Distributed under the MIT Software License. -* See accompanying file LICENSE.txt or copy at -* https://opensource.org/licenses/MIT -***/ - -/* -// this file was generated by the 'parse_bitrel' program in the tools section -// using the data files from directory 'tools/data/3565' -// -// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check -// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) -// dm[80] is the expanded message block XOR-difference defined by the DV -// testt is the step to do the recompression from for collision detection -// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check -// -// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs -// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met -// thus one needs to do the recompression check for each DV that has its bit set -*/ - -#ifndef SHA1DC_UBC_CHECK_H -#define SHA1DC_UBC_CHECK_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef SHA1DC_NO_STANDARD_INCLUDES -#include -#endif - -#define DVMASKSIZE 1 -typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t; -extern dv_info_t sha1_dvs[]; -void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]); - -#define DOSTORESTATE58 -#define DOSTORESTATE65 - -#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0]) - -#if defined(__cplusplus) -} -#endif - -#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H -#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H -#endif - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash/sha1.h libgit2-1.1.0+dfsg.1/src/hash/sha1.h --- libgit2-0.28.5+dfsg.1/src/hash/sha1.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash/sha1.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_sha1_h__ +#define INCLUDE_hash_sha1_h__ + +#include "common.h" + +typedef struct git_hash_sha1_ctx git_hash_sha1_ctx; + +#if defined(GIT_SHA1_COLLISIONDETECT) +# include "sha1/collisiondetect.h" +#elif defined(GIT_SHA1_COMMON_CRYPTO) +# include "sha1/common_crypto.h" +#elif defined(GIT_SHA1_OPENSSL) +# include "sha1/openssl.h" +#elif defined(GIT_SHA1_WIN32) +# include "sha1/win32.h" +#elif defined(GIT_SHA1_MBEDTLS) +# include "sha1/mbedtls.h" +#else +# include "sha1/generic.h" +#endif + +int git_hash_sha1_global_init(void); + +int git_hash_sha1_ctx_init(git_hash_sha1_ctx *ctx); +void git_hash_sha1_ctx_cleanup(git_hash_sha1_ctx *ctx); + +int git_hash_sha1_init(git_hash_sha1_ctx *c); +int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len); +int git_hash_sha1_final(git_oid *out, git_hash_sha1_ctx *c); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/hash.c libgit2-1.1.0+dfsg.1/src/hash.c --- libgit2-0.28.5+dfsg.1/src/hash.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,6 +7,67 @@ #include "hash.h" +int git_hash_global_init(void) +{ + return git_hash_sha1_global_init(); +} + +int git_hash_ctx_init(git_hash_ctx *ctx) +{ + int error; + + if ((error = git_hash_sha1_ctx_init(&ctx->sha1)) < 0) + return error; + + ctx->algo = GIT_HASH_ALGO_SHA1; + + return 0; +} + +void git_hash_ctx_cleanup(git_hash_ctx *ctx) +{ + switch (ctx->algo) { + case GIT_HASH_ALGO_SHA1: + git_hash_sha1_ctx_cleanup(&ctx->sha1); + return; + default: + assert(0); + } +} + +int git_hash_init(git_hash_ctx *ctx) +{ + switch (ctx->algo) { + case GIT_HASH_ALGO_SHA1: + return git_hash_sha1_init(&ctx->sha1); + default: + assert(0); + return -1; + } +} + +int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + switch (ctx->algo) { + case GIT_HASH_ALGO_SHA1: + return git_hash_sha1_update(&ctx->sha1, data, len); + default: + assert(0); + return -1; + } +} + +int git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + switch (ctx->algo) { + case GIT_HASH_ALGO_SHA1: + return git_hash_sha1_final(out, &ctx->sha1); + default: + assert(0); + return -1; + } +} + int git_hash_buf(git_oid *out, const void *data, size_t len) { git_hash_ctx ctx; diff -Nru libgit2-0.28.5+dfsg.1/src/hash.h libgit2-1.1.0+dfsg.1/src/hash.h --- libgit2-0.28.5+dfsg.1/src/hash.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hash.h 2020-10-12 18:53:06.000000000 +0000 @@ -4,6 +4,7 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ + #ifndef INCLUDE_hash_h__ #define INCLUDE_hash_h__ @@ -11,33 +12,30 @@ #include "git2/oid.h" -typedef struct git_hash_prov git_hash_prov; -typedef struct git_hash_ctx git_hash_ctx; - -int git_hash_ctx_init(git_hash_ctx *ctx); -void git_hash_ctx_cleanup(git_hash_ctx *ctx); - -#if defined(GIT_SHA1_COLLISIONDETECT) -# include "hash/hash_collisiondetect.h" -#elif defined(GIT_SHA1_COMMON_CRYPTO) -# include "hash/hash_common_crypto.h" -#elif defined(GIT_SHA1_OPENSSL) -# include "hash/hash_openssl.h" -#elif defined(GIT_SHA1_WIN32) -# include "hash/hash_win32.h" -#elif defined(GIT_SHA1_MBEDTLS) -# include "hash/hash_mbedtls.h" -#else -# include "hash/hash_generic.h" -#endif - -int git_hash_global_init(void); - typedef struct { void *data; size_t len; } git_buf_vec; +typedef enum { + GIT_HASH_ALGO_UNKNOWN = 0, + GIT_HASH_ALGO_SHA1, +} git_hash_algo_t; + +#include "hash/sha1.h" + +typedef struct git_hash_ctx { + union { + git_hash_sha1_ctx sha1; + }; + git_hash_algo_t algo; +} git_hash_ctx; + +int git_hash_global_init(void); + +int git_hash_ctx_init(git_hash_ctx *ctx); +void git_hash_ctx_cleanup(git_hash_ctx *ctx); + int git_hash_init(git_hash_ctx *c); int git_hash_update(git_hash_ctx *c, const void *data, size_t len); int git_hash_final(git_oid *out, git_hash_ctx *c); diff -Nru libgit2-0.28.5+dfsg.1/src/hashsig.c libgit2-1.1.0+dfsg.1/src/hashsig.c --- libgit2-0.28.5+dfsg.1/src/hashsig.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/hashsig.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ #include "common.h" #include "git2/sys/hashsig.h" -#include "fileops.h" +#include "futils.h" #include "util.h" typedef uint32_t hashsig_t; diff -Nru libgit2-0.28.5+dfsg.1/src/idxmap.c libgit2-1.1.0+dfsg.1/src/idxmap.c --- libgit2-0.28.5+dfsg.1/src/idxmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/idxmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,122 +32,126 @@ __KHASH_IMPL(idx, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_equal) __KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal) -int git_idxmap_alloc(git_idxmap **map) +int git_idxmap_new(git_idxmap **out) { - if ((*map = kh_init(idx)) == NULL) { - git_error_set_oom(); - return -1; - } + *out = kh_init(idx); + GIT_ERROR_CHECK_ALLOC(*out); return 0; } -int git_idxmap_icase_alloc(git_idxmap_icase **map) +int git_idxmap_icase_new(git_idxmap_icase **out) { - if ((*map = kh_init(idxicase)) == NULL) { - git_error_set_oom(); - return -1; - } + *out = kh_init(idxicase); + GIT_ERROR_CHECK_ALLOC(*out); return 0; } -void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval) +void git_idxmap_free(git_idxmap *map) { - khiter_t idx = kh_put(idx, map, key, rval); - - if ((*rval) >= 0) { - if ((*rval) == 0) - kh_key(map, idx) = key; - kh_val(map, idx) = value; - } + kh_destroy(idx, map); } -void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval) +void git_idxmap_icase_free(git_idxmap_icase *map) { - khiter_t idx = kh_put(idxicase, map, key, rval); - - if ((*rval) >= 0) { - if ((*rval) == 0) - kh_key(map, idx) = key; - kh_val(map, idx) = value; - } + kh_destroy(idxicase, map); } -size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key) +void git_idxmap_clear(git_idxmap *map) { - return kh_get(idx, map, key); + kh_clear(idx, map); } -size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key) +void git_idxmap_icase_clear(git_idxmap_icase *map) { - return kh_get(idxicase, map, key); + kh_clear(idxicase, map); } -void *git_idxmap_value_at(git_idxmap *map, size_t idx) +int git_idxmap_resize(git_idxmap *map, size_t size) { - return kh_val(map, idx); + if (!git__is_uint32(size) || + kh_resize(idx, map, (khiter_t)size) < 0) { + git_error_set_oom(); + return -1; + } + return 0; } -int git_idxmap_valid_index(git_idxmap *map, size_t idx) +int git_idxmap_icase_resize(git_idxmap_icase *map, size_t size) { - return idx != kh_end(map); + if (!git__is_uint32(size) || + kh_resize(idxicase, map, (khiter_t)size) < 0) { + git_error_set_oom(); + return -1; + } + return 0; } -int git_idxmap_has_data(git_idxmap *map, size_t idx) +void *git_idxmap_get(git_idxmap *map, const git_index_entry *key) { - return kh_exist(map, idx); + size_t idx = kh_get(idx, map, key); + if (idx == kh_end(map) || !kh_exist(map, idx)) + return NULL; + return kh_val(map, idx); } -void git_idxmap_resize(git_idxmap *map, size_t size) +int git_idxmap_set(git_idxmap *map, const git_index_entry *key, void *value) { - kh_resize(idx, map, size); -} + size_t idx; + int rval; -void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size) -{ - kh_resize(idxicase, map, size); -} + idx = kh_put(idx, map, key, &rval); + if (rval < 0) + return -1; -void git_idxmap_free(git_idxmap *map) -{ - kh_destroy(idx, map); -} + if (rval == 0) + kh_key(map, idx) = key; -void git_idxmap_icase_free(git_idxmap_icase *map) -{ - kh_destroy(idxicase, map); + kh_val(map, idx) = value; + + return 0; } -void git_idxmap_clear(git_idxmap *map) +int git_idxmap_icase_set(git_idxmap_icase *map, const git_index_entry *key, void *value) { - kh_clear(idx, map); + size_t idx; + int rval; + + idx = kh_put(idxicase, map, key, &rval); + if (rval < 0) + return -1; + + if (rval == 0) + kh_key(map, idx) = key; + + kh_val(map, idx) = value; + + return 0; } -void git_idxmap_icase_clear(git_idxmap_icase *map) +void *git_idxmap_icase_get(git_idxmap_icase *map, const git_index_entry *key) { - kh_clear(idxicase, map); + size_t idx = kh_get(idxicase, map, key); + if (idx == kh_end(map) || !kh_exist(map, idx)) + return NULL; + return kh_val(map, idx); } -void git_idxmap_delete_at(git_idxmap *map, size_t idx) +int git_idxmap_delete(git_idxmap *map, const git_index_entry *key) { + khiter_t idx = kh_get(idx, map, key); + if (idx == kh_end(map)) + return GIT_ENOTFOUND; kh_del(idx, map, idx); + return 0; } -void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx) +int git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key) { + khiter_t idx = kh_get(idxicase, map, key); + if (idx == kh_end(map)) + return GIT_ENOTFOUND; kh_del(idxicase, map, idx); -} - -void git_idxmap_delete(git_idxmap *map, const git_index_entry *key) -{ - khiter_t idx = git_idxmap_lookup_index(map, key); - if (git_idxmap_valid_index(map, idx)) - git_idxmap_delete_at(map, idx); -} -void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key) -{ - khiter_t idx = git_idxmap_icase_lookup_index(map, key); - if (git_idxmap_valid_index((git_idxmap *)map, idx)) - git_idxmap_icase_delete_at(map, idx); + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/idxmap.h libgit2-1.1.0+dfsg.1/src/idxmap.h --- libgit2-0.28.5+dfsg.1/src/idxmap.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/idxmap.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,31 +11,167 @@ #include "git2/index.h" +/** A map with `git_index_entry`s as key. */ typedef struct kh_idx_s git_idxmap; +/** A map with case-insensitive `git_index_entry`s as key */ typedef struct kh_idxicase_s git_idxmap_icase; -int git_idxmap_alloc(git_idxmap **map); -int git_idxmap_icase_alloc(git_idxmap_icase **map); -void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval); -void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval); - -size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key); -size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key); -void *git_idxmap_value_at(git_idxmap *map, size_t idx); -int git_idxmap_valid_index(git_idxmap *map, size_t idx); -int git_idxmap_has_data(git_idxmap *map, size_t idx); - -void git_idxmap_resize(git_idxmap *map, size_t size); -void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size); +/** + * Allocate a new index entry map. + * + * @param out Pointer to the map that shall be allocated. + * @return 0 on success, an error code if allocation has failed. + */ +int git_idxmap_new(git_idxmap **out); + +/** + * Allocate a new case-insensitive index entry map. + * + * @param out Pointer to the map that shall be allocated. + * @return 0 on success, an error code if allocation has failed. + */ +int git_idxmap_icase_new(git_idxmap_icase **out); + +/** + * Free memory associated with the map. + * + * Note that this function will _not_ free values added to this + * map. + * + * @param map Pointer to the map that is to be free'd. May be + * `NULL`. + */ void git_idxmap_free(git_idxmap *map); + +/** + * Free memory associated with the map. + * + * Note that this function will _not_ free values added to this + * map. + * + * @param map Pointer to the map that is to be free'd. May be + * `NULL`. + */ void git_idxmap_icase_free(git_idxmap_icase *map); + +/** + * Clear all entries from the map. + * + * This function will remove all entries from the associated map. + * Memory associated with it will not be released, though. + * + * @param map Pointer to the map that shall be cleared. May be + * `NULL`. + */ void git_idxmap_clear(git_idxmap *map); -void git_idxmap_icase_clear(git_idxmap_icase *map); -void git_idxmap_delete_at(git_idxmap *map, size_t idx); -void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx); +/** + * Clear all entries from the map. + * + * This function will remove all entries from the associated map. + * Memory associated with it will not be released, though. + * + * @param map Pointer to the map that shall be cleared. May be + * `NULL`. + */ +void git_idxmap_icase_clear(git_idxmap_icase *map); -void git_idxmap_delete(git_idxmap *map, const git_index_entry *key); -void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key); +/** + * Resize the map by allocating more memory. + * + * @param map map that shall be resized + * @param size count of entries that the map shall hold + * @return `0` if the map was successfully resized, a negative + * error code otherwise + */ +int git_idxmap_resize(git_idxmap *map, size_t size); + +/** + * Resize the map by allocating more memory. + * + * @param map map that shall be resized + * @param size count of entries that the map shall hold + * @return `0` if the map was successfully resized, a negative + * error code otherwise + */ +int git_idxmap_icase_resize(git_idxmap_icase *map, size_t size); + +/** + * Return value associated with the given key. + * + * @param map map to search key in + * @param key key to search for; the index entry will be searched + * for by its case-sensitive path + * @return value associated with the given key or NULL if the key was not found + */ +void *git_idxmap_get(git_idxmap *map, const git_index_entry *key); + +/** + * Return value associated with the given key. + * + * @param map map to search key in + * @param key key to search for; the index entry will be searched + * for by its case-insensitive path + * @return value associated with the given key or NULL if the key was not found + */ +void *git_idxmap_icase_get(git_idxmap_icase *map, const git_index_entry *key); + +/** + * Set the entry for key to value. + * + * If the map has no corresponding entry for the given key, a new + * entry will be created with the given value. If an entry exists + * already, its value will be updated to match the given value. + * + * @param map map to create new entry in + * @param key key to set + * @param value value to associate the key with; may be NULL + * @return zero if the key was successfully set, a negative error + * code otherwise + */ +int git_idxmap_set(git_idxmap *map, const git_index_entry *key, void *value); + +/** + * Set the entry for key to value. + * + * If the map has no corresponding entry for the given key, a new + * entry will be created with the given value. If an entry exists + * already, its value will be updated to match the given value. + * + * @param map map to create new entry in + * @param key key to set + * @param value value to associate the key with; may be NULL + * @return zero if the key was successfully set, a negative error + * code otherwise + */ +int git_idxmap_icase_set(git_idxmap_icase *map, const git_index_entry *key, void *value); + +/** + * Delete an entry from the map. + * + * Delete the given key and its value from the map. If no such + * key exists, this will do nothing. + * + * @param map map to delete key in + * @param key key to delete + * @return `0` if the key has been deleted, GIT_ENOTFOUND if no + * such key was found, a negative code in case of an + * error + */ +int git_idxmap_delete(git_idxmap *map, const git_index_entry *key); + +/** + * Delete an entry from the map. + * + * Delete the given key and its value from the map. If no such + * key exists, this will do nothing. + * + * @param map map to delete key in + * @param key key to delete + * @return `0` if the key has been deleted, GIT_ENOTFOUND if no + * such key was found, a negative code in case of an + * error + */ +int git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key); #endif diff -Nru libgit2-0.28.5+dfsg.1/src/ignore.c libgit2-1.1.0+dfsg.1/src/ignore.c --- libgit2-0.28.5+dfsg.1/src/ignore.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/ignore.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,7 +12,7 @@ #include "attrcache.h" #include "path.h" #include "config.h" -#include "fnmatch.h" +#include "wildmatch.h" #define GIT_IGNORE_INTERNAL "[internal]exclude" @@ -101,7 +101,7 @@ */ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match) { - int error = 0, fnflags; + int error = 0, wildmatch_flags; size_t i; git_attr_fnmatch *rule; char *path; @@ -109,9 +109,9 @@ *out = 0; - fnflags = FNM_PATHNAME; + wildmatch_flags = WM_PATHNAME; if (match->flags & GIT_ATTR_FNMATCH_ICASE) - fnflags |= FNM_IGNORECASE; + wildmatch_flags |= WM_CASEFOLD; /* path of the file relative to the workdir, so we match the rules in subdirs */ if (match->containing_dir) { @@ -141,13 +141,8 @@ if (git_buf_oom(&buf)) goto out; - if ((error = p_fnmatch(git_buf_cstr(&buf), path, fnflags)) < 0) { - git_error_set(GIT_ERROR_INVALID, "error matching pattern"); - goto out; - } - /* if we found a match, we want to keep this rule */ - if (error != FNM_NOMATCH) { + if ((wildmatch(git_buf_cstr(&buf), path, wildmatch_flags)) == WM_MATCH) { *out = 1; error = 0; goto out; @@ -163,14 +158,16 @@ } static int parse_ignore_file( - git_repository *repo, git_attr_file *attrs, const char *data) + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros) { int error = 0; int ignore_case = false; const char *scan = data, *context = NULL; git_attr_fnmatch *match = NULL; - if (git_repository__cvar(&ignore_case, repo, GIT_CVAR_IGNORECASE) < 0) + GIT_UNUSED(allow_macros); + + if (git_repository__configmap_lookup(&ignore_case, repo, GIT_CONFIGMAP_IGNORECASE) < 0) git_error_clear(); /* if subdir file path, convert context for file paths */ @@ -193,9 +190,7 @@ } match->flags = - GIT_ATTR_FNMATCH_ALLOWSPACE | - GIT_ATTR_FNMATCH_ALLOWNEG | - GIT_ATTR_FNMATCH_NOLEADINGDIR; + GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG; if (!(error = git_attr_fnmatch__parse( match, &attrs->pool, context, &scan))) @@ -246,9 +241,8 @@ int error = 0; git_attr_file *file = NULL; - error = git_attr_cache__get( - &file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, - base, filename, parse_ignore_file); + error = git_attr_cache__get(&file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, + base, filename, parse_ignore_file, false); if (error < 0) return error; @@ -274,12 +268,12 @@ if ((error = git_attr_cache__init(repo)) < 0) return error; - error = git_attr_cache__get( - out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, GIT_IGNORE_INTERNAL, NULL); + error = git_attr_cache__get(out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, + GIT_IGNORE_INTERNAL, NULL, false); /* if internal rules list is empty, insert default rules */ if (!error && !(*out)->rules.length) - error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES); + error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES, false); return error; } @@ -299,8 +293,8 @@ ignores->repo = repo; /* Read the ignore_case flag */ - if ((error = git_repository__cvar( - &ignores->ignore_case, repo, GIT_CVAR_IGNORECASE)) < 0) + if ((error = git_repository__configmap_lookup( + &ignores->ignore_case, repo, GIT_CONFIGMAP_IGNORECASE)) < 0) goto cleanup; if ((error = git_attr_cache__init(repo)) < 0) @@ -337,16 +331,13 @@ goto cleanup; } - if ((error = git_repository_item_path(&infopath, - repo, GIT_REPOSITORY_ITEM_INFO)) < 0) - goto cleanup; - - /* load .git/info/exclude */ - error = push_ignore_file( - ignores, &ignores->ign_global, - infopath.ptr, GIT_IGNORE_FILE_INREPO); - if (error < 0) - goto cleanup; + /* load .git/info/exclude if possible */ + if ((error = git_repository_item_path(&infopath, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || + (error = push_ignore_file(ignores, &ignores->ign_global, infopath.ptr, GIT_IGNORE_FILE_INREPO)) < 0) { + if (error != GIT_ENOTFOUND) + goto cleanup; + error = 0; + } /* load core.excludesfile */ if (git_repository_attr_cache(repo)->cfg_excl_file != NULL) @@ -495,7 +486,7 @@ if ((error = get_internal_ignores(&ign_internal, repo)) < 0) return error; - error = parse_ignore_file(repo, ign_internal, rules); + error = parse_ignore_file(repo, ign_internal, rules, false); git_attr_file__free(ign_internal); return error; @@ -511,7 +502,7 @@ if (!(error = git_attr_file__clear_rules(ign_internal, true))) error = parse_ignore_file( - repo, ign_internal, GIT_IGNORE_DEFAULT_RULES); + repo, ign_internal, GIT_IGNORE_DEFAULT_RULES, false); git_attr_file__free(ign_internal); return error; diff -Nru libgit2-0.28.5+dfsg.1/src/index.c libgit2-1.1.0+dfsg.1/src/index.c --- libgit2-0.28.5+dfsg.1/src/index.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/index.c 2020-10-12 18:53:06.000000000 +0000 @@ -27,29 +27,6 @@ #include "git2/config.h" #include "git2/sys/index.h" -#define INSERT_IN_MAP_EX(idx, map, e, err) do { \ - if ((idx)->ignore_case) \ - git_idxmap_icase_insert((git_idxmap_icase *) (map), (e), (e), (err)); \ - else \ - git_idxmap_insert((map), (e), (e), (err)); \ - } while (0) - -#define INSERT_IN_MAP(idx, e, err) INSERT_IN_MAP_EX(idx, (idx)->entries_map, e, err) - -#define LOOKUP_IN_MAP(p, idx, k) do { \ - if ((idx)->ignore_case) \ - (p) = git_idxmap_icase_lookup_index((git_idxmap_icase *) index->entries_map, (k)); \ - else \ - (p) = git_idxmap_lookup_index(index->entries_map, (k)); \ - } while (0) - -#define DELETE_IN_MAP(idx, e) do { \ - if ((idx)->ignore_case) \ - git_idxmap_icase_delete((git_idxmap_icase *) (idx)->entries_map, (e)); \ - else \ - git_idxmap_delete((idx)->entries_map, (e)); \ - } while (0) - static int index_apply_to_wd_diff(git_index *index, int action, const git_strarray *paths, unsigned int flags, git_index_matched_path_cb cb, void *payload); @@ -148,6 +125,30 @@ static void index_entry_free(git_index_entry *entry); static void index_entry_reuc_free(git_index_reuc_entry *reuc); +GIT_INLINE(int) index_map_set(git_idxmap *map, git_index_entry *e, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_set((git_idxmap_icase *) map, e, e); + else + return git_idxmap_set(map, e, e); +} + +GIT_INLINE(int) index_map_delete(git_idxmap *map, git_index_entry *e, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_delete((git_idxmap_icase *) map, e); + else + return git_idxmap_delete(map, e); +} + +GIT_INLINE(int) index_map_resize(git_idxmap *map, size_t count, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_resize((git_idxmap_icase *) map, count); + else + return git_idxmap_resize(map, count); +} + int git_index_entry_srch(const void *key, const void *array_member) { const struct entry_srch_key *srch_key = key; @@ -410,7 +411,8 @@ index = git__calloc(1, sizeof(git_index)); GIT_ERROR_CHECK_ALLOC(index); - git_pool_init(&index->tree_pool, 1); + if (git_pool_init(&index->tree_pool, 1) < 0) + goto fail; if (index_path != NULL) { index->index_file_path = git__strdup(index_path); @@ -423,10 +425,10 @@ } if (git_vector_init(&index->entries, 32, git_index_entry_cmp) < 0 || - git_idxmap_alloc(&index->entries_map) < 0 || - git_vector_init(&index->names, 8, conflict_name_cmp) < 0 || - git_vector_init(&index->reuc, 8, reuc_cmp) < 0 || - git_vector_init(&index->deleted, 8, git_index_entry_cmp) < 0) + git_idxmap_new(&index->entries_map) < 0 || + git_vector_init(&index->names, 8, conflict_name_cmp) < 0 || + git_vector_init(&index->reuc, 8, reuc_cmp) < 0 || + git_vector_init(&index->deleted, 8, git_index_entry_cmp) < 0) goto fail; index->entries_cmp_path = git__strcmp_cb; @@ -507,7 +509,7 @@ if (entry != NULL) { git_tree_cache_invalidate_path(index->tree, entry->path); - DELETE_IN_MAP(index, entry); + index_map_delete(index->entries_map, entry, index->ignore_case); } error = git_vector_remove(&index->entries, pos); @@ -538,13 +540,19 @@ git_idxmap_clear(index->entries_map); while (!error && index->entries.length > 0) error = index_remove_entry(index, index->entries.length - 1); + + if (error) + goto done; + index_free_deleted(index); - git_index_reuc_clear(index); - git_index_name_clear(index); + if ((error = git_index_name_clear(index)) < 0 || + (error = git_index_reuc_clear(index)) < 0) + goto done; git_futils_filestamp_set(&index->stamp, NULL); +done: return error; } @@ -570,11 +578,11 @@ return create_index_error( -1, "cannot access repository to set index caps"); - if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORECASE)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_IGNORECASE)) index->ignore_case = (val != 0); - if (!git_repository__cvar(&val, repo, GIT_CVAR_FILEMODE)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_FILEMODE)) index->distrust_filemode = (val == 0); - if (!git_repository__cvar(&val, repo, GIT_CVAR_SYMLINKS)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_SYMLINKS)) index->no_symlinks = (val == 0); } else { @@ -852,20 +860,24 @@ git_index *index, const char *path, int stage) { git_index_entry key = {{ 0 }}; - size_t pos; + git_index_entry *value; assert(index); key.path = path; GIT_INDEX_ENTRY_STAGE_SET(&key, stage); - LOOKUP_IN_MAP(pos, index, &key); + if (index->ignore_case) + value = git_idxmap_icase_get((git_idxmap_icase *) index->entries_map, &key); + else + value = git_idxmap_get(index->entries_map, &key); - if (git_idxmap_valid_index(index->entries_map, pos)) - return git_idxmap_value_at(index->entries_map, pos); + if (!value) { + git_error_set(GIT_ERROR_INDEX, "index does not contain '%s'", path); + return NULL; + } - git_error_set(GIT_ERROR_INDEX, "index does not contain '%s'", path); - return NULL; + return value; } void git_index_entry__init_from_stat( @@ -1398,10 +1410,9 @@ * at the sorted position. (Since we re-sort after each insert to * check for dups, this is actually cheaper in the long run.) */ - if ((error = git_vector_insert_sorted(&index->entries, entry, index_no_dups)) < 0) + if ((error = git_vector_insert_sorted(&index->entries, entry, index_no_dups)) < 0 || + (error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) goto out; - - INSERT_IN_MAP(index, entry, &error); } index->dirty = 1; @@ -1453,7 +1464,7 @@ return (is_file_or_link(filemode) || filemode == GIT_FILEMODE_COMMIT); } -int git_index_add_frombuffer( +int git_index_add_from_buffer( git_index *index, const git_index_entry *source_entry, const void *buffer, size_t len) { @@ -1473,17 +1484,22 @@ return -1; } + if (len > UINT32_MAX) { + git_error_set(GIT_ERROR_INDEX, "buffer is too large"); + return -1; + } + if (index_entry_dup(&entry, index, source_entry) < 0) return -1; - error = git_blob_create_frombuffer(&id, INDEX_OWNER(index), buffer, len); + error = git_blob_create_from_buffer(&id, INDEX_OWNER(index), buffer, len); if (error < 0) { index_entry_free(entry); return error; } git_oid_cpy(&entry->id, &id); - entry->file_size = len; + entry->file_size = (uint32_t)len; if ((error = index_insert(index, &entry, 1, true, true, true)) < 0) return error; @@ -1610,41 +1626,42 @@ int git_index__fill(git_index *index, const git_vector *source_entries) { const git_index_entry *source_entry = NULL; + int error = 0; size_t i; - int ret = 0; assert(index); if (!source_entries->length) return 0; - git_vector_size_hint(&index->entries, source_entries->length); - git_idxmap_resize(index->entries_map, (size_t)(source_entries->length * 1.3)); + if (git_vector_size_hint(&index->entries, source_entries->length) < 0 || + index_map_resize(index->entries_map, (size_t)(source_entries->length * 1.3), + index->ignore_case) < 0) + return -1; git_vector_foreach(source_entries, i, source_entry) { git_index_entry *entry = NULL; - if ((ret = index_entry_dup(&entry, index, source_entry)) < 0) + if ((error = index_entry_dup(&entry, index, source_entry)) < 0) break; index_entry_adjust_namemask(entry, ((struct entry_internal *)entry)->pathlen); entry->flags_extended |= GIT_INDEX_ENTRY_UPTODATE; entry->mode = git_index__create_mode(entry->mode); - if ((ret = git_vector_insert(&index->entries, entry)) < 0) + if ((error = git_vector_insert(&index->entries, entry)) < 0) break; - INSERT_IN_MAP(index, entry, &ret); - if (ret < 0) + if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) break; index->dirty = 1; } - if (!ret) + if (!error) git_vector_sort(&index->entries); - return ret; + return error; } @@ -1677,7 +1694,7 @@ remove_key.path = path; GIT_INDEX_ENTRY_STAGE_SET(&remove_key, stage); - DELETE_IN_MAP(index, &remove_key); + index_map_delete(index->entries_map, &remove_key, index->ignore_case); if (index_find(&position, index, path, 0, stage) < 0) { git_error_set( @@ -2126,7 +2143,7 @@ return 0; } -void git_index_name_clear(git_index *index) +int git_index_name_clear(git_index *index) { size_t i; git_index_name_entry *conflict_name; @@ -2139,6 +2156,8 @@ git_vector_clear(&index->names); index->dirty = 1; + + return 0; } size_t git_index_reuc_entrycount(git_index *index) @@ -2235,7 +2254,7 @@ return error; } -void git_index_reuc_clear(git_index *index) +int git_index_reuc_clear(git_index *index) { size_t i; @@ -2247,6 +2266,8 @@ git_vector_clear(&index->reuc); index->dirty = 1; + + return 0; } static int index_error_invalid(const char *message) @@ -2607,10 +2628,8 @@ assert(!index->entries.length); - if (index->ignore_case) - git_idxmap_icase_resize((git_idxmap_icase *) index->entries_map, header.entry_count); - else - git_idxmap_resize(index->entries_map, header.entry_count); + if ((error = index_map_resize(index->entries_map, header.entry_count, index->ignore_case)) < 0) + return error; /* Parse all the entries */ for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) { @@ -2627,9 +2646,7 @@ goto done; } - INSERT_IN_MAP(index, entry, &error); - - if (error < 0) { + if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) { index_entry_free(entry); goto done; } @@ -2728,7 +2745,7 @@ ++same_len; } path_len -= same_len; - varint_len = git_encode_varint(NULL, 0, same_len); + varint_len = git_encode_varint(NULL, 0, strlen(last) - same_len); } disk_size = index_entry_size(path_len, varint_len, entry->flags); @@ -2764,22 +2781,24 @@ ondisk.flags = htons(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 & GIT_INDEX_ENTRY_EXTENDED_FLAGS); - memcpy(mem, &ondisk_ext, offsetof(struct entry_long, path)); - path = ((struct entry_long*)mem)->path; - disk_size -= offsetof(struct entry_long, path); + memcpy(mem, &ondisk_ext, path_offset); + path = (char *)mem + path_offset; + disk_size -= path_offset; } else { - memcpy(mem, &ondisk, offsetof(struct entry_short, path)); - path = ((struct entry_short*)mem)->path; - disk_size -= offsetof(struct entry_short, path); + const size_t path_offset = offsetof(struct entry_short, path); + memcpy(mem, &ondisk, path_offset); + path = (char *)mem + path_offset; + disk_size -= path_offset; } if (last) { varint_len = git_encode_varint((unsigned char *) path, - disk_size, same_len); + disk_size, strlen(last) - same_len); assert(varint_len > 0); path += varint_len; disk_size -= varint_len; @@ -3106,7 +3125,7 @@ size_t i; git_index_entry *e; - if (git_idxmap_alloc(&entries_map) < 0) + if (git_idxmap_new(&entries_map) < 0) return -1; git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */ @@ -3124,15 +3143,11 @@ if ((error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data)) < 0) goto cleanup; - if (index->ignore_case) - git_idxmap_icase_resize((git_idxmap_icase *) entries_map, entries.length); - else - git_idxmap_resize(entries_map, entries.length); + if ((error = index_map_resize(entries_map, entries.length, index->ignore_case)) < 0) + goto cleanup; git_vector_foreach(&entries, i, e) { - INSERT_IN_MAP_EX(index, entries_map, e, &error); - - if (error < 0) { + if ((error = index_map_set(entries_map, e, index->ignore_case)) < 0) { git_error_set(GIT_ERROR_INDEX, "failed to insert entry into map"); return error; } @@ -3180,14 +3195,13 @@ assert((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE)); if ((error = git_vector_init(&new_entries, new_length_hint, index->entries._cmp)) < 0 || - (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 || - (error = git_idxmap_alloc(&new_entries_map)) < 0) + (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 || + (error = git_idxmap_new(&new_entries_map)) < 0) goto done; - if (index->ignore_case && new_length_hint) - git_idxmap_icase_resize((git_idxmap_icase *) new_entries_map, new_length_hint); - else if (new_length_hint) - git_idxmap_resize(new_entries_map, new_length_hint); + if (new_length_hint && (error = index_map_resize(new_entries_map, new_length_hint, + index->ignore_case)) < 0) + goto done; opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_INCLUDE_CONFLICTS; @@ -3251,7 +3265,8 @@ if (add_entry) { if ((error = git_vector_insert(&new_entries, add_entry)) == 0) - INSERT_IN_MAP_EX(index, new_entries_map, add_entry, &error); + error = index_map_set(new_entries_map, add_entry, + index->ignore_case); } if (remove_entry && error >= 0) @@ -3275,8 +3290,9 @@ } } - git_index_name_clear(index); - git_index_reuc_clear(index); + if ((error = git_index_name_clear(index)) < 0 || + (error = git_index_reuc_clear(index)) < 0) + goto done; git_vector_swap(&new_entries, &index->entries); new_entries_map = git__swap(index->entries_map, new_entries_map); @@ -3700,3 +3716,14 @@ git_index_free(writer->index); writer->index = NULL; } + +/* Deprecated functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_index_add_frombuffer( + git_index *index, const git_index_entry *source_entry, + const void *buffer, size_t len) +{ + return git_index_add_from_buffer(index, source_entry, buffer, len); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/indexer.c libgit2-1.1.0+dfsg.1/src/indexer.c --- libgit2-0.28.5+dfsg.1/src/indexer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/indexer.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,6 +19,7 @@ #include "pack.h" #include "filebuf.h" #include "oid.h" +#include "oidarray.h" #include "oidmap.h" #include "zstream.h" #include "object.h" @@ -46,8 +47,8 @@ struct git_pack_header hdr; struct git_pack_file *pack; unsigned int mode; - git_off_t off; - git_off_t entry_start; + off64_t off; + off64_t entry_start; git_object_t entry_type; git_buf entry_data; git_packfile_stream stream; @@ -57,7 +58,7 @@ unsigned int fanout[256]; git_hash_ctx hash_ctx; git_oid hash; - git_transfer_progress_cb progress_cb; + git_indexer_progress_cb progress_cb; void *progress_payload; char objbuf[8*1024]; @@ -74,7 +75,7 @@ }; struct delta_info { - git_off_t delta_off; + off64_t delta_off; }; const git_oid *git_indexer_hash(const git_indexer *idx) @@ -115,13 +116,20 @@ return git_oid__cmp(&entrya->oid, &entryb->oid); } -int git_indexer_init_options(git_indexer_options *opts, unsigned int version) +int git_indexer_options_init(git_indexer_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_indexer_options, GIT_INDEXER_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_indexer_init_options(git_indexer_options *opts, unsigned int version) +{ + return git_indexer_options_init(opts, version); +} +#endif + int git_indexer_new( git_indexer **out, const char *prefix, @@ -144,11 +152,12 @@ idx->progress_cb = opts.progress_cb; idx->progress_payload = opts.progress_cb_payload; idx->mode = mode ? mode : GIT_PACK_FILE_MODE; - git_hash_ctx_init(&idx->hash_ctx); - git_hash_ctx_init(&idx->trailer); git_buf_init(&idx->entry_data, 0); - idx->expected_oids = git_oidmap_alloc(); - GIT_ERROR_CHECK_ALLOC(idx->expected_oids); + + if ((error = git_hash_ctx_init(&idx->hash_ctx)) < 0 || + (error = git_hash_ctx_init(&idx->trailer)) < 0 || + (error = git_oidmap_new(&idx->expected_oids)) < 0) + goto cleanup; idx->do_verify = opts.verify; @@ -213,7 +222,7 @@ return 0; } -static int hash_header(git_hash_ctx *ctx, git_off_t len, git_object_t type) +static int hash_header(git_hash_ctx *ctx, off64_t len, git_object_t type) { char buffer[64]; size_t hdrlen; @@ -258,10 +267,11 @@ if (type == GIT_OBJECT_REF_DELTA) { idx->off += GIT_OID_RAWSZ; } else { - git_off_t base_off = get_delta_base(idx->pack, &w, &idx->off, type, idx->entry_start); + off64_t base_off; + int error = get_delta_base(&base_off, idx->pack, &w, &idx->off, type, idx->entry_start); git_mwindow_close(&w); - if (base_off < 0) - return (int)base_off; + if (error < 0) + return error; } return 0; @@ -284,7 +294,7 @@ return 0; } -static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start, git_off_t size) +static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, off64_t start, off64_t size) { void *ptr; uint32_t crc; @@ -308,10 +318,8 @@ return 0; } -static void add_expected_oid(git_indexer *idx, const git_oid *oid) +static int add_expected_oid(git_indexer *idx, const git_oid *oid) { - int ret; - /* * If we know about that object because it is stored in our ODB or * because we have already processed it as part of our pack file, we do @@ -321,15 +329,18 @@ !git_oidmap_exists(idx->pack->idx_cache, oid) && !git_oidmap_exists(idx->expected_oids, oid)) { git_oid *dup = git__malloc(sizeof(*oid)); + GIT_ERROR_CHECK_ALLOC(dup); git_oid_cpy(dup, oid); - git_oidmap_put(idx->expected_oids, dup, &ret); + return git_oidmap_set(idx->expected_oids, dup, dup); } + + return 0; } static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj) { git_object *object; - size_t keyidx; + git_oid *expected; int error; if (obj->type != GIT_OBJECT_BLOB && @@ -341,11 +352,9 @@ if ((error = git_object__from_raw(&object, obj->data, obj->len, obj->type)) < 0) goto out; - keyidx = git_oidmap_lookup_index(idx->expected_oids, &object->cached.oid); - if (git_oidmap_valid_index(idx->expected_oids, keyidx)) { - const git_oid *key = git_oidmap_key(idx->expected_oids, keyidx); - git__free((git_oid *) key); - git_oidmap_delete_at(idx->expected_oids, keyidx); + if ((expected = git_oidmap_get(idx->expected_oids, &object->cached.oid)) != NULL) { + git_oidmap_delete(idx->expected_oids, &object->cached.oid); + git__free(expected); } /* @@ -363,7 +372,8 @@ size_t i; git_array_foreach(tree->entries, i, entry) - add_expected_oid(idx, entry->oid); + if (add_expected_oid(idx, entry->oid) < 0) + goto out; break; } @@ -374,9 +384,11 @@ size_t i; git_array_foreach(commit->parent_ids, i, parent_oid) - add_expected_oid(idx, parent_oid); + if (add_expected_oid(idx, parent_oid) < 0) + goto out; - add_expected_oid(idx, &commit->tree_id); + if (add_expected_oid(idx, &commit->tree_id) < 0) + goto out; break; } @@ -384,7 +396,8 @@ { git_tag *tag = (git_tag *) object; - add_expected_oid(idx, &tag->target); + if (add_expected_oid(idx, &tag->target) < 0) + goto out; break; } @@ -402,12 +415,11 @@ static int store_object(git_indexer *idx) { int i, error; - size_t k; git_oid oid; struct entry *entry; - git_off_t entry_size; + off64_t entry_size; struct git_pack_entry *pentry; - git_off_t entry_start = idx->entry_start; + off64_t entry_start = idx->entry_start; entry = git__calloc(1, sizeof(*entry)); GIT_ERROR_CHECK_ALLOC(entry); @@ -415,7 +427,10 @@ pentry = git__calloc(1, sizeof(struct git_pack_entry)); GIT_ERROR_CHECK_ALLOC(pentry); - git_hash_final(&oid, &idx->hash_ctx); + if (git_hash_final(&oid, &idx->hash_ctx)) { + git__free(pentry); + goto on_error; + } entry_size = idx->off - entry_start; if (entry_start > UINT31_MAX) { entry->offset = UINT32_MAX; @@ -438,22 +453,18 @@ git_oid_cpy(&pentry->sha1, &oid); pentry->offset = entry_start; - k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error); - if (error == -1) { + if (git_oidmap_exists(idx->pack->idx_cache, &pentry->sha1)) { + git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->sha1)); git__free(pentry); - git_error_set_oom(); goto on_error; } - if (error == 0) { - git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->sha1)); + if ((error = git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry)) < 0) { git__free(pentry); + git_error_set_oom(); goto on_error; } - - git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry); - git_oid_cpy(&entry->oid, &oid); if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0) @@ -480,10 +491,9 @@ return git_oidmap_exists(idx->pack->idx_cache, id); } -static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start) +static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, off64_t entry_start) { - int i, error; - size_t k; + int i; if (entry_start > UINT31_MAX) { entry->offset = UINT32_MAX; @@ -493,15 +503,13 @@ } pentry->offset = entry_start; - k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error); - if (error <= 0) { + if (git_oidmap_exists(idx->pack->idx_cache, &pentry->sha1) || + git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry) < 0) { git_error_set(GIT_ERROR_INDEXER, "cannot insert object into pack"); return -1; } - git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry); - /* Add the object to the list */ if (git_vector_insert(&idx->objects, entry) < 0) return -1; @@ -513,7 +521,7 @@ return 0; } -static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_start) +static int hash_and_save(git_indexer *idx, git_rawobj *obj, off64_t entry_start) { git_oid oid; size_t entry_size; @@ -548,7 +556,7 @@ return -1; } -static int do_progress_callback(git_indexer *idx, git_transfer_progress *stats) +static int do_progress_callback(git_indexer *idx, git_indexer_progress *stats) { if (idx->progress_cb) return git_error_set_after_callback_function( @@ -594,12 +602,12 @@ idx->inbuf_len += size - to_expell; } -static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size) +static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size) { git_file fd = idx->pack->mwf.fd; size_t mmap_alignment; size_t page_offset; - git_off_t page_start; + off64_t page_start; unsigned char *map_data; git_map map; int error; @@ -625,11 +633,11 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size) { - git_off_t new_size; + off64_t new_size; size_t mmap_alignment; size_t page_offset; - git_off_t page_start; - git_off_t current_size = idx->pack->mwf.size; + off64_t page_start; + off64_t current_size = idx->pack->mwf.size; int fd = idx->pack->mwf.fd; int error; @@ -656,10 +664,10 @@ return write_at(idx, data, idx->pack->mwf.size, size); } -static int read_stream_object(git_indexer *idx, git_transfer_progress *stats) +static int read_stream_object(git_indexer *idx, git_indexer_progress *stats) { git_packfile_stream *stream = &idx->stream; - git_off_t entry_start = idx->off; + off64_t entry_start = idx->off; size_t entry_size; git_object_t type; git_mwindow *w = NULL; @@ -745,7 +753,7 @@ return 0; } -int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats) +int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_indexer_progress *stats) { int error = -1; struct git_pack_header *hdr = &idx->hdr; @@ -781,8 +789,8 @@ return -1; } - idx->pack->idx_cache = git_oidmap_alloc(); - GIT_ERROR_CHECK_ALLOC(idx->pack->idx_cache); + if (git_oidmap_new(&idx->pack->idx_cache) < 0) + return -1; idx->pack->has_cache = 1; if (git_vector_init(&idx->objects, total_objects, objects_cmp) < 0) @@ -863,7 +871,7 @@ git_oid foo = {{0}}; unsigned char hdr[64]; git_buf buf = GIT_BUF_INIT; - git_off_t entry_start; + off64_t entry_start; const void *data; size_t len, hdr_len; int error; @@ -929,7 +937,7 @@ return error; } -static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats) +static int fix_thin_pack(git_indexer *idx, git_indexer_progress *stats) { int error, found_ref_delta = 0; unsigned int i; @@ -937,7 +945,7 @@ size_t size; git_object_t type; git_mwindow *w = NULL; - git_off_t curpos = 0; + off64_t curpos = 0; unsigned char *base_info; unsigned int left = 0; git_oid base; @@ -991,7 +999,7 @@ return 0; } -static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats) +static int resolve_deltas(git_indexer *idx, git_indexer_progress *stats) { unsigned int i; int error; @@ -1048,11 +1056,11 @@ return 0; } -static int update_header_and_rehash(git_indexer *idx, git_transfer_progress *stats) +static int update_header_and_rehash(git_indexer *idx, git_indexer_progress *stats) { void *ptr; size_t chunk = 1024*1024; - git_off_t hashed = 0; + off64_t hashed = 0; git_mwindow *w = NULL; git_mwindow_file *mwf; unsigned int left; @@ -1089,7 +1097,7 @@ return 0; } -int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) +int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats) { git_mwindow *w = NULL; unsigned int i, long_offsets = 0, left; @@ -1292,7 +1300,9 @@ void git_indexer_free(git_indexer *idx) { - size_t pos; + const git_oid *key; + git_oid *value; + size_t iter; if (idx == NULL) return; @@ -1321,14 +1331,9 @@ git_mutex_unlock(&git__mwindow_mutex); } - for (pos = git_oidmap_begin(idx->expected_oids); - pos != git_oidmap_end(idx->expected_oids); pos++) - { - if (git_oidmap_has_data(idx->expected_oids, pos)) { - git__free((git_oid *) git_oidmap_key(idx->expected_oids, pos)); - git_oidmap_delete_at(idx->expected_oids, pos); - } - } + iter = 0; + while (git_oidmap_iterate((void **) &value, idx->expected_oids, &iter, &key) == 0) + git__free(value); git_hash_ctx_cleanup(&idx->trailer); git_hash_ctx_cleanup(&idx->hash_ctx); diff -Nru libgit2-0.28.5+dfsg.1/src/index.h libgit2-1.1.0+dfsg.1/src/index.h --- libgit2-0.28.5+dfsg.1/src/index.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/index.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ #include "common.h" -#include "fileops.h" +#include "futils.h" #include "filebuf.h" #include "vector.h" #include "idxmap.h" diff -Nru libgit2-0.28.5+dfsg.1/src/integer.h libgit2-1.1.0+dfsg.1/src/integer.h --- libgit2-0.28.5+dfsg.1/src/integer.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/integer.h 2020-10-12 18:53:06.000000000 +0000 @@ -8,10 +8,10 @@ #define INCLUDE_integer_h__ /** @return true if p fits into the range of a size_t */ -GIT_INLINE(int) git__is_sizet(git_off_t p) +GIT_INLINE(int) git__is_sizet(int64_t p) { size_t r = (size_t)p; - return p == (git_off_t)r; + return p == (int64_t)r; } /** @return true if p fits into the range of an ssize_t */ @@ -21,6 +21,13 @@ return p == (size_t)r; } +/** @return true if p fits into the range of a uint16_t */ +GIT_INLINE(int) git__is_uint16(size_t p) +{ + uint16_t r = (uint16_t)p; + return p == (size_t)r; +} + /** @return true if p fits into the range of a uint32_t */ GIT_INLINE(int) git__is_uint32(size_t p) { @@ -29,10 +36,10 @@ } /** @return true if p fits into the range of an unsigned long */ -GIT_INLINE(int) git__is_ulong(git_off_t p) +GIT_INLINE(int) git__is_ulong(int64_t p) { unsigned long r = (unsigned long)p; - return p == (git_off_t)r; + return p == (int64_t)r; } /** @return true if p fits into the range of an int */ diff -Nru libgit2-0.28.5+dfsg.1/src/iterator.c libgit2-1.1.0+dfsg.1/src/iterator.c --- libgit2-0.28.5+dfsg.1/src/iterator.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/iterator.c 2020-10-12 18:53:06.000000000 +0000 @@ -145,7 +145,7 @@ (iter->flags & GIT_ITERATOR_PRECOMPOSE_UNICODE) == 0 && (iter->flags & GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE) == 0) { - if (git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) < 0) + if (git_repository__configmap_lookup(&precompose, repo, GIT_CONFIGMAP_PRECOMPOSE) < 0) git_error_clear(); else if (precompose) iter->flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; @@ -405,7 +405,7 @@ iter = git__calloc(1, sizeof(empty_iterator)); GIT_ERROR_CHECK_ALLOC(iter); - iter->base.type = GIT_ITERATOR_TYPE_EMPTY; + iter->base.type = GIT_ITERATOR_EMPTY; iter->base.cb = &callbacks; iter->base.flags = options->flags; @@ -897,9 +897,8 @@ { int error; - git_pool_init(&iter->entry_pool, sizeof(tree_iterator_entry)); - - if ((error = tree_iterator_frame_init(iter, iter->root, NULL)) < 0) + if ((error = git_pool_init(&iter->entry_pool, sizeof(tree_iterator_entry))) < 0 || + (error = tree_iterator_frame_init(iter, iter->root, NULL)) < 0) return error; iter->base.flags &= ~GIT_ITERATOR_FIRST_ACCESS; @@ -950,7 +949,7 @@ iter = git__calloc(1, sizeof(tree_iterator)); GIT_ERROR_CHECK_ALLOC(iter); - iter->base.type = GIT_ITERATOR_TYPE_TREE; + iter->base.type = GIT_ITERATOR_TREE; iter->base.cb = &callbacks; if ((error = iterator_init_common(&iter->base, @@ -974,7 +973,7 @@ tree_iterator_frame *frame; tree_iterator_entry *entry; - assert(i->type == GIT_ITERATOR_TYPE_TREE); + assert(i->type == GIT_ITERATOR_TREE); iter = (tree_iterator *)i; @@ -991,7 +990,7 @@ tree_iterator *iter; tree_iterator_frame *frame; - assert(i->type == GIT_ITERATOR_TYPE_TREE); + assert(i->type == GIT_ITERATOR_TREE); iter = (tree_iterator *)i; @@ -1271,7 +1270,7 @@ return 0; } - if (iter->base.type == GIT_ITERATOR_TYPE_WORKDIR) + if (iter->base.type == GIT_ITERATOR_WORKDIR) return git_repository_hashfile(&entry->id, iter->base.repo, entry->path, GIT_OBJECT_BLOB, NULL); @@ -1376,7 +1375,8 @@ filesystem_iterator_entry_cmp)) < 0) goto done; - git_pool_init(&new_frame->entry_pool, 1); + if ((error = git_pool_init(&new_frame->entry_pool, 1)) < 0) + goto done; /* check if this directory is ignored */ filesystem_iterator_frame_push_ignores(iter, frame_entry, new_frame); @@ -1522,7 +1522,7 @@ static int filesystem_iterator_current( const git_index_entry **out, git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); if (!iterator__has_been_accessed(i)) return iter->base.cb->advance(out, i); @@ -1569,7 +1569,7 @@ static int filesystem_iterator_advance( const git_index_entry **out, git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); bool is_dir; int error = 0; @@ -1628,7 +1628,7 @@ static int filesystem_iterator_advance_into( const git_index_entry **out, git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); filesystem_iterator_frame *frame; filesystem_iterator_entry *prev_entry; int error; @@ -1665,11 +1665,11 @@ int git_iterator_current_workdir_path(git_buf **out, git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); const git_index_entry *entry; - if (i->type != GIT_ITERATOR_TYPE_FS && - i->type != GIT_ITERATOR_TYPE_WORKDIR) { + if (i->type != GIT_ITERATOR_FS && + i->type != GIT_ITERATOR_WORKDIR) { *out = NULL; return 0; } @@ -1725,18 +1725,22 @@ bool git_iterator_current_is_ignored(git_iterator *i) { - if (i->type != GIT_ITERATOR_TYPE_WORKDIR) + filesystem_iterator *iter = NULL; + + if (i->type != GIT_ITERATOR_WORKDIR) return false; - return filesystem_iterator_current_is_ignored((filesystem_iterator *)i); + iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); + + return filesystem_iterator_current_is_ignored(iter); } bool git_iterator_current_tree_is_ignored(git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); filesystem_iterator_frame *frame; - if (i->type != GIT_ITERATOR_TYPE_WORKDIR) + if (i->type != GIT_ITERATOR_WORKDIR) return false; frame = filesystem_iterator_current_frame(iter); @@ -1748,7 +1752,7 @@ git_iterator_status_t *status, git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); filesystem_iterator_frame *current_frame; filesystem_iterator_entry *current_entry; const git_index_entry *entry = NULL; @@ -1867,7 +1871,7 @@ static int filesystem_iterator_reset(git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); filesystem_iterator_clear(iter); return filesystem_iterator_init(iter); @@ -1875,7 +1879,7 @@ static void filesystem_iterator_free(git_iterator *i) { - filesystem_iterator *iter = (filesystem_iterator *)i; + filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base); git__free(iter->root); git_buf_dispose(&iter->current_path); git_tree_free(iter->tree); @@ -1890,7 +1894,7 @@ const char *root, git_index *index, git_tree *tree, - git_iterator_type_t type, + git_iterator_t type, git_iterator_options *options) { filesystem_iterator *iter; @@ -1967,7 +1971,7 @@ git_iterator_options *options) { return iterator_for_filesystem(out, - NULL, root, NULL, NULL, GIT_ITERATOR_TYPE_FS, options); + NULL, root, NULL, NULL, GIT_ITERATOR_FS, options); } int git_iterator_for_workdir_ext( @@ -1995,7 +1999,7 @@ GIT_ITERATOR_IGNORE_DOT_GIT; return iterator_for_filesystem(out, - repo, repo_workdir, index, tree, GIT_ITERATOR_TYPE_WORKDIR, &options); + repo, repo_workdir, index, tree, GIT_ITERATOR_WORKDIR, &options); } @@ -2084,7 +2088,7 @@ static int index_iterator_advance( const git_index_entry **out, git_iterator *i) { - index_iterator *iter = (index_iterator *)i; + index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base); const git_index_entry *entry = NULL; bool is_submodule; int error = 0; @@ -2157,7 +2161,7 @@ static int index_iterator_advance_into( const git_index_entry **out, git_iterator *i) { - index_iterator *iter = (index_iterator *)i; + index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base); if (! S_ISDIR(iter->tree_entry.mode)) { if (out) @@ -2175,7 +2179,7 @@ git_iterator_status_t *status, git_iterator *i) { - index_iterator *iter = (index_iterator *)i; + index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base); const git_index_entry *entry; int error; @@ -2204,7 +2208,7 @@ static int index_iterator_reset(git_iterator *i) { - index_iterator *iter = (index_iterator *)i; + index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base); index_iterator_clear(iter); return index_iterator_init(iter); @@ -2212,7 +2216,7 @@ static void index_iterator_free(git_iterator *i) { - index_iterator *iter = (index_iterator *)i; + index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base); git_index_snapshot_release(&iter->entries, iter->base.index); git_buf_dispose(&iter->tree_buf); @@ -2244,7 +2248,7 @@ iter = git__calloc(1, sizeof(index_iterator)); GIT_ERROR_CHECK_ALLOC(iter); - iter->base.type = GIT_ITERATOR_TYPE_INDEX; + iter->base.type = GIT_ITERATOR_INDEX; iter->base.cb = &callbacks; if ((error = iterator_init_common(&iter->base, repo, index, options)) < 0 || diff -Nru libgit2-0.28.5+dfsg.1/src/iterator.h libgit2-1.1.0+dfsg.1/src/iterator.h --- libgit2-0.28.5+dfsg.1/src/iterator.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/iterator.h 2020-10-12 18:53:06.000000000 +0000 @@ -17,12 +17,12 @@ typedef struct git_iterator git_iterator; typedef enum { - GIT_ITERATOR_TYPE_EMPTY = 0, - GIT_ITERATOR_TYPE_TREE = 1, - GIT_ITERATOR_TYPE_INDEX = 2, - GIT_ITERATOR_TYPE_WORKDIR = 3, - GIT_ITERATOR_TYPE_FS = 4, -} git_iterator_type_t; + GIT_ITERATOR_EMPTY = 0, + GIT_ITERATOR_TREE = 1, + GIT_ITERATOR_INDEX = 2, + GIT_ITERATOR_WORKDIR = 3, + GIT_ITERATOR_FS = 4, +} git_iterator_t; typedef enum { /** ignore case for entry sort order */ @@ -78,7 +78,7 @@ } git_iterator_callbacks; struct git_iterator { - git_iterator_type_t type; + git_iterator_t type; git_iterator_callbacks *cb; git_repository *repo; @@ -238,7 +238,7 @@ extern int git_iterator_reset_range( git_iterator *iter, const char *start, const char *end); -GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter) +GIT_INLINE(git_iterator_t) git_iterator_type(git_iterator *iter) { return iter->type; } diff -Nru libgit2-0.28.5+dfsg.1/src/map.h libgit2-1.1.0+dfsg.1/src/map.h --- libgit2-0.28.5+dfsg.1/src/map.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/map.h 2020-10-12 18:53:06.000000000 +0000 @@ -40,7 +40,7 @@ assert((prot & GIT_PROT_WRITE) || (prot & GIT_PROT_READ)); \ assert((flags & GIT_MAP_FIXED) == 0); } while (0) -extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset); +extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset); extern int p_munmap(git_map *map); #endif diff -Nru libgit2-0.28.5+dfsg.1/src/merge.c libgit2-1.1.0+dfsg.1/src/merge.c --- libgit2-0.28.5+dfsg.1/src/merge.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/merge.c 2020-10-12 18:53:06.000000000 +0000 @@ -68,9 +68,19 @@ git_merge_diff *prev_conflict; }; +/* + * This acts as a negative cache entry marker. In case we've tried to calculate + * similarity metrics for a given blob already but `git_hashsig` determined + * that it's too small in order to have a meaningful hash signature, we will + * insert the address of this marker instead of `NULL`. Like this, we can + * easily check whether we have checked a gien entry already and skip doing the + * calculation again and again. + */ +static int cache_invalid_marker; + /* Merge base computation */ -int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[]) +static int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[]) { git_revwalk *walk = NULL; git_vector list; @@ -310,46 +320,55 @@ return 0; } -static void clear_commit_marks_1(git_commit_list **plist, +static int clear_commit_marks_1(git_commit_list **plist, git_commit_list_node *commit, unsigned int mark) { while (commit) { unsigned int i; if (!(mark & commit->flags)) - return; + return 0; commit->flags &= ~mark; for (i = 1; i < commit->out_degree; i++) { git_commit_list_node *p = commit->parents[i]; - git_commit_list_insert(p, plist); + if (git_commit_list_insert(p, plist) == NULL) + return -1; } commit = commit->out_degree ? commit->parents[0] : NULL; } + + return 0; } -static void clear_commit_marks_many(git_vector *commits, unsigned int mark) +static int clear_commit_marks_many(git_vector *commits, unsigned int mark) { git_commit_list *list = NULL; git_commit_list_node *c; unsigned int i; git_vector_foreach(commits, i, c) { - git_commit_list_insert(c, &list); + if (git_commit_list_insert(c, &list) == NULL) + return -1; } while (list) - clear_commit_marks_1(&list, git_commit_list_pop(&list), mark); + if (clear_commit_marks_1(&list, git_commit_list_pop(&list), mark) < 0) + return -1; + return 0; } -static void clear_commit_marks(git_commit_list_node *commit, unsigned int mark) +static int clear_commit_marks(git_commit_list_node *commit, unsigned int mark) { git_commit_list *list = NULL; - git_commit_list_insert(commit, &list); + if (git_commit_list_insert(commit, &list) == NULL) + return -1; while (list) - clear_commit_marks_1(&list, git_commit_list_pop(&list), mark); + if (clear_commit_marks_1(&list, git_commit_list_pop(&list), mark) < 0) + return -1; + return 0; } static int paint_down_to_common( @@ -466,10 +485,11 @@ redundant[filled_index[j]] = 1; } - clear_commit_marks(commit, ALL_FLAGS); - clear_commit_marks_many(&work, ALL_FLAGS); - git_commit_list_free(&common); + + if ((error = clear_commit_marks(commit, ALL_FLAGS)) < 0 || + (error = clear_commit_marks_many(&work, ALL_FLAGS)) < 0) + goto done; } for (i = 0; i < commits->length; ++i) { @@ -531,10 +551,9 @@ while (result) git_vector_insert(&redundant, git_commit_list_pop(&result)); - clear_commit_marks(one, ALL_FLAGS); - clear_commit_marks_many(twos, ALL_FLAGS); - - if ((error = remove_redundant(walk, &redundant)) < 0) { + if ((error = clear_commit_marks(one, ALL_FLAGS)) < 0 || + (error = clear_commit_marks_many(twos, ALL_FLAGS)) < 0 || + (error = remove_redundant(walk, &redundant)) < 0) { git_vector_free(&redundant); return error; } @@ -867,7 +886,7 @@ git_oid_cpy(&result->id, &oid); result->mode = mode; - result->file_size = buf.size; + result->file_size = (uint32_t)buf.size; result->path = git_pool_strdup(&diff_list->pool, path); GIT_ERROR_CHECK_ALLOC(result->path); @@ -1015,9 +1034,12 @@ { git_blob *blob; git_diff_file diff_file = {{{0}}}; - git_off_t blobsize; + git_object_size_t blobsize; int error; + if (*out || *out == &cache_invalid_marker) + return 0; + *out = NULL; if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0) @@ -1038,6 +1060,8 @@ error = opts->metric->buffer_signature(out, &diff_file, git_blob_rawcontent(blob), (size_t)blobsize, opts->metric->payload); + if (error == GIT_EBUFS) + *out = &cache_invalid_marker; git_blob_free(blob); @@ -1060,18 +1084,16 @@ return 0; /* update signature cache if needed */ - if (!cache[a_idx] && (error = index_entry_similarity_calc(&cache[a_idx], repo, a, opts)) < 0) - return error; - if (!cache[b_idx] && (error = index_entry_similarity_calc(&cache[b_idx], repo, b, opts)) < 0) + if ((error = index_entry_similarity_calc(&cache[a_idx], repo, a, opts)) < 0 || + (error = index_entry_similarity_calc(&cache[b_idx], repo, b, opts)) < 0) return error; /* some metrics may not wish to process this file (too big / too small) */ - if (!cache[a_idx] || !cache[b_idx]) + if (cache[a_idx] == &cache_invalid_marker || cache[b_idx] == &cache_invalid_marker) return 0; /* compare signatures */ - if (opts->metric->similarity( - &score, cache[a_idx], cache[b_idx], opts->metric->payload) < 0) + if (opts->metric->similarity(&score, cache[a_idx], cache[b_idx], opts->metric->payload) < 0) return -1; /* clip score */ @@ -1104,14 +1126,12 @@ git_oidmap_free(map); } -static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx) { - size_t pos; +static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx) +{ deletes_by_oid_queue *queue; size_t *array_entry; - int error; - pos = git_oidmap_lookup_index(map, id); - if (!git_oidmap_valid_index(map, pos)) { + if ((queue = git_oidmap_get(map, id)) == NULL) { queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue)); GIT_ERROR_CHECK_ALLOC(queue); @@ -1119,11 +1139,9 @@ queue->next_pos = 0; queue->first_entry = idx; - git_oidmap_insert(map, id, queue, &error); - if (error < 0) + if (git_oidmap_set(map, id, queue) < 0) return -1; } else { - queue = git_oidmap_value_at(map, pos); array_entry = git_array_alloc(queue->arr); GIT_ERROR_CHECK_ALLOC(array_entry); *array_entry = idx; @@ -1132,18 +1150,14 @@ return 0; } -static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id) { - size_t pos; +static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id) +{ deletes_by_oid_queue *queue; size_t *array_entry; - pos = git_oidmap_lookup_index(map, id); - - if (!git_oidmap_valid_index(map, pos)) + if ((queue = git_oidmap_get(map, id)) == NULL) return GIT_ENOTFOUND; - queue = git_oidmap_value_at(map, pos); - if (queue->next_pos == 0) { *idx = queue->first_entry; } else { @@ -1168,8 +1182,8 @@ git_oidmap *ours_deletes_by_oid = NULL, *theirs_deletes_by_oid = NULL; int error = 0; - if (!(ours_deletes_by_oid = git_oidmap_alloc()) || - !(theirs_deletes_by_oid = git_oidmap_alloc())) { + if (git_oidmap_new(&ours_deletes_by_oid) < 0 || + git_oidmap_new(&theirs_deletes_by_oid) < 0) { error = -1; goto done; } @@ -1549,7 +1563,7 @@ done: if (cache != NULL) { for (i = 0; i < cache_size; ++i) { - if (cache[i] != NULL) + if (cache[i] != NULL && cache[i] != &cache_invalid_marker) opts->metric->free_signature(cache[i], opts->metric->payload); } @@ -1796,12 +1810,12 @@ diff_list->repo = repo; - git_pool_init(&diff_list->pool, 1); - if (git_vector_init(&diff_list->staged, 0, NULL) < 0 || - git_vector_init(&diff_list->conflicts, 0, NULL) < 0 || - git_vector_init(&diff_list->resolved, 0, NULL) < 0) { - git_merge_diff_list__free(diff_list); + if (git_pool_init(&diff_list->pool, 1) < 0 || + git_vector_init(&diff_list->staged, 0, NULL) < 0 || + git_vector_init(&diff_list->conflicts, 0, NULL) < 0 || + git_vector_init(&diff_list->resolved, 0, NULL) < 0) { + git_merge_diff_list__free(diff_list); return NULL; } @@ -2831,7 +2845,7 @@ return error; } -const char *merge_their_label(const char *branchname) +static const char *merge_their_label(const char *branchname) { const char *slash; @@ -3120,9 +3134,6 @@ *ancestor_head_out = NULL; *our_head_out = NULL; - if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0) - goto done; - if ((error = git_annotated_commit_from_ref(&our_head, repo, our_ref)) < 0) goto done; @@ -3333,24 +3344,46 @@ return error; } -int git_merge_init_options(git_merge_options *opts, unsigned int version) +int git_merge_options_init(git_merge_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_merge_options, GIT_MERGE_OPTIONS_INIT); return 0; } -int git_merge_file_init_input(git_merge_file_input *input, unsigned int version) +#ifndef GIT_DEPRECATE_HARD +int git_merge_init_options(git_merge_options *opts, unsigned int version) +{ + return git_merge_options_init(opts, version); +} +#endif + +int git_merge_file_input_init(git_merge_file_input *input, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( input, version, git_merge_file_input, GIT_MERGE_FILE_INPUT_INIT); return 0; } -int git_merge_file_init_options( +#ifndef GIT_DEPRECATE_HARD +int git_merge_file_init_input(git_merge_file_input *input, unsigned int version) +{ + return git_merge_file_input_init(input, version); +} +#endif + +int git_merge_file_options_init( git_merge_file_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_merge_file_options, GIT_MERGE_FILE_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_merge_file_init_options( + git_merge_file_options *opts, unsigned int version) +{ + return git_merge_file_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/merge_driver.c libgit2-1.1.0+dfsg.1/src/merge_driver.c --- libgit2-0.28.5+dfsg.1/src/merge_driver.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/merge_driver.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,7 +32,7 @@ static void git_merge_driver_global_shutdown(void); -const git_repository* git_merge_driver_source_repo(const git_merge_driver_source *src) +git_repository* git_merge_driver_source_repo(const git_merge_driver_source *src) { assert(src); return src->repo; @@ -371,17 +371,17 @@ return error; /* set: use the built-in 3-way merge driver ("text") */ - if (GIT_ATTR_TRUE(value)) + if (GIT_ATTR_IS_TRUE(value)) *out = merge_driver_name__text; /* unset: do not merge ("binary") */ - else if (GIT_ATTR_FALSE(value)) + else if (GIT_ATTR_IS_FALSE(value)) *out = merge_driver_name__binary; - else if (GIT_ATTR_UNSPECIFIED(value) && default_driver) + else if (GIT_ATTR_IS_UNSPECIFIED(value) && default_driver) *out = default_driver; - else if (GIT_ATTR_UNSPECIFIED(value)) + else if (GIT_ATTR_IS_UNSPECIFIED(value)) *out = merge_driver_name__text; else diff -Nru libgit2-0.28.5+dfsg.1/src/merge_file.c libgit2-1.1.0+dfsg.1/src/merge_file.c --- libgit2-0.28.5+dfsg.1/src/merge_file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/merge_file.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ #include "repository.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" #include "index.h" #include "diff_xdiff.h" #include "merge.h" @@ -28,7 +28,7 @@ #define GIT_MERGE_FILE_SIDE_EXISTS(X) ((X)->mode != 0) -int git_merge_file__input_from_index( +static int merge_file_input_from_index( git_merge_file_input *input_out, git_odb_object **odb_object_out, git_odb *odb, @@ -276,17 +276,15 @@ goto done; if (ancestor) { - if ((error = git_merge_file__input_from_index( + if ((error = merge_file_input_from_index( &ancestor_input, &odb_object[0], odb, ancestor)) < 0) goto done; ancestor_ptr = &ancestor_input; } - if ((error = git_merge_file__input_from_index( - &our_input, &odb_object[1], odb, ours)) < 0 || - (error = git_merge_file__input_from_index( - &their_input, &odb_object[2], odb, theirs)) < 0) + if ((error = merge_file_input_from_index(&our_input, &odb_object[1], odb, ours)) < 0 || + (error = merge_file_input_from_index(&their_input, &odb_object[2], odb, theirs)) < 0) goto done; error = merge_file__from_inputs(out, diff -Nru libgit2-0.28.5+dfsg.1/src/merge.h libgit2-1.1.0+dfsg.1/src/merge.h --- libgit2-0.28.5+dfsg.1/src/merge.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/merge.h 2020-10-12 18:53:06.000000000 +0000 @@ -84,7 +84,7 @@ /* The child of a folder that is in a directory/file conflict. */ GIT_MERGE_DIFF_DF_CHILD = (1 << 11), -} git_merge_diff_type_t; +} git_merge_diff_t; typedef struct { git_repository *repo; @@ -113,7 +113,7 @@ * Description of changes to one file across three trees. */ typedef struct { - git_merge_diff_type_t type; + git_merge_diff_t type; git_index_entry ancestor_entry; diff -Nru libgit2-0.28.5+dfsg.1/src/midx.c libgit2-1.1.0+dfsg.1/src/midx.c --- libgit2-0.28.5+dfsg.1/src/midx.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/midx.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,418 @@ +/* + * 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 "midx.h" + +#include "buffer.h" +#include "futils.h" +#include "hash.h" +#include "odb.h" +#include "pack.h" + +#define GIT_MIDX_FILE_MODE 0444 + +#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ +#define MIDX_VERSION 1 +#define MIDX_OBJECT_ID_VERSION 1 +struct git_midx_header { + uint32_t signature; + uint8_t version; + uint8_t object_id_version; + uint8_t chunks; + uint8_t base_midx_files; + uint32_t packfiles; +}; + +#define MIDX_PACKFILE_NAMES_ID 0x504e414d /* "PNAM" */ +#define MIDX_OID_FANOUT_ID 0x4f494446 /* "OIDF" */ +#define MIDX_OID_LOOKUP_ID 0x4f49444c /* "OIDL" */ +#define MIDX_OBJECT_OFFSETS_ID 0x4f4f4646 /* "OOFF" */ +#define MIDX_OBJECT_LARGE_OFFSETS_ID 0x4c4f4646 /* "LOFF" */ + +struct git_midx_chunk { + off64_t offset; + size_t length; +}; + +static int midx_error(const char *message) +{ + git_error_set(GIT_ERROR_ODB, "invalid multi-pack-index file - %s", message); + return -1; +} + +static int midx_parse_packfile_names( + git_midx_file *idx, + const unsigned char *data, + uint32_t packfiles, + struct git_midx_chunk *chunk) +{ + int error; + uint32_t i; + char *packfile_name = (char *)(data + chunk->offset); + size_t chunk_size = chunk->length, len; + if (chunk->offset == 0) + return midx_error("missing Packfile Names chunk"); + if (chunk->length == 0) + return midx_error("empty Packfile Names chunk"); + if ((error = git_vector_init(&idx->packfile_names, packfiles, git__strcmp_cb)) < 0) + return error; + for (i = 0; i < packfiles; ++i) { + len = p_strnlen(packfile_name, chunk_size); + if (len == 0) + return midx_error("empty packfile name"); + if (len + 1 > chunk_size) + return midx_error("unterminated packfile name"); + git_vector_insert(&idx->packfile_names, packfile_name); + if (i && strcmp(git_vector_get(&idx->packfile_names, i - 1), packfile_name) >= 0) + return midx_error("packfile names are not sorted"); + if (strlen(packfile_name) <= strlen(".idx") || git__suffixcmp(packfile_name, ".idx") != 0) + return midx_error("non-.idx packfile name"); + if (strchr(packfile_name, '/') != NULL || strchr(packfile_name, '\\') != NULL) + return midx_error("non-local packfile"); + packfile_name += len + 1; + chunk_size -= len + 1; + } + return 0; +} + +static int midx_parse_oid_fanout( + git_midx_file *idx, + const unsigned char *data, + struct git_midx_chunk *chunk_oid_fanout) +{ + uint32_t i, nr; + if (chunk_oid_fanout->offset == 0) + return midx_error("missing OID Fanout chunk"); + if (chunk_oid_fanout->length == 0) + return midx_error("empty OID Fanout chunk"); + if (chunk_oid_fanout->length != 256 * 4) + return midx_error("OID Fanout chunk has wrong length"); + + idx->oid_fanout = (const uint32_t *)(data + chunk_oid_fanout->offset); + nr = 0; + for (i = 0; i < 256; ++i) { + uint32_t n = ntohl(idx->oid_fanout[i]); + if (n < nr) + return midx_error("index is non-monotonic"); + nr = n; + } + idx->num_objects = nr; + return 0; +} + +static int midx_parse_oid_lookup( + git_midx_file *idx, + const unsigned char *data, + struct git_midx_chunk *chunk_oid_lookup) +{ + uint32_t i; + git_oid *oid, *prev_oid, zero_oid = {{0}}; + + 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 * 20) + return midx_error("OID Lookup chunk has wrong length"); + + idx->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset); + prev_oid = &zero_oid; + for (i = 0; i < idx->num_objects; ++i, ++oid) { + if (git_oid_cmp(prev_oid, oid) >= 0) + return midx_error("OID Lookup index is non-monotonic"); + prev_oid = oid; + } + + return 0; +} + +static int midx_parse_object_offsets( + git_midx_file *idx, + const unsigned char *data, + struct git_midx_chunk *chunk_object_offsets) +{ + if (chunk_object_offsets->offset == 0) + return midx_error("missing Object Offsets chunk"); + if (chunk_object_offsets->length == 0) + return midx_error("empty Object Offsets chunk"); + if (chunk_object_offsets->length != idx->num_objects * 8) + return midx_error("Object Offsets chunk has wrong length"); + + idx->object_offsets = data + chunk_object_offsets->offset; + + return 0; +} + +static int midx_parse_object_large_offsets( + git_midx_file *idx, + const unsigned char *data, + struct git_midx_chunk *chunk_object_large_offsets) +{ + if (chunk_object_large_offsets->length == 0) + return 0; + if (chunk_object_large_offsets->length % 8 != 0) + return midx_error("malformed Object Large Offsets chunk"); + + idx->object_large_offsets = data + chunk_object_large_offsets->offset; + idx->num_object_large_offsets = chunk_object_large_offsets->length / 8; + + return 0; +} + +int git_midx_parse( + git_midx_file *idx, + const unsigned char *data, + size_t size) +{ + struct git_midx_header *hdr; + const unsigned char *chunk_hdr; + struct git_midx_chunk *last_chunk; + uint32_t i; + off64_t last_chunk_offset, chunk_offset, trailer_offset; + git_oid idx_checksum = {{0}}; + 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}; + + assert(idx); + + if (size < sizeof(struct git_midx_header) + 20) + return midx_error("multi-pack index is too short"); + + hdr = ((struct git_midx_header *)data); + + if (hdr->signature != htonl(MIDX_SIGNATURE) || + hdr->version != MIDX_VERSION || + hdr->object_id_version != MIDX_OBJECT_ID_VERSION) { + return midx_error("unsupported multi-pack index version"); + } + if (hdr->chunks == 0) + return midx_error("no chunks in multi-pack index"); + + /* + * The very first chunk's offset should be after the header, all the chunk + * headers, and a special zero chunk. + */ + last_chunk_offset = + sizeof(struct git_midx_header) + + (1 + hdr->chunks) * 12; + trailer_offset = size - 20; + if (trailer_offset < last_chunk_offset) + return midx_error("wrong index size"); + git_oid_cpy(&idx->checksum, (git_oid *)(data + trailer_offset)); + + if (git_hash_buf(&idx_checksum, data, (size_t)trailer_offset) < 0) + return midx_error("could not calculate signature"); + if (!git_oid_equal(&idx_checksum, &idx->checksum)) + return midx_error("index signature mismatch"); + + chunk_hdr = data + sizeof(struct git_midx_header); + last_chunk = NULL; + for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) { + chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32 | + ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8)))); + if (chunk_offset < last_chunk_offset) + return midx_error("chunks are non-monotonic"); + if (chunk_offset >= trailer_offset) + return midx_error("chunks extend beyond the trailer"); + if (last_chunk != NULL) + last_chunk->length = (size_t)(chunk_offset - last_chunk_offset); + last_chunk_offset = chunk_offset; + + switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) { + case MIDX_PACKFILE_NAMES_ID: + chunk_packfile_names.offset = last_chunk_offset; + last_chunk = &chunk_packfile_names; + break; + + case MIDX_OID_FANOUT_ID: + chunk_oid_fanout.offset = last_chunk_offset; + last_chunk = &chunk_oid_fanout; + break; + + case MIDX_OID_LOOKUP_ID: + chunk_oid_lookup.offset = last_chunk_offset; + last_chunk = &chunk_oid_lookup; + break; + + case MIDX_OBJECT_OFFSETS_ID: + chunk_object_offsets.offset = last_chunk_offset; + last_chunk = &chunk_object_offsets; + break; + + case MIDX_OBJECT_LARGE_OFFSETS_ID: + chunk_object_large_offsets.offset = last_chunk_offset; + last_chunk = &chunk_object_large_offsets; + break; + + default: + return midx_error("unrecognized chunk ID"); + } + } + last_chunk->length = (size_t)(trailer_offset - last_chunk_offset); + + error = midx_parse_packfile_names( + idx, data, ntohl(hdr->packfiles), &chunk_packfile_names); + if (error < 0) + return error; + error = midx_parse_oid_fanout(idx, data, &chunk_oid_fanout); + if (error < 0) + return error; + error = midx_parse_oid_lookup(idx, data, &chunk_oid_lookup); + if (error < 0) + return error; + error = midx_parse_object_offsets(idx, data, &chunk_object_offsets); + if (error < 0) + return error; + error = midx_parse_object_large_offsets(idx, data, &chunk_object_large_offsets); + if (error < 0) + return error; + + return 0; +} + +int git_midx_open( + git_midx_file **idx_out, + const char *path) +{ + git_midx_file *idx; + git_file fd = -1; + size_t idx_size; + struct stat st; + int error; + + /* TODO: properly open the file without access time using O_NOATIME */ + fd = git_futils_open_ro(path); + if (fd < 0) + return fd; + + if (p_fstat(fd, &st) < 0) { + p_close(fd); + git_error_set(GIT_ERROR_ODB, "multi-pack-index file not found - '%s'", path); + return -1; + } + + if (!S_ISREG(st.st_mode) || !git__is_sizet(st.st_size)) { + p_close(fd); + git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path); + return -1; + } + idx_size = (size_t)st.st_size; + + idx = git__calloc(1, sizeof(git_midx_file)); + GIT_ERROR_CHECK_ALLOC(idx); + + error = git_futils_mmap_ro(&idx->index_map, fd, 0, idx_size); + p_close(fd); + if (error < 0) { + git_midx_free(idx); + return error; + } + + if ((error = git_midx_parse(idx, idx->index_map.data, idx_size)) < 0) { + git_midx_free(idx); + return error; + } + + *idx_out = idx; + return 0; +} + +int git_midx_entry_find( + git_midx_entry *e, + git_midx_file *idx, + const git_oid *short_oid, + size_t len) +{ + int pos, found = 0; + size_t pack_index; + uint32_t hi, lo; + const git_oid *current = NULL; + const unsigned char *object_offset; + off64_t offset; + + assert(idx); + + 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_sha1(idx->oid_lookup, 20, lo, hi, short_oid->id); + + if (pos >= 0) { + /* An object matching exactly the oid was found */ + found = 1; + current = idx->oid_lookup + pos; + } 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; + + if (!git_oid_ncmp(short_oid, current, len)) + found = 1; + } + } + + if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) { + /* Check for ambiguousity */ + const git_oid *next = current + 1; + + if (!git_oid_ncmp(short_oid, next, len)) { + found = 2; + } + } + + if (!found) + return git_odb__error_notfound("failed to find offset for multi-pack index entry", short_oid, len); + if (found > 1) + return git_odb__error_ambiguous("found multiple offsets for multi-pack index entry"); + + object_offset = idx->object_offsets + pos * 8; + offset = ntohl(*((uint32_t *)(object_offset + 4))); + if (offset & 0x80000000) { + uint32_t object_large_offsets_pos = offset & 0x7fffffff; + const unsigned char *object_large_offsets_index = idx->object_large_offsets; + + /* Make sure we're not being sent out of bounds */ + if (object_large_offsets_pos >= idx->num_object_large_offsets) + return git_odb__error_notfound("invalid index into the object large offsets table", short_oid, len); + + object_large_offsets_index += 8 * object_large_offsets_pos; + + offset = (((uint64_t)ntohl(*((uint32_t *)(object_large_offsets_index + 0)))) << 32) | + ntohl(*((uint32_t *)(object_large_offsets_index + 4))); + } + pack_index = ntohl(*((uint32_t *)(object_offset + 0))); + if (pack_index >= git_vector_length(&idx->packfile_names)) + return midx_error("invalid index into the packfile names table"); + e->pack_index = pack_index; + e->offset = offset; + git_oid_cpy(&e->sha1, current); + return 0; +} + +void git_midx_close(git_midx_file *idx) +{ + assert(idx); + + if (idx->index_map.data) + git_futils_mmap_free(&idx->index_map); + git_vector_free(&idx->packfile_names); +} + +void git_midx_free(git_midx_file *idx) +{ + if (!idx) + return; + + git_midx_close(idx); + git__free(idx); +} diff -Nru libgit2-0.28.5+dfsg.1/src/midx.h libgit2-1.1.0+dfsg.1/src/midx.h --- libgit2-0.28.5+dfsg.1/src/midx.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/midx.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * 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_midx_h__ +#define INCLUDE_midx_h__ + +#include "common.h" + +#include + +#include "map.h" +#include "mwindow.h" + +/* + * A multi-pack-index file. + * + * This file contains a merged index for multiple independent .pack files. This + * can help speed up locating objects without requiring a garbage collection + * cycle to create a single .pack file. + * + * Support for this feature was added in git 2.21, and requires the + * `core.multiPackIndex` config option to be set. + */ +typedef struct git_midx_file { + git_map index_map; + + /* The table of Packfile Names. */ + git_vector packfile_names; + + /* The OID Fanout table. */ + const uint32_t *oid_fanout; + /* The total number of objects in the index. */ + uint32_t num_objects; + + /* The OID Lookup table. */ + git_oid *oid_lookup; + + /* The Object Offsets table. Each entry has two 4-byte fields with the pack index and the offset. */ + const unsigned char *object_offsets; + + /* The Object Large Offsets table. */ + const unsigned char *object_large_offsets; + /* 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. */ + git_oid checksum; +} git_midx_file; + +/* + * An entry in the multi-pack-index file. Similar in purpose to git_pack_entry. + */ +typedef struct git_midx_entry { + /* The index within idx->packfile_names where the packfile name can be found. */ + size_t pack_index; + /* The offset within the .pack file where the requested object is found. */ + off64_t offset; + /* The SHA-1 hash of the requested object. */ + git_oid sha1; +} git_midx_entry; + +int git_midx_open( + git_midx_file **idx_out, + const char *path); +int git_midx_entry_find( + git_midx_entry *e, + git_midx_file *idx, + const git_oid *short_oid, + size_t len); +void git_midx_close(git_midx_file *idx); +void git_midx_free(git_midx_file *idx); + +/* This is exposed for use in the fuzzers. */ +int git_midx_parse( + git_midx_file *idx, + const unsigned char *data, + size_t size); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/mwindow.c libgit2-1.1.0+dfsg.1/src/mwindow.c --- libgit2-0.28.5+dfsg.1/src/mwindow.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/mwindow.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ #include "mwindow.h" #include "vector.h" -#include "fileops.h" +#include "futils.h" #include "map.h" #include "global.h" #include "strmap.h" @@ -22,11 +22,15 @@ #define DEFAULT_MAPPED_LIMIT \ ((1024 * 1024) * (sizeof(void*) >= 8 ? 8192ULL : 256UL)) +/* default is unlimited */ +#define DEFAULT_FILE_LIMIT 0 + size_t git_mwindow__window_size = DEFAULT_WINDOW_SIZE; size_t git_mwindow__mapped_limit = DEFAULT_MAPPED_LIMIT; +size_t git_mwindow__file_limit = DEFAULT_FILE_LIMIT; /* Whenever you want to read or modify this, grab git__mwindow_mutex */ -static git_mwindow_ctl mem_ctl; +git_mwindow_ctl git_mwindow__mem_ctl; /* Global list of mwindow files, to open packs once across repos */ git_strmap *git__pack_cache = NULL; @@ -44,15 +48,14 @@ assert(!git__pack_cache); git__on_shutdown(git_mwindow_files_free); - return git_strmap_alloc(&git__pack_cache); + return git_strmap_new(&git__pack_cache); } int git_mwindow_get_pack(struct git_pack_file **out, const char *path) { - int error; - char *packname; - size_t pos; struct git_pack_file *pack; + char *packname; + int error; if ((error = git_packfile__name(&packname, path)) < 0) return error; @@ -62,13 +65,11 @@ return -1; } - pos = git_strmap_lookup_index(git__pack_cache, packname); + pack = git_strmap_get(git__pack_cache, packname); git__free(packname); - if (git_strmap_valid_index(git__pack_cache, pos)) { - pack = git_strmap_value_at(git__pack_cache, pos); + if (pack != NULL) { git_atomic_inc(&pack->refcount); - git_mutex_unlock(&git__mwindow_mutex); *out = pack; return 0; @@ -82,7 +83,7 @@ git_atomic_inc(&pack->refcount); - git_strmap_insert(git__pack_cache, pack->pack_name, pack, &error); + error = git_strmap_set(git__pack_cache, pack->pack_name, pack); git_mutex_unlock(&git__mwindow_mutex); if (error < 0) { @@ -97,7 +98,6 @@ void git_mwindow_put_pack(struct git_pack_file *pack) { int count; - size_t pos; if (git_mutex_lock(&git__mwindow_mutex) < 0) return; @@ -105,13 +105,12 @@ /* put before get would be a corrupted state */ assert(git__pack_cache); - pos = git_strmap_lookup_index(git__pack_cache, pack->pack_name); /* if we cannot find it, the state is corrupted */ - assert(git_strmap_valid_index(git__pack_cache, pos)); + assert(git_strmap_exists(git__pack_cache, pack->pack_name)); count = git_atomic_dec(&pack->refcount); if (count == 0) { - git_strmap_delete_at(git__pack_cache, pos); + git_strmap_delete(git__pack_cache, pack->pack_name); git_packfile_free(pack); } @@ -137,7 +136,7 @@ */ void git_mwindow_free_all_locked(git_mwindow_file *mwf) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; size_t i; /* @@ -172,91 +171,155 @@ /* * Check if a window 'win' contains the address 'offset' */ -int git_mwindow_contains(git_mwindow *win, git_off_t offset) +int git_mwindow_contains(git_mwindow *win, off64_t offset) { - git_off_t win_off = win->offset; + off64_t win_off = win->offset; return win_off <= offset - && offset <= (git_off_t)(win_off + win->window_map.len); + && offset <= (off64_t)(win_off + win->window_map.len); } +#define GIT_MWINDOW__LRU -1 +#define GIT_MWINDOW__MRU 1 + /* - * Find the least-recently-used window in a file + * Find the least- or most-recently-used window in a file that is not currently + * being used. The 'only_unused' flag controls whether the caller requires the + * file to only have unused windows. If '*out_window' is non-null, it is used as + * a starting point for the comparison. + * + * Returns whether such a window was found in the file. */ -static void git_mwindow_scan_lru( - git_mwindow_file *mwf, - git_mwindow **lru_w, - git_mwindow **lru_l) -{ - git_mwindow *w, *w_l; +static bool git_mwindow_scan_recently_used( + git_mwindow_file *mwf, + git_mwindow **out_window, + git_mwindow **out_last, + bool only_unused, + int comparison_sign) +{ + git_mwindow *w, *w_last; + git_mwindow *lru_window = NULL, *lru_last = NULL; + bool found = false; + + assert(mwf); + assert(out_window); + + lru_window = *out_window; + if (out_last) + lru_last = *out_last; + + for (w_last = NULL, w = mwf->windows; w; w_last = w, w = w->next) { + if (w->inuse_cnt) { + if (only_unused) + return false; + /* This window is currently being used. Skip it. */ + continue; + } - for (w_l = NULL, w = mwf->windows; w; w = w->next) { - if (!w->inuse_cnt) { - /* - * If the current one is more recent than the last one, - * store it in the output parameter. If lru_w is NULL, - * it's the first loop, so store it as well. - */ - if (!*lru_w || w->last_used < (*lru_w)->last_used) { - *lru_w = w; - *lru_l = w_l; - } + /* + * If the current one is more (or less) recent than the last one, + * store it in the output parameter. If lru_window is NULL, + * it's the first loop, so store it as well. + */ + if (!lru_window || + (comparison_sign == GIT_MWINDOW__LRU && lru_window->last_used > w->last_used) || + (comparison_sign == GIT_MWINDOW__MRU && lru_window->last_used < w->last_used)) { + lru_window = w; + lru_last = w_last; + found = true; } - w_l = w; } + + if (!found) + return false; + + *out_window = lru_window; + if (out_last) + *out_last = lru_last; + return true; } /* - * Close the least recently used window. You should check to see if - * the file descriptors need closing from time to time. Called under - * lock from new_window. + * Close the least recently used window (that is currently not being used) out + * of all the files. Called under lock from new_window. */ -static int git_mwindow_close_lru(git_mwindow_file *mwf) +static int git_mwindow_close_lru_window(void) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; + git_mwindow_file *cur; size_t i; - git_mwindow *lru_w = NULL, *lru_l = NULL, **list = &mwf->windows; + git_mwindow *lru_window = NULL, *lru_last = NULL, **list = NULL; - /* FIXME: Does this give us any advantage? */ - if(mwf->windows) - git_mwindow_scan_lru(mwf, &lru_w, &lru_l); - - for (i = 0; i < ctl->windowfiles.length; ++i) { - git_mwindow *last = lru_w; - git_mwindow_file *cur = git_vector_get(&ctl->windowfiles, i); - git_mwindow_scan_lru(cur, &lru_w, &lru_l); - if (lru_w != last) + git_vector_foreach(&ctl->windowfiles, i, cur) { + if (git_mwindow_scan_recently_used( + cur, &lru_window, &lru_last, false, GIT_MWINDOW__LRU)) { list = &cur->windows; + } } - if (!lru_w) { + if (!lru_window) { git_error_set(GIT_ERROR_OS, "failed to close memory window; couldn't find LRU"); return -1; } - ctl->mapped -= lru_w->window_map.len; - git_futils_mmap_free(&lru_w->window_map); + ctl->mapped -= lru_window->window_map.len; + git_futils_mmap_free(&lru_window->window_map); - if (lru_l) - lru_l->next = lru_w->next; + if (lru_last) + lru_last->next = lru_window->next; else - *list = lru_w->next; + *list = lru_window->next; - git__free(lru_w); + git__free(lru_window); ctl->open_windows--; return 0; } +/* + * Close the file that does not have any open windows AND whose + * most-recently-used window is the least-recently used one across all + * currently open files. + * + * Called under lock from new_window. + */ +static int git_mwindow_close_lru_file(void) +{ + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; + git_mwindow_file *lru_file = NULL, *current_file = NULL; + git_mwindow *lru_window = NULL; + size_t i; + + git_vector_foreach(&ctl->windowfiles, i, current_file) { + git_mwindow *mru_window = NULL; + if (!git_mwindow_scan_recently_used( + current_file, &mru_window, NULL, true, GIT_MWINDOW__MRU)) { + continue; + } + if (!lru_window || lru_window->last_used > mru_window->last_used) + lru_file = current_file; + } + + if (!lru_file) { + git_error_set(GIT_ERROR_OS, "failed to close memory window file; couldn't find LRU"); + return -1; + } + + git_mwindow_free_all_locked(lru_file); + p_close(lru_file->fd); + lru_file->fd = -1; + + return 0; +} + /* This gets called under lock from git_mwindow_open */ static git_mwindow *new_window( - git_mwindow_file *mwf, git_file fd, - git_off_t size, - git_off_t offset) + off64_t size, + off64_t offset) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; size_t walign = git_mwindow__window_size / 2; - git_off_t len; + off64_t len; git_mwindow *w; w = git__malloc(sizeof(*w)); @@ -268,13 +331,13 @@ w->offset = (offset / walign) * walign; len = size - w->offset; - if (len > (git_off_t)git_mwindow__window_size) - len = (git_off_t)git_mwindow__window_size; + if (len > (off64_t)git_mwindow__window_size) + len = (off64_t)git_mwindow__window_size; ctl->mapped += (size_t)len; while (git_mwindow__mapped_limit < ctl->mapped && - git_mwindow_close_lru(mwf) == 0) /* nop */; + git_mwindow_close_lru_window() == 0) /* nop */; /* * We treat `mapped_limit` as a soft limit. If we can't find a @@ -288,7 +351,7 @@ * we're below our soft limits, so free up what we can and try again. */ - while (git_mwindow_close_lru(mwf) == 0) + while (git_mwindow_close_lru_window() == 0) /* nop */; if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) { @@ -316,11 +379,11 @@ unsigned char *git_mwindow_open( git_mwindow_file *mwf, git_mwindow **cursor, - git_off_t offset, + off64_t offset, size_t extra, unsigned int *left) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; git_mwindow *w = *cursor; if (git_mutex_lock(&git__mwindow_mutex)) { @@ -344,7 +407,7 @@ * one. */ if (!w) { - w = new_window(mwf, mwf->fd, mwf->size, offset); + w = new_window(mwf->fd, mwf->size, offset); if (w == NULL) { git_mutex_unlock(&git__mwindow_mutex); return NULL; @@ -372,7 +435,7 @@ int git_mwindow_file_register(git_mwindow_file *mwf) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; int ret; if (git_mutex_lock(&git__mwindow_mutex)) { @@ -386,6 +449,11 @@ return -1; } + if (git_mwindow__file_limit) { + while (git_mwindow__file_limit <= ctl->windowfiles.length && + git_mwindow_close_lru_file() == 0) /* nop */; + } + ret = git_vector_insert(&ctl->windowfiles, mwf); git_mutex_unlock(&git__mwindow_mutex); @@ -394,7 +462,7 @@ void git_mwindow_file_deregister(git_mwindow_file *mwf) { - git_mwindow_ctl *ctl = &mem_ctl; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; git_mwindow_file *cur; size_t i; diff -Nru libgit2-0.28.5+dfsg.1/src/mwindow.h libgit2-1.1.0+dfsg.1/src/mwindow.h --- libgit2-0.28.5+dfsg.1/src/mwindow.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/mwindow.h 2020-10-12 18:53:06.000000000 +0000 @@ -16,7 +16,7 @@ typedef struct git_mwindow { struct git_mwindow *next; git_map window_map; - git_off_t offset; + off64_t offset; size_t last_used; size_t inuse_cnt; } git_mwindow; @@ -24,7 +24,7 @@ typedef struct git_mwindow_file { git_mwindow *windows; int fd; - git_off_t size; + off64_t size; } git_mwindow_file; typedef struct git_mwindow_ctl { @@ -37,10 +37,10 @@ git_vector windowfiles; } git_mwindow_ctl; -int git_mwindow_contains(git_mwindow *win, git_off_t offset); +int git_mwindow_contains(git_mwindow *win, off64_t offset); void git_mwindow_free_all(git_mwindow_file *mwf); /* locks */ void git_mwindow_free_all_locked(git_mwindow_file *mwf); /* run under lock */ -unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, size_t extra, unsigned int *left); +unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, off64_t offset, size_t extra, unsigned int *left); int git_mwindow_file_register(git_mwindow_file *mwf); void git_mwindow_file_deregister(git_mwindow_file *mwf); void git_mwindow_close(git_mwindow **w_cursor); diff -Nru libgit2-0.28.5+dfsg.1/src/net.c libgit2-1.1.0+dfsg.1/src/net.c --- libgit2-0.28.5+dfsg.1/src/net.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/net.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,416 @@ +/* + * 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 "net.h" +#include "netops.h" + +#include +#include "git2/errors.h" + +#include "posix.h" +#include "buffer.h" +#include "http_parser.h" +#include "global.h" + +#define DEFAULT_PORT_HTTP "80" +#define DEFAULT_PORT_HTTPS "443" +#define DEFAULT_PORT_GIT "9418" +#define DEFAULT_PORT_SSH "22" + +static const char *default_port_for_scheme(const char *scheme) +{ + if (strcmp(scheme, "http") == 0) + return DEFAULT_PORT_HTTP; + else if (strcmp(scheme, "https") == 0) + return DEFAULT_PORT_HTTPS; + else if (strcmp(scheme, "git") == 0) + return DEFAULT_PORT_GIT; + else if (strcmp(scheme, "ssh") == 0) + return DEFAULT_PORT_SSH; + + return NULL; +} + +int git_net_url_parse(git_net_url *url, const char *given) +{ + struct http_parser_url u = {0}; + bool has_scheme, has_host, has_port, has_path, has_query, has_userinfo; + git_buf scheme = GIT_BUF_INIT, + host = GIT_BUF_INIT, + port = GIT_BUF_INIT, + path = GIT_BUF_INIT, + username = GIT_BUF_INIT, + password = GIT_BUF_INIT, + query = GIT_BUF_INIT; + int error = GIT_EINVALIDSPEC; + + if (http_parser_parse_url(given, strlen(given), false, &u)) { + git_error_set(GIT_ERROR_NET, "malformed URL '%s'", given); + goto done; + } + + has_scheme = !!(u.field_set & (1 << UF_SCHEMA)); + has_host = !!(u.field_set & (1 << UF_HOST)); + has_port = !!(u.field_set & (1 << UF_PORT)); + has_path = !!(u.field_set & (1 << UF_PATH)); + has_query = !!(u.field_set & (1 << UF_QUERY)); + has_userinfo = !!(u.field_set & (1 << UF_USERINFO)); + + if (has_scheme) { + const char *url_scheme = given + u.field_data[UF_SCHEMA].off; + size_t url_scheme_len = u.field_data[UF_SCHEMA].len; + git_buf_put(&scheme, url_scheme, url_scheme_len); + git__strntolower(scheme.ptr, scheme.size); + } else { + git_error_set(GIT_ERROR_NET, "malformed URL '%s'", given); + goto done; + } + + if (has_host) { + const char *url_host = given + u.field_data[UF_HOST].off; + size_t url_host_len = u.field_data[UF_HOST].len; + git_buf_decode_percent(&host, url_host, url_host_len); + } + + if (has_port) { + const char *url_port = given + u.field_data[UF_PORT].off; + size_t url_port_len = u.field_data[UF_PORT].len; + git_buf_put(&port, url_port, url_port_len); + } else { + const char *default_port = default_port_for_scheme(scheme.ptr); + + if (default_port == NULL) { + git_error_set(GIT_ERROR_NET, "unknown scheme for URL '%s'", given); + goto done; + } + + git_buf_puts(&port, default_port); + } + + if (has_path) { + const char *url_path = given + u.field_data[UF_PATH].off; + size_t url_path_len = u.field_data[UF_PATH].len; + git_buf_put(&path, url_path, url_path_len); + } else { + git_buf_puts(&path, "/"); + } + + if (has_query) { + const char *url_query = given + u.field_data[UF_QUERY].off; + size_t url_query_len = u.field_data[UF_QUERY].len; + git_buf_decode_percent(&query, url_query, url_query_len); + } + + if (has_userinfo) { + const char *url_userinfo = given + u.field_data[UF_USERINFO].off; + size_t url_userinfo_len = u.field_data[UF_USERINFO].len; + const char *colon = memchr(url_userinfo, ':', url_userinfo_len); + + if (colon) { + const char *url_username = url_userinfo; + size_t url_username_len = colon - url_userinfo; + const char *url_password = colon + 1; + size_t url_password_len = url_userinfo_len - (url_username_len + 1); + + git_buf_decode_percent(&username, url_username, url_username_len); + git_buf_decode_percent(&password, url_password, url_password_len); + } else { + git_buf_decode_percent(&username, url_userinfo, url_userinfo_len); + } + } + + if (git_buf_oom(&scheme) || + git_buf_oom(&host) || + git_buf_oom(&port) || + git_buf_oom(&path) || + git_buf_oom(&query) || + git_buf_oom(&username) || + git_buf_oom(&password)) + return -1; + + url->scheme = git_buf_detach(&scheme); + url->host = git_buf_detach(&host); + url->port = git_buf_detach(&port); + url->path = git_buf_detach(&path); + url->query = git_buf_detach(&query); + url->username = git_buf_detach(&username); + url->password = git_buf_detach(&password); + + error = 0; + +done: + git_buf_dispose(&scheme); + git_buf_dispose(&host); + git_buf_dispose(&port); + git_buf_dispose(&path); + git_buf_dispose(&query); + git_buf_dispose(&username); + git_buf_dispose(&password); + return error; +} + +int git_net_url_joinpath( + git_net_url *out, + git_net_url *one, + const char *two) +{ + git_buf path = GIT_BUF_INIT; + const char *query; + size_t one_len, two_len; + + git_net_url_dispose(out); + + if ((query = strchr(two, '?')) != NULL) { + two_len = query - two; + + if (*(++query) != '\0') { + out->query = git__strdup(query); + GIT_ERROR_CHECK_ALLOC(out->query); + } + } else { + two_len = strlen(two); + } + + /* Strip all trailing `/`s from the first path */ + one_len = one->path ? strlen(one->path) : 0; + while (one_len && one->path[one_len - 1] == '/') + one_len--; + + /* Strip all leading `/`s from the second path */ + while (*two == '/') { + two++; + two_len--; + } + + git_buf_put(&path, one->path, one_len); + git_buf_putc(&path, '/'); + git_buf_put(&path, two, two_len); + + if (git_buf_oom(&path)) + return -1; + + out->path = git_buf_detach(&path); + + if (one->scheme) { + out->scheme = git__strdup(one->scheme); + GIT_ERROR_CHECK_ALLOC(out->scheme); + } + + if (one->host) { + out->host = git__strdup(one->host); + GIT_ERROR_CHECK_ALLOC(out->host); + } + + if (one->port) { + out->port = git__strdup(one->port); + GIT_ERROR_CHECK_ALLOC(out->port); + } + + if (one->username) { + out->username = git__strdup(one->username); + GIT_ERROR_CHECK_ALLOC(out->username); + } + + if (one->password) { + out->password = git__strdup(one->password); + GIT_ERROR_CHECK_ALLOC(out->password); + } + + return 0; +} + +/* + * Some servers strip the query parameters from the Location header + * when sending a redirect. Others leave it in place. + * Check for both, starting with the stripped case first, + * since it appears to be more common. + */ +static void remove_service_suffix( + git_net_url *url, + const char *service_suffix) +{ + const char *service_query = strchr(service_suffix, '?'); + size_t full_suffix_len = strlen(service_suffix); + size_t suffix_len = service_query ? + (size_t)(service_query - service_suffix) : full_suffix_len; + size_t path_len = strlen(url->path); + ssize_t truncate = -1; + + /* + * Check for a redirect without query parameters, + * like "/newloc/info/refs"' + */ + if (suffix_len && path_len >= suffix_len) { + size_t suffix_offset = path_len - suffix_len; + + if (git__strncmp(url->path + suffix_offset, service_suffix, suffix_len) == 0 && + (!service_query || git__strcmp(url->query, service_query + 1) == 0)) { + truncate = suffix_offset; + } + } + + /* + * If we haven't already found where to truncate to remove the + * suffix, check for a redirect with query parameters, like + * "/newloc/info/refs?service=git-upload-pack" + */ + if (truncate < 0 && git__suffixcmp(url->path, service_suffix) == 0) + truncate = path_len - full_suffix_len; + + /* Ensure we leave a minimum of '/' as the path */ + if (truncate == 0) + truncate++; + + if (truncate > 0) { + url->path[truncate] = '\0'; + + git__free(url->query); + url->query = NULL; + } +} + +int git_net_url_apply_redirect( + git_net_url *url, + const char *redirect_location, + const char *service_suffix) +{ + git_net_url tmp = GIT_NET_URL_INIT; + int error = 0; + + assert(url && redirect_location); + + if (redirect_location[0] == '/') { + git__free(url->path); + + if ((url->path = git__strdup(redirect_location)) == NULL) { + error = -1; + goto done; + } + } else { + git_net_url *original = url; + + if ((error = git_net_url_parse(&tmp, redirect_location)) < 0) + goto done; + + /* Validate that this is a legal redirection */ + + if (original->scheme && + strcmp(original->scheme, tmp.scheme) != 0 && + strcmp(tmp.scheme, "https") != 0) { + git_error_set(GIT_ERROR_NET, "cannot redirect from '%s' to '%s'", + original->scheme, tmp.scheme); + + error = -1; + goto done; + } + + if (original->host && + git__strcasecmp(original->host, tmp.host) != 0) { + git_error_set(GIT_ERROR_NET, "cannot redirect from '%s' to '%s'", + original->host, tmp.host); + + error = -1; + goto done; + } + + git_net_url_swap(url, &tmp); + } + + /* Remove the service suffix if it was given to us */ + if (service_suffix) + remove_service_suffix(url, service_suffix); + +done: + git_net_url_dispose(&tmp); + return error; +} + +bool git_net_url_valid(git_net_url *url) +{ + return (url->host && url->port && url->path); +} + +int git_net_url_is_default_port(git_net_url *url) +{ + const char *default_port; + + if ((default_port = default_port_for_scheme(url->scheme)) != NULL) + return (strcmp(url->port, default_port) == 0); + else + return false; +} + +void git_net_url_swap(git_net_url *a, git_net_url *b) +{ + git_net_url tmp = GIT_NET_URL_INIT; + + memcpy(&tmp, a, sizeof(git_net_url)); + memcpy(a, b, sizeof(git_net_url)); + memcpy(b, &tmp, sizeof(git_net_url)); +} + +int git_net_url_fmt(git_buf *buf, git_net_url *url) +{ + git_buf_puts(buf, url->scheme); + git_buf_puts(buf, "://"); + + if (url->username) { + git_buf_puts(buf, url->username); + + if (url->password) { + git_buf_puts(buf, ":"); + git_buf_puts(buf, url->password); + } + + git_buf_putc(buf, '@'); + } + + git_buf_puts(buf, url->host); + + if (url->port && !git_net_url_is_default_port(url)) { + git_buf_putc(buf, ':'); + git_buf_puts(buf, url->port); + } + + git_buf_puts(buf, url->path ? url->path : "/"); + + if (url->query) { + git_buf_putc(buf, '?'); + git_buf_puts(buf, url->query); + } + + return git_buf_oom(buf) ? -1 : 0; +} + +int git_net_url_fmt_path(git_buf *buf, git_net_url *url) +{ + git_buf_puts(buf, url->path ? url->path : "/"); + + if (url->query) { + git_buf_putc(buf, '?'); + git_buf_puts(buf, url->query); + } + + return git_buf_oom(buf) ? -1 : 0; +} + +void git_net_url_dispose(git_net_url *url) +{ + if (url->username) + git__memzero(url->username, strlen(url->username)); + + if (url->password) + git__memzero(url->password, strlen(url->password)); + + git__free(url->scheme); url->scheme = NULL; + git__free(url->host); url->host = NULL; + git__free(url->port); url->port = NULL; + git__free(url->path); url->path = NULL; + git__free(url->query); url->query = NULL; + git__free(url->username); url->username = NULL; + git__free(url->password); url->password = NULL; +} diff -Nru libgit2-0.28.5+dfsg.1/src/net.h libgit2-1.1.0+dfsg.1/src/net.h --- libgit2-0.28.5+dfsg.1/src/net.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/net.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * 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_net_h__ +#define INCLUDE_net_h__ + +#include "common.h" + +typedef struct git_net_url { + char *scheme; + char *host; + char *port; + char *path; + char *query; + char *username; + char *password; +} git_net_url; + +#define GIT_NET_URL_INIT { NULL } + +/** Parses a string containing a URL into a structure. */ +extern int git_net_url_parse(git_net_url *url, const char *str); + +/** Appends a path and/or query string to the given URL */ +extern int git_net_url_joinpath( + git_net_url *out, + git_net_url *in, + const char *path); + +/** Ensures that a URL is minimally valid (contains a host, port and path) */ +extern bool git_net_url_valid(git_net_url *url); + +/** Returns nonzero if the URL is on the default port. */ +extern int git_net_url_is_default_port(git_net_url *url); + +/* Applies a redirect to the URL with a git-aware service suffix. */ +extern int git_net_url_apply_redirect( + git_net_url *url, + const char *redirect_location, + const char *service_suffix); + +/** Swaps the contents of one URL for another. */ +extern void git_net_url_swap(git_net_url *a, git_net_url *b); + +/** Places the URL into the given buffer. */ +extern int git_net_url_fmt(git_buf *out, git_net_url *url); + +/** Place the path and query string into the given buffer. */ +extern int git_net_url_fmt_path(git_buf *buf, git_net_url *url); + +/** Disposes the contents of the structure. */ +extern void git_net_url_dispose(git_net_url *url); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/netops.c libgit2-1.1.0+dfsg.1/src/netops.c --- libgit2-0.28.5+dfsg.1/src/netops.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/netops.c 2020-10-12 18:53:06.000000000 +0000 @@ -37,14 +37,17 @@ static int recv_stream(gitno_buffer *buf) { git_stream *io = (git_stream *) buf->cb_data; - int ret; + size_t readlen = buf->len - buf->offset; + ssize_t ret; - ret = git_stream_read(io, buf->data + buf->offset, buf->len - buf->offset); + 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 ret; + return (int)ret; } void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len) @@ -118,222 +121,3 @@ return -1; } - -static const char *default_port_http = "80"; -static const char *default_port_https = "443"; - -const char *gitno__default_port( - gitno_connection_data *data) -{ - return data->use_ssl ? default_port_https : default_port_http; -} - -static const char *prefix_http = "http://"; -static const char *prefix_https = "https://"; - -int gitno_connection_data_from_url( - gitno_connection_data *data, - const char *url, - const char *service_suffix) -{ - int error = -1; - const char *default_port = NULL, *path_search_start = NULL; - char *original_host = NULL; - - /* service_suffix is optional */ - assert(data && url); - - /* Save these for comparison later */ - original_host = data->host; - data->host = NULL; - gitno_connection_data_free_ptrs(data); - - if (!git__prefixcmp(url, prefix_http)) { - path_search_start = url + strlen(prefix_http); - default_port = default_port_http; - - if (data->use_ssl) { - git_error_set(GIT_ERROR_NET, "redirect from HTTPS to HTTP is not allowed"); - goto cleanup; - } - } else if (!git__prefixcmp(url, prefix_https)) { - path_search_start = url + strlen(prefix_https); - default_port = default_port_https; - data->use_ssl = true; - } else if (url[0] == '/') - default_port = gitno__default_port(data); - - if (!default_port) { - git_error_set(GIT_ERROR_NET, "unrecognized URL prefix"); - goto cleanup; - } - - error = gitno_extract_url_parts( - &data->host, &data->port, &data->path, &data->user, &data->pass, - url, default_port); - - if (url[0] == '/') { - /* Relative redirect; reuse original host name and port */ - path_search_start = url; - git__free(data->host); - data->host = original_host; - original_host = NULL; - } - - if (!error) { - const char *path = strchr(path_search_start, '/'); - size_t pathlen = strlen(path); - size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; - - if (suffixlen && - !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) { - git__free(data->path); - data->path = git__strndup(path, pathlen - suffixlen); - } else { - git__free(data->path); - data->path = git__strdup(path); - } - - /* Check for errors in the resulting data */ - if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { - git_error_set(GIT_ERROR_NET, "cross host redirect not allowed"); - error = -1; - } - } - -cleanup: - if (original_host) git__free(original_host); - return error; -} - -int gitno_connection_data_fmt(git_buf *buf, gitno_connection_data *d) -{ - if (d->host) { - git_buf_puts(buf, d->use_ssl ? prefix_https : prefix_http); - - if (d->user) { - git_buf_puts(buf, d->user); - - if (d->pass) { - git_buf_puts(buf, ":"); - git_buf_puts(buf, d->pass); - } - - git_buf_putc(buf, '@'); - } - - git_buf_puts(buf, d->host); - - if (d->port && strcmp(d->port, gitno__default_port(d))) { - git_buf_putc(buf, ':'); - git_buf_puts(buf, d->port); - } - } - - git_buf_puts(buf, d->path ? d->path : "/"); - - return git_buf_oom(buf) ? -1 : 0; -} - -void gitno_connection_data_free_ptrs(gitno_connection_data *d) -{ - git__free(d->host); d->host = NULL; - git__free(d->port); d->port = NULL; - git__free(d->path); d->path = NULL; - git__free(d->user); d->user = NULL; - git__free(d->pass); d->pass = NULL; -} - -int gitno_extract_url_parts( - char **host_out, - char **port_out, - char **path_out, - char **username_out, - char **password_out, - const char *url, - const char *default_port) -{ - struct http_parser_url u = {0}; - bool has_host, has_port, has_path, has_userinfo; - git_buf host = GIT_BUF_INIT, - port = GIT_BUF_INIT, - path = GIT_BUF_INIT, - username = GIT_BUF_INIT, - password = GIT_BUF_INIT; - int error = 0; - - if (http_parser_parse_url(url, strlen(url), false, &u)) { - git_error_set(GIT_ERROR_NET, "malformed URL '%s'", url); - error = GIT_EINVALIDSPEC; - goto done; - } - - has_host = !!(u.field_set & (1 << UF_HOST)); - has_port = !!(u.field_set & (1 << UF_PORT)); - has_path = !!(u.field_set & (1 << UF_PATH)); - has_userinfo = !!(u.field_set & (1 << UF_USERINFO)); - - if (has_host) { - const char *url_host = url + u.field_data[UF_HOST].off; - size_t url_host_len = u.field_data[UF_HOST].len; - git_buf_decode_percent(&host, url_host, url_host_len); - } - - if (has_port) { - const char *url_port = url + u.field_data[UF_PORT].off; - size_t url_port_len = u.field_data[UF_PORT].len; - git_buf_put(&port, url_port, url_port_len); - } else { - git_buf_puts(&port, default_port); - } - - if (has_path && path_out) { - const char *url_path = url + u.field_data[UF_PATH].off; - size_t url_path_len = u.field_data[UF_PATH].len; - git_buf_decode_percent(&path, url_path, url_path_len); - } else if (path_out) { - git_error_set(GIT_ERROR_NET, "invalid url, missing path"); - error = GIT_EINVALIDSPEC; - goto done; - } - - if (has_userinfo) { - const char *url_userinfo = url + u.field_data[UF_USERINFO].off; - size_t url_userinfo_len = u.field_data[UF_USERINFO].len; - const char *colon = memchr(url_userinfo, ':', url_userinfo_len); - - if (colon) { - const char *url_username = url_userinfo; - size_t url_username_len = colon - url_userinfo; - const char *url_password = colon + 1; - size_t url_password_len = url_userinfo_len - (url_username_len + 1); - - git_buf_decode_percent(&username, url_username, url_username_len); - git_buf_decode_percent(&password, url_password, url_password_len); - } else { - git_buf_decode_percent(&username, url_userinfo, url_userinfo_len); - } - } - - if (git_buf_oom(&host) || - git_buf_oom(&port) || - git_buf_oom(&path) || - git_buf_oom(&username) || - git_buf_oom(&password)) - return -1; - - *host_out = git_buf_detach(&host); - *port_out = git_buf_detach(&port); - if (path_out) - *path_out = git_buf_detach(&path); - *username_out = git_buf_detach(&username); - *password_out = git_buf_detach(&password); - -done: - git_buf_dispose(&host); - git_buf_dispose(&port); - git_buf_dispose(&path); - git_buf_dispose(&username); - git_buf_dispose(&password); - return error; -} diff -Nru libgit2-0.28.5+dfsg.1/src/netops.h libgit2-1.1.0+dfsg.1/src/netops.h --- libgit2-0.28.5+dfsg.1/src/netops.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/netops.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,6 +11,7 @@ #include "posix.h" #include "stream.h" +#include "net.h" #ifdef GIT_OPENSSL # include @@ -64,41 +65,4 @@ void gitno_consume(gitno_buffer *buf, const char *ptr); void gitno_consume_n(gitno_buffer *buf, size_t cons); -typedef struct gitno_connection_data { - char *host; - char *port; - char *path; - char *user; - char *pass; - bool use_ssl; -} gitno_connection_data; - -/* - * This replaces all the pointers in `data` with freshly-allocated strings, - * that the caller is responsible for freeing. - * `gitno_connection_data_free_ptrs` is good for this. - */ - -int gitno_connection_data_from_url( - gitno_connection_data *data, - const char *url, - const char *service_suffix); - -/* Format a URL into a buffer */ -int gitno_connection_data_fmt(git_buf *buf, gitno_connection_data *data); - -/* This frees all the pointers IN the struct, but not the struct itself. */ -void gitno_connection_data_free_ptrs(gitno_connection_data *data); - -int gitno_extract_url_parts( - char **host, - char **port, - char **path, - char **username, - char **password, - const char *url, - const char *default_port); - -const char *gitno__default_port(gitno_connection_data *data); - #endif diff -Nru libgit2-0.28.5+dfsg.1/src/notes.c libgit2-1.1.0+dfsg.1/src/notes.c --- libgit2-0.28.5+dfsg.1/src/notes.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/notes.c 2020-10-12 18:53:06.000000000 +0000 @@ -288,7 +288,7 @@ /* TODO: should we apply filters? */ /* create note object */ - if ((error = git_blob_create_frombuffer(&oid, repo, note, strlen(note))) < 0) + if ((error = git_blob_create_from_buffer(&oid, repo, note, strlen(note))) < 0) goto cleanup; if ((error = manipulate_note_in_tree_r( @@ -320,7 +320,7 @@ git_blob *blob) { git_note *note = NULL; - git_off_t blobsize; + git_object_size_t blobsize; note = git__malloc(sizeof(git_note)); GIT_ERROR_CHECK_ALLOC(note); @@ -808,8 +808,11 @@ git_oid_cpy(note_id, &item->id); - if (!(error = process_entry_path(item->path, annotated_id))) - git_iterator_advance(NULL, it); + if ((error = process_entry_path(item->path, annotated_id)) < 0) + return error; - return error; + if ((error = git_iterator_advance(NULL, it)) < 0 && error != GIT_ITEROVER) + return error; + + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/object.c libgit2-1.1.0+dfsg.1/src/object.c --- libgit2-0.28.5+dfsg.1/src/object.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/object.c 2020-10-12 18:53:06.000000000 +0000 @@ -21,6 +21,7 @@ bool git_object__strict_input_validation = true; extern int git_odb_hash(git_oid *out, const void *data, size_t len, git_object_t type); +size_t git_object__size(git_object_t type); typedef struct { const char *str; /* type name string */ @@ -85,7 +86,8 @@ GIT_ERROR_CHECK_ALLOC(object); object->cached.flags = GIT_CACHE_STORE_PARSED; object->cached.type = type; - git_odb_hash(&object->cached.oid, data, size, type); + if ((error = git_odb_hash(&object->cached.oid, data, size, type)) < 0) + return error; /* Parse raw object data */ def = &git_objects_table[type]; @@ -200,7 +202,7 @@ if (type != GIT_OBJECT_ANY && type != object->cached.type) { git_object_free(object); git_error_set(GIT_ERROR_INVALID, - "the requested type does not match the type in ODB"); + "the requested type does not match the type in the ODB"); return GIT_ENOTFOUND; } @@ -496,7 +498,7 @@ git_buf_sanitize(out); repo = git_object_owner(obj); - if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0) + if ((error = git_repository__configmap_lookup(&len, repo, GIT_CONFIGMAP_ABBREV)) < 0) return error; if ((error = git_repository_odb(&odb, repo)) < 0) @@ -549,4 +551,3 @@ return true; } - diff -Nru libgit2-0.28.5+dfsg.1/src/object.h libgit2-1.1.0+dfsg.1/src/object.h --- libgit2-0.28.5+dfsg.1/src/object.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/object.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,6 +11,8 @@ #include "repository.h" +#define GIT_OBJECT_SIZE_MAX UINT64_MAX + extern bool git_object__strict_input_validation; /** Base git object for inheritance */ diff -Nru libgit2-0.28.5+dfsg.1/src/odb.c libgit2-1.1.0+dfsg.1/src/odb.c --- libgit2-0.28.5+dfsg.1/src/odb.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/odb.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include #include "git2/object.h" #include "git2/sys/odb_backend.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "delta.h" #include "filter.h" @@ -44,8 +44,8 @@ static git_cache *odb_cache(git_odb *odb) { - if (odb->rc.owner != NULL) { - git_repository *owner = odb->rc.owner; + git_repository *owner = GIT_REFCOUNT_OWNER(odb); + if (owner != NULL) { return &owner->objects; } @@ -89,7 +89,7 @@ size_t *written, char *hdr, size_t hdr_size, - git_off_t obj_len, + git_object_size_t obj_len, git_object_t obj_type) { const char *type_str = git_object_type2string(obj_type); @@ -320,20 +320,26 @@ int git_odb_hashfile(git_oid *out, const char *path, git_object_t type) { - git_off_t size; - int result, fd = git_futils_open_ro(path); - if (fd < 0) + uint64_t size; + int fd, error = 0; + + if ((fd = git_futils_open_ro(path)) < 0) return fd; - if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) { + if ((error = git_futils_filesize(&size, fd)) < 0) + goto done; + + if (!git__is_sizet(size)) { git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems"); - p_close(fd); - return -1; + error = -1; + goto done; } - result = git_odb__hashfd(out, fd, (size_t)size, type); + error = git_odb__hashfd(out, fd, (size_t)size, type); + +done: p_close(fd); - return result; + return error; } int git_odb_hash(git_oid *id, const void *data, size_t len, git_object_t type) @@ -385,7 +391,7 @@ git__free(stream); } -static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, git_off_t size, git_object_t type) +static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, git_object_size_t size, git_object_t type) { fake_wstream *stream; size_t blobsize; @@ -448,7 +454,7 @@ return -1; } if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) { - git_cache_free(&db->own_cache); + git_cache_dispose(&db->own_cache); git__free(db); return -1; } @@ -548,6 +554,7 @@ #else if (p_stat(objects_dir, &st) < 0) { if (as_alternates) + /* this should warn */ return 0; git_error_set(GIT_ERROR_ODB, "failed to load object database in '%s'", objects_dir); @@ -657,7 +664,7 @@ int git_odb__set_caps(git_odb *odb, int caps) { if (caps == GIT_ODB_CAP_FROM_OWNER) { - git_repository *repo = odb->rc.owner; + git_repository *repo = GIT_REFCOUNT_OWNER(odb); int val; if (!repo) { @@ -665,7 +672,7 @@ return -1; } - if (!git_repository__cvar(&val, repo, GIT_CVAR_FSYNCOBJECTFILES)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_FSYNCOBJECTFILES)) odb->do_fsync = !!val; } @@ -686,7 +693,7 @@ } git_vector_free(&db->backends); - git_cache_free(&db->own_cache); + git_cache_dispose(&db->own_cache); git__memzero(db, sizeof(*db)); git__free(db); @@ -766,7 +773,7 @@ assert(db && id); - if (git_oid_iszero(id)) + if (git_oid_is_zero(id)) return 0; if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { @@ -994,7 +1001,7 @@ *out = NULL; - if (git_oid_iszero(id)) + if (git_oid_is_zero(id)) return error_null_oid(GIT_ENOTFOUND, "cannot read object"); if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { @@ -1099,7 +1106,7 @@ assert(out && db && id); - if (git_oid_iszero(id)) + if (git_oid_is_zero(id)) return error_null_oid(GIT_ENOTFOUND, "cannot read object"); *out = git_cache_get_raw(odb_cache(db), id); @@ -1123,7 +1130,7 @@ size_t _unused; int error; - if (git_oid_iszero(id)) + if (git_oid_is_zero(id)) return error_null_oid(GIT_ENOTFOUND, "cannot get object type"); if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { @@ -1276,20 +1283,21 @@ git_oid *oid, git_odb *db, const void *data, size_t len, git_object_t type) { size_t i; - int error = GIT_ERROR; + int error; git_odb_stream *stream; assert(oid && db); - git_odb_hash(oid, data, len, type); + if ((error = git_odb_hash(oid, data, len, type)) < 0) + return error; - if (git_oid_iszero(oid)) + if (git_oid_is_zero(oid)) return error_null_oid(GIT_EINVALID, "cannot write object"); if (git_odb__freshen(db, oid)) return 0; - for (i = 0; i < db->backends.length && error < 0; ++i) { + for (i = 0, error = GIT_ERROR; i < db->backends.length && error < 0; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; @@ -1318,7 +1326,7 @@ return error; } -static int hash_header(git_hash_ctx *ctx, git_off_t size, git_object_t type) +static int hash_header(git_hash_ctx *ctx, git_object_size_t size, git_object_t type) { char header[64]; size_t hdrlen; @@ -1332,7 +1340,7 @@ } int git_odb_open_wstream( - git_odb_stream **stream, git_odb *db, git_off_t size, git_object_t type) + git_odb_stream **stream, git_odb *db, git_object_size_t size, git_object_t type) { size_t i, writes = 0; int error = GIT_ERROR; @@ -1468,7 +1476,7 @@ return error; } -int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer_progress_cb progress_cb, void *progress_payload) +int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_indexer_progress_cb progress_cb, void *progress_payload) { size_t i, writes = 0; int error = GIT_ERROR; @@ -1497,12 +1505,25 @@ return error; } -void *git_odb_backend_malloc(git_odb_backend *backend, size_t len) +void *git_odb_backend_data_alloc(git_odb_backend *backend, size_t len) { GIT_UNUSED(backend); return git__malloc(len); } +#ifndef GIT_DEPRECATE_HARD +void *git_odb_backend_malloc(git_odb_backend *backend, size_t len) +{ + return git_odb_backend_data_alloc(backend, len); +} +#endif + +void git_odb_backend_data_free(git_odb_backend *backend, void *data) +{ + GIT_UNUSED(backend); + git__free(data); +} + int git_odb_refresh(struct git_odb *db) { size_t i; diff -Nru libgit2-0.28.5+dfsg.1/src/odb.h libgit2-1.1.0+dfsg.1/src/odb.h --- libgit2-0.28.5+dfsg.1/src/odb.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/odb.h 2020-10-12 18:53:06.000000000 +0000 @@ -70,7 +70,8 @@ /* * Format the object header such as it would appear in the on-disk object */ -int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, git_off_t obj_len, git_object_t obj_type); +int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, git_object_size_t obj_len, git_object_t obj_type); + /* * Hash an open file descriptor. * This is a performance call when the contents of a fd need to be hashed, @@ -95,7 +96,7 @@ * symlink, then the raw contents of the symlink will be hashed. Otherwise, * this will fallback to `git_odb__hashfd`. * - * The hash type for this call is always `GIT_OBJIECT_BLOB` because + * The hash type for this call is always `GIT_OBJECT_BLOB` because * symlinks may only point to blobs. */ int git_odb__hashlink(git_oid *out, const char *path); diff -Nru libgit2-0.28.5+dfsg.1/src/odb_loose.c libgit2-1.1.0+dfsg.1/src/odb_loose.c --- libgit2-0.28.5+dfsg.1/src/odb_loose.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/odb_loose.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include #include "git2/object.h" #include "git2/sys/odb_backend.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "odb.h" #include "delta.h" @@ -304,7 +304,7 @@ * (including the initial sequence in the head buffer). */ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) || - (body = git__malloc(alloc_size)) == NULL) { + (body = git__calloc(1, alloc_size)) == NULL) { error = -1; goto done; } @@ -386,8 +386,8 @@ git_rawobj *out, const unsigned char *data, size_t len) { git_zstream zs = GIT_ZSTREAM_INIT; - obj_hdr hdr; - unsigned char inflated[MAX_HEADER_LEN]; + obj_hdr hdr = {0}; + unsigned char inflated[MAX_HEADER_LEN] = {0}; size_t header_len, inflated_len = sizeof(inflated); int error; @@ -408,7 +408,8 @@ static int read_header_loose(git_rawobj *out, git_buf *loc) { unsigned char obj[1024]; - int fd, obj_len, error; + ssize_t obj_len; + int fd, error; assert(out && loc); @@ -417,10 +418,14 @@ out->data = NULL; - if ((error = fd = git_futils_open_ro(loc->ptr)) < 0 || - (error = obj_len = p_read(fd, obj, sizeof(obj))) < 0) + if ((error = fd = git_futils_open_ro(loc->ptr)) < 0) goto done; + if ((obj_len = p_read(fd, obj, sizeof(obj))) < 0) { + error = (int)obj_len; + goto done; + } + if (!is_zlib_compressed_data(obj, (size_t)obj_len)) error = read_header_loose_packlike(out, obj, (size_t)obj_len); else @@ -819,7 +824,7 @@ return flags; } -static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_object_t type) +static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_object_size_t length, git_object_t type) { loose_backend *backend; loose_writestream *stream = NULL; @@ -828,7 +833,7 @@ size_t hdrlen; int error; - assert(_backend && length >= 0); + assert(_backend); backend = (loose_backend *)_backend; *stream_out = NULL; @@ -871,6 +876,8 @@ size_t start_remain = stream->start_len - stream->start_read; int total = 0, error; + buffer_len = min(buffer_len, INT_MAX); + /* * if we read more than just the header in the initial read, play * that back for the caller. @@ -882,20 +889,20 @@ buffer += chunk; stream->start_read += chunk; - total += chunk; + total += (int)chunk; buffer_len -= chunk; } if (buffer_len) { - size_t chunk = min(buffer_len, INT_MAX); + size_t chunk = buffer_len; if ((error = git_zstream_get_output(buffer, &chunk, &stream->zstream)) < 0) return error; - total += chunk; + total += (int)chunk; } - return total; + return (int)total; } static void loose_backend__readstream_free(git_odb_stream *_stream) diff -Nru libgit2-0.28.5+dfsg.1/src/odb_mempack.c libgit2-1.1.0+dfsg.1/src/odb_mempack.c --- libgit2-0.28.5+dfsg.1/src/odb_mempack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/odb_mempack.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include "git2/object.h" #include "git2/sys/odb_backend.h" #include "git2/sys/mempack.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "odb.h" #include "array.h" @@ -37,15 +37,9 @@ { struct memory_packer_db *db = (struct memory_packer_db *)_backend; struct memobject *obj = NULL; - size_t pos; size_t alloc_len; - int rval; - pos = git_oidmap_put(db->objects, oid, &rval); - if (rval < 0) - return -1; - - if (rval == 0) + if (git_oidmap_exists(db->objects, oid)) return 0; GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len); @@ -57,8 +51,8 @@ obj->len = len; obj->type = type; - git_oidmap_set_key_at(db->objects, pos, &obj->oid); - git_oidmap_set_value_at(db->objects, pos, obj); + if (git_oidmap_set(db->objects, &obj->oid, obj) < 0) + return -1; if (type == GIT_OBJECT_COMMIT) { struct memobject **store = git_array_alloc(db->commits); @@ -79,15 +73,11 @@ static int impl__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid) { struct memory_packer_db *db = (struct memory_packer_db *)backend; - struct memobject *obj = NULL; - size_t pos; + struct memobject *obj; - pos = git_oidmap_lookup_index(db->objects, oid); - if (!git_oidmap_valid_index(db->objects, pos)) + if ((obj = git_oidmap_get(db->objects, oid)) == NULL) return GIT_ENOTFOUND; - obj = git_oidmap_value_at(db->objects, pos); - *len_p = obj->len; *type_p = obj->type; *buffer_p = git__malloc(obj->len); @@ -100,15 +90,11 @@ static int impl__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid) { struct memory_packer_db *db = (struct memory_packer_db *)backend; - struct memobject *obj = NULL; - size_t pos; + struct memobject *obj; - pos = git_oidmap_lookup_index(db->objects, oid); - if (!git_oidmap_valid_index(db->objects, pos)) + if ((obj = git_oidmap_get(db->objects, oid)) == NULL) return GIT_ENOTFOUND; - obj = git_oidmap_value_at(db->objects, pos); - *len_p = obj->len; *type_p = obj->type; return 0; @@ -124,6 +110,8 @@ if (git_packbuilder_new(&packbuilder, repo) < 0) return -1; + git_packbuilder_set_threads(packbuilder, 0); + for (i = 0; i < db->commits.size; ++i) { struct memobject *commit = db->commits.ptr[i]; @@ -139,7 +127,7 @@ return err; } -void git_mempack_reset(git_odb_backend *_backend) +int git_mempack_reset(git_odb_backend *_backend) { struct memory_packer_db *db = (struct memory_packer_db *)_backend; struct memobject *object = NULL; @@ -151,6 +139,8 @@ git_array_clear(db->commits); git_oidmap_clear(db->objects); + + return 0; } static void impl__free(git_odb_backend *_backend) @@ -171,7 +161,8 @@ db = git__calloc(1, sizeof(struct memory_packer_db)); GIT_ERROR_CHECK_ALLOC(db); - db->objects = git_oidmap_alloc(); + if (git_oidmap_new(&db->objects) < 0) + return -1; db->parent.version = GIT_ODB_BACKEND_VERSION; db->parent.read = &impl__read; diff -Nru libgit2-0.28.5+dfsg.1/src/odb_pack.c libgit2-1.1.0+dfsg.1/src/odb_pack.c --- libgit2-0.28.5+dfsg.1/src/odb_pack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/odb_pack.c 2020-10-12 18:53:06.000000000 +0000 @@ -11,11 +11,10 @@ #include "git2/repository.h" #include "git2/indexer.h" #include "git2/sys/odb_backend.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "odb.h" #include "delta.h" -#include "sha1_lookup.h" #include "mwindow.h" #include "pack.h" @@ -485,7 +484,7 @@ return 0; } -static int pack_backend__writepack_append(struct git_odb_writepack *_writepack, const void *data, size_t size, git_transfer_progress *stats) +static int pack_backend__writepack_append(struct git_odb_writepack *_writepack, const void *data, size_t size, git_indexer_progress *stats) { struct pack_writepack *writepack = (struct pack_writepack *)_writepack; @@ -494,7 +493,7 @@ return git_indexer_append(writepack->indexer, data, size, stats); } -static int pack_backend__writepack_commit(struct git_odb_writepack *_writepack, git_transfer_progress *stats) +static int pack_backend__writepack_commit(struct git_odb_writepack *_writepack, git_indexer_progress *stats) { struct pack_writepack *writepack = (struct pack_writepack *)_writepack; @@ -516,7 +515,7 @@ static int pack_backend__writepack(struct git_odb_writepack **out, git_odb_backend *_backend, git_odb *odb, - git_transfer_progress_cb progress_cb, + git_indexer_progress_cb progress_cb, void *progress_payload) { git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT; diff -Nru libgit2-0.28.5+dfsg.1/src/offmap.c libgit2-1.1.0+dfsg.1/src/offmap.c --- libgit2-0.28.5+dfsg.1/src/offmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/offmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,13 +14,17 @@ #define kfree git__free #include "khash.h" -__KHASH_TYPE(off, git_off_t, void *) +__KHASH_TYPE(off, off64_t, void *) -__KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) +__KHASH_IMPL(off, static kh_inline, off64_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) -git_offmap *git_offmap_alloc(void) + +int git_offmap_new(git_offmap **out) { - return kh_init(off); + *out = kh_init(off); + GIT_ERROR_CHECK_ALLOC(*out); + + return 0; } void git_offmap_free(git_offmap *map) @@ -33,81 +37,65 @@ kh_clear(off, map); } -size_t git_offmap_num_entries(git_offmap *map) +size_t git_offmap_size(git_offmap *map) { return kh_size(map); } -size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key) -{ - return kh_get(off, map, key); -} - -int git_offmap_valid_index(git_offmap *map, size_t idx) +void *git_offmap_get(git_offmap *map, const off64_t key) { - return idx != kh_end(map); -} - -int git_offmap_exists(git_offmap *map, const git_off_t key) -{ - return kh_get(off, map, key) != kh_end(map); + size_t idx = kh_get(off, map, key); + if (idx == kh_end(map) || !kh_exist(map, idx)) + return NULL; + return kh_val(map, idx); } -int git_offmap_has_data(git_offmap *map, size_t idx) +int git_offmap_set(git_offmap *map, const off64_t key, void *value) { - return kh_exist(map, idx); -} + size_t idx; + int rval; -git_off_t git_offmap_key_at(git_offmap *map, size_t idx) -{ - return kh_key(map, idx); -} + idx = kh_put(off, map, key, &rval); + if (rval < 0) + return -1; -void *git_offmap_value_at(git_offmap *map, size_t idx) -{ - return kh_val(map, idx); -} + if (rval == 0) + kh_key(map, idx) = key; -void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value) -{ kh_val(map, idx) = value; + + return 0; } -void git_offmap_delete_at(git_offmap *map, size_t idx) +int git_offmap_delete(git_offmap *map, const off64_t key) { + khiter_t idx = kh_get(off, map, key); + if (idx == kh_end(map)) + return GIT_ENOTFOUND; kh_del(off, map, idx); + return 0; } -int git_offmap_put(git_offmap *map, const git_off_t key, int *err) +int git_offmap_exists(git_offmap *map, const off64_t key) { - return kh_put(off, map, key, err); + return kh_get(off, map, key) != kh_end(map); } -void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval) +int git_offmap_iterate(void **value, git_offmap *map, size_t *iter, off64_t *key) { - khiter_t idx = kh_put(off, map, key, rval); + size_t i = *iter; - if ((*rval) >= 0) { - if ((*rval) == 0) - kh_key(map, idx) = key; - kh_val(map, idx) = value; - } -} + while (i < map->n_buckets && !kh_exist(map, i)) + i++; -void git_offmap_delete(git_offmap *map, const git_off_t key) -{ - khiter_t idx = git_offmap_lookup_index(map, key); - if (git_offmap_valid_index(map, idx)) - git_offmap_delete_at(map, idx); -} + if (i >= map->n_buckets) + return GIT_ITEROVER; -size_t git_offmap_begin(git_offmap *map) -{ - GIT_UNUSED(map); - return 0; -} + if (key) + *key = kh_key(map, i); + if (value) + *value = kh_value(map, i); + *iter = ++i; -size_t git_offmap_end(git_offmap *map) -{ - return map->n_buckets; + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/offmap.h libgit2-1.1.0+dfsg.1/src/offmap.h --- libgit2-0.28.5+dfsg.1/src/offmap.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/offmap.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,44 +11,122 @@ #include "git2/types.h" +/** A map with `off64_t`s as key. */ typedef struct kh_off_s git_offmap; -git_offmap *git_offmap_alloc(void); +/** + * Allocate a new `off64_t` map. + * + * @param out Pointer to the map that shall be allocated. + * @return 0 on success, an error code if allocation has failed. + */ +int git_offmap_new(git_offmap **out); + +/** + * Free memory associated with the map. + * + * Note that this function will _not_ free values added to this + * map. + * + * @param map Pointer to the map that is to be free'd. May be + * `NULL`. + */ void git_offmap_free(git_offmap *map); -void git_offmap_clear(git_offmap *map); - -size_t git_offmap_num_entries(git_offmap *map); -size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key); -int git_offmap_valid_index(git_offmap *map, size_t idx); +/** + * Clear all entries from the map. + * + * This function will remove all entries from the associated map. + * Memory associated with it will not be released, though. + * + * @param map Pointer to the map that shall be cleared. May be + * `NULL`. + */ +void git_offmap_clear(git_offmap *map); -int git_offmap_exists(git_offmap *map, const git_off_t key); -int git_offmap_has_data(git_offmap *map, size_t idx); +/** + * Return the number of elements in the map. + * + * @parameter map map containing the elements + * @return number of elements in the map + */ +size_t git_offmap_size(git_offmap *map); + +/** + * Return value associated with the given key. + * + * @param map map to search key in + * @param key key to search for + * @return value associated with the given key or NULL if the key was not found + */ +void *git_offmap_get(git_offmap *map, const off64_t key); + +/** + * Set the entry for key to value. + * + * If the map has no corresponding entry for the given key, a new + * entry will be created with the given value. If an entry exists + * already, its value will be updated to match the given value. + * + * @param map map to create new entry in + * @param key key to set + * @param value value to associate the key with; may be NULL + * @return zero if the key was successfully set, a negative error + * code otherwise + */ +int git_offmap_set(git_offmap *map, const off64_t key, void *value); + +/** + * Delete an entry from the map. + * + * Delete the given key and its value from the map. If no such + * key exists, this will do nothing. + * + * @param map map to delete key in + * @param key key to delete + * @return `0` if the key has been deleted, GIT_ENOTFOUND if no + * such key was found, a negative code in case of an + * error + */ +int git_offmap_delete(git_offmap *map, const off64_t key); + +/** + * Check whether a key exists in the given map. + * + * @param map map to query for the key + * @param key key to search for + * @return 0 if the key has not been found, 1 otherwise + */ +int git_offmap_exists(git_offmap *map, const off64_t key); + +/** + * Iterate over entries of the map. + * + * This functions allows to iterate over all key-value entries of + * the map. The current position is stored in the `iter` variable + * and should be initialized to `0` before the first call to this + * function. + * + * @param map map to iterate over + * @param value pointer to the variable where to store the current + * value. May be NULL. + * @param iter iterator storing the current position. Initialize + * with zero previous to the first call. + * @param key pointer to the variable where to store the current + * key. May be NULL. + * @return `0` if the next entry was correctly retrieved. + * GIT_ITEROVER if no entries are left. A negative error + * code otherwise. + */ +int git_offmap_iterate(void **value, git_offmap *map, size_t *iter, off64_t *key); -git_off_t git_offmap_key_at(git_offmap *map, size_t idx); -void *git_offmap_value_at(git_offmap *map, size_t idx); -void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value); -void git_offmap_delete_at(git_offmap *map, size_t idx); - -int git_offmap_put(git_offmap *map, const git_off_t key, int *err); -void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval); -void git_offmap_delete(git_offmap *map, const git_off_t key); - -size_t git_offmap_begin(git_offmap *map); -size_t git_offmap_end(git_offmap *map); - -#define git_offmap_foreach(h, kvar, vvar, code) { size_t __i; \ - for (__i = git_offmap_begin(h); __i != git_offmap_end(h); ++__i) { \ - if (!git_offmap_has_data(h,__i)) continue; \ - (kvar) = git_offmap_key_at(h,__i); \ - (vvar) = git_offmap_value_at(h,__i); \ +#define git_offmap_foreach(h, kvar, vvar, code) { size_t __i = 0; \ + while (git_offmap_iterate((void **) &(vvar), h, &__i, &(kvar)) == 0) { \ code; \ } } -#define git_offmap_foreach_value(h, vvar, code) { size_t __i; \ - for (__i = git_offmap_begin(h); __i != git_offmap_end(h); ++__i) { \ - if (!git_offmap_has_data(h,__i)) continue; \ - (vvar) = git_offmap_value_at(h,__i); \ +#define git_offmap_foreach_value(h, vvar, code) { size_t __i = 0; \ + while (git_offmap_iterate((void **) &(vvar), h, &__i, NULL) == 0) { \ code; \ } } diff -Nru libgit2-0.28.5+dfsg.1/src/oid.c libgit2-1.1.0+dfsg.1/src/oid.c --- libgit2-0.28.5+dfsg.1/src/oid.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/oid.c 2020-10-12 18:53:06.000000000 +0000 @@ -64,13 +64,13 @@ return str; } -void git_oid_nfmt(char *str, size_t n, const git_oid *oid) +int git_oid_nfmt(char *str, size_t n, const git_oid *oid) { size_t i, max_i; if (!oid) { memset(str, 0, n); - return; + return 0; } if (n > GIT_OID_HEXSZ) { memset(&str[GIT_OID_HEXSZ], 0, n - GIT_OID_HEXSZ); @@ -84,14 +84,16 @@ if (n & 1) *str++ = to_hex[oid->id[i] >> 4]; + + return 0; } -void git_oid_fmt(char *str, const git_oid *oid) +int git_oid_fmt(char *str, const git_oid *oid) { - git_oid_nfmt(str, GIT_OID_HEXSZ, oid); + return git_oid_nfmt(str, GIT_OID_HEXSZ, oid); } -void git_oid_pathfmt(char *str, const git_oid *oid) +int git_oid_pathfmt(char *str, const git_oid *oid) { size_t i; @@ -99,6 +101,8 @@ *str++ = '/'; for (i = 1; i < sizeof(oid->id); i++) str = fmt_one(str, oid->id[i]); + + return 0; } char *git_oid_tostr_s(const git_oid *oid) @@ -167,14 +171,16 @@ git_buf_putc(buf, '\n'); } -void git_oid_fromraw(git_oid *out, const unsigned char *raw) +int git_oid_fromraw(git_oid *out, const unsigned char *raw) { memcpy(out->id, raw, sizeof(out->id)); + return 0; } -void git_oid_cpy(git_oid *out, const git_oid *src) +int git_oid_cpy(git_oid *out, const git_oid *src) { memcpy(out->id, src->id, sizeof(out->id)); + return 0; } int git_oid_cmp(const git_oid *a, const git_oid *b) @@ -237,7 +243,7 @@ return git_oid_strcmp(oid_a, str) == 0 ? 0 : -1; } -int git_oid_iszero(const git_oid *oid_a) +int git_oid_is_zero(const git_oid *oid_a) { const unsigned char *a = oid_a->id; unsigned int i; @@ -247,6 +253,13 @@ return 1; } +#ifndef GIT_DEPRECATE_HARD +int git_oid_iszero(const git_oid *oid_a) +{ + return git_oid_is_zero(oid_a); +} +#endif + typedef short node_index; typedef union { diff -Nru libgit2-0.28.5+dfsg.1/src/oidmap.c libgit2-1.1.0+dfsg.1/src/oidmap.c --- libgit2-0.28.5+dfsg.1/src/oidmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/oidmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,9 +25,12 @@ __KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal) -git_oidmap *git_oidmap_alloc() +int git_oidmap_new(git_oidmap **out) { - return kh_init(oid); + *out = kh_init(oid); + GIT_ERROR_CHECK_ALLOC(*out); + + return 0; } void git_oidmap_free(git_oidmap *map) @@ -45,81 +48,60 @@ return kh_size(map); } -size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key) -{ - return kh_get(oid, map, key); -} - -int git_oidmap_valid_index(git_oidmap *map, size_t idx) -{ - return idx != kh_end(map); -} - -int git_oidmap_exists(git_oidmap *map, const git_oid *key) +void *git_oidmap_get(git_oidmap *map, const git_oid *key) { - return kh_get(oid, map, key) != kh_end(map); -} - -int git_oidmap_has_data(git_oidmap *map, size_t idx) -{ - return kh_exist(map, idx); + size_t idx = kh_get(oid, map, key); + if (idx == kh_end(map) || !kh_exist(map, idx)) + return NULL; + return kh_val(map, idx); } -const git_oid *git_oidmap_key(git_oidmap *map, size_t idx) +int git_oidmap_set(git_oidmap *map, const git_oid *key, void *value) { - return kh_key(map, idx); -} + size_t idx; + int rval; -void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key) -{ - kh_key(map, idx) = key; -} + idx = kh_put(oid, map, key, &rval); + if (rval < 0) + return -1; -void *git_oidmap_value_at(git_oidmap *map, size_t idx) -{ - return kh_val(map, idx); -} + if (rval == 0) + kh_key(map, idx) = key; -void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value) -{ kh_val(map, idx) = value; + + return 0; } -void git_oidmap_delete_at(git_oidmap *map, size_t idx) +int git_oidmap_delete(git_oidmap *map, const git_oid *key) { + khiter_t idx = kh_get(oid, map, key); + if (idx == kh_end(map)) + return GIT_ENOTFOUND; kh_del(oid, map, idx); + return 0; } -int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err) +int git_oidmap_exists(git_oidmap *map, const git_oid *key) { - return kh_put(oid, map, key, err); + return kh_get(oid, map, key) != kh_end(map); } -void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval) +int git_oidmap_iterate(void **value, git_oidmap *map, size_t *iter, const git_oid **key) { - khiter_t idx = kh_put(oid, map, key, rval); + size_t i = *iter; - if ((*rval) >= 0) { - if ((*rval) == 0) - kh_key(map, idx) = key; - kh_val(map, idx) = value; - } -} + while (i < map->n_buckets && !kh_exist(map, i)) + i++; -void git_oidmap_delete(git_oidmap *map, const git_oid *key) -{ - khiter_t idx = git_oidmap_lookup_index(map, key); - if (git_oidmap_valid_index(map, idx)) - git_oidmap_delete_at(map, idx); -} + if (i >= map->n_buckets) + return GIT_ITEROVER; -size_t git_oidmap_begin(git_oidmap *map) -{ - GIT_UNUSED(map); - return 0; -} + if (key) + *key = kh_key(map, i); + if (value) + *value = kh_value(map, i); + *iter = ++i; -size_t git_oidmap_end(git_oidmap *map) -{ - return map->n_buckets; + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/oidmap.h libgit2-1.1.0+dfsg.1/src/oidmap.h --- libgit2-0.28.5+dfsg.1/src/oidmap.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/oidmap.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,37 +11,117 @@ #include "git2/oid.h" +/** A map with `git_oid`s as key. */ typedef struct kh_oid_s git_oidmap; -git_oidmap *git_oidmap_alloc(void); +/** + * Allocate a new OID map. + * + * @param out Pointer to the map that shall be allocated. + * @return 0 on success, an error code if allocation has failed. + */ +int git_oidmap_new(git_oidmap **out); + +/** + * Free memory associated with the map. + * + * Note that this function will _not_ free values added to this + * map. + * + * @param map Pointer to the map that is to be free'd. May be + * `NULL`. + */ void git_oidmap_free(git_oidmap *map); + +/** + * Clear all entries from the map. + * + * This function will remove all entries from the associated map. + * Memory associated with it will not be released, though. + * + * @param map Pointer to the map that shall be cleared. May be + * `NULL`. + */ void git_oidmap_clear(git_oidmap *map); +/** + * Return the number of elements in the map. + * + * @parameter map map containing the elements + * @return number of elements in the map + */ size_t git_oidmap_size(git_oidmap *map); -size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key); -int git_oidmap_valid_index(git_oidmap *map, size_t idx); - +/** + * Return value associated with the given key. + * + * @param map map to search key in + * @param key key to search for + * @return value associated with the given key or NULL if the key was not found + */ +void *git_oidmap_get(git_oidmap *map, const git_oid *key); + +/** + * Set the entry for key to value. + * + * If the map has no corresponding entry for the given key, a new + * entry will be created with the given value. If an entry exists + * already, its value will be updated to match the given value. + * + * @param map map to create new entry in + * @param key key to set + * @param value value to associate the key with; may be NULL + * @return zero if the key was successfully set, a negative error + * code otherwise + */ +int git_oidmap_set(git_oidmap *map, const git_oid *key, void *value); + +/** + * Delete an entry from the map. + * + * Delete the given key and its value from the map. If no such + * key exists, this will do nothing. + * + * @param map map to delete key in + * @param key key to delete + * @return `0` if the key has been deleted, GIT_ENOTFOUND if no + * such key was found, a negative code in case of an + * error + */ +int git_oidmap_delete(git_oidmap *map, const git_oid *key); + +/** + * Check whether a key exists in the given map. + * + * @param map map to query for the key + * @param key key to search for + * @return 0 if the key has not been found, 1 otherwise + */ int git_oidmap_exists(git_oidmap *map, const git_oid *key); -int git_oidmap_has_data(git_oidmap *map, size_t idx); -const git_oid *git_oidmap_key(git_oidmap *map, size_t idx); -void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key); -void *git_oidmap_value_at(git_oidmap *map, size_t idx); -void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value); -void git_oidmap_delete_at(git_oidmap *map, size_t idx); - -int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err); -void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval); -void git_oidmap_delete(git_oidmap *map, const git_oid *key); - -size_t git_oidmap_begin(git_oidmap *map); -size_t git_oidmap_end(git_oidmap *map); - -#define git_oidmap_foreach_value(h, vvar, code) { size_t __i; \ - for (__i = git_oidmap_begin(h); __i != git_oidmap_end(h); ++__i) { \ - if (!git_oidmap_has_data(h,__i)) continue; \ - (vvar) = git_oidmap_value_at(h,__i); \ +/** + * Iterate over entries of the map. + * + * This functions allows to iterate over all key-value entries of + * the map. The current position is stored in the `iter` variable + * and should be initialized to `0` before the first call to this + * function. + * + * @param map map to iterate over + * @param value pointer to the variable where to store the current + * value. May be NULL. + * @param iter iterator storing the current position. Initialize + * with zero previous to the first call. + * @param key pointer to the variable where to store the current + * key. May be NULL. + * @return `0` if the next entry was correctly retrieved. + * GIT_ITEROVER if no entries are left. A negative error + * code otherwise. + */ +int git_oidmap_iterate(void **value, git_oidmap *map, size_t *iter, const git_oid **key); + +#define git_oidmap_foreach_value(h, vvar, code) { size_t __i = 0; \ + while (git_oidmap_iterate((void **) &(vvar), h, &__i, NULL) == 0) { \ code; \ } } diff -Nru libgit2-0.28.5+dfsg.1/src/pack.c libgit2-1.1.0+dfsg.1/src/pack.c --- libgit2-0.28.5+dfsg.1/src/pack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pack.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,22 +7,22 @@ #include "pack.h" -#include "odb.h" #include "delta.h" -#include "sha1_lookup.h" +#include "futils.h" #include "mwindow.h" -#include "fileops.h" +#include "odb.h" #include "oid.h" -#include +/* Option to bypass checking existence of '.keep' files */ +bool git_disable_pack_keep_file_checks = false; static int packfile_open(struct git_pack_file *p); -static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n); +static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n); static int packfile_unpack_compressed( git_rawobj *obj, struct git_pack_file *p, git_mwindow **w_curs, - git_off_t *curpos, + off64_t *curpos, size_t size, git_object_t type); @@ -34,7 +34,7 @@ * GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ. */ static int pack_entry_find_offset( - git_off_t *offset_out, + off64_t *offset_out, git_oid *found_oid, struct git_pack_file *p, const git_oid *short_oid, @@ -89,8 +89,8 @@ static int cache_init(git_pack_cache *cache) { - cache->entries = git_offmap_alloc(); - GIT_ERROR_CHECK_ALLOC(cache->entries); + if (git_offmap_new(&cache->entries) < 0) + return -1; cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT; @@ -106,17 +106,14 @@ return 0; } -static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset) +static git_pack_cache_entry *cache_get(git_pack_cache *cache, off64_t offset) { - git_pack_cache_entry *entry = NULL; - size_t k; + git_pack_cache_entry *entry; if (git_mutex_lock(&cache->lock) < 0) return NULL; - k = git_offmap_lookup_index(cache->entries, offset); - if (git_offmap_valid_index(cache->entries, k)) { /* found it */ - entry = git_offmap_value_at(cache->entries, k); + if ((entry = git_offmap_get(cache->entries, offset)) != NULL) { git_atomic_inc(&entry->refcount); entry->last_usage = cache->use_ctr++; } @@ -128,7 +125,7 @@ /* Run with the cache lock held */ static void free_lowest_entry(git_pack_cache *cache) { - git_off_t offset; + off64_t offset; git_pack_cache_entry *entry; git_offmap_foreach(cache->entries, offset, entry, { @@ -144,11 +141,10 @@ git_pack_cache_entry **cached_out, git_pack_cache *cache, git_rawobj *base, - git_off_t offset) + off64_t offset) { git_pack_cache_entry *entry; - int error, exists = 0; - size_t k; + int exists; if (base->len > GIT_PACK_CACHE_SIZE_LIMIT) return -1; @@ -166,9 +162,7 @@ while (cache->memory_used + base->len > cache->memory_limit) free_lowest_entry(cache); - k = git_offmap_put(cache->entries, offset, &error); - assert(error != 0); - git_offmap_set_value_at(cache->entries, k, entry); + git_offmap_set(cache->entries, offset, entry); cache->memory_used += entry->raw.len; *cached_out = entry; @@ -348,7 +342,7 @@ static unsigned char *pack_window_open( struct git_pack_file *p, git_mwindow **w_cursor, - git_off_t offset, + off64_t offset, unsigned int *left) { if (p->mwf.fd == -1 && packfile_open(p) < 0) @@ -444,7 +438,7 @@ git_object_t *type_p, git_mwindow_file *mwf, git_mwindow **w_curs, - git_off_t *curpos) + off64_t *curpos) { unsigned char *base; unsigned int left; @@ -477,13 +471,13 @@ size_t *size_p, git_object_t *type_p, struct git_pack_file *p, - git_off_t offset) + off64_t offset) { git_mwindow *w_curs = NULL; - git_off_t curpos = offset; + off64_t curpos = offset; size_t size; git_object_t type; - git_off_t base_offset; + off64_t base_offset; int error; error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos); @@ -494,8 +488,12 @@ size_t base_size; git_packfile_stream stream; - base_offset = get_delta_base(p, &w_curs, &curpos, type, offset); + error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset); git_mwindow_close(&w_curs); + + if (error < 0) + return error; + if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0) return error; error = git_delta_read_header_fromstream(&base_size, size_p, &stream); @@ -514,8 +512,12 @@ return error; if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA) break; - base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset); + + error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset); git_mwindow_close(&w_curs); + + if (error < 0) + return error; } *type_p = type; @@ -531,13 +533,13 @@ * cache, we stop calculating there. */ static int pack_dependency_chain(git_dependency_chain *chain_out, - git_pack_cache_entry **cached_out, git_off_t *cached_off, + git_pack_cache_entry **cached_out, off64_t *cached_off, struct pack_chain_elem *small_stack, size_t *stack_sz, - struct git_pack_file *p, git_off_t obj_offset) + struct git_pack_file *p, off64_t obj_offset) { git_dependency_chain chain = GIT_ARRAY_INIT; git_mwindow *w_curs = NULL; - git_off_t curpos = obj_offset, base_offset; + off64_t curpos = obj_offset, base_offset; int error = 0, use_heap = 0; size_t size, elem_pos; git_object_t type; @@ -589,17 +591,11 @@ if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA) break; - base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset); + error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset); git_mwindow_close(&w_curs); - if (base_offset == 0) { - error = packfile_error("delta offset is zero"); - goto on_error; - } - if (base_offset < 0) { /* must actually be an error code */ - error = (int)base_offset; + if (error < 0) goto on_error; - } /* we need to pass the pos *after* the delta-base bit */ elem->offset = curpos; @@ -622,10 +618,10 @@ int git_packfile_unpack( git_rawobj *obj, struct git_pack_file *p, - git_off_t *obj_offset) + off64_t *obj_offset) { git_mwindow *w_curs = NULL; - git_off_t curpos = *obj_offset; + off64_t curpos = *obj_offset; int error, free_base = 0; git_dependency_chain chain = GIT_ARRAY_INIT; struct pack_chain_elem *elem = NULL, *stack; @@ -768,31 +764,13 @@ return error; } -static void *use_git_alloc(void *opaq, unsigned int count, unsigned int size) +int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, off64_t curpos) { - GIT_UNUSED(opaq); - return git__calloc(count, size); -} - -static void use_git_free(void *opaq, void *ptr) -{ - GIT_UNUSED(opaq); - git__free(ptr); -} - -int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, git_off_t curpos) -{ - int st; - memset(obj, 0, sizeof(git_packfile_stream)); obj->curpos = curpos; obj->p = p; - obj->zstream.zalloc = use_git_alloc; - obj->zstream.zfree = use_git_free; - obj->zstream.next_in = Z_NULL; - obj->zstream.next_out = Z_NULL; - st = inflateInit(&obj->zstream); - if (st != Z_OK) { + + if (git_zstream_init(&obj->zstream, GIT_ZSTREAM_INFLATE) < 0) { git_error_set(GIT_ERROR_ZLIB, "failed to init packfile stream"); return -1; } @@ -802,128 +780,127 @@ ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len) { + unsigned int window_len; unsigned char *in; - size_t written; - int st; + int error; if (obj->done) return 0; - in = pack_window_open(obj->p, &obj->mw, obj->curpos, &obj->zstream.avail_in); - if (in == NULL) + if ((in = pack_window_open(obj->p, &obj->mw, obj->curpos, &window_len)) == NULL) return GIT_EBUFS; - obj->zstream.next_out = buffer; - obj->zstream.avail_out = (unsigned int)len; - obj->zstream.next_in = in; - - st = inflate(&obj->zstream, Z_SYNC_FLUSH); - git_mwindow_close(&obj->mw); - - obj->curpos += obj->zstream.next_in - in; - written = len - obj->zstream.avail_out; - - if (st != Z_OK && st != Z_STREAM_END) { + if ((error = git_zstream_set_input(&obj->zstream, in, window_len)) < 0 || + (error = git_zstream_get_output_chunk(buffer, &len, &obj->zstream)) < 0) { + git_mwindow_close(&obj->mw); git_error_set(GIT_ERROR_ZLIB, "error reading from the zlib stream"); return -1; } - if (st == Z_STREAM_END) - obj->done = 1; + git_mwindow_close(&obj->mw); + obj->curpos += window_len - obj->zstream.in_len; + + if (git_zstream_eos(&obj->zstream)) + obj->done = 1; /* If we didn't write anything out but we're not done, we need more data */ - if (!written && st != Z_STREAM_END) + if (!len && !git_zstream_eos(&obj->zstream)) return GIT_EBUFS; - return written; + return len; } void git_packfile_stream_dispose(git_packfile_stream *obj) { - inflateEnd(&obj->zstream); + git_zstream_free(&obj->zstream); } static int packfile_unpack_compressed( git_rawobj *obj, struct git_pack_file *p, - git_mwindow **w_curs, - git_off_t *curpos, + git_mwindow **mwindow, + off64_t *position, size_t size, git_object_t type) { - size_t buf_size; - int st; - z_stream stream; - unsigned char *buffer, *in; - - GIT_ERROR_CHECK_ALLOC_ADD(&buf_size, size, 1); - buffer = git__calloc(1, buf_size); - GIT_ERROR_CHECK_ALLOC(buffer); - - memset(&stream, 0, sizeof(stream)); - stream.next_out = buffer; - stream.avail_out = (uInt)buf_size; - stream.zalloc = use_git_alloc; - stream.zfree = use_git_free; - - st = inflateInit(&stream); - if (st != Z_OK) { - git__free(buffer); - git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack"); + git_zstream zstream = GIT_ZSTREAM_INIT; + size_t buffer_len, total = 0; + char *data = NULL; + int error; - return -1; + GIT_ERROR_CHECK_ALLOC_ADD(&buffer_len, size, 1); + data = git__calloc(1, buffer_len); + GIT_ERROR_CHECK_ALLOC(data); + + if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0) { + git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack"); + goto out; } do { - in = pack_window_open(p, w_curs, *curpos, &stream.avail_in); - stream.next_in = in; - st = inflate(&stream, Z_FINISH); - git_mwindow_close(w_curs); - - if (!stream.avail_out) - break; /* the payload is larger than it should be */ - - if (st == Z_BUF_ERROR && in == NULL) { - inflateEnd(&stream); - git__free(buffer); - return GIT_EBUFS; + size_t bytes = buffer_len - total; + unsigned int window_len; + unsigned char *in; + + if ((in = pack_window_open(p, mwindow, *position, &window_len)) == NULL) { + error = -1; + goto out; } - *curpos += stream.next_in - in; - } while (st == Z_OK || st == Z_BUF_ERROR); + if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 || + (error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) { + git_mwindow_close(mwindow); + goto out; + } - inflateEnd(&stream); + git_mwindow_close(mwindow); - if ((st != Z_STREAM_END) || stream.total_out != size) { - git__free(buffer); + if (!bytes) + break; + + *position += window_len - zstream.in_len; + total += bytes; + } while (!git_zstream_eos(&zstream)); + + if (total != size || !git_zstream_eos(&zstream)) { git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream"); - return -1; + error = -1; + goto out; } obj->type = type; obj->len = size; - obj->data = buffer; - return 0; + obj->data = data; + +out: + git_zstream_free(&zstream); + if (error) + git__free(data); + + return error; } /* * curpos is where the data starts, delta_obj_offset is the where the * header starts */ -git_off_t get_delta_base( - struct git_pack_file *p, - git_mwindow **w_curs, - git_off_t *curpos, - git_object_t type, - git_off_t delta_obj_offset) +int get_delta_base( + off64_t *delta_base_out, + struct git_pack_file *p, + git_mwindow **w_curs, + off64_t *curpos, + git_object_t type, + off64_t delta_obj_offset) { unsigned int left = 0; unsigned char *base_info; - git_off_t base_offset; + off64_t base_offset; git_oid unused; + assert(delta_base_out); + base_info = pack_window_open(p, w_curs, *curpos, &left); /* Assumption: the only reason this would fail is because the file is too small */ if (base_info == NULL) @@ -943,25 +920,28 @@ return GIT_EBUFS; unsigned_base_offset += 1; if (!unsigned_base_offset || MSB(unsigned_base_offset, 7)) - return 0; /* overflow */ + return packfile_error("overflow"); c = base_info[used++]; unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127); } if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset) - return 0; /* out of bound */ + return packfile_error("out of bounds"); base_offset = delta_obj_offset - unsigned_base_offset; *curpos += used; } else if (type == GIT_OBJECT_REF_DELTA) { /* If we have the cooperative cache, search in it first */ if (p->has_cache) { + struct git_pack_entry *entry; git_oid oid; - size_t k; git_oid_fromraw(&oid, base_info); - k = git_oidmap_lookup_index(p->idx_cache, &oid); - if (git_oidmap_valid_index(p->idx_cache, k)) { + if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) { + if (entry->offset == 0) + return packfile_error("delta offset is zero"); + *curpos += 20; - return ((struct git_pack_entry *)git_oidmap_value_at(p->idx_cache, k))->offset; + *delta_base_out = entry->offset; + return 0; } else { /* If we're building an index, don't try to find the pack * entry; we just haven't seen it yet. We'll make @@ -976,9 +956,13 @@ return packfile_error("base entry delta is not in the same pack"); *curpos += 20; } else - return 0; + return packfile_error("unknown object type"); + + if (base_offset == 0) + return packfile_error("delta offset is zero"); - return base_offset; + *delta_base_out = base_offset; + return 0; } /*********************************************************** @@ -1049,7 +1033,7 @@ if (!p->mwf.size) { if (!S_ISREG(st.st_mode)) goto cleanup; - p->mwf.size = (git_off_t)st.st_size; + p->mwf.size = (off64_t)st.st_size; } else if (p->mwf.size != st.st_size) goto cleanup; @@ -1141,9 +1125,11 @@ if (git__suffixcmp(path, ".idx") == 0) { size_t root_len = path_len - strlen(".idx"); - memcpy(p->pack_name + root_len, ".keep", sizeof(".keep")); - if (git_path_exists(p->pack_name) == true) - p->pack_keep = 1; + if (!git_disable_pack_keep_file_checks) { + memcpy(p->pack_name + root_len, ".keep", sizeof(".keep")); + if (git_path_exists(p->pack_name) == true) + p->pack_keep = 1; + } memcpy(p->pack_name + root_len, ".pack", sizeof(".pack")); } @@ -1184,7 +1170,7 @@ * ***********************************************************/ -static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n) +static off64_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n) { const unsigned char *index = p->index_map.data; const unsigned char *end = index + p->index_map.len; @@ -1271,8 +1257,29 @@ return error; } +int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo, + unsigned hi, const unsigned char *oid_prefix) +{ + const unsigned char *base = oid_lookup_table; + + while (lo < hi) { + unsigned mi = (lo + hi) / 2; + int cmp = git_oid__hashcmp(base + mi * stride, oid_prefix); + + if (!cmp) + return mi; + + if (cmp > 0) + hi = mi; + else + lo = mi+1; + } + + return -((int)lo)-1; +} + static int pack_entry_find_offset( - git_off_t *offset_out, + off64_t *offset_out, git_oid *found_oid, struct git_pack_file *p, const git_oid *short_oid, @@ -1282,7 +1289,7 @@ const unsigned char *index; unsigned hi, lo, stride; int pos, found = 0; - git_off_t offset; + off64_t offset; const unsigned char *current = 0; *offset_out = 0; @@ -1319,7 +1326,7 @@ short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects); #endif - pos = sha1_position(index, stride, lo, hi, short_oid->id); + pos = git_pack__lookup_sha1(index, stride, lo, hi, short_oid->id); if (pos >= 0) { /* An object matching exactly the oid was found */ @@ -1377,7 +1384,7 @@ const git_oid *short_oid, size_t len) { - git_off_t offset; + off64_t offset; git_oid found_oid; int error; diff -Nru libgit2-0.28.5+dfsg.1/src/pack.h libgit2-1.1.0+dfsg.1/src/pack.h --- libgit2-0.28.5+dfsg.1/src/pack.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pack.h 2020-10-12 18:53:06.000000000 +0000 @@ -10,15 +10,15 @@ #include "common.h" -#include - #include "git2/oid.h" +#include "array.h" #include "map.h" #include "mwindow.h" #include "odb.h" +#include "offmap.h" #include "oidmap.h" -#include "array.h" +#include "zstream.h" #define GIT_PACK_FILE_MODE 0444 @@ -63,17 +63,14 @@ } git_pack_cache_entry; struct pack_chain_elem { - git_off_t base_key; - git_off_t offset; + off64_t base_key; + off64_t offset; size_t size; git_object_t type; }; typedef git_array_t(struct pack_chain_elem) git_dependency_chain; -#include "offmap.h" -#include "oidmap.h" - #define GIT_PACK_CACHE_MEMORY_LIMIT 16 * 1024 * 1024 #define GIT_PACK_CACHE_SIZE_LIMIT 1024 * 1024 /* don't bother caching anything over 1MB */ @@ -109,16 +106,29 @@ char pack_name[GIT_FLEX_ARRAY]; /* more */ }; +/** + * Return the position where an OID (or a prefix) would be inserted within the + * OID Lookup Table of an .idx file. This performs binary search between the lo + * and hi indices. + * + * The stride parameter is provided because .idx files version 1 store the OIDs + * interleaved with the 4-byte file offsets of the objects within the .pack + * file (stride = 24), whereas files with version 2 store them in a contiguous + * flat array (stride = 20). + */ +int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo, + unsigned hi, const unsigned char *oid_prefix); + struct git_pack_entry { - git_off_t offset; + off64_t offset; git_oid sha1; struct git_pack_file *p; }; typedef struct git_packfile_stream { - git_off_t curpos; + off64_t curpos; int done; - z_stream zstream; + git_zstream zstream; struct git_pack_file *p; git_mwindow *mw; } git_packfile_stream; @@ -132,23 +142,27 @@ git_object_t *type_p, git_mwindow_file *mwf, git_mwindow **w_curs, - git_off_t *curpos); + off64_t *curpos); int git_packfile_resolve_header( size_t *size_p, git_object_t *type_p, struct git_pack_file *p, - git_off_t offset); + off64_t offset); -int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset); +int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, off64_t *obj_offset); -int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, git_off_t curpos); +int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p, off64_t curpos); ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len); void git_packfile_stream_dispose(git_packfile_stream *obj); -git_off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs, - git_off_t *curpos, git_object_t type, - git_off_t delta_obj_offset); +int get_delta_base( + off64_t *delta_base_out, + struct git_pack_file *p, + git_mwindow **w_curs, + off64_t *curpos, + git_object_t type, + off64_t delta_obj_offset); void git_packfile_close(struct git_pack_file *p, bool unlink_packfile); void git_packfile_free(struct git_pack_file *p); diff -Nru libgit2-0.28.5+dfsg.1/src/pack-objects.c libgit2-1.1.0+dfsg.1/src/pack-objects.c --- libgit2-0.28.5+dfsg.1/src/pack-objects.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pack-objects.c 2020-10-12 18:53:06.000000000 +0000 @@ -38,7 +38,7 @@ struct pack_write_context { git_indexer *indexer; - git_transfer_progress *stats; + git_indexer_progress *stats; }; struct walk_object { @@ -141,16 +141,11 @@ pb = git__calloc(1, sizeof(*pb)); GIT_ERROR_CHECK_ALLOC(pb); - pb->object_ix = git_oidmap_alloc(); - if (!pb->object_ix) + if (git_oidmap_new(&pb->object_ix) < 0 || + git_oidmap_new(&pb->walk_objects) < 0 || + git_pool_init(&pb->object_pool, sizeof(struct walk_object)) < 0) goto on_error; - pb->walk_objects = git_oidmap_alloc(); - if (!pb->walk_objects) - goto on_error; - - git_pool_init(&pb->object_pool, sizeof(struct walk_object)); - pb->repo = repo; pb->nr_threads = 1; /* do not spawn any thread by default */ @@ -194,24 +189,26 @@ return pb->nr_threads; } -static void rehash(git_packbuilder *pb) +static int rehash(git_packbuilder *pb) { git_pobject *po; - size_t pos, i; - int ret; + size_t i; git_oidmap_clear(pb->object_ix); + for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) { - pos = git_oidmap_put(pb->object_ix, &po->id, &ret); - git_oidmap_set_value_at(pb->object_ix, pos, po); + if (git_oidmap_set(pb->object_ix, &po->id, po) < 0) + return -1; } + + return 0; } int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, const char *name) { git_pobject *po; - size_t newsize, pos; + size_t newsize; int ret; assert(pb && oid); @@ -223,7 +220,7 @@ if (pb->nr_objects >= pb->nr_alloc) { GIT_ERROR_CHECK_ALLOC_ADD(&newsize, pb->nr_alloc, 1024); - GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2); + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize / 2, 3); if (!git__is_uint32(newsize)) { git_error_set(GIT_ERROR_NOMEMORY, "packfile too large to fit in memory."); @@ -235,7 +232,9 @@ pb->object_list = git__reallocarray(pb->object_list, pb->nr_alloc, sizeof(*po)); GIT_ERROR_CHECK_ALLOC(pb->object_list); - rehash(pb); + + if (rehash(pb) < 0) + return -1; } po = pb->object_list + pb->nr_objects; @@ -248,13 +247,10 @@ git_oid_cpy(&po->id, oid); po->hash = name_hash(name); - pos = git_oidmap_put(pb->object_ix, &po->id, &ret); - if (ret < 0) { + if (git_oidmap_set(pb->object_ix, &po->id, po) < 0) { git_error_set_oom(); - return ret; + return -1; } - assert(ret != 0); - git_oidmap_set_value_at(pb->object_ix, pos, po); pb->done = false; @@ -375,7 +371,9 @@ GIT_ERROR_CHECK_ALLOC(zbuf); git_zstream_reset(&pb->zstream); - git_zstream_set_input(&pb->zstream, data, data_len); + + if ((error = git_zstream_set_input(&pb->zstream, data, data_len)) < 0) + goto done; while (!git_zstream_done(&pb->zstream)) { if ((error = git_zstream_get_output(zbuf, &zbuf_len, &pb->zstream)) < 0 || @@ -514,15 +512,12 @@ { git_packbuilder *pb = data; git_pobject *po; - size_t pos; GIT_UNUSED(name); - pos = git_oidmap_lookup_index(pb->object_ix, oid); - if (!git_oidmap_valid_index(pb->object_ix, pos)) + if ((po = git_oidmap_get(pb->object_ix, oid)) == NULL) return 0; - po = git_oidmap_value_at(pb->object_ix, pos); po->tagged = 1; /* TODO: peel objects */ @@ -1383,40 +1378,51 @@ git_packbuilder *pb, const char *path, unsigned int mode, - git_transfer_progress_cb progress_cb, + git_indexer_progress_cb progress_cb, void *progress_cb_payload) { + int error = -1; + git_buf object_path = GIT_BUF_INIT; git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT; - git_indexer *indexer; - git_transfer_progress stats; + git_indexer *indexer = NULL; + git_indexer_progress stats; struct pack_write_context ctx; int t; PREPARE_PACK; + if (path == NULL) { + if ((error = git_repository_item_path(&object_path, pb->repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0) + goto cleanup; + if ((error = git_buf_joinpath(&object_path, git_buf_cstr(&object_path), "pack")) < 0) + goto cleanup; + path = git_buf_cstr(&object_path); + } + opts.progress_cb = progress_cb; opts.progress_cb_payload = progress_cb_payload; - if (git_indexer_new( - &indexer, path, mode, pb->odb, &opts) < 0) - return -1; + if ((error = git_indexer_new(&indexer, path, mode, pb->odb, &opts)) < 0) + goto cleanup; - if (!git_repository__cvar(&t, pb->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) + if (!git_repository__configmap_lookup(&t, pb->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t) git_indexer__set_fsync(indexer, 1); ctx.indexer = indexer; ctx.stats = &stats; - if (git_packbuilder_foreach(pb, write_cb, &ctx) < 0 || - git_indexer_commit(indexer, &stats) < 0) { - git_indexer_free(indexer); - return -1; - } + if ((error = git_packbuilder_foreach(pb, write_cb, &ctx)) < 0) + goto cleanup; + + if ((error = git_indexer_commit(indexer, &stats)) < 0) + goto cleanup; git_oid_cpy(&pb->pack_oid, git_indexer_hash(indexer)); +cleanup: git_indexer_free(indexer); - return 0; + git_buf_dispose(&object_path); + return error; } #undef PREPARE_PACK @@ -1539,18 +1545,15 @@ static int retrieve_object(struct walk_object **out, git_packbuilder *pb, const git_oid *id) { - int error; - size_t pos; struct walk_object *obj; + int error; - pos = git_oidmap_lookup_index(pb->walk_objects, id); - if (git_oidmap_valid_index(pb->walk_objects, pos)) { - obj = git_oidmap_value_at(pb->walk_objects, pos); - } else { + if ((obj = git_oidmap_get(pb->walk_objects, id)) == NULL) { if ((error = lookup_walk_object(&obj, pb, id)) < 0) return error; - git_oidmap_insert(pb->walk_objects, &obj->id, obj, &error); + if ((error = git_oidmap_set(pb->walk_objects, &obj->id, obj)) < 0) + return error; } *out = obj; @@ -1639,7 +1642,7 @@ return 0; } -int insert_tree(git_packbuilder *pb, git_tree *tree) +static int pack_objects_insert_tree(git_packbuilder *pb, git_tree *tree) { size_t i; int error; @@ -1666,7 +1669,7 @@ if ((error = git_tree_lookup(&subtree, pb->repo, entry_id)) < 0) return error; - error = insert_tree(pb, subtree); + error = pack_objects_insert_tree(pb, subtree); git_tree_free(subtree); if (error < 0) @@ -1692,7 +1695,7 @@ return error; } -int insert_commit(git_packbuilder *pb, struct walk_object *obj) +static int pack_objects_insert_commit(git_packbuilder *pb, struct walk_object *obj) { int error; git_commit *commit = NULL; @@ -1709,7 +1712,7 @@ if ((error = git_tree_lookup(&tree, pb->repo, git_commit_tree_id(commit))) < 0) goto cleanup; - if ((error = insert_tree(pb, tree)) < 0) + if ((error = pack_objects_insert_tree(pb, tree)) < 0) goto cleanup; cleanup: @@ -1744,7 +1747,7 @@ if (obj->seen || obj->uninteresting) continue; - if ((error = insert_commit(pb, obj)) < 0) + if ((error = pack_objects_insert_commit(pb, obj)) < 0) return error; } diff -Nru libgit2-0.28.5+dfsg.1/src/pack-objects.h libgit2-1.1.0+dfsg.1/src/pack-objects.h --- libgit2-0.28.5+dfsg.1/src/pack-objects.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pack-objects.h 2020-10-12 18:53:06.000000000 +0000 @@ -30,7 +30,7 @@ typedef struct git_pobject { git_oid id; git_object_t type; - git_off_t offset; + off64_t offset; size_t size; diff -Nru libgit2-0.28.5+dfsg.1/src/parse.c libgit2-1.1.0+dfsg.1/src/parse.c --- libgit2-0.28.5+dfsg.1/src/parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -101,6 +101,16 @@ return 0; } +int git_parse_advance_oid(git_oid *out, git_parse_ctx *ctx) +{ + if (ctx->line_len < GIT_OID_HEXSZ) + return -1; + if ((git_oid_fromstrn(out, ctx->line, GIT_OID_HEXSZ)) < 0) + return -1; + git_parse_advance_chars(ctx, GIT_OID_HEXSZ); + return 0; +} + int git_parse_peek(char *out, git_parse_ctx *ctx, int flags) { size_t remain = ctx->line_len; diff -Nru libgit2-0.28.5+dfsg.1/src/parse.h libgit2-1.1.0+dfsg.1/src/parse.h --- libgit2-0.28.5+dfsg.1/src/parse.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/parse.h 2020-10-12 18:53:06.000000000 +0000 @@ -23,12 +23,11 @@ size_t line_num; } git_parse_ctx; +#define GIT_PARSE_CTX_INIT { 0 } + int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len); void git_parse_ctx_clear(git_parse_ctx *ctx); -#define git_parse_err(...) \ - ( git_error_set(GIT_ERROR_PATCH, __VA_ARGS__), -1 ) - #define git_parse_ctx_contains_s(ctx, str) \ git_parse_ctx_contains(ctx, str, sizeof(str) - 1) @@ -51,6 +50,7 @@ int git_parse_advance_ws(git_parse_ctx *ctx); int git_parse_advance_nl(git_parse_ctx *ctx); int git_parse_advance_digit(int64_t *out, git_parse_ctx *ctx, int base); +int git_parse_advance_oid(git_oid *out, git_parse_ctx *ctx); enum GIT_PARSE_PEEK_FLAGS { GIT_PARSE_PEEK_SKIP_WHITESPACE = (1 << 0) diff -Nru libgit2-0.28.5+dfsg.1/src/patch.c libgit2-1.1.0+dfsg.1/src/patch.c --- libgit2-0.28.5+dfsg.1/src/patch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/patch.c 2020-10-12 18:53:06.000000000 +0000 @@ -79,7 +79,7 @@ git_buf file_header = GIT_BUF_INIT; if (git_diff_delta__format_file_header( - &file_header, patch->delta, NULL, NULL, 0) < 0) + &file_header, patch->delta, NULL, NULL, 0, true) < 0) git_error_clear(); else out += git_buf_len(&file_header); diff -Nru libgit2-0.28.5+dfsg.1/src/patch_generate.c libgit2-1.1.0+dfsg.1/src/patch_generate.c --- libgit2-0.28.5+dfsg.1/src/patch_generate.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/patch_generate.c 2020-10-12 18:53:06.000000000 +0000 @@ -15,7 +15,7 @@ #include "diff_xdiff.h" #include "delta.h" #include "zstream.h" -#include "fileops.h" +#include "futils.h" static void diff_output_init( git_patch_generated_output *, const git_diff_options *, git_diff_file_cb, @@ -209,9 +209,7 @@ if ((error = git_diff_file_content__load( &patch->ofile, &patch->base.diff_opts)) < 0 || - should_skip_binary(patch, patch->ofile.file)) - goto cleanup; - if ((error = git_diff_file_content__load( + (error = git_diff_file_content__load( &patch->nfile, &patch->base.diff_opts)) < 0 || should_skip_binary(patch, patch->nfile.file)) goto cleanup; diff -Nru libgit2-0.28.5+dfsg.1/src/patch_parse.c libgit2-1.1.0+dfsg.1/src/patch_parse.c --- libgit2-0.28.5+dfsg.1/src/patch_parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/patch_parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -33,7 +33,19 @@ char *old_prefix, *new_prefix; } git_patch_parsed; -static int header_path_len(git_patch_parse_ctx *ctx) +static int git_parse_err(const char *fmt, ...) GIT_FORMAT_PRINTF(1, 2); +static int git_parse_err(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + git_error_vset(GIT_ERROR_PATCH, fmt, ap); + va_end(ap); + + return -1; +} + +static size_t header_path_len(git_patch_parse_ctx *ctx) { bool inquote = 0; bool quoted = git_parse_ctx_contains_s(&ctx->parse_ctx, "\""); @@ -186,7 +198,7 @@ return -1; if (git_parse_peek(&c, &ctx->parse_ctx, 0) == 0 && c == ' ') { - uint16_t mode; + uint16_t mode = 0; git_parse_advance_chars(&ctx->parse_ctx, 1); @@ -219,9 +231,9 @@ git_patch_parsed *patch, git_patch_parse_ctx *ctx) { - git__free((char *)patch->base.delta->old_file.path); + git__free((char *)patch->base.delta->new_file.path); - patch->base.delta->old_file.path = NULL; + patch->base.delta->new_file.path = NULL; patch->base.delta->status = GIT_DELTA_DELETED; patch->base.delta->nfiles = 1; @@ -232,9 +244,9 @@ git_patch_parsed *patch, git_patch_parse_ctx *ctx) { - git__free((char *)patch->base.delta->new_file.path); + git__free((char *)patch->base.delta->old_file.path); - patch->base.delta->new_file.path = NULL; + patch->base.delta->old_file.path = NULL; patch->base.delta->status = GIT_DELTA_ADDED; patch->base.delta->nfiles = 1; @@ -395,10 +407,12 @@ { "--- " , STATE_DIFF, STATE_PATH, parse_header_git_oldpath }, { "--- " , STATE_INDEX, STATE_PATH, parse_header_git_oldpath }, + { "--- " , STATE_FILEMODE, STATE_PATH, parse_header_git_oldpath }, { "+++ " , STATE_PATH, STATE_END, parse_header_git_newpath }, { "GIT binary patch" , STATE_INDEX, STATE_END, NULL }, { "Binary files " , STATE_INDEX, STATE_END, NULL }, + { "similarity index " , STATE_END, STATE_SIMILARITY, parse_header_similarity }, { "similarity index " , STATE_DIFF, STATE_SIMILARITY, parse_header_similarity }, { "dissimilarity index ", STATE_DIFF, STATE_SIMILARITY, parse_header_dissimilarity }, { "rename from " , STATE_SIMILARITY, STATE_RENAME, parse_header_renamefrom }, @@ -479,7 +493,7 @@ static int parse_int(int *out, git_patch_parse_ctx *ctx) { - git_off_t num; + int64_t num; if (git_parse_advance_digit(&num, &ctx->parse_ctx, 10) < 0 || !git__is_int(num)) return -1; @@ -753,7 +767,7 @@ { git_diff_binary_t type = GIT_DIFF_BINARY_NONE; git_buf base85 = GIT_BUF_INIT, decoded = GIT_BUF_INIT; - git_off_t len; + int64_t len; int error = 0; if (git_parse_ctx_contains_s(&ctx->parse_ctx, "literal ")) { @@ -872,6 +886,11 @@ if (!old || !new) return git_parse_err("corrupt binary data without paths at line %"PRIuZ, ctx->parse_ctx.line_num); + if (patch->base.delta->status == GIT_DELTA_ADDED) + old = "/dev/null"; + else if (patch->base.delta->status == GIT_DELTA_DELETED) + new = "/dev/null"; + if (git_parse_advance_expected_str(&ctx->parse_ctx, "Binary files ") < 0 || git_parse_advance_expected_str(&ctx->parse_ctx, old) < 0 || git_parse_advance_expected_str(&ctx->parse_ctx, " and ") < 0 || @@ -923,7 +942,7 @@ return parse_patch_hunks(patch, ctx); } -int check_header_names( +static int check_header_names( const char *one, const char *two, const char *old_or_new, @@ -1008,13 +1027,17 @@ /* Prefer the rename filenames as they are unambiguous and unprefixed */ if (patch->rename_old_path) patch->base.delta->old_file.path = patch->rename_old_path; - else + else if (prefixed_old) patch->base.delta->old_file.path = prefixed_old + old_prefixlen; + else + patch->base.delta->old_file.path = NULL; if (patch->rename_new_path) patch->base.delta->new_file.path = patch->rename_new_path; - else + else if (prefixed_new) patch->base.delta->new_file.path = prefixed_new + new_prefixlen; + else + patch->base.delta->new_file.path = NULL; if (!patch->base.delta->old_file.path && !patch->base.delta->new_file.path) diff -Nru libgit2-0.28.5+dfsg.1/src/path.c libgit2-1.1.0+dfsg.1/src/path.c --- libgit2-0.28.5+dfsg.1/src/path.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/path.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,7 +14,7 @@ #include "win32/w32_buffer.h" #include "win32/w32_util.h" #include "win32/version.h" -#include +#include #else #include #endif @@ -183,7 +183,13 @@ while (endp > path && *endp == '/') endp--; - if ((len = win32_prefix_length(path, endp - path + 1)) > 0) { + if (endp - path + 1 > INT_MAX) { + git_error_set(GIT_ERROR_INVALID, "path too long"); + len = -1; + goto Exit; + } + + if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) { is_prefix = 1; goto Exit; } @@ -203,7 +209,13 @@ endp--; } while (endp > path && *endp == '/'); - if ((len = win32_prefix_length(path, endp - path + 1)) > 0) { + if (endp - path + 1 > INT_MAX) { + git_error_set(GIT_ERROR_INVALID, "path too long"); + len = -1; + goto Exit; + } + + if ((len = win32_prefix_length(path, (int)(endp - path + 1))) > 0) { is_prefix = 1; goto Exit; } @@ -299,15 +311,18 @@ while (path[offset] && path[offset] != '/' && path[offset] != '\\') offset++; } + + if (path[offset] == '\\') + return offset; #endif - if (path[offset] == '/' || path[offset] == '\\') + if (path[offset] == '/') return offset; return -1; /* Not a real error - signals that path is not rooted */ } -void git_path_trim_slashes(git_buf *path) +static void path_trim_slashes(git_buf *path) { int ceiling = git_path_root(path->ptr) + 1; assert(ceiling >= 0); @@ -1204,7 +1219,7 @@ if (git_buf_puts(&diriter->path_utf8, path) < 0) return -1; - git_path_trim_slashes(&diriter->path_utf8); + path_trim_slashes(&diriter->path_utf8); if (diriter->path_utf8.size == 0) { git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path); @@ -1353,7 +1368,7 @@ if (git_buf_puts(&diriter->path, path) < 0) return -1; - git_path_trim_slashes(&diriter->path); + path_trim_slashes(&diriter->path); if (diriter->path.size == 0) { git_error_set(GIT_ERROR_FILESYSTEM, "could not open directory '%s'", path); @@ -1849,12 +1864,12 @@ #endif if (repo && !protectHFS) - error = git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS); + error = git_repository__configmap_lookup(&protectHFS, repo, GIT_CONFIGMAP_PROTECTHFS); if (!error && protectHFS) flags |= GIT_PATH_REJECT_DOT_GIT_HFS; if (repo) - error = git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS); + error = git_repository__configmap_lookup(&protectNTFS, repo, GIT_CONFIGMAP_PROTECTNTFS); if (!error && protectNTFS) flags |= GIT_PATH_REJECT_DOT_GIT_NTFS; @@ -1942,6 +1957,28 @@ } } +bool git_path_supports_symlinks(const char *dir) +{ + git_buf path = GIT_BUF_INIT; + bool supported = false; + struct stat st; + int fd; + + if ((fd = git_futils_mktmp(&path, dir, 0666)) < 0 || + p_close(fd) < 0 || + p_unlink(path.ptr) < 0 || + p_symlink("testing", path.ptr) < 0 || + p_lstat(path.ptr, &st) < 0) + goto done; + + supported = (S_ISLNK(st.st_mode) != 0); +done: + if (path.size) + (void)p_unlink(path.ptr); + git_buf_dispose(&path); + return supported; +} + int git_path_validate_system_file_ownership(const char *path) { #ifndef GIT_WIN32 @@ -2008,7 +2045,7 @@ git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid"); ret = GIT_ERROR; } - free(info); + git__free(info); cleanup: if (descriptor) diff -Nru libgit2-0.28.5+dfsg.1/src/path.h libgit2-1.1.0+dfsg.1/src/path.h --- libgit2-0.28.5+dfsg.1/src/path.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/path.h 2020-10-12 18:53:06.000000000 +0000 @@ -647,6 +647,8 @@ */ int git_path_normalize_slashes(git_buf *out, const char *path); +bool git_path_supports_symlinks(const char *dir); + /** * Validate a system file's ownership * diff -Nru libgit2-0.28.5+dfsg.1/src/pathspec.c libgit2-1.1.0+dfsg.1/src/pathspec.c --- libgit2-0.28.5+dfsg.1/src/pathspec.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pathspec.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,6 +16,7 @@ #include "index.h" #include "bitvec.h" #include "diff.h" +#include "wildmatch.h" /* what is the common non-wildcard prefix for all items in the pathspec */ char *git_pathspec_prefix(const git_strarray *pathspec) @@ -84,8 +85,7 @@ if (!match) return -1; - match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE | - GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_NOLEADINGDIR; + match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG; ret = git_attr_fnmatch__parse(match, strpool, NULL, &pattern); if (ret == GIT_ENOTFOUND) { @@ -110,7 +110,7 @@ } struct pathspec_match_context { - int fnmatch_flags; + int wildmatch_flags; int (*strcomp)(const char *, const char *); int (*strncomp)(const char *, const char *, size_t); }; @@ -121,11 +121,11 @@ bool casefold) { if (disable_fnmatch) - ctxt->fnmatch_flags = -1; + ctxt->wildmatch_flags = -1; else if (casefold) - ctxt->fnmatch_flags = FNM_CASEFOLD; + ctxt->wildmatch_flags = WM_CASEFOLD; else - ctxt->fnmatch_flags = 0; + ctxt->wildmatch_flags = 0; if (casefold) { ctxt->strcomp = git__strcasecmp; @@ -141,16 +141,16 @@ struct pathspec_match_context *ctxt, const char *path) { - int result = (match->flags & GIT_ATTR_FNMATCH_MATCH_ALL) ? 0 : FNM_NOMATCH; + int result = (match->flags & GIT_ATTR_FNMATCH_MATCH_ALL) ? 0 : WM_NOMATCH; - if (result == FNM_NOMATCH) - result = ctxt->strcomp(match->pattern, path) ? FNM_NOMATCH : 0; + if (result == WM_NOMATCH) + result = ctxt->strcomp(match->pattern, path) ? WM_NOMATCH : 0; - if (ctxt->fnmatch_flags >= 0 && result == FNM_NOMATCH) - result = p_fnmatch(match->pattern, path, ctxt->fnmatch_flags); + if (ctxt->wildmatch_flags >= 0 && result == WM_NOMATCH) + result = wildmatch(match->pattern, path, ctxt->wildmatch_flags); /* if we didn't match, look for exact dirname prefix match */ - if (result == FNM_NOMATCH && + if (result == WM_NOMATCH && (match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 && ctxt->strncomp(path, match->pattern, match->length) == 0 && path[match->length] == '/') @@ -159,7 +159,7 @@ /* if we didn't match and this is a negative match, check for exact * match of filename with leading '!' */ - if (result == FNM_NOMATCH && + if (result == WM_NOMATCH && (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0 && *path == '!' && ctxt->strncomp(path + 1, match->pattern, match->length) == 0 && @@ -238,9 +238,9 @@ memset(ps, 0, sizeof(*ps)); ps->prefix = git_pathspec_prefix(paths); - git_pool_init(&ps->pool, 1); - if ((error = git_pathspec__vinit(&ps->pathspec, paths, &ps->pool)) < 0) + if ((error = git_pool_init(&ps->pool, 1)) < 0 || + (error = git_pathspec__vinit(&ps->pathspec, paths, &ps->pool)) < 0) git_pathspec__clear(ps); return error; @@ -316,7 +316,8 @@ if (!m) return NULL; - git_pool_init(&m->pool, 1); + if (git_pool_init(&m->pool, 1) < 0) + return NULL; /* need to keep reference to pathspec and increment refcount because * failures array stores pointers to the pattern strings of the @@ -422,7 +423,7 @@ if ((error = git_iterator_reset_range(iter, ps->prefix, ps->prefix)) < 0) goto done; - if (git_iterator_type(iter) == GIT_ITERATOR_TYPE_WORKDIR && + if (git_iterator_type(iter) == GIT_ITERATOR_WORKDIR && (error = git_repository_index__weakptr( &index, git_iterator_owner(iter))) < 0) goto done; diff -Nru libgit2-0.28.5+dfsg.1/src/pool.c libgit2-1.1.0+dfsg.1/src/pool.c --- libgit2-0.28.5+dfsg.1/src/pool.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pool.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,37 +14,36 @@ struct git_pool_page { git_pool_page *next; - uint32_t size; - uint32_t avail; + size_t size; + size_t avail; GIT_ALIGN(char data[GIT_FLEX_ARRAY], 8); }; -static void *pool_alloc_page(git_pool *pool, uint32_t size); +static void *pool_alloc_page(git_pool *pool, size_t size); -uint32_t git_pool__system_page_size(void) -{ - static uint32_t size = 0; +#ifndef GIT_DEBUG_POOL - if (!size) { - size_t page_size; - if (git__page_size(&page_size) < 0) - page_size = 4096; - /* allow space for malloc overhead */ - size = page_size - (2 * sizeof(void *)) - sizeof(git_pool_page); - } +static size_t system_page_size = 0; - return size; +int git_pool_global_init(void) +{ + if (git__page_size(&system_page_size) < 0) + system_page_size = 4096; + /* allow space for malloc overhead */ + system_page_size -= (2 * sizeof(void *)) + sizeof(git_pool_page); + return 0; } -#ifndef GIT_DEBUG_POOL -void git_pool_init(git_pool *pool, uint32_t item_size) +int git_pool_init(git_pool *pool, size_t item_size) { assert(pool); assert(item_size >= 1); memset(pool, 0, sizeof(git_pool)); pool->item_size = item_size; - pool->page_size = git_pool__system_page_size(); + pool->page_size = system_page_size; + + return 0; } void git_pool_clear(git_pool *pool) @@ -59,10 +58,10 @@ pool->pages = NULL; } -static void *pool_alloc_page(git_pool *pool, uint32_t size) +static void *pool_alloc_page(git_pool *pool, size_t size) { git_pool_page *page; - const uint32_t new_page_size = (size <= pool->page_size) ? pool->page_size : size; + const size_t new_page_size = (size <= pool->page_size) ? pool->page_size : size; size_t alloc_size; if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) || @@ -78,7 +77,7 @@ return page->data; } -static void *pool_alloc(git_pool *pool, uint32_t size) +static void *pool_alloc(git_pool *pool, size_t size) { git_pool_page *page = pool->pages; void *ptr = NULL; @@ -112,6 +111,11 @@ #else +int git_pool_global_init(void) +{ + return 0; +} + static int git_pool__ptr_cmp(const void * a, const void * b) { if(a > b) { @@ -125,7 +129,7 @@ } } -void git_pool_init(git_pool *pool, uint32_t item_size) +int git_pool_init(git_pool *pool, size_t item_size) { assert(pool); assert(item_size >= 1); @@ -134,6 +138,8 @@ pool->item_size = item_size; pool->page_size = git_pool__system_page_size(); git_vector_init(&pool->allocations, 100, git_pool__ptr_cmp); + + return 0; } void git_pool_clear(git_pool *pool) @@ -141,7 +147,7 @@ git_vector_free_deep(&pool->allocations); } -static void *pool_alloc(git_pool *pool, uint32_t size) { +static void *pool_alloc(git_pool *pool, size_t size) { void *ptr = NULL; if((ptr = git__malloc(size)) == NULL) { return NULL; @@ -169,26 +175,26 @@ memcpy(b, &temp, sizeof(temp)); } -static uint32_t alloc_size(git_pool *pool, uint32_t count) +static size_t alloc_size(git_pool *pool, size_t count) { - const uint32_t align = sizeof(void *) - 1; + const size_t align = sizeof(void *) - 1; if (pool->item_size > 1) { - const uint32_t item_size = (pool->item_size + align) & ~align; + const size_t item_size = (pool->item_size + align) & ~align; return item_size * count; } return (count + align) & ~align; } -void *git_pool_malloc(git_pool *pool, uint32_t items) +void *git_pool_malloc(git_pool *pool, size_t items) { return pool_alloc(pool, alloc_size(pool, items)); } -void *git_pool_mallocz(git_pool *pool, uint32_t items) +void *git_pool_mallocz(git_pool *pool, size_t items) { - const uint32_t size = alloc_size(pool, items); + const size_t size = alloc_size(pool, items); void *ptr = pool_alloc(pool, size); if (ptr) memset(ptr, 0x0, size); @@ -201,10 +207,10 @@ assert(pool && str && pool->item_size == sizeof(char)); - if ((uint32_t)(n + 1) < n) + if (n == SIZE_MAX) return NULL; - if ((ptr = git_pool_malloc(pool, (uint32_t)(n + 1))) != NULL) { + if ((ptr = git_pool_malloc(pool, (n + 1))) != NULL) { memcpy(ptr, str, n); ptr[n] = '\0'; } @@ -226,14 +232,18 @@ char *git_pool_strcat(git_pool *pool, const char *a, const char *b) { void *ptr; - size_t len_a, len_b; + size_t len_a, len_b, total; assert(pool && pool->item_size == sizeof(char)); len_a = a ? strlen(a) : 0; len_b = b ? strlen(b) : 0; - if ((ptr = git_pool_malloc(pool, (uint32_t)(len_a + len_b + 1))) != NULL) { + if (GIT_ADD_SIZET_OVERFLOW(&total, len_a, len_b) || + GIT_ADD_SIZET_OVERFLOW(&total, total, 1)) + return NULL; + + if ((ptr = git_pool_malloc(pool, total)) != NULL) { if (len_a) memcpy(ptr, a, len_a); if (len_b) diff -Nru libgit2-0.28.5+dfsg.1/src/pool.h libgit2-1.1.0+dfsg.1/src/pool.h --- libgit2-0.28.5+dfsg.1/src/pool.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/pool.h 2020-10-12 18:53:06.000000000 +0000 @@ -32,8 +32,8 @@ */ typedef struct { git_pool_page *pages; /* allocated pages */ - uint32_t item_size; /* size of single alloc unit in bytes */ - uint32_t page_size; /* size of page in bytes */ + size_t item_size; /* size of single alloc unit in bytes */ + size_t page_size; /* size of page in bytes */ } git_pool; #define GIT_POOL_INIT { NULL, 0, 0 } @@ -57,8 +57,8 @@ */ typedef struct { git_vector allocations; - uint32_t item_size; - uint32_t page_size; + size_t item_size; + size_t page_size; } git_pool; #define GIT_POOL_INIT { GIT_VECTOR_INIT, 0, 0 } @@ -81,7 +81,7 @@ * Of course, you can use this in other ways, but those are the * two most common patterns. */ -extern void git_pool_init(git_pool *pool, uint32_t item_size); +extern int git_pool_init(git_pool *pool, size_t item_size); /** * Free all items in pool @@ -96,8 +96,8 @@ /** * Allocate space for one or more items from a pool. */ -extern void *git_pool_malloc(git_pool *pool, uint32_t items); -extern void *git_pool_mallocz(git_pool *pool, uint32_t items); +extern void *git_pool_malloc(git_pool *pool, size_t items); +extern void *git_pool_mallocz(git_pool *pool, size_t items); /** * Allocate space and duplicate string data into it. @@ -135,4 +135,12 @@ #endif extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr); +/** + * This function is being called by our global setup routines to + * initialize the system pool size. + * + * @return 0 on success, <0 on failure + */ +extern int git_pool_global_init(void); + #endif diff -Nru libgit2-0.28.5+dfsg.1/src/posix.c libgit2-1.1.0+dfsg.1/src/posix.c --- libgit2-0.28.5+dfsg.1/src/posix.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/posix.c 2020-10-12 18:53:06.000000000 +0000 @@ -28,11 +28,11 @@ GIT_UNUSED(hints); - if ((ainfo = malloc(sizeof(struct addrinfo))) == NULL) + if ((ainfo = git__malloc(sizeof(struct addrinfo))) == NULL) return -1; if ((ainfo->ai_hostent = gethostbyname(host)) == NULL) { - free(ainfo); + git__free(ainfo); return -2; } @@ -65,7 +65,7 @@ ai = ainfo; for (p = 1; ainfo->ai_hostent->h_addr_list[p] != NULL; p++) { - if (!(ai->ai_next = malloc(sizeof(struct addrinfo)))) { + if (!(ai->ai_next = git__malloc(sizeof(struct addrinfo)))) { p_freeaddrinfo(ainfo); return -1; } @@ -89,7 +89,7 @@ while(p != NULL) { next = p->ai_next; - free(p); + git__free(p); p = next; } } @@ -235,7 +235,7 @@ } -int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset) +int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset) { GIT_MMAP_VALIDATE(out, len, prot, flags); @@ -247,7 +247,7 @@ return -1; } - out->data = malloc(len); + out->data = git__malloc(len); GIT_ERROR_CHECK_ALLOC(out->data); if (!git__is_ssizet(len) || @@ -264,7 +264,7 @@ int p_munmap(git_map *map) { assert(map != NULL); - free(map->data); + git__free(map->data); return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/posix.h libgit2-1.1.0+dfsg.1/src/posix.h --- libgit2-0.28.5+dfsg.1/src/posix.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/posix.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,7 +11,6 @@ #include #include -#include "fnmatch.h" /* stat: file mode type testing macros */ #ifndef S_IFGITLINK @@ -90,6 +89,18 @@ #define EAFNOSUPPORT (INT_MAX-1) #endif +/* Provide a 64-bit size for offsets. */ + +#if defined(_MSC_VER) +typedef __int64 off64_t; +#elif defined(__HAIKU__) +typedef __haiku_std_int64 off64_t; +#elif defined(__APPLE__) +typedef __int64_t off64_t; +#else +typedef int64_t off64_t; +#endif + typedef int git_file; /** diff -Nru libgit2-0.28.5+dfsg.1/src/proxy.c libgit2-1.1.0+dfsg.1/src/proxy.c --- libgit2-0.28.5+dfsg.1/src/proxy.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/proxy.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,17 +9,24 @@ #include "git2/proxy.h" -int git_proxy_init_options(git_proxy_options *opts, unsigned int version) +int git_proxy_options_init(git_proxy_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_proxy_options, GIT_PROXY_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_proxy_init_options(git_proxy_options *opts, unsigned int version) +{ + return git_proxy_options_init(opts, version); +} +#endif + int git_proxy_options_dup(git_proxy_options *tgt, const git_proxy_options *src) { if (!src) { - git_proxy_init_options(tgt, GIT_PROXY_OPTIONS_VERSION); + git_proxy_options_init(tgt, GIT_PROXY_OPTIONS_VERSION); return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/push.c libgit2-1.1.0+dfsg.1/src/push.c --- libgit2-0.28.5+dfsg.1/src/push.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/push.c 2020-10-12 18:53:06.000000000 +0000 @@ -196,7 +196,7 @@ continue; /* Update the remote ref */ - if (git_oid_iszero(&push_spec->loid)) { + if (git_oid_is_zero(&push_spec->loid)) { error = git_reference_lookup(&remote_ref, push->remote->repo, git_buf_cstr(&remote_ref_name)); if (error >= 0) { @@ -281,7 +281,7 @@ git_object_t type; size_t size; - if (git_oid_iszero(&spec->loid)) + if (git_oid_is_zero(&spec->loid)) /* * Delete reference on remote side; * nothing to do here. @@ -319,7 +319,7 @@ if (!spec->refspec.force) { git_oid base; - if (git_oid_iszero(&spec->roid)) + if (git_oid_is_zero(&spec->roid)) continue; if (!git_odb_exists(push->repo->_odb, &spec->roid)) { @@ -346,11 +346,12 @@ } git_vector_foreach(&push->remote->refs, i, head) { - if (git_oid_iszero(&head->oid)) + if (git_oid_is_zero(&head->oid)) continue; - /* TODO */ - git_revwalk_hide(rw, &head->oid); + if ((error = git_revwalk_hide(rw, &head->oid)) < 0 && + error != GIT_ENOTFOUND && error != GIT_EINVALIDSPEC && error != GIT_EPEEL) + goto on_error; } error = git_packbuilder_insert_walk(push->pb, rw); @@ -547,9 +548,16 @@ git__free(push); } -int git_push_init_options(git_push_options *opts, unsigned int version) +int git_push_options_init(git_push_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_push_options, GIT_PUSH_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_push_init_options(git_push_options *opts, unsigned int version) +{ + return git_push_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/reader.c libgit2-1.1.0+dfsg.1/src/reader.c --- libgit2-0.28.5+dfsg.1/src/reader.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/reader.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,7 +7,7 @@ #include "reader.h" -#include "fileops.h" +#include "futils.h" #include "blob.h" #include "git2/tree.h" @@ -32,7 +32,7 @@ tree_reader *reader = (tree_reader *)_reader; git_tree_entry *tree_entry = NULL; git_blob *blob = NULL; - git_off_t blobsize; + git_object_size_t blobsize; int error; if ((error = git_tree_entry_bypath(&tree_entry, reader->tree, filename)) < 0 || diff -Nru libgit2-0.28.5+dfsg.1/src/rebase.c libgit2-1.1.0+dfsg.1/src/rebase.c --- libgit2-0.28.5+dfsg.1/src/rebase.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/rebase.c 2020-10-12 18:53:06.000000000 +0000 @@ -49,18 +49,18 @@ #define REBASE_FILE_MODE 0666 typedef enum { - GIT_REBASE_TYPE_NONE = 0, - GIT_REBASE_TYPE_APPLY = 1, - GIT_REBASE_TYPE_MERGE = 2, - GIT_REBASE_TYPE_INTERACTIVE = 3, -} git_rebase_type_t; + GIT_REBASE_NONE = 0, + GIT_REBASE_APPLY = 1, + GIT_REBASE_MERGE = 2, + GIT_REBASE_INTERACTIVE = 3, +} git_rebase_t; struct git_rebase { git_repository *repo; git_rebase_options options; - git_rebase_type_t type; + git_rebase_t type; char *state_path; int head_detached : 1, @@ -86,18 +86,18 @@ #define GIT_REBASE_STATE_INIT {0} static int rebase_state_type( - git_rebase_type_t *type_out, + git_rebase_t *type_out, char **path_out, git_repository *repo) { git_buf path = GIT_BUF_INIT; - git_rebase_type_t type = GIT_REBASE_TYPE_NONE; + git_rebase_t type = GIT_REBASE_NONE; if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0) return -1; if (git_path_isdir(git_buf_cstr(&path))) { - type = GIT_REBASE_TYPE_APPLY; + type = GIT_REBASE_APPLY; goto done; } @@ -106,14 +106,14 @@ return -1; if (git_path_isdir(git_buf_cstr(&path))) { - type = GIT_REBASE_TYPE_MERGE; + type = GIT_REBASE_MERGE; goto done; } done: *type_out = type; - if (type != GIT_REBASE_TYPE_NONE && path_out) + if (type != GIT_REBASE_NONE && path_out) *path_out = git_buf_detach(&path); git_buf_dispose(&path); @@ -268,7 +268,7 @@ if (rebase_opts) memcpy(&rebase->options, rebase_opts, sizeof(git_rebase_options)); else - git_rebase_init_options(&rebase->options, GIT_REBASE_OPTIONS_VERSION); + git_rebase_options_init(&rebase->options, GIT_REBASE_OPTIONS_VERSION); if (rebase_opts && rebase_opts->rewrite_notes_ref) { rebase->options.rewrite_notes_ref = git__strdup(rebase_opts->rewrite_notes_ref); @@ -298,7 +298,8 @@ git_rebase *rebase; git_buf path = GIT_BUF_INIT, orig_head_name = GIT_BUF_INIT, orig_head_id = GIT_BUF_INIT, onto_id = GIT_BUF_INIT; - int state_path_len, error; + size_t state_path_len; + int error; assert(repo); @@ -313,7 +314,7 @@ if ((error = rebase_state_type(&rebase->type, &rebase->state_path, repo)) < 0) goto done; - if (rebase->type == GIT_REBASE_TYPE_NONE) { + if (rebase->type == GIT_REBASE_NONE) { git_error_set(GIT_ERROR_REBASE, "there is no rebase in progress"); error = GIT_ENOTFOUND; goto done; @@ -369,14 +370,14 @@ rebase->orig_head_name = git_buf_detach(&orig_head_name); switch (rebase->type) { - case GIT_REBASE_TYPE_INTERACTIVE: + case GIT_REBASE_INTERACTIVE: git_error_set(GIT_ERROR_REBASE, "interactive rebase is not supported"); error = -1; break; - case GIT_REBASE_TYPE_MERGE: + case GIT_REBASE_MERGE: error = rebase_open_merge(rebase); break; - case GIT_REBASE_TYPE_APPLY: + case GIT_REBASE_APPLY: git_error_set(GIT_ERROR_REBASE, "patch application rebase is not supported"); error = -1; break; @@ -493,22 +494,29 @@ return rebase_setupfiles_merge(rebase); } -int git_rebase_init_options(git_rebase_options *opts, unsigned int version) +int git_rebase_options_init(git_rebase_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_rebase_options, GIT_REBASE_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_rebase_init_options(git_rebase_options *opts, unsigned int version) +{ + return git_rebase_options_init(opts, version); +} +#endif + static int rebase_ensure_not_in_progress(git_repository *repo) { int error; - git_rebase_type_t type; + git_rebase_t type; if ((error = rebase_state_type(&type, NULL, repo)) < 0) return error; - if (type != GIT_REBASE_TYPE_NONE) { + if (type != GIT_REBASE_NONE) { git_error_set(GIT_ERROR_REBASE, "there is an existing rebase in progress"); return -1; } @@ -723,7 +731,7 @@ rebase->repo = repo; rebase->inmemory = inmemory; - rebase->type = GIT_REBASE_TYPE_MERGE; + rebase->type = GIT_REBASE_MERGE; if ((error = rebase_init_operations(rebase, repo, branch, upstream, onto)) < 0) goto done; @@ -758,7 +766,7 @@ if (!checkout_opts->ancestor_label) checkout_opts->ancestor_label = "ancestor"; - if (rebase->type == GIT_REBASE_TYPE_MERGE) { + if (rebase->type == GIT_REBASE_MERGE) { if (!checkout_opts->our_label) checkout_opts->our_label = rebase->onto_name; @@ -911,7 +919,7 @@ if (rebase->inmemory) error = rebase_next_inmemory(out, rebase); - else if (rebase->type == GIT_REBASE_TYPE_MERGE) + else if (rebase->type == GIT_REBASE_MERGE) error = rebase_next_merge(out, rebase); else abort(); @@ -945,6 +953,10 @@ git_commit *current_commit = NULL, *commit = NULL; git_tree *parent_tree = NULL, *tree = NULL; git_oid tree_id, commit_id; + git_buf commit_content = GIT_BUF_INIT, commit_signature = GIT_BUF_INIT, + signature_field = GIT_BUF_INIT; + const char *signature_field_string = NULL, + *commit_signature_string = NULL; int error; operation = git_array_get(rebase->operations, rebase->current); @@ -975,10 +987,40 @@ message = git_commit_message(current_commit); } - if ((error = git_commit_create(&commit_id, rebase->repo, NULL, author, - committer, message_encoding, message, tree, 1, - (const git_commit **)&parent_commit)) < 0 || - (error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0) + if ((error = git_commit_create_buffer(&commit_content, rebase->repo, author, committer, + message_encoding, message, tree, 1, (const git_commit **)&parent_commit)) < 0) + goto done; + + if (rebase->options.signing_cb) { + git_error_clear(); + error = git_error_set_after_callback_function(rebase->options.signing_cb( + &commit_signature, &signature_field, git_buf_cstr(&commit_content), + rebase->options.payload), "commit signing_cb failed"); + if (error == GIT_PASSTHROUGH) { + git_buf_dispose(&commit_signature); + git_buf_dispose(&signature_field); + git_error_clear(); + error = GIT_OK; + } else if (error < 0) + goto done; + } + + if (git_buf_is_allocated(&commit_signature)) { + assert(git_buf_contains_nul(&commit_signature)); + commit_signature_string = git_buf_cstr(&commit_signature); + } + + if (git_buf_is_allocated(&signature_field)) { + assert(git_buf_contains_nul(&signature_field)); + signature_field_string = git_buf_cstr(&signature_field); + } + + if ((error = git_commit_create_with_signature(&commit_id, rebase->repo, + git_buf_cstr(&commit_content), commit_signature_string, + signature_field_string))) + goto done; + + if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0) goto done; *out = commit; @@ -987,6 +1029,9 @@ if (error < 0) git_commit_free(commit); + git_buf_dispose(&commit_signature); + git_buf_dispose(&signature_field); + git_buf_dispose(&commit_content); git_commit_free(current_commit); git_tree_free(parent_tree); git_tree_free(tree); @@ -1085,7 +1130,7 @@ if (rebase->inmemory) error = rebase_commit_inmemory( id, rebase, author, committer, message_encoding, message); - else if (rebase->type == GIT_REBASE_TYPE_MERGE) + else if (rebase->type == GIT_REBASE_MERGE) error = rebase_commit_merge( id, rebase, author, committer, message_encoding, message); else @@ -1327,6 +1372,22 @@ return error; } +const char *git_rebase_orig_head_name(git_rebase *rebase) { + return rebase->orig_head_name; +} + +const git_oid *git_rebase_orig_head_id(git_rebase *rebase) { + return &rebase->orig_head_id; +} + +const char *git_rebase_onto_name(git_rebase *rebase) { + return rebase->onto_name; +} + +const git_oid *git_rebase_onto_id(git_rebase *rebase) { + return &rebase->onto_id; +} + size_t git_rebase_operation_entrycount(git_rebase *rebase) { assert(rebase); diff -Nru libgit2-0.28.5+dfsg.1/src/refdb.c libgit2-1.1.0+dfsg.1/src/refdb.c --- libgit2-0.28.5+dfsg.1/src/refdb.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refdb.c 2020-10-12 18:53:06.000000000 +0000 @@ -17,6 +17,9 @@ #include "reflog.h" #include "posix.h" +#define DEFAULT_NESTING_LEVEL 5 +#define MAX_NESTING_LEVEL 10 + int git_refdb_new(git_refdb **out, git_repository *repo) { git_refdb *db; @@ -66,6 +69,18 @@ int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend) { + GIT_ERROR_CHECK_VERSION(backend, GIT_REFDB_BACKEND_VERSION, "git_refdb_backend"); + + if (!backend->exists || !backend->lookup || !backend->iterator || + !backend->write || !backend->rename || !backend->del || + !backend->has_log || !backend->ensure_log || !backend->free || + !backend->reflog_read || !backend->reflog_write || + !backend->reflog_rename || !backend->reflog_delete || + (backend->lock && !backend->unlock)) { + git_error_set(GIT_ERROR_REFERENCE, "incomplete refdb backend implementation"); + return GIT_EINVALID; + } + refdb_free_backend(db); db->backend = backend; @@ -122,6 +137,59 @@ return 0; } +int git_refdb_resolve( + git_reference **out, + git_refdb *db, + const char *ref_name, + int max_nesting) +{ + git_reference *ref = NULL; + int error = 0, nesting; + + *out = NULL; + + if (max_nesting > MAX_NESTING_LEVEL) + max_nesting = MAX_NESTING_LEVEL; + else if (max_nesting < 0) + max_nesting = DEFAULT_NESTING_LEVEL; + + if ((error = git_refdb_lookup(&ref, db, ref_name)) < 0) + goto out; + + for (nesting = 0; nesting < max_nesting; nesting++) { + git_reference *resolved; + + if (ref->type == GIT_REFERENCE_DIRECT) + break; + + if ((error = git_refdb_lookup(&resolved, db, git_reference_symbolic_target(ref))) < 0) { + /* If we found a symbolic reference with a nonexistent target, return it. */ + if (error == GIT_ENOTFOUND) { + error = 0; + *out = ref; + ref = NULL; + } + goto out; + } + + git_reference_free(ref); + ref = resolved; + } + + if (ref->type != GIT_REFERENCE_DIRECT && max_nesting != 0) { + git_error_set(GIT_ERROR_REFERENCE, + "cannot resolve reference (>%u levels deep)", max_nesting); + error = -1; + goto out; + } + + *out = ref; + ref = NULL; +out: + git_reference_free(ref); + return error; +} + int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob) { int error; @@ -219,6 +287,85 @@ return 0; } +int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref) +{ + int error, logall; + + error = git_repository__configmap_lookup(&logall, db->repo, GIT_CONFIGMAP_LOGALLREFUPDATES); + if (error < 0) + return error; + + /* Defaults to the opposite of the repo being bare */ + if (logall == GIT_LOGALLREFUPDATES_UNSET) + logall = !git_repository_is_bare(db->repo); + + *out = 0; + switch (logall) { + case GIT_LOGALLREFUPDATES_FALSE: + *out = 0; + break; + + case GIT_LOGALLREFUPDATES_TRUE: + /* Only write if it already has a log, + * or if it's under heads/, remotes/ or notes/ + */ + *out = git_refdb_has_log(db, ref->name) || + !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) || + !git__strcmp(ref->name, GIT_HEAD_FILE) || + !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) || + !git__prefixcmp(ref->name, GIT_REFS_NOTES_DIR); + break; + + case GIT_LOGALLREFUPDATES_ALWAYS: + *out = 1; + break; + } + + return 0; +} + +int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref) +{ + git_reference *head = NULL, *resolved = NULL; + const char *name; + int error; + + *out = 0; + + if (ref->type == GIT_REFERENCE_SYMBOLIC) { + error = 0; + goto out; + } + + if ((error = git_refdb_lookup(&head, db, GIT_HEAD_FILE)) < 0) + goto out; + + if (git_reference_type(head) == GIT_REFERENCE_DIRECT) + goto out; + + /* Go down the symref chain until we find the branch */ + if ((error = git_refdb_resolve(&resolved, db, git_reference_symbolic_target(head), -1)) < 0) { + if (error != GIT_ENOTFOUND) + goto out; + error = 0; + name = git_reference_symbolic_target(head); + } else if (git_reference_type(resolved) == GIT_REFERENCE_SYMBOLIC) { + name = git_reference_symbolic_target(resolved); + } else { + name = git_reference_name(resolved); + } + + if (strcmp(name, ref->name)) + goto out; + + *out = 1; + +out: + git_reference_free(resolved); + git_reference_free(head); + return error; +} + int git_refdb_has_log(git_refdb *db, const char *refname) { assert(db && refname); diff -Nru libgit2-0.28.5+dfsg.1/src/refdb_fs.c libgit2-1.1.0+dfsg.1/src/refdb_fs.c --- libgit2-0.28.5+dfsg.1/src/refdb_fs.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refdb_fs.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,19 +5,19 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include "refdb_fs.h" - #include "refs.h" #include "hash.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "filebuf.h" #include "pack.h" +#include "parse.h" #include "reflog.h" #include "refdb.h" #include "iterator.h" #include "sortedcache.h" #include "signature.h" +#include "wildmatch.h" #include #include @@ -327,21 +327,33 @@ git_refdb_backend *_backend, const char *ref_name) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); git_buf ref_path = GIT_BUF_INIT; int error; assert(backend); - if ((error = packed_reload(backend)) < 0 || - (error = git_buf_joinpath(&ref_path, backend->gitpath, ref_name)) < 0) - return error; + *exists = 0; + + if ((error = git_buf_joinpath(&ref_path, backend->gitpath, ref_name)) < 0) + goto out; + + if (git_path_isfile(ref_path.ptr)) { + *exists = 1; + goto out; + } + + if ((error = packed_reload(backend)) < 0) + goto out; - *exists = git_path_isfile(ref_path.ptr) || - (git_sortedcache_lookup(backend->refcache, ref_name) != NULL); + if (git_sortedcache_lookup(backend->refcache, ref_name) != NULL) { + *exists = 1; + goto out; + } +out: git_buf_dispose(&ref_path); - return 0; + return error; } static const char *loose_parse_symbolic(git_buf *file_content) @@ -457,7 +469,7 @@ git_refdb_backend *_backend, const char *ref_name) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); int error; assert(backend); @@ -490,7 +502,7 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) { - refdb_fs_iter *iter = (refdb_fs_iter *) _iter; + refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent); git_vector_free(&iter->loose); git_pool_clear(&iter->pool); @@ -552,7 +564,6 @@ while (!error && !git_iterator_advance(&entry, fsit)) { const char *ref_name; - struct packref *ref; char *ref_dup; git_buf_truncate(&path, ref_prefix_len); @@ -560,15 +571,9 @@ ref_name = git_buf_cstr(&path); if (git__suffixcmp(ref_name, ".lock") == 0 || - (iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) + (iter->glob && wildmatch(iter->glob, ref_name, 0) != 0)) continue; - git_sortedcache_rlock(backend->refcache); - ref = git_sortedcache_lookup(backend->refcache, ref_name); - if (ref) - ref->flags |= PACKREF_SHADOWED; - git_sortedcache_runlock(backend->refcache); - ref_dup = git_pool_strdup(&iter->pool, ref_name); if (!ref_dup) error = -1; @@ -586,24 +591,24 @@ git_reference **out, git_reference_iterator *_iter) { int error = GIT_ITEROVER; - refdb_fs_iter *iter = (refdb_fs_iter *)_iter; - refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; + refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent); + refdb_fs_backend *backend = GIT_CONTAINER_OF(iter->parent.db->backend, refdb_fs_backend, parent); struct packref *ref; while (iter->loose_pos < iter->loose.length) { const char *path = git_vector_get(&iter->loose, iter->loose_pos++); - if (loose_lookup(out, backend, path) == 0) + if (loose_lookup(out, backend, path) == 0) { + ref = git_sortedcache_lookup(iter->cache, path); + if (ref) + ref->flags |= PACKREF_SHADOWED; + return 0; + } git_error_clear(); } - if (!iter->cache) { - if ((error = git_sortedcache_copy(&iter->cache, backend->refcache, 1, NULL, NULL)) < 0) - return error; - } - error = GIT_ITEROVER; while (iter->packed_pos < git_sortedcache_entrycount(iter->cache)) { ref = git_sortedcache_entry(iter->cache, iter->packed_pos++); @@ -612,7 +617,7 @@ if (ref->flags & PACKREF_SHADOWED) continue; - if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0) + if (iter->glob && wildmatch(iter->glob, ref->name, 0) != 0) continue; *out = git_reference__alloc(ref->name, &ref->oid, &ref->peel); @@ -627,14 +632,19 @@ const char **out, git_reference_iterator *_iter) { int error = GIT_ITEROVER; - refdb_fs_iter *iter = (refdb_fs_iter *)_iter; - refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; + refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent); + refdb_fs_backend *backend = GIT_CONTAINER_OF(iter->parent.db->backend, refdb_fs_backend, parent); struct packref *ref; while (iter->loose_pos < iter->loose.length) { const char *path = git_vector_get(&iter->loose, iter->loose_pos++); + struct packref *ref; if (loose_lookup(NULL, backend, path) == 0) { + ref = git_sortedcache_lookup(iter->cache, path); + if (ref) + ref->flags |= PACKREF_SHADOWED; + *out = path; return 0; } @@ -642,11 +652,6 @@ git_error_clear(); } - if (!iter->cache) { - if ((error = git_sortedcache_copy(&iter->cache, backend->refcache, 1, NULL, NULL)) < 0) - return error; - } - error = GIT_ITEROVER; while (iter->packed_pos < git_sortedcache_entrycount(iter->cache)) { ref = git_sortedcache_entry(iter->cache, iter->packed_pos++); @@ -655,7 +660,7 @@ if (ref->flags & PACKREF_SHADOWED) continue; - if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0) + if (iter->glob && wildmatch(iter->glob, ref->name, 0) != 0) continue; *out = ref->name; @@ -669,40 +674,45 @@ static int refdb_fs_backend__iterator( git_reference_iterator **out, git_refdb_backend *_backend, const char *glob) { + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); + refdb_fs_iter *iter = NULL; int error; - refdb_fs_iter *iter; - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; assert(backend); - if ((error = packed_reload(backend)) < 0) - return error; - iter = git__calloc(1, sizeof(refdb_fs_iter)); GIT_ERROR_CHECK_ALLOC(iter); - git_pool_init(&iter->pool, 1); + if ((error = git_pool_init(&iter->pool, 1)) < 0) + goto out; - if (git_vector_init(&iter->loose, 8, NULL) < 0) - goto fail; + if ((error = git_vector_init(&iter->loose, 8, NULL)) < 0) + goto out; if (glob != NULL && - (iter->glob = git_pool_strdup(&iter->pool, glob)) == NULL) - goto fail; + (iter->glob = git_pool_strdup(&iter->pool, glob)) == NULL) { + error = GIT_ERROR_NOMEMORY; + goto out; + } + + if ((error = iter_load_loose_paths(backend, iter)) < 0) + goto out; + + if ((error = packed_reload(backend)) < 0) + goto out; + + if ((error = git_sortedcache_copy(&iter->cache, backend->refcache, 1, NULL, NULL)) < 0) + goto out; iter->parent.next = refdb_fs_backend__iterator_next; iter->parent.next_name = refdb_fs_backend__iterator_next_name; iter->parent.free = refdb_fs_backend__iterator_free; - if (iter_load_loose_paths(backend, iter) < 0) - goto fail; - *out = (git_reference_iterator *)iter; - return 0; - -fail: - refdb_fs_backend__iterator_free((git_reference_iterator *)iter); - return -1; +out: + if (error) + refdb_fs_backend__iterator_free((git_reference_iterator *)iter); + return error; } static bool ref_is_available( @@ -829,7 +839,7 @@ { int error; git_filebuf *lock; - refdb_fs_backend *backend = (refdb_fs_backend *) _backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); lock = git__calloc(1, sizeof(git_filebuf)); GIT_ERROR_CHECK_ALLOC(lock); @@ -848,16 +858,17 @@ const git_reference *ref, git_filebuf *file, int update_reflog, - const git_signature *who, - const char *message, const git_oid *old_id, - const char *old_target); + const char *old_target, + const git_signature *who, + const char *message); static int refdb_fs_backend__delete_tail( git_refdb_backend *_backend, git_filebuf *file, const char *ref_name, - const git_oid *old_id, const char *old_target); + const git_oid *old_id, + const char *old_target); static int refdb_fs_backend__unlock(git_refdb_backend *backend, void *payload, int success, int update_reflog, const git_reference *ref, const git_signature *sig, const char *message) @@ -868,7 +879,7 @@ if (success == 2) error = refdb_fs_backend__delete_tail(backend, lock, ref->name, NULL, NULL); else if (success) - error = refdb_fs_backend__write_tail(backend, ref, lock, update_reflog, sig, message, NULL, NULL); + error = refdb_fs_backend__write_tail(backend, ref, lock, update_reflog, NULL, NULL, sig, message); else git_filebuf_cleanup(lock); @@ -1087,46 +1098,37 @@ return error; } -static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *author, const char *message); -static int has_reflog(git_repository *repo, const char *name); - -static int should_write_reflog(int *write, git_repository *repo, const char *name) +static int packed_delete(refdb_fs_backend *backend, const char *ref_name) { - int error, logall; - - error = git_repository__cvar(&logall, repo, GIT_CVAR_LOGALLREFUPDATES); - if (error < 0) - return error; + size_t pack_pos; + int error, found = 0; - /* Defaults to the opposite of the repo being bare */ - if (logall == GIT_LOGALLREFUPDATES_UNSET) - logall = !git_repository_is_bare(repo); - - *write = 0; - switch (logall) { - case GIT_LOGALLREFUPDATES_FALSE: - *write = 0; - break; + if ((error = packed_reload(backend)) < 0) + goto cleanup; - case GIT_LOGALLREFUPDATES_TRUE: - /* Only write if it already has a log, - * or if it's under heads/, remotes/ or notes/ - */ - *write = has_reflog(repo, name) || - !git__prefixcmp(name, GIT_REFS_HEADS_DIR) || - !git__strcmp(name, GIT_HEAD_FILE) || - !git__prefixcmp(name, GIT_REFS_REMOTES_DIR) || - !git__prefixcmp(name, GIT_REFS_NOTES_DIR); - break; + if ((error = git_sortedcache_wlock(backend->refcache)) < 0) + goto cleanup; - case GIT_LOGALLREFUPDATES_ALWAYS: - *write = 1; - break; + /* If a packed reference exists, remove it from the packfile and repack if necessary */ + error = git_sortedcache_lookup_index(&pack_pos, backend->refcache, ref_name); + if (error == 0) { + error = git_sortedcache_remove(backend->refcache, pack_pos); + found = 1; } + if (error == GIT_ENOTFOUND) + error = 0; - return 0; + git_sortedcache_wunlock(backend->refcache); + + if (found) + error = packed_write(backend); + +cleanup: + return error; } +static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *author, const char *message); + static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name, const git_oid *old_id, const char *old_target) { @@ -1179,54 +1181,28 @@ */ static int maybe_append_head(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message) { - int error; + git_reference *head = NULL; + git_refdb *refdb = NULL; + int error, write_reflog; git_oid old_id; - git_reference *tmp = NULL, *head = NULL, *peeled = NULL; - const char *name; - if (ref->type == GIT_REFERENCE_SYMBOLIC) - return 0; + if ((error = git_repository_refdb(&refdb, backend->repo)) < 0 || + (error = git_refdb_should_write_head_reflog(&write_reflog, refdb, ref)) < 0) + goto out; + if (!write_reflog) + goto out; /* if we can't resolve, we use {0}*40 as old id */ if (git_reference_name_to_id(&old_id, backend->repo, ref->name) < 0) memset(&old_id, 0, sizeof(old_id)); - if ((error = git_reference_lookup(&head, backend->repo, GIT_HEAD_FILE)) < 0) - return error; - - if (git_reference_type(head) == GIT_REFERENCE_DIRECT) - goto cleanup; - - if ((error = git_reference_lookup(&tmp, backend->repo, GIT_HEAD_FILE)) < 0) - goto cleanup; - - /* Go down the symref chain until we find the branch */ - while (git_reference_type(tmp) == GIT_REFERENCE_SYMBOLIC) { - error = git_reference_lookup(&peeled, backend->repo, git_reference_symbolic_target(tmp)); - if (error < 0) - break; - - git_reference_free(tmp); - tmp = peeled; - } - - if (error == GIT_ENOTFOUND) { - error = 0; - name = git_reference_symbolic_target(tmp); - } else if (error < 0) { - goto cleanup; - } else { - name = git_reference_name(tmp); - } - - if (strcmp(name, ref->name)) - goto cleanup; - - error = reflog_append(backend, head, &old_id, git_reference_target(ref), who, message); + if ((error = git_reference_lookup(&head, backend->repo, GIT_HEAD_FILE)) < 0 || + (error = reflog_append(backend, head, &old_id, git_reference_target(ref), who, message)) < 0) + goto out; -cleanup: - git_reference_free(tmp); +out: git_reference_free(head); + git_refdb_free(refdb); return error; } @@ -1239,7 +1215,7 @@ const git_oid *old_id, const char *old_target) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); git_filebuf file = GIT_FILEBUF_INIT; int error = 0; @@ -1252,7 +1228,7 @@ if ((error = loose_lock(&file, backend, ref->name)) < 0) return error; - return refdb_fs_backend__write_tail(_backend, ref, &file, true, who, message, old_id, old_target); + return refdb_fs_backend__write_tail(_backend, ref, &file, true, old_id, old_target, who, message); } static int refdb_fs_backend__write_tail( @@ -1260,12 +1236,12 @@ const git_reference *ref, git_filebuf *file, int update_reflog, - const git_signature *who, - const char *message, const git_oid *old_id, - const char *old_target) + const char *old_target, + const git_signature *who, + const char *message) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); int error = 0, cmp = 0, should_write; const char *new_target = NULL; const git_oid *new_id = NULL; @@ -1295,7 +1271,10 @@ } if (update_reflog) { - if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0) + git_refdb *refdb; + + if ((error = git_repository_refdb__weakptr(&refdb, backend->repo)) < 0 || + (error = git_refdb_should_write_reflog(&should_write, refdb, ref)) < 0) goto on_error; if (should_write) { @@ -1313,10 +1292,10 @@ return error; } -static void refdb_fs_backend__try_delete_empty_ref_hierarchie( +static void refdb_fs_backend__prune_refs( refdb_fs_backend *backend, const char *ref_name, - bool reflog) + const char *prefix) { git_buf relative_path = GIT_BUF_INIT; git_buf base_path = GIT_BUF_INIT; @@ -1334,8 +1313,8 @@ git_buf_truncate(&relative_path, commonlen); - if (reflog) { - if (git_buf_join3(&base_path, '/', backend->commonpath, GIT_REFLOG_DIR, git_buf_cstr(&relative_path)) < 0) + if (prefix) { + if (git_buf_join3(&base_path, '/', backend->commonpath, prefix, git_buf_cstr(&relative_path)) < 0) goto cleanup; } else { if (git_buf_joinpath(&base_path, backend->commonpath, git_buf_cstr(&relative_path)) < 0) @@ -1355,7 +1334,7 @@ const char *ref_name, const git_oid *old_id, const char *old_target) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); git_filebuf file = GIT_FILEBUF_INIT; int error = 0; @@ -1372,17 +1351,34 @@ return refdb_fs_backend__delete_tail(_backend, &file, ref_name, old_id, old_target); } +static int loose_delete(refdb_fs_backend *backend, const char *ref_name) +{ + git_buf loose_path = GIT_BUF_INIT; + int error = 0; + + if (git_buf_joinpath(&loose_path, backend->commonpath, ref_name) < 0) + return -1; + + error = p_unlink(loose_path.ptr); + if (error < 0 && errno == ENOENT) + error = GIT_ENOTFOUND; + else if (error != 0) + error = -1; + + git_buf_dispose(&loose_path); + + return error; +} + static int refdb_fs_backend__delete_tail( git_refdb_backend *_backend, git_filebuf *file, const char *ref_name, const git_oid *old_id, const char *old_target) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; - git_buf loose_path = GIT_BUF_INIT; - size_t pack_pos; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); int error = 0, cmp = 0; - bool loose_deleted = 0; + bool packed_deleted = 0; error = cmp_old_ref(&cmp, _backend, ref_name, old_id, old_target); if (error < 0) @@ -1394,44 +1390,41 @@ goto cleanup; } - /* If a loose reference exists, remove it from the filesystem */ - if (git_buf_joinpath(&loose_path, backend->commonpath, ref_name) < 0) - return -1; - - - error = p_unlink(loose_path.ptr); - if (error < 0 && errno == ENOENT) - error = 0; - else if (error < 0) + /* + * To ensure that an external observer will see either the current ref value + * (because the loose ref still exists), or a missing ref (after the packed-file is + * unlocked, there will be nothing left), we must ensure things happen in the + * following order: + * + * - the packed-ref file is locked and loaded, as well as a loose one, if it exists + * - we optimistically delete a packed ref, keeping track of whether it existed + * - we delete the loose ref, note that we have its .lock + * - the loose ref is "unlocked", then the packed-ref file is rewritten and unlocked + * - we should prune the path components if a loose ref was deleted + * + * Note that, because our packed backend doesn't expose its filesystem lock, + * we might not be able to guarantee that this is what actually happens (ie. + * as our current code never write packed-refs.lock, nothing stops observers + * from grabbing a "stale" value from there). + */ + if ((error = packed_delete(backend, ref_name)) < 0 && error != GIT_ENOTFOUND) goto cleanup; - else if (error == 0) - loose_deleted = 1; - if ((error = packed_reload(backend)) < 0) - goto cleanup; + if (error == 0) + packed_deleted = 1; - /* If a packed reference exists, remove it from the packfile and repack */ - if ((error = git_sortedcache_wlock(backend->refcache)) < 0) + if ((error = loose_delete(backend, ref_name)) < 0 && error != GIT_ENOTFOUND) goto cleanup; - if (!(error = git_sortedcache_lookup_index( - &pack_pos, backend->refcache, ref_name))) - error = git_sortedcache_remove(backend->refcache, pack_pos); - - git_sortedcache_wunlock(backend->refcache); - if (error == GIT_ENOTFOUND) { - error = loose_deleted ? 0 : ref_error_notfound(ref_name); + error = packed_deleted ? 0 : ref_error_notfound(ref_name); goto cleanup; } - error = packed_write(backend); - cleanup: - git_buf_dispose(&loose_path); git_filebuf_cleanup(file); - if (loose_deleted) - refdb_fs_backend__try_delete_empty_ref_hierarchie(backend, ref_name, false); + if (error == 0) + refdb_fs_backend__prune_refs(backend, ref_name, ""); return error; } @@ -1446,8 +1439,8 @@ const git_signature *who, const char *message) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; - git_reference *old, *new; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); + git_reference *old, *new = NULL; git_filebuf file = GIT_FILEBUF_INIT; int error; @@ -1463,7 +1456,7 @@ return error; } - new = git_reference__set_name(old, new_name); + new = git_reference__realloc(&old, new_name); if (!new) { git_reference_free(old); return -1; @@ -1502,7 +1495,7 @@ static int refdb_fs_backend__compress(git_refdb_backend *_backend) { int error; - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); assert(backend); @@ -1516,7 +1509,7 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) { - refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); assert(backend); @@ -1597,70 +1590,57 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size) { - const char *ptr; - git_reflog_entry *entry; + git_parse_ctx parser = GIT_PARSE_CTX_INIT; -#define seek_forward(_increase) do { \ - if (_increase >= buf_size) { \ - git_error_set(GIT_ERROR_INVALID, "ran out of data while parsing reflog"); \ - goto fail; \ - } \ - buf += _increase; \ - buf_size -= _increase; \ - } while (0) + if ((git_parse_ctx_init(&parser, buf, buf_size)) < 0) + return -1; - while (buf_size > GIT_REFLOG_SIZE_MIN) { - entry = git__calloc(1, sizeof(git_reflog_entry)); - GIT_ERROR_CHECK_ALLOC(entry); + for (; parser.remain_len; git_parse_advance_line(&parser)) { + git_reflog_entry *entry; + const char *sig; + char c; - entry->committer = git__calloc(1, sizeof(git_signature)); + entry = git__calloc(1, sizeof(*entry)); + GIT_ERROR_CHECK_ALLOC(entry); + entry->committer = git__calloc(1, sizeof(*entry->committer)); GIT_ERROR_CHECK_ALLOC(entry->committer); - if (git_oid_fromstrn(&entry->oid_old, buf, GIT_OID_HEXSZ) < 0) - goto fail; - seek_forward(GIT_OID_HEXSZ + 1); - - if (git_oid_fromstrn(&entry->oid_cur, buf, GIT_OID_HEXSZ) < 0) - goto fail; - seek_forward(GIT_OID_HEXSZ + 1); - - ptr = buf; - - /* Seek forward to the end of the signature. */ - while (*buf && *buf != '\t' && *buf != '\n') - seek_forward(1); + if (git_parse_advance_oid(&entry->oid_old, &parser) < 0 || + git_parse_advance_expected(&parser, " ", 1) < 0 || + git_parse_advance_oid(&entry->oid_cur, &parser) < 0) + goto next; + + sig = parser.line; + while (git_parse_peek(&c, &parser, 0) == 0 && c != '\t' && c != '\n') + git_parse_advance_chars(&parser, 1); + + if (git_signature__parse(entry->committer, &sig, parser.line, NULL, 0) < 0) + goto next; + + if (c == '\t') { + size_t len; + git_parse_advance_chars(&parser, 1); + + len = parser.line_len; + if (parser.line[len - 1] == '\n') + len--; - if (git_signature__parse(entry->committer, &ptr, buf + 1, NULL, *buf) < 0) - goto fail; - - if (*buf == '\t') { - /* We got a message. Read everything till we reach LF. */ - seek_forward(1); - ptr = buf; - - while (*buf && *buf != '\n') - seek_forward(1); - - entry->msg = git__strndup(ptr, buf - ptr); + entry->msg = git__strndup(parser.line, len); GIT_ERROR_CHECK_ALLOC(entry->msg); - } else - entry->msg = NULL; + } - while (*buf && *buf == '\n' && buf_size > 1) - seek_forward(1); + if ((git_vector_insert(&log->entries, entry)) < 0) { + git_reflog_entry__free(entry); + return -1; + } - if (git_vector_insert(&log->entries, entry) < 0) - goto fail; + continue; + +next: + git_reflog_entry__free(entry); } return 0; - -#undef seek_forward - -fail: - git_reflog_entry__free(entry); - - return -1; } static int create_new_reflog_file(const char *filepath) @@ -1694,7 +1674,7 @@ assert(_backend && name); - backend = (refdb_fs_backend *) _backend; + backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); repo = backend->repo; if ((error = retrieve_reflog_path(&path, repo, name)) < 0) @@ -1727,7 +1707,7 @@ assert(_backend && name); - backend = (refdb_fs_backend *) _backend; + backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); return has_reflog(backend->repo, name); } @@ -1743,7 +1723,7 @@ assert(out && _backend && name); - backend = (refdb_fs_backend *) _backend; + backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); repo = backend->repo; if (reflog_alloc(&log, name) < 0) @@ -1802,8 +1782,15 @@ git_buf_rtrim(buf); if (msg) { + size_t i; + git_buf_putc(buf, '\t'); git_buf_puts(buf, msg); + + for (i = 0; i < buf->size - 2; i++) + if (buf->ptr[i] == '\n') + buf->ptr[i] = ' '; + git_buf_rtrim(buf); } git_buf_putc(buf, '\n'); @@ -1853,7 +1840,7 @@ assert(_backend && reflog); - backend = (refdb_fs_backend *) _backend; + backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); if ((error = lock_reflog(&fbuf, backend, reflog->ref_name)) < 0) return -1; @@ -1894,7 +1881,7 @@ !(old && new)) return 0; - /* From here on is_symoblic also means that it's HEAD */ + /* From here on is_symbolic also means that it's HEAD */ if (old) { git_oid_cpy(&old_id, old); @@ -1975,7 +1962,7 @@ assert(_backend && old_name && new_name); - backend = (refdb_fs_backend *) _backend; + backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); repo = backend->repo; if ((error = git_reference__normalize_name( @@ -2046,7 +2033,7 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name) { - refdb_fs_backend *backend = (refdb_fs_backend *) _backend; + refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent); git_buf path = GIT_BUF_INIT; int error; @@ -2061,7 +2048,7 @@ if ((error = p_unlink(path.ptr)) < 0) goto out; - refdb_fs_backend__try_delete_empty_ref_hierarchie(backend, name, true); + refdb_fs_backend__prune_refs(backend, name, GIT_REFLOG_DIR); out: git_buf_dispose(&path); @@ -2107,15 +2094,15 @@ git_buf_dispose(&gitpath); - if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) { + if (!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_IGNORECASE) && t) { backend->iterator_flags |= GIT_ITERATOR_IGNORE_CASE; backend->direach_flags |= GIT_PATH_DIR_IGNORE_CASE; } - if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_PRECOMPOSE) && t) { + if (!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_PRECOMPOSE) && t) { backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; backend->direach_flags |= GIT_PATH_DIR_PRECOMPOSE_UNICODE; } - if ((!git_repository__cvar(&t, backend->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) || + if ((!git_repository__configmap_lookup(&t, backend->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t) || git_repository__fsync_gitdir) backend->fsync = 1; backend->iterator_flags |= GIT_ITERATOR_DESCEND_SYMLINKS; diff -Nru libgit2-0.28.5+dfsg.1/src/refdb_fs.h libgit2-1.1.0+dfsg.1/src/refdb_fs.h --- libgit2-0.28.5+dfsg.1/src/refdb_fs.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refdb_fs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#ifndef INCLUDE_refdb_fs_h__ -#define INCLUDE_refdb_fs_h__ - -#include "common.h" - -#include "strmap.h" - -typedef struct { - git_strmap *packfile; - time_t packfile_time; -} git_refcache; - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/refdb.h libgit2-1.1.0+dfsg.1/src/refdb.h --- libgit2-0.28.5+dfsg.1/src/refdb.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refdb.h 2020-10-12 18:53:06.000000000 +0000 @@ -30,6 +30,31 @@ git_refdb *refdb, const char *ref_name); +/** + * Resolve the reference by following symbolic references. + * + * Given a reference name, this function will follow any symbolic references up + * to `max_nesting` deep and return the resolved direct reference. If any of + * the intermediate symbolic references points to a non-existing reference, + * then that symbolic reference is returned instead with an error code of `0`. + * If the given reference is a direct reference already, it is returned + * directly. + * + * If `max_nesting` is `0`, the reference will not be resolved. If it's + * negative, it will be set to the default resolve depth which is `5`. + * + * @param out Pointer to store the result in. + * @param db The refdb to use for resolving the reference. + * @param ref_name The reference name to lookup and resolve. + * @param max_nesting The maximum nesting depth. + * @return `0` on success, a negative error code otherwise. + */ +int git_refdb_resolve( + git_reference **out, + git_refdb *db, + const char *ref_name, + int max_nesting); + int git_refdb_rename( git_reference **out, git_refdb *db, @@ -50,6 +75,50 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name); int git_refdb_reflog_write(git_reflog *reflog); +/** + * Determine whether a reflog entry should be created for the given reference. + * + * Whether or not writing to a reference should create a reflog entry is + * dependent on a number of things. Most importantly, there's the + * "core.logAllRefUpdates" setting that controls in which situations a + * reference should get a corresponding reflog entry. The following values for + * it are understood: + * + * - "false": Do not log reference updates. + * + * - "true": Log normal reference updates. This will write entries for + * references in "refs/heads", "refs/remotes", "refs/notes" and + * "HEAD" or if the reference already has a log entry. + * + * - "always": Always create a reflog entry. + * + * If unset, the value will default to "true" for non-bare repositories and + * "false" for bare ones. + * + * @param out pointer to which the result will be written, `1` means a reflog + * entry should be written, `0` means none should be written. + * @param db The refdb to decide this for. + * @param ref The reference one wants to check. + * @return `0` on success, a negative error code otherwise. + */ +int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref); + +/** + * Determine whether a reflog entry should be created for HEAD if creating one + * for the given reference + * + * In case the given reference is being pointed to by HEAD, then creating a + * reflog entry for this reference also requires us to create a corresponding + * reflog entry for HEAD. This function can be used to determine that scenario. + * + * @param out pointer to which the result will be written, `1` means a reflog + * entry should be written, `0` means none should be written. + * @param db The refdb to decide this for. + * @param ref The reference one wants to check. + * @return `0` on success, a negative error code otherwise. + */ +int git_refdb_should_write_head_reflog(int *out, git_refdb *db, const git_reference *ref); + int git_refdb_has_log(git_refdb *db, const char *refname); int git_refdb_ensure_log(git_refdb *refdb, const char *refname); diff -Nru libgit2-0.28.5+dfsg.1/src/reflog.c libgit2-1.1.0+dfsg.1/src/reflog.c --- libgit2-0.28.5+dfsg.1/src/reflog.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/reflog.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,12 +12,8 @@ #include "signature.h" #include "refdb.h" -#include - -git_reflog_entry *git_reflog_entry__alloc(void) -{ - return git__calloc(1, sizeof(git_reflog_entry)); -} +#include "git2/sys/refdb_backend.h" +#include "git2/sys/reflog.h" void git_reflog_entry__free(git_reflog_entry *entry) { @@ -74,9 +70,8 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) { - git_reflog_entry *entry; const git_reflog_entry *previous; - const char *newline; + git_reflog_entry *entry; assert(reflog && new_oid && committer); @@ -87,19 +82,18 @@ goto cleanup; if (msg != NULL) { - if ((entry->msg = git__strdup(msg)) == NULL) - goto cleanup; + size_t i, msglen = strlen(msg); - newline = strchr(msg, '\n'); - - if (newline) { - if (newline[1] != '\0') { - git_error_set(GIT_ERROR_INVALID, "reflog message cannot contain newline"); - goto cleanup; - } + if ((entry->msg = git__strndup(msg, msglen)) == NULL) + goto cleanup; - entry->msg[newline - msg] = '\0'; - } + /* + * Replace all newlines with spaces, except for + * the final trailing newline. + */ + for (i = 0; i < msglen; i++) + if (entry->msg[i] == '\n') + entry->msg[i] = ' '; } previous = git_reflog_entry_byindex(reflog, 0); diff -Nru libgit2-0.28.5+dfsg.1/src/refs.c libgit2-1.1.0+dfsg.1/src/refs.c --- libgit2-0.28.5+dfsg.1/src/refs.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refs.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ #include "hash.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "filebuf.h" #include "pack.h" #include "reflog.h" @@ -27,9 +27,6 @@ bool git_reference__enable_symbolic_ref_target_validation = true; -#define DEFAULT_NESTING_LEVEL 5 -#define MAX_NESTING_LEVEL 10 - enum { GIT_PACKREF_HAS_PEEL = 1, GIT_PACKREF_WAS_LOOSE = 2 @@ -91,18 +88,23 @@ return ref; } -git_reference *git_reference__set_name( - git_reference *ref, const char *name) +git_reference *git_reference__realloc( + git_reference **ptr_to_ref, const char *name) { - size_t namelen = strlen(name); - size_t reflen; + size_t namelen, reflen; git_reference *rewrite = NULL; + assert(ptr_to_ref && name); + + namelen = strlen(name); + if (!GIT_ADD_SIZET_OVERFLOW(&reflen, sizeof(git_reference), namelen) && !GIT_ADD_SIZET_OVERFLOW(&reflen, reflen, 1) && - (rewrite = git__realloc(ref, reflen)) != NULL) + (rewrite = git__realloc(*ptr_to_ref, reflen)) != NULL) memcpy(rewrite->name, name, namelen + 1); + *ptr_to_ref = NULL; + return rewrite; } @@ -193,7 +195,7 @@ int precompose; unsigned int flags = GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL; - if (!git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) && + if (!git_repository__configmap_lookup(&precompose, repo, GIT_CONFIGMAP_PRECOMPOSE) && precompose) flags |= GIT_REFERENCE_FORMAT__PRECOMPOSE_UNICODE; @@ -209,89 +211,32 @@ const char *name, int max_nesting) { - git_refname_t scan_name; - git_reference_t scan_type; - int error = 0, nesting; - git_reference *ref = NULL; + git_refname_t normalized; git_refdb *refdb; + int error = 0; assert(ref_out && repo && name); - *ref_out = NULL; - - if (max_nesting > MAX_NESTING_LEVEL) - max_nesting = MAX_NESTING_LEVEL; - else if (max_nesting < 0) - max_nesting = DEFAULT_NESTING_LEVEL; - - scan_type = GIT_REFERENCE_SYMBOLIC; - - if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0) - return error; - - if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + if ((error = reference_normalize_for_repo(normalized, repo, name, true)) < 0 || + (error = git_repository_refdb__weakptr(&refdb, repo)) < 0 || + (error = git_refdb_resolve(ref_out, refdb, normalized, max_nesting)) < 0) return error; - for (nesting = max_nesting; - nesting >= 0 && scan_type == GIT_REFERENCE_SYMBOLIC; - nesting--) - { - if (nesting != max_nesting) { - strncpy(scan_name, ref->target.symbolic, sizeof(scan_name)); - git_reference_free(ref); - } - - if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0) - return error; - - scan_type = ref->type; - } - - if (scan_type != GIT_REFERENCE_DIRECT && max_nesting != 0) { - git_error_set(GIT_ERROR_REFERENCE, - "cannot resolve reference (>%u levels deep)", max_nesting); - git_reference_free(ref); - return -1; + /* + * The resolved reference may be a symbolic reference in case its + * target doesn't exist. If the user asked us to resolve (e.g. + * `max_nesting != 0`), then we need to return an error in case we got + * a symbolic reference back. + */ + if (max_nesting && git_reference_type(*ref_out) == GIT_REFERENCE_SYMBOLIC) { + git_reference_free(*ref_out); + *ref_out = NULL; + return GIT_ENOTFOUND; } - *ref_out = ref; return 0; } -int git_reference__read_head( - git_reference **out, - git_repository *repo, - const char *path) -{ - git_buf reference = GIT_BUF_INIT; - char *name = NULL; - int error; - - if ((error = git_futils_readbuffer(&reference, path)) < 0) - goto out; - git_buf_rtrim(&reference); - - if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) { - git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF)); - - name = git_path_basename(path); - - if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) { - error = -1; - goto out; - } - } else { - if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0) - goto out; - } - -out: - git__free(name); - git_buf_dispose(&reference); - - return error; -} - int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname) { int error = 0, i; @@ -391,7 +336,7 @@ { assert(ref); - if (ref->type != GIT_REFERENCE_DIRECT || git_oid_iszero(&ref->peel)) + if (ref->type != GIT_REFERENCE_DIRECT || git_oid_is_zero(&ref->peel)) return NULL; return &ref->peel; @@ -475,7 +420,7 @@ return 0; } -int configured_ident(git_signature **out, const git_repository *repo) +static int refs_configured_ident(git_signature **out, const git_repository *repo) { if (repo->ident_name && repo->ident_email) return git_signature_now(out, repo->ident_name, repo->ident_email); @@ -489,7 +434,7 @@ int error; git_signature *who; - if(((error = configured_ident(&who, repo)) < 0) && + if(((error = refs_configured_ident(&who, repo)) < 0) && ((error = git_signature_default(&who, repo)) < 0) && ((error = git_signature_now(&who, "unknown", "unknown")) < 0)) return error; @@ -626,84 +571,33 @@ typedef struct { const char *old_name; git_refname_t new_name; -} rename_cb_data; +} refs_update_head_payload; -static int update_wt_heads(git_repository *repo, const char *path, void *payload) +static int refs_update_head(git_repository *worktree, void *_payload) { - rename_cb_data *data = (rename_cb_data *) payload; - git_reference *head = NULL; - char *gitdir = NULL; + refs_update_head_payload *payload = (refs_update_head_payload *)_payload; + git_reference *head = NULL, *updated = NULL; int error; - if ((error = git_reference__read_head(&head, repo, path)) < 0) { - git_error_set(GIT_ERROR_REFERENCE, "could not read HEAD when renaming references"); - goto out; - } - - if ((gitdir = git_path_dirname(path)) == NULL) { - error = -1; + if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0) goto out; - } if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC || - git__strcmp(head->target.symbolic, data->old_name) != 0) { - error = 0; + git__strcmp(git_reference_symbolic_target(head), payload->old_name) != 0) goto out; - } - /* Update HEAD it was pointing to the reference being renamed */ - if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) { + /* Update HEAD if it was pointing to the reference being renamed */ + if ((error = git_reference_symbolic_set_target(&updated, head, payload->new_name, NULL)) < 0) { git_error_set(GIT_ERROR_REFERENCE, "failed to update HEAD after renaming reference"); goto out; } out: + git_reference_free(updated); git_reference_free(head); - git__free(gitdir); - return error; } -static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force, - const git_signature *signature, const char *message) -{ - git_repository *repo; - git_refname_t normalized; - bool should_head_be_updated = false; - int error = 0; - - assert(ref && new_name && signature); - - repo = git_reference_owner(ref); - - if ((error = reference_normalize_for_repo( - normalized, repo, new_name, true)) < 0) - return error; - - /* Check if we have to update HEAD. */ - if ((error = git_branch_is_head(ref)) < 0) - return error; - - should_head_be_updated = (error > 0); - - if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0) - return error; - - /* Update HEAD if it was pointing to the reference being renamed */ - if (should_head_be_updated) { - error = git_repository_set_head(ref->db->repo, normalized); - } else { - rename_cb_data payload; - payload.old_name = ref->name; - memcpy(&payload.new_name, &normalized, sizeof(normalized)); - - error = git_repository_foreach_head(repo, update_wt_heads, &payload); - } - - return error; -} - - int git_reference_rename( git_reference **out, git_reference *ref, @@ -711,17 +605,28 @@ int force, const char *log_message) { - git_signature *who; + refs_update_head_payload payload; + git_signature *signature = NULL; + git_repository *repo; int error; assert(out && ref); - if ((error = git_reference__log_signature(&who, ref->db->repo)) < 0) - return error; + repo = git_reference_owner(ref); - error = reference__rename(out, ref, new_name, force, who, log_message); - git_signature_free(who); + if ((error = git_reference__log_signature(&signature, repo)) < 0 || + (error = reference_normalize_for_repo(payload.new_name, repo, new_name, true)) < 0 || + (error = git_refdb_rename(out, ref->db, ref->name, payload.new_name, force, signature, log_message)) < 0) + goto out; + + payload.old_name = ref->name; + /* We may have to update any HEAD that was pointing to the renamed reference. */ + if ((error = git_repository_foreach_worktree(repo, refs_update_head, &payload)) < 0) + goto out; + +out: + git_signature_free(signature); return error; } @@ -902,14 +807,13 @@ case '\\': case '?': case '[': - case '*': return 0; default: return 1; } } -static int ensure_segment_validity(const char *name) +static int ensure_segment_validity(const char *name, char may_contain_glob) { const char *current = name; char prev = '\0'; @@ -932,6 +836,12 @@ if (prev == '@' && *current == '{') return -1; /* Refname contains "@{" */ + if (*current == '*') { + if (!may_contain_glob) + return -1; + may_contain_glob = 0; + } + prev = *current; } @@ -1010,19 +920,20 @@ } while (true) { - segment_len = ensure_segment_validity(current); - if (segment_len < 0) { - if ((process_flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN) && - current[0] == '*' && - (current[1] == '\0' || current[1] == '/')) { - /* Accept one wildcard as a full refname component. */ - process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN; - segment_len = 1; - } else - goto cleanup; - } + char may_contain_glob = process_flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN; + + segment_len = ensure_segment_validity(current, may_contain_glob); + if (segment_len < 0) + goto cleanup; if (segment_len > 0) { + /* + * There may only be one glob in a pattern, thus we reset + * the pattern-flag in case the current segment has one. + */ + if (memchr(current, '*', segment_len)) + process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN; + if (normalize) { size_t cur_len = git_buf_len(buf); @@ -1143,40 +1054,6 @@ return git_oid__cmp(&ref1->target.oid, &ref2->target.oid); } -/** - * Get the end of a chain of references. If the final one is not - * found, we return the reference just before that. - */ -static int get_terminal(git_reference **out, git_repository *repo, const char *ref_name, int nesting) -{ - git_reference *ref; - int error = 0; - - if (nesting > MAX_NESTING_LEVEL) { - git_error_set(GIT_ERROR_REFERENCE, "reference chain too deep (%d)", nesting); - return GIT_ENOTFOUND; - } - - /* set to NULL to let the caller know that they're at the end of the chain */ - if ((error = git_reference_lookup(&ref, repo, ref_name)) < 0) { - *out = NULL; - return error; - } - - if (git_reference_type(ref) == GIT_REFERENCE_DIRECT) { - *out = ref; - error = 0; - } else { - error = get_terminal(out, repo, git_reference_symbolic_target(ref), nesting + 1); - if (error == GIT_ENOTFOUND && !*out) - *out = ref; - else - git_reference_free(ref); - } - - return error; -} - /* * Starting with the reference given by `ref_name`, follows symbolic * references until a direct reference is found and updated the OID @@ -1191,31 +1068,37 @@ { git_reference *ref = NULL, *ref2 = NULL; git_signature *who = NULL; + git_refdb *refdb = NULL; const git_signature *to_use; int error = 0; if (!sig && (error = git_reference__log_signature(&who, repo)) < 0) - return error; + goto out; to_use = sig ? sig : who; - error = get_terminal(&ref, repo, ref_name, 0); - /* found a dangling symref */ - if (error == GIT_ENOTFOUND && ref) { - assert(git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC); - git_error_clear(); + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + goto out; + + if ((error = git_refdb_resolve(&ref, refdb, ref_name, -1)) < 0) { + if (error == GIT_ENOTFOUND) { + git_error_clear(); + error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use, + log_message, NULL, NULL); + } + goto out; + } + + /* In case the resolved reference is symbolic, then it's a dangling symref. */ + if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) { error = reference__create(&ref2, repo, ref->target.symbolic, oid, NULL, 0, to_use, log_message, NULL, NULL); - } else if (error == GIT_ENOTFOUND) { - git_error_clear(); - error = reference__create(&ref2, repo, ref_name, oid, NULL, 0, to_use, - log_message, NULL, NULL); - } else if (error == 0) { - assert(git_reference_type(ref) == GIT_REFERENCE_DIRECT); + } else { error = reference__create(&ref2, repo, ref->name, oid, NULL, 1, to_use, log_message, &ref->target.oid, NULL); } +out: git_reference_free(ref2); git_reference_free(ref); git_signature_free(who); @@ -1379,7 +1262,7 @@ * to a commit. So we only want to use the peeled value * if it is not zero and the target is not a tag. */ - if (target_type != GIT_OBJECT_TAG && !git_oid_iszero(&resolved->peel)) { + if (target_type != GIT_OBJECT_TAG && !git_oid_is_zero(&resolved->peel)) { error = git_object_lookup(&target, git_reference_owner(ref), &resolved->peel, GIT_OBJECT_ANY); } else { diff -Nru libgit2-0.28.5+dfsg.1/src/refs.h libgit2-1.1.0+dfsg.1/src/refs.h --- libgit2-0.28.5+dfsg.1/src/refs.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refs.h 2020-10-12 18:53:06.000000000 +0000 @@ -45,7 +45,6 @@ #define GIT_REBASE_APPLY_DIR "rebase-apply/" #define GIT_REBASE_APPLY_REBASING_FILE GIT_REBASE_APPLY_DIR "rebasing" #define GIT_REBASE_APPLY_APPLYING_FILE GIT_REBASE_APPLY_DIR "applying" -#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master" #define GIT_SEQUENCER_DIR "sequencer/" #define GIT_SEQUENCER_HEAD_FILE GIT_SEQUENCER_DIR "head" @@ -75,7 +74,14 @@ char name[GIT_FLEX_ARRAY]; }; -git_reference *git_reference__set_name(git_reference *ref, const char *name); +/** + * Reallocate the reference with a new name + * + * Note that this is a dangerous operation, as on success, all existing + * pointers to the old reference will now be dangling. Only call this on objects + * you control, possibly using `git_reference_dup`. + */ +git_reference *git_reference__realloc(git_reference **ptr_to_ref, const char *name); int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags); int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *sig, const char *log_message); @@ -83,6 +89,7 @@ int git_reference__is_branch(const char *ref_name); int git_reference__is_remote(const char *ref_name); int git_reference__is_tag(const char *ref_name); +int git_reference__is_note(const char *ref_name); const char *git_reference__shorthand(const char *name); /** @@ -108,24 +115,6 @@ const char *name, int max_deref); -/** - * Read reference from a file. - * - * This function will read in the file at `path`. If it is a - * symref, it will return a new unresolved symbolic reference - * with the given name pointing to the reference pointed to by - * the file. If it is not a symbolic reference, it will return - * the resolved reference. - * - * Note that because the refdb is not involved for symbolic references, they - * won't be owned, hence you should either not make the returned reference - * 'externally visible', or perform the lookup before returning it to the user. - */ -int git_reference__read_head( - git_reference **out, - git_repository *repo, - const char *path); - int git_reference__log_signature(git_signature **out, git_repository *repo); /** Update a reference after a commit. */ diff -Nru libgit2-0.28.5+dfsg.1/src/refspec.c libgit2-1.1.0+dfsg.1/src/refspec.c --- libgit2-0.28.5+dfsg.1/src/refspec.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/refspec.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,10 +9,10 @@ #include "git2/errors.h" -#include "util.h" -#include "posix.h" #include "refs.h" +#include "util.h" #include "vector.h" +#include "wildmatch.h" int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch) { @@ -213,7 +213,7 @@ if (refspec == NULL || refspec->src == NULL) return false; - return (p_fnmatch(refspec->src, refname, 0) == 0); + return (wildmatch(refspec->src, refname, 0) == 0); } int git_refspec_dst_matches(const git_refspec *refspec, const char *refname) @@ -221,14 +221,13 @@ if (refspec == NULL || refspec->dst == NULL) return false; - return (p_fnmatch(refspec->dst, refname, 0) == 0); + return (wildmatch(refspec->dst, refname, 0) == 0); } static int refspec_transform( git_buf *out, const char *from, const char *to, const char *name) { const char *from_star, *to_star; - const char *name_slash, *from_slash; size_t replacement_len, star_offset; git_buf_sanitize(out); @@ -251,17 +250,11 @@ /* the first half is copied over */ git_buf_put(out, to, to_star - to); - /* then we copy over the replacement, from the star's offset to the next slash in 'name' */ - name_slash = strchr(name + star_offset, '/'); - if (!name_slash) - name_slash = strrchr(name, '\0'); - - /* if there is no slash after the star in 'from', we want to copy everything over */ - from_slash = strchr(from + star_offset, '/'); - if (!from_slash) - name_slash = strrchr(name, '\0'); - - replacement_len = (name_slash - name) - star_offset; + /* + * Copy over the name, but exclude the trailing part in "from" starting + * after the glob + */ + replacement_len = strlen(name + star_offset) - strlen(from_star + 1); git_buf_put(out, name + star_offset, replacement_len); return git_buf_puts(out, to_star + 1); diff -Nru libgit2-0.28.5+dfsg.1/src/regexp.c libgit2-1.1.0+dfsg.1/src/regexp.c --- libgit2-0.28.5+dfsg.1/src/regexp.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/regexp.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,221 @@ +/* + * 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 "regexp.h" + +#if defined(GIT_REGEX_BUILTIN) || defined(GIT_REGEX_PCRE) + +int git_regexp_compile(git_regexp *r, const char *pattern, int flags) +{ + int erroffset, cflags = 0; + const char *error = NULL; + + if (flags & GIT_REGEXP_ICASE) + cflags |= PCRE_CASELESS; + + if ((*r = pcre_compile(pattern, cflags, &error, &erroffset, NULL)) == NULL) { + git_error_set_str(GIT_ERROR_REGEX, error); + return GIT_EINVALIDSPEC; + } + + return 0; +} + +void git_regexp_dispose(git_regexp *r) +{ + pcre_free(*r); + *r = NULL; +} + +int git_regexp_match(const git_regexp *r, const char *string) +{ + int error; + if ((error = pcre_exec(*r, NULL, string, (int) strlen(string), 0, 0, NULL, 0)) < 0) + return (error == PCRE_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + return 0; +} + +int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) +{ + int static_ovec[9] = {0}, *ovec; + int error; + size_t i; + + /* The ovec array always needs to be a mutiple of three */ + if (nmatches <= ARRAY_SIZE(static_ovec) / 3) + ovec = static_ovec; + else + ovec = git__calloc(nmatches * 3, sizeof(*ovec)); + GIT_ERROR_CHECK_ALLOC(ovec); + + if ((error = pcre_exec(*r, NULL, string, (int) strlen(string), 0, 0, ovec, (int) nmatches * 3)) < 0) + goto out; + + if (error == 0) + error = (int) nmatches; + + for (i = 0; i < (unsigned int) error; i++) { + matches[i].start = (ovec[i * 2] < 0) ? -1 : ovec[i * 2]; + matches[i].end = (ovec[i * 2 + 1] < 0) ? -1 : ovec[i * 2 + 1]; + } + for (i = (unsigned int) error; i < nmatches; i++) + matches[i].start = matches[i].end = -1; + +out: + if (nmatches > ARRAY_SIZE(static_ovec) / 3) + git__free(ovec); + if (error < 0) + return (error == PCRE_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + return 0; +} + +#elif defined(GIT_REGEX_PCRE2) + +int git_regexp_compile(git_regexp *r, const char *pattern, int flags) +{ + unsigned char errmsg[1024]; + PCRE2_SIZE erroff; + int error, cflags = 0; + + if (flags & GIT_REGEXP_ICASE) + cflags |= PCRE2_CASELESS; + + if ((*r = pcre2_compile((const unsigned char *) pattern, PCRE2_ZERO_TERMINATED, + cflags, &error, &erroff, NULL)) == NULL) { + pcre2_get_error_message(error, errmsg, sizeof(errmsg)); + git_error_set_str(GIT_ERROR_REGEX, (char *) errmsg); + return GIT_EINVALIDSPEC; + } + + return 0; +} + +void git_regexp_dispose(git_regexp *r) +{ + pcre2_code_free(*r); + *r = NULL; +} + +int git_regexp_match(const git_regexp *r, const char *string) +{ + pcre2_match_data *data; + int error; + + data = pcre2_match_data_create(1, NULL); + GIT_ERROR_CHECK_ALLOC(data); + + if ((error = pcre2_match(*r, (const unsigned char *) string, strlen(string), + 0, 0, data, NULL)) < 0) + return (error == PCRE2_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + + pcre2_match_data_free(data); + return 0; +} + +int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) +{ + pcre2_match_data *data = NULL; + PCRE2_SIZE *ovec; + int error; + size_t i; + + if ((data = pcre2_match_data_create(nmatches, NULL)) == NULL) { + git_error_set_oom(); + goto out; + } + + if ((error = pcre2_match(*r, (const unsigned char *) string, strlen(string), + 0, 0, data, NULL)) < 0) + goto out; + + if (error == 0 || (unsigned int) error > nmatches) + error = nmatches; + ovec = pcre2_get_ovector_pointer(data); + + for (i = 0; i < (unsigned int) error; i++) { + matches[i].start = (ovec[i * 2] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2]; + matches[i].end = (ovec[i * 2 + 1] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2 + 1]; + } + for (i = (unsigned int) error; i < nmatches; i++) + matches[i].start = matches[i].end = -1; + +out: + pcre2_match_data_free(data); + if (error < 0) + return (error == PCRE2_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + return 0; +} + +#elif defined(GIT_REGEX_REGCOMP) || defined(GIT_REGEX_REGCOMP_L) + +#if defined(GIT_REGEX_REGCOMP_L) +# include +#endif + +int git_regexp_compile(git_regexp *r, const char *pattern, int flags) +{ + int cflags = REG_EXTENDED, error; + char errmsg[1024]; + + if (flags & GIT_REGEXP_ICASE) + cflags |= REG_ICASE; + +# if defined(GIT_REGEX_REGCOMP) + if ((error = regcomp(r, pattern, cflags)) != 0) +# else + if ((error = regcomp_l(r, pattern, cflags, (locale_t) 0)) != 0) +# endif + { + regerror(error, r, errmsg, sizeof(errmsg)); + git_error_set_str(GIT_ERROR_REGEX, errmsg); + return GIT_EINVALIDSPEC; + } + + return 0; +} + +void git_regexp_dispose(git_regexp *r) +{ + regfree(r); +} + +int git_regexp_match(const git_regexp *r, const char *string) +{ + int error; + if ((error = regexec(r, string, 0, NULL, 0)) != 0) + return (error == REG_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + return 0; +} + +int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) +{ + regmatch_t static_m[3], *m; + int error; + size_t i; + + if (nmatches <= ARRAY_SIZE(static_m)) + m = static_m; + else + m = git__calloc(nmatches, sizeof(*m)); + + if ((error = regexec(r, string, nmatches, m, 0)) != 0) + goto out; + + for (i = 0; i < nmatches; i++) { + matches[i].start = (m[i].rm_so < 0) ? -1 : m[i].rm_so; + matches[i].end = (m[i].rm_eo < 0) ? -1 : m[i].rm_eo; + } + +out: + if (nmatches > ARRAY_SIZE(static_m)) + git__free(m); + if (error) + return (error == REG_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; + return 0; +} + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/regexp.h libgit2-1.1.0+dfsg.1/src/regexp.h --- libgit2-0.28.5+dfsg.1/src/regexp.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/regexp.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * 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_regexp_h__ +#define INCLUDE_regexp_h__ + +#include "common.h" + +#if defined(GIT_REGEX_BUILTIN) || defined(GIT_REGEX_PCRE) +# include "pcre.h" +typedef pcre *git_regexp; +# define GIT_REGEX_INIT NULL +#elif defined(GIT_REGEX_PCRE2) +# define PCRE2_CODE_UNIT_WIDTH 8 +# include +typedef pcre2_code *git_regexp; +# define GIT_REGEX_INIT NULL +#elif defined(GIT_REGEX_REGCOMP) || defined(GIT_REGEX_REGCOMP_L) +# include +typedef regex_t git_regexp; +# define GIT_REGEX_INIT { 0 } +#else +# error "No regex backend" +#endif + +/** Options supported by @git_regexp_compile. */ +typedef enum { + /** Enable case-insensitive matching */ + GIT_REGEXP_ICASE = (1 << 0) +} git_regexp_flags_t; + +/** Structure containing information about regular expression matching groups */ +typedef struct { + /** Start of the given match. -1 if the group didn't match anything */ + ssize_t start; + /** End of the given match. -1 if the group didn't match anything */ + ssize_t end; +} git_regmatch; + +/** + * Compile a regular expression. The compiled expression needs to + * be cleaned up afterwards with `git_regexp_dispose`. + * + * @param r Pointer to the storage where to initialize the regular expression. + * @param pattern The pattern that shall be compiled. + * @param flags Flags to alter how the pattern shall be handled. + * 0 for defaults, otherwise see @git_regexp_flags_t. + * @return 0 on success, otherwise a negative return value. + */ +int git_regexp_compile(git_regexp *r, const char *pattern, int flags); + +/** + * Free memory associated with the regular expression + * + * @param r The regular expression structure to dispose. + */ +void git_regexp_dispose(git_regexp *r); + +/** + * Test whether a given string matches a compiled regular + * expression. + * + * @param r Compiled regular expression. + * @param string String to match against the regular expression. + * @return 0 if the string matches, a negative error code + * otherwise. GIT_ENOTFOUND if no match was found, + * GIT_EINVALIDSPEC if the regular expression matching + * was invalid. + */ +int git_regexp_match(const git_regexp *r, const char *string); + +/** + * Search for matches inside of a given string. + * + * Given a regular expression with capturing groups, this + * function will populate provided @git_regmatch structures with + * offsets for each of the given matches. Non-matching groups + * will have start and end values of the respective @git_regmatch + * structure set to -1. + * + * @param r Compiled regular expression. + * @param string String to match against the regular expression. + * @param nmatches Number of @git_regmatch structures provided by + * the user. + * @param matches Pointer to an array of @git_regmatch structures. + * @return 0 if the string matches, a negative error code + * otherwise. GIT_ENOTFOUND if no match was found, + * GIT_EINVALIDSPEC if the regular expression matching + * was invalid. + */ +int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/remote.c libgit2-1.1.0+dfsg.1/src/remote.c --- libgit2-0.28.5+dfsg.1/src/remote.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/remote.c 2020-10-12 18:53:06.000000000 +0000 @@ -136,35 +136,6 @@ return 0; } -#if 0 -/* We could export this as a helper */ -static int get_check_cert(int *out, git_repository *repo) -{ - git_config *cfg; - const char *val; - int error = 0; - - assert(out && repo); - - /* By default, we *DO* want to verify the certificate. */ - *out = 1; - - /* Go through the possible sources for SSL verification settings, from - * most specific to least specific. */ - - /* GIT_SSL_NO_VERIFY environment variable */ - if ((val = p_getenv("GIT_SSL_NO_VERIFY")) != NULL) - return git_config_parse_bool(out, val); - - /* http.sslVerify config setting */ - if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) - return error; - - *out = git_config__get_bool_force(cfg, "http.sslverify", 1); - return 0; -} -#endif - static int canonicalize_url(git_buf *out, const char *in) { if (in == NULL || strlen(in) == 0) { @@ -217,13 +188,20 @@ return GIT_EEXISTS; } -int git_remote_create_init_options(git_remote_create_options *opts, unsigned int version) +int git_remote_create_options_init(git_remote_create_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_remote_create_options, GIT_REMOTE_CREATE_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_remote_create_init_options(git_remote_create_options *opts, unsigned int version) +{ + return git_remote_create_options_init(opts, version); +} +#endif + int git_remote_create_with_opts(git_remote **out, const char *url, const git_remote_create_options *opts) { git_remote *remote = NULL; @@ -670,24 +648,47 @@ return set_url(repo, remote, CONFIG_PUSHURL_FMT, url); } -const char* git_remote__urlfordirection(git_remote *remote, int direction) +static int resolve_url(git_buf *resolved_url, const char *url, int direction, const git_remote_callbacks *callbacks) { - assert(remote); + int status; + + if (callbacks && callbacks->resolve_url) { + git_buf_clear(resolved_url); + status = callbacks->resolve_url(resolved_url, url, direction, callbacks->payload); + if (status != GIT_PASSTHROUGH) { + git_error_set_after_callback_function(status, "git_resolve_url_cb"); + git_buf_sanitize(resolved_url); + return status; + } + } + + return git_buf_sets(resolved_url, url); +} +int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks) +{ + const char *url = NULL; + + assert(remote); assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH); if (direction == GIT_DIRECTION_FETCH) { - return remote->url; + url = remote->url; + } else if (direction == GIT_DIRECTION_PUSH) { + url = remote->pushurl ? remote->pushurl : remote->url; } - if (direction == GIT_DIRECTION_PUSH) { - return remote->pushurl ? remote->pushurl : remote->url; + if (!url) { + git_error_set(GIT_ERROR_INVALID, + "malformed remote '%s' - missing %s URL", + remote->name ? remote->name : "(anonymous)", + direction == GIT_DIRECTION_FETCH ? "fetch" : "push"); + return GIT_EINVALID; } - - return NULL; + return resolve_url(url_out, url, direction, callbacks); } -int set_transport_callbacks(git_transport *t, const git_remote_callbacks *cbs) +static int remote_transport_set_callbacks(git_transport *t, const git_remote_callbacks *cbs) { if (!t->set_callbacks || !cbs) return 0; @@ -707,11 +708,11 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn) { git_transport *t; - const char *url; + git_buf url = GIT_BUF_INIT; int flags = GIT_TRANSPORTFLAGS_NONE; int error; void *payload = NULL; - git_cred_acquire_cb credentials = NULL; + git_credential_acquire_cb credentials = NULL; git_transport_cb transport = NULL; assert(remote); @@ -728,39 +729,38 @@ t = remote->transport; - url = git_remote__urlfordirection(remote, direction); - if (url == NULL) { - git_error_set(GIT_ERROR_INVALID, - "Malformed remote '%s' - missing %s URL", - remote->name ? remote->name : "(anonymous)", - direction == GIT_DIRECTION_FETCH ? "fetch" : "push"); - return -1; - } + if ((error = git_remote__urlfordirection(&url, remote, direction, callbacks)) < 0) + goto on_error; /* If we don't have a transport object yet, and the caller specified a * custom transport factory, use that */ if (!t && transport && (error = transport(&t, remote, payload)) < 0) - return error; + goto on_error; /* If we still don't have a transport, then use the global * transport registrations which map URI schemes to transport factories */ - if (!t && (error = git_transport_new(&t, remote, url)) < 0) - return error; + if (!t && (error = git_transport_new(&t, remote, url.ptr)) < 0) + goto on_error; if ((error = set_transport_custom_headers(t, conn->custom_headers)) != 0) goto on_error; - if ((error = set_transport_callbacks(t, callbacks)) < 0 || - (error = t->connect(t, url, credentials, payload, conn->proxy, direction, flags)) != 0) + if ((error = remote_transport_set_callbacks(t, callbacks)) < 0 || + (error = t->connect(t, url.ptr, credentials, payload, conn->proxy, direction, flags)) != 0) goto on_error; remote->transport = t; + git_buf_dispose(&url); + return 0; on_error: - t->free(t); + if (t) + t->free(t); + + git_buf_dispose(&url); if (t == remote->transport) remote->transport = NULL; @@ -1239,7 +1239,7 @@ } out: - git_strarray_free(&arr); + git_strarray_dispose(&arr); return error; } @@ -1678,20 +1678,24 @@ return remote->transport->is_connected(remote->transport); } -void git_remote_stop(git_remote *remote) +int git_remote_stop(git_remote *remote) { assert(remote); if (remote->transport && remote->transport->cancel) remote->transport->cancel(remote->transport); + + return 0; } -void git_remote_disconnect(git_remote *remote) +int git_remote_disconnect(git_remote *remote) { assert(remote); if (git_remote_connected(remote)) remote->transport->close(remote->transport); + + return 0; } void git_remote_free(git_remote *remote) @@ -1770,7 +1774,7 @@ return 0; } -const git_transfer_progress* git_remote_stats(git_remote *remote) +const git_indexer_progress *git_remote_stats(git_remote *remote) { assert(remote); return &remote->stats; @@ -2371,29 +2375,36 @@ const git_remote_head *guess = NULL; const git_oid *head_id; size_t heads_len, i; + git_buf local_default = GIT_BUF_INIT; int error; assert(out); if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0) - return error; - - if (heads_len == 0) - return GIT_ENOTFOUND; + goto done; - if (strcmp(heads[0]->name, GIT_HEAD_FILE)) - return GIT_ENOTFOUND; + if (heads_len == 0 || strcmp(heads[0]->name, GIT_HEAD_FILE)) { + error = GIT_ENOTFOUND; + goto done; + } git_buf_sanitize(out); + /* the first one must be HEAD so if that has the symref info, we're done */ - if (heads[0]->symref_target) - return git_buf_puts(out, heads[0]->symref_target); + if (heads[0]->symref_target) { + error = git_buf_puts(out, heads[0]->symref_target); + goto done; + } /* * If there's no symref information, we have to look over them - * and guess. We return the first match unless the master - * branch is a candidate. Then we return the master branch. + * and guess. We return the first match unless the default + * branch is a candidate. Then we return the default branch. */ + + if ((error = git_repository_initialbranch(&local_default, remote->repo)) < 0) + goto done; + head_id = &heads[0]->oid; for (i = 1; i < heads_len; i++) { @@ -2408,16 +2419,22 @@ continue; } - if (!git__strcmp(GIT_REFS_HEADS_MASTER_FILE, heads[i]->name)) { + if (!git__strcmp(local_default.ptr, heads[i]->name)) { guess = heads[i]; break; } } - if (!guess) - return GIT_ENOTFOUND; + if (!guess) { + error = GIT_ENOTFOUND; + goto done; + } - return git_buf_puts(out, guess->name); + error = git_buf_puts(out, guess->name); + +done: + git_buf_dispose(&local_default); + return error; } int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts) diff -Nru libgit2-0.28.5+dfsg.1/src/remote.h libgit2-1.1.0+dfsg.1/src/remote.h --- libgit2-0.28.5+dfsg.1/src/remote.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/remote.h 2020-10-12 18:53:06.000000000 +0000 @@ -29,7 +29,7 @@ git_transport *transport; git_repository *repo; git_push *push; - git_transfer_progress stats; + git_indexer_progress stats; unsigned int need_pack; git_remote_autotag_option_t download_tags; int prune_refs; @@ -45,7 +45,7 @@ int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn); -const char* git_remote__urlfordirection(struct git_remote *remote, int direction); +int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks); int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url); git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname); diff -Nru libgit2-0.28.5+dfsg.1/src/repository.c libgit2-1.1.0+dfsg.1/src/repository.c --- libgit2-0.28.5+dfsg.1/src/repository.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/repository.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,7 +16,7 @@ #include "commit.h" #include "tag.h" #include "blob.h" -#include "fileops.h" +#include "futils.h" #include "sysdir.h" #include "filebuf.h" #include "index.h" @@ -42,35 +42,38 @@ static const struct { git_repository_item_t parent; + git_repository_item_t fallback; const char *name; bool directory; } items[] = { - { GIT_REPOSITORY_ITEM_GITDIR, NULL, true }, - { GIT_REPOSITORY_ITEM_WORKDIR, NULL, true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true }, - { GIT_REPOSITORY_ITEM_GITDIR, "index", false }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "config", false }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "info", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true }, - { GIT_REPOSITORY_ITEM_GITDIR, "modules", true }, - { GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true } + { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true }, + { GIT_REPOSITORY_ITEM_WORKDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true }, + { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "index", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "objects", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "refs", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "packed-refs", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "remotes", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "config", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "info", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "hooks", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "logs", true }, + { GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "modules", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "worktrees", true } }; -static int check_repositoryformatversion(git_config *config); +static int check_repositoryformatversion(int *version, git_config *config); +static int check_extensions(git_config *config, int version); #define GIT_COMMONDIR_FILE "commondir" #define GIT_GITDIR_FILE "gitdir" #define GIT_FILE_CONTENT_PREFIX "gitdir:" -#define GIT_BRANCH_MASTER "master" +#define GIT_BRANCH_DEFAULT "master" #define GIT_REPO_VERSION 0 +#define GIT_REPO_MAX_VERSION 1 git_buf git_repository__reserved_names_win32[] = { { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) }, @@ -121,7 +124,7 @@ git_config_free(config); } - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); } static void set_index(git_repository *repo, git_index *index) @@ -137,7 +140,7 @@ } } -void git_repository__cleanup(git_repository *repo) +int git_repository__cleanup(git_repository *repo) { assert(repo); @@ -149,6 +152,8 @@ set_index(repo, NULL); set_odb(repo, NULL); set_refdb(repo, NULL); + + return 0; } void git_repository_free(git_repository *repo) @@ -160,7 +165,7 @@ git_repository__cleanup(repo); - git_cache_free(&repo->objects); + git_cache_dispose(&repo->objects); git_diff_driver_registry_free(repo->diff_drivers); repo->diff_drivers = NULL; @@ -186,19 +191,25 @@ * * Open a repository object from its path */ -static bool valid_repository_path(git_buf *repository_path, git_buf *common_path) +static int is_valid_repository_path(bool *out, git_buf *repository_path, git_buf *common_path) { + int error; + + *out = false; + /* Check if we have a separate commondir (e.g. we have a * worktree) */ if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) { git_buf common_link = GIT_BUF_INIT; - git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE); - git_futils_readbuffer(&common_link, common_link.ptr); - git_buf_rtrim(&common_link); + if ((error = git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE)) < 0 || + (error = git_futils_readbuffer(&common_link, common_link.ptr)) < 0) + return error; + git_buf_rtrim(&common_link); if (git_path_is_relative(common_link.ptr)) { - git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr); + if ((error = git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr)) < 0) + return error; } else { git_buf_swap(common_path, &common_link); } @@ -206,24 +217,26 @@ git_buf_dispose(&common_link); } else { - git_buf_set(common_path, repository_path->ptr, repository_path->size); + if ((error = git_buf_set(common_path, repository_path->ptr, repository_path->size)) < 0) + return error; } /* Make sure the commondir path always has a trailing * slash */ if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1) - git_buf_putc(common_path, '/'); + if ((error = git_buf_putc(common_path, '/')) < 0) + return error; /* Ensure HEAD file exists */ if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false) - return false; - + return 0; /* Check files in common dir */ if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false) - return false; + return 0; if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false) - return false; + return 0; - return true; + *out = true; + return 0; } static git_repository *repository_alloc(void) @@ -238,14 +251,14 @@ if (!repo->reserved_names.ptr) goto on_error; - /* set all the entries in the cvar cache to `unset` */ - git_repository__cvar_cache_clear(repo); + /* set all the entries in the configmap cache to `unset` */ + git_repository__configmap_lookup_cache_clear(repo); return repo; on_error: if (repo) - git_cache_free(&repo->objects); + git_cache_dispose(&repo->objects); git__free(repo); return NULL; @@ -438,15 +451,15 @@ uint32_t flags, const char *ceiling_dirs) { - int error; git_buf path = GIT_BUF_INIT; git_buf repo_link = GIT_BUF_INIT; git_buf common_link = GIT_BUF_INIT; struct stat st; dev_t initial_device = 0; int min_iterations; - bool in_dot_git; + bool in_dot_git, is_valid; size_t ceiling_offset = 0; + int error; git_buf_clear(gitdir_path); @@ -472,9 +485,8 @@ for (;;) { if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) { if (!in_dot_git) { - error = git_buf_joinpath(&path, path.ptr, DOT_GIT); - if (error < 0) - break; + if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0) + goto out; } in_dot_git = !in_dot_git; } @@ -488,28 +500,33 @@ break; if (S_ISDIR(st.st_mode)) { - if (valid_repository_path(&path, &common_link)) { - git_path_to_dir(&path); - git_buf_set(gitdir_path, path.ptr, path.size); + if ((error = is_valid_repository_path(&is_valid, &path, &common_link)) < 0) + goto out; + + if (is_valid) { + if ((error = git_path_to_dir(&path)) < 0 || + (error = git_buf_set(gitdir_path, path.ptr, path.size)) < 0) + goto out; if (gitlink_path) - git_buf_attach(gitlink_path, - git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0); + if ((error = git_buf_attach(gitlink_path, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0) + goto out; if (commondir_path) git_buf_swap(&common_link, commondir_path); break; } - } - else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) { - error = read_gitfile(&repo_link, path.ptr); - if (error < 0) - break; - if (valid_repository_path(&repo_link, &common_link)) { + } else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) { + if ((error = read_gitfile(&repo_link, path.ptr)) < 0 || + (error = is_valid_repository_path(&is_valid, &repo_link, &common_link)) < 0) + goto out; + + if (is_valid) { git_buf_swap(gitdir_path, &repo_link); if (gitlink_path) - error = git_buf_put(gitlink_path, path.ptr, path.size); + if ((error = git_buf_put(gitlink_path, path.ptr, path.size)) < 0) + goto out; if (commondir_path) git_buf_swap(&common_link, commondir_path); } @@ -520,10 +537,8 @@ /* Move up one directory. If we're in_dot_git, we'll search the * parent itself next. If we're !in_dot_git, we'll search .git * in the parent directory next (added at the top of the loop). */ - if (git_path_dirname_r(&path, path.ptr) < 0) { - error = -1; - break; - } + if ((error = git_path_dirname_r(&path, path.ptr)) < 0) + goto out; /* Once we've checked the directory (and .git if applicable), * find the ceiling for a search. */ @@ -531,31 +546,28 @@ ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs); /* Check if we should stop searching here. */ - if (min_iterations == 0 - && (path.ptr[ceiling_offset] == 0 - || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH))) + if (min_iterations == 0 && + (path.ptr[ceiling_offset] == 0 || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH))) break; } - if (!error && workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) { + if (workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) { if (!git_buf_len(gitdir_path)) git_buf_clear(workdir_path); - else { - git_path_dirname_r(workdir_path, path.ptr); - git_path_to_dir(workdir_path); - } - if (git_buf_oom(workdir_path)) - return -1; + else if ((error = git_path_dirname_r(workdir_path, path.ptr)) < 0 || + (error = git_path_to_dir(workdir_path)) < 0) + goto out; } /* If we didn't find the repository, and we don't have any other error * to report, report that. */ - if (!git_buf_len(gitdir_path) && !error) { - git_error_set(GIT_ERROR_REPOSITORY, - "could not find repository from '%s'", start_path); + if (!git_buf_len(gitdir_path)) { + git_error_set(GIT_ERROR_REPOSITORY, "could not find repository from '%s'", start_path); error = GIT_ENOTFOUND; + goto out; } +out: git_buf_dispose(&path); git_buf_dispose(&repo_link); git_buf_dispose(&common_link); @@ -566,14 +578,16 @@ git_repository **repo_ptr, const char *bare_path) { - int error; git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT; git_repository *repo = NULL; + bool is_valid; + int error; - if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0) + if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0 || + (error = is_valid_repository_path(&is_valid, &path, &common_path)) < 0) return error; - if (!valid_repository_path(&path, &common_path)) { + if (!is_valid) { git_buf_dispose(&path); git_buf_dispose(&common_path); git_error_set(GIT_ERROR_REPOSITORY, "path is not a repository: %s", bare_path); @@ -801,6 +815,7 @@ gitlink = GIT_BUF_INIT, commondir = GIT_BUF_INIT; git_repository *repo = NULL; git_config *config = NULL; + int version = 0; if (flags & GIT_REPOSITORY_OPEN_FROM_ENV) return _git_repository_open_ext_from_env(repo_ptr, start_path); @@ -842,7 +857,10 @@ if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; - if (config && (error = check_repositoryformatversion(config)) < 0) + if (config && (error = check_repositoryformatversion(&version, config)) < 0) + goto cleanup; + + if ((error = check_extensions(config, version)) < 0) goto cleanup; if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) @@ -864,8 +882,7 @@ if (error < 0) git_repository_free(repo); - - if (repo_ptr) + else if (repo_ptr) *repo_ptr = repo; return error; @@ -881,7 +898,8 @@ { git_buf path = GIT_BUF_INIT; git_repository *repo = NULL; - int len, err; + size_t len; + int err; assert(repo_out && wt); @@ -1069,10 +1087,11 @@ return git_config_snapshot(out, weak); } -void git_repository_set_config(git_repository *repo, git_config *config) +int git_repository_set_config(git_repository *repo, git_config *config) { assert(repo && config); set_config(repo, config); + return 0; } int git_repository_odb__weakptr(git_odb **out, git_repository *repo) @@ -1120,10 +1139,11 @@ return 0; } -void git_repository_set_odb(git_repository *repo, git_odb *odb) +int git_repository_set_odb(git_repository *repo, git_odb *odb) { assert(repo && odb); set_odb(repo, odb); + return 0; } int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo) @@ -1160,10 +1180,11 @@ return 0; } -void git_repository_set_refdb(git_repository *repo, git_refdb *refdb) +int git_repository_set_refdb(git_repository *repo, git_refdb *refdb) { assert(repo && refdb); set_refdb(repo, refdb); + return 0; } int git_repository_index__weakptr(git_index **out, git_repository *repo) @@ -1209,10 +1230,11 @@ return 0; } -void git_repository_set_index(git_repository *repo, git_index *index) +int git_repository_set_index(git_repository *repo, git_index *index) { assert(repo); set_index(repo, index); + return 0; } int git_repository_set_namespace(git_repository *repo, const char *namespace) @@ -1288,8 +1310,8 @@ int (*prefixcmp)(const char *, const char *); int error, ignorecase; - error = git_repository__cvar( - &ignorecase, repo, GIT_CVAR_IGNORECASE); + error = git_repository__configmap_lookup( + &ignorecase, repo, GIT_CONFIGMAP_IGNORECASE); prefixcmp = (error || ignorecase) ? git__prefixcmp_icase : git__prefixcmp; @@ -1334,11 +1356,11 @@ } #endif -static int check_repositoryformatversion(git_config *config) +static int check_repositoryformatversion(int *version, git_config *config) { - int version, error; + int error; - error = git_config_get_int32(&version, config, "core.repositoryformatversion"); + error = git_config_get_int32(version, config, "core.repositoryformatversion"); /* git ignores this if the config variable isn't there */ if (error == GIT_ENOTFOUND) return 0; @@ -1346,45 +1368,59 @@ if (error < 0) return -1; - if (GIT_REPO_VERSION < version) { + if (GIT_REPO_MAX_VERSION < *version) { git_error_set(GIT_ERROR_REPOSITORY, - "unsupported repository version %d. Only versions up to %d are supported.", - version, GIT_REPO_VERSION); + "unsupported repository version %d; only versions up to %d are supported", + *version, GIT_REPO_MAX_VERSION); return -1; } return 0; } +static int check_valid_extension(const git_config_entry *entry, void *payload) +{ + GIT_UNUSED(payload); + + if (!strcmp(entry->name, "extensions.noop")) + return 0; + + git_error_set(GIT_ERROR_REPOSITORY, "unsupported extension name %s", entry->name); + return -1; +} + +static int check_extensions(git_config *config, int version) +{ + if (version < 1) + return 0; + + return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL); +} + int git_repository_create_head(const char *git_dir, const char *ref_name) { git_buf ref_path = GIT_BUF_INIT; git_filebuf ref = GIT_FILEBUF_INIT; const char *fmt; + int error; - if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 || - git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0) - goto fail; - - if (!ref_name) - ref_name = GIT_BRANCH_MASTER; + if ((error = git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) < 0 || + (error = git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE)) < 0) + goto out; if (git__prefixcmp(ref_name, GIT_REFS_DIR) == 0) fmt = "ref: %s\n"; else fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n"; - if (git_filebuf_printf(&ref, fmt, ref_name) < 0 || - git_filebuf_commit(&ref) < 0) - goto fail; - - git_buf_dispose(&ref_path); - return 0; + if ((error = git_filebuf_printf(&ref, fmt, ref_name)) < 0 || + (error = git_filebuf_commit(&ref)) < 0) + goto out; -fail: +out: git_buf_dispose(&ref_path); git_filebuf_cleanup(&ref); - return -1; + return error; } static bool is_chmod_supported(const char *file_path) @@ -1422,9 +1458,6 @@ git_buf xdg_buf = GIT_BUF_INIT; git_buf system_buf = GIT_BUF_INIT; git_buf programdata_buf = GIT_BUF_INIT; - git_buf path = GIT_BUF_INIT; - int fd; - struct stat st; int symlinks = 0; /* @@ -1451,23 +1484,14 @@ goto done; #endif - if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 || - p_close(fd) < 0 || - p_unlink(path.ptr) < 0 || - p_symlink("testing", path.ptr) < 0 || - p_lstat(path.ptr, &st) < 0) + if (!(symlinks = git_path_supports_symlinks(wd_path))) goto done; - symlinks = (S_ISLNK(st.st_mode) != 0); - - (void)p_unlink(path.ptr); - done: git_buf_dispose(&global_buf); git_buf_dispose(&xdg_buf); git_buf_dispose(&system_buf); git_buf_dispose(&programdata_buf); - git_buf_dispose(&path); git_config_free(config); return symlinks != 0; } @@ -1581,11 +1605,15 @@ git_config *config = NULL; bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0); + int version = 0; if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0) goto cleanup; - if (is_reinit && (error = check_repositoryformatversion(config)) < 0) + if (is_reinit && (error = check_repositoryformatversion(&version, config)) < 0) + goto cleanup; + + if ((error = check_extensions(config, version)) < 0) goto cleanup; #define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \ @@ -1661,7 +1689,7 @@ git_config_free(config); git_buf_dispose(&path); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); if (!repo->is_bare && recurse) (void)git_submodule_foreach(repo, repo_reinit_submodule_fs, NULL); @@ -2030,6 +2058,43 @@ return error; } +static int repo_init_head(const char *repo_dir, const char *given) +{ + git_config *cfg = NULL; + git_buf head_path = GIT_BUF_INIT, cfg_branch = GIT_BUF_INIT; + const char *initial_head = NULL; + int error; + + if ((error = git_buf_joinpath(&head_path, repo_dir, GIT_HEAD_FILE)) < 0) + goto out; + + /* + * A template may have set a HEAD; use that unless it's been + * overridden by the caller's given initial head setting. + */ + if (git_path_exists(head_path.ptr) && !given) + goto out; + + if (given) { + initial_head = given; + } else if ((error = git_config_open_default(&cfg)) >= 0 && + (error = git_config_get_string_buf(&cfg_branch, cfg, "init.defaultbranch")) >= 0) { + initial_head = cfg_branch.ptr; + } + + if (!initial_head) + initial_head = GIT_BRANCH_DEFAULT; + + error = git_repository_create_head(repo_dir, initial_head); + +out: + git_config_free(cfg); + git_buf_dispose(&head_path); + git_buf_dispose(&cfg_branch); + + return error; +} + static int repo_init_create_origin(git_repository *repo, const char *url) { int error; @@ -2059,53 +2124,53 @@ const char *given_repo, git_repository_init_options *opts) { - int error; git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT, common_path = GIT_BUF_INIT; const char *wd; + bool is_valid; + int error; assert(out && given_repo && opts); GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options"); - error = repo_init_directories(&repo_path, &wd_path, given_repo, opts); - if (error < 0) - goto cleanup; + if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0) + goto out; wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path); - if (valid_repository_path(&repo_path, &common_path)) { + if ((error = is_valid_repository_path(&is_valid, &repo_path, &common_path)) < 0) + goto out; + + if (is_valid) { if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) { git_error_set(GIT_ERROR_REPOSITORY, "attempt to reinitialize '%s'", given_repo); error = GIT_EEXISTS; - goto cleanup; + goto out; } opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; - error = repo_init_config( - repo_path.ptr, wd, opts->flags, opts->mode); + if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0) + goto out; /* TODO: reinitialize the templates */ + } else { + if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 || + (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0 || + (error = repo_init_head(repo_path.ptr, opts->initial_head)) < 0) + goto out; } - else { - if (!(error = repo_init_structure( - repo_path.ptr, wd, opts)) && - !(error = repo_init_config( - repo_path.ptr, wd, opts->flags, opts->mode))) - error = git_repository_create_head( - repo_path.ptr, opts->initial_head); - } - if (error < 0) - goto cleanup; - error = git_repository_open(out, repo_path.ptr); + if ((error = git_repository_open(out, repo_path.ptr)) < 0) + goto out; - if (!error && opts->origin_url) - error = repo_init_create_origin(*out, opts->origin_url); + if (opts->origin_url && + (error = repo_init_create_origin(*out, opts->origin_url)) < 0) + goto out; -cleanup: +out: git_buf_dispose(&common_path); git_buf_dispose(&repo_path); git_buf_dispose(&wd_path); @@ -2136,12 +2201,6 @@ return exists; } -static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file) -{ - git_buf_clear(out); - return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file); -} - int git_repository_head_detached_for_worktree(git_repository *repo, const char *name) { git_reference *ref = NULL; @@ -2182,7 +2241,8 @@ int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name) { - git_buf path = GIT_BUF_INIT; + git_repository *worktree_repo = NULL; + git_worktree *worktree = NULL; git_reference *head = NULL; int error; @@ -2190,58 +2250,68 @@ *out = NULL; - if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 || - (error = git_reference__read_head(&head, repo, path.ptr)) < 0) + if ((error = git_worktree_lookup(&worktree, repo, name)) < 0 || + (error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0 || + (error = git_reference_lookup(&head, worktree_repo, GIT_HEAD_FILE)) < 0) goto out; if (git_reference_type(head) != GIT_REFERENCE_DIRECT) { - git_reference *resolved; - - error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1); - git_reference_free(head); - head = resolved; + if ((error = git_reference_lookup_resolved(out, worktree_repo, git_reference_symbolic_target(head), -1)) < 0) + goto out; + } else { + *out = head; + head = NULL; } - *out = head; - out: - if (error) - git_reference_free(head); - - git_buf_dispose(&path); - + git_reference_free(head); + git_worktree_free(worktree); + git_repository_free(worktree_repo); return error; } -int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload) +int git_repository_foreach_worktree(git_repository *repo, + git_repository_foreach_worktree_cb cb, + void *payload) { - git_strarray worktrees = GIT_VECTOR_INIT; - git_buf path = GIT_BUF_INIT; + git_strarray worktrees = {0}; + git_repository *worktree_repo = NULL; + git_worktree *worktree = NULL; int error; size_t i; - /* Execute callback for HEAD of commondir */ - if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 || - (error = cb(repo, path.ptr, payload) != 0)) + if ((error = git_repository_open(&worktree_repo, repo->commondir)) < 0 || + (error = cb(worktree_repo, payload) != 0)) goto out; - if ((error = git_worktree_list(&worktrees, repo)) < 0) { - error = 0; + git_repository_free(worktree_repo); + worktree_repo = NULL; + + if ((error = git_worktree_list(&worktrees, repo)) < 0) goto out; - } - /* Execute callback for all worktree HEADs */ for (i = 0; i < worktrees.count; i++) { - if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0) + git_repository_free(worktree_repo); + worktree_repo = NULL; + git_worktree_free(worktree); + worktree = NULL; + + if ((error = git_worktree_lookup(&worktree, repo, worktrees.strings[i]) < 0) || + (error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0) { + if (error != GIT_ENOTFOUND) + goto out; + error = 0; continue; + } - if ((error = cb(repo, path.ptr, payload)) != 0) + if ((error = cb(worktree_repo, payload)) != 0) goto out; } out: - git_buf_dispose(&path); - git_strarray_free(&worktrees); + git_strarray_dispose(&worktrees); + git_repository_free(worktree_repo); + git_worktree_free(worktree); return error; } @@ -2284,30 +2354,66 @@ return error; } +int git_repository_initialbranch(git_buf *out, git_repository *repo) +{ + git_config *config; + git_config_entry *entry = NULL; + const char *branch; + int error; + + if ((error = git_repository_config__weakptr(&config, repo)) < 0) + return error; + + if ((error = git_config_get_entry(&entry, config, "init.defaultbranch")) == 0) { + branch = entry->value; + } + else if (error == GIT_ENOTFOUND) { + branch = GIT_BRANCH_DEFAULT; + } + else { + goto done; + } + + if ((error = git_buf_puts(out, GIT_REFS_HEADS_DIR)) < 0 || + (error = git_buf_puts(out, branch)) < 0) + goto done; + + if (!git_reference_is_valid_name(out->ptr)) { + git_error_set(GIT_ERROR_INVALID, "the value of init.defaultBranch is not a valid reference name"); + error = -1; + } + +done: + git_config_entry_free(entry); + return error; +} + int git_repository_is_empty(git_repository *repo) { git_reference *head = NULL; - int is_empty = 0; + git_buf initialbranch = GIT_BUF_INIT; + int result = 0; - if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) - return -1; + if ((result = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0 || + (result = git_repository_initialbranch(&initialbranch, repo)) < 0) + goto done; - if (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC) - is_empty = - (strcmp(git_reference_symbolic_target(head), - GIT_REFS_HEADS_DIR "master") == 0) && - repo_contains_no_reference(repo); + result = (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC && + strcmp(git_reference_symbolic_target(head), initialbranch.ptr) == 0 && + repo_contains_no_reference(repo)); +done: git_reference_free(head); + git_buf_dispose(&initialbranch); - return is_empty; + return result; } -int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item) +static const char *resolved_parent_path(const git_repository *repo, git_repository_item_t item, git_repository_item_t fallback) { const char *parent; - switch (items[item].parent) { + switch (item) { case GIT_REPOSITORY_ITEM_GITDIR: parent = git_repository_path(repo); break; @@ -2319,9 +2425,17 @@ break; default: git_error_set(GIT_ERROR_INVALID, "invalid item directory"); - return -1; + return NULL; } + if (!parent && fallback != GIT_REPOSITORY_ITEM__LAST) + return resolved_parent_path(repo, fallback, GIT_REPOSITORY_ITEM__LAST); + + return parent; +} +int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item) +{ + const char *parent = resolved_parent_path(repo, items[item].parent, items[item].fallback); if (parent == NULL) { git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository"); return GIT_ENOTFOUND; @@ -2536,7 +2650,7 @@ int error; git_filter_list *fl = NULL; git_file fd = -1; - git_off_t len; + uint64_t len; git_buf full_path = GIT_BUF_INIT; assert(out && path && repo); /* as_path can be NULL */ @@ -2573,11 +2687,8 @@ goto cleanup; } - len = git_futils_filesize(fd); - if (len < 0) { - error = (int)len; + if ((error = git_futils_filesize(&len, fd)) < 0) goto cleanup; - } if (!git__is_sizet(len)) { git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems"); @@ -2866,7 +2977,7 @@ return st.st_size == 0 ? 0 : 1; } -int git_repository_init_init_options( +int git_repository_init_options_init( git_repository_init_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( @@ -2875,6 +2986,14 @@ return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_repository_init_init_options( + git_repository_init_options *opts, unsigned int version) +{ + return git_repository_init_options_init(opts, version); +} +#endif + int git_repository_ident(const char **name, const char **email, const git_repository *repo) { *name = repo->ident_name; @@ -2912,7 +3031,7 @@ assert(repo); - if ((error = git_strmap_alloc(&repo->submodule_cache))) + if ((error = git_strmap_new(&repo->submodule_cache))) return error; error = git_submodule__map(repo, repo->submodule_cache); diff -Nru libgit2-0.28.5+dfsg.1/src/repository.h libgit2-1.1.0+dfsg.1/src/repository.h --- libgit2-0.28.5+dfsg.1/src/repository.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/repository.h 2020-10-12 18:53:06.000000000 +0000 @@ -37,34 +37,34 @@ /** Cvar cache identifiers */ typedef enum { - GIT_CVAR_AUTO_CRLF = 0, /* core.autocrlf */ - GIT_CVAR_EOL, /* core.eol */ - GIT_CVAR_SYMLINKS, /* core.symlinks */ - GIT_CVAR_IGNORECASE, /* core.ignorecase */ - GIT_CVAR_FILEMODE, /* core.filemode */ - GIT_CVAR_IGNORESTAT, /* core.ignorestat */ - GIT_CVAR_TRUSTCTIME, /* core.trustctime */ - GIT_CVAR_ABBREV, /* core.abbrev */ - GIT_CVAR_PRECOMPOSE, /* core.precomposeunicode */ - GIT_CVAR_SAFE_CRLF, /* core.safecrlf */ - GIT_CVAR_LOGALLREFUPDATES, /* core.logallrefupdates */ - GIT_CVAR_PROTECTHFS, /* core.protectHFS */ - GIT_CVAR_PROTECTNTFS, /* core.protectNTFS */ - GIT_CVAR_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */ - GIT_CVAR_CACHE_MAX -} git_cvar_cached; + GIT_CONFIGMAP_AUTO_CRLF = 0, /* core.autocrlf */ + GIT_CONFIGMAP_EOL, /* core.eol */ + GIT_CONFIGMAP_SYMLINKS, /* core.symlinks */ + GIT_CONFIGMAP_IGNORECASE, /* core.ignorecase */ + GIT_CONFIGMAP_FILEMODE, /* core.filemode */ + GIT_CONFIGMAP_IGNORESTAT, /* core.ignorestat */ + GIT_CONFIGMAP_TRUSTCTIME, /* core.trustctime */ + GIT_CONFIGMAP_ABBREV, /* core.abbrev */ + GIT_CONFIGMAP_PRECOMPOSE, /* core.precomposeunicode */ + GIT_CONFIGMAP_SAFE_CRLF, /* core.safecrlf */ + GIT_CONFIGMAP_LOGALLREFUPDATES, /* core.logallrefupdates */ + GIT_CONFIGMAP_PROTECTHFS, /* core.protectHFS */ + GIT_CONFIGMAP_PROTECTNTFS, /* core.protectNTFS */ + GIT_CONFIGMAP_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */ + GIT_CONFIGMAP_CACHE_MAX +} git_configmap_item; /** - * CVAR value enumerations + * Configuration map value enumerations * - * These are the values that are actually stored in the cvar cache, instead - * of their string equivalents. These values are internal and symbolic; - * make sure that none of them is set to `-1`, since that is the unique - * identifier for "not cached" + * These are the values that are actually stored in the configmap cache, + * instead of their string equivalents. These values are internal and + * symbolic; make sure that none of them is set to `-1`, since that is + * the unique identifier for "not cached" */ typedef enum { /* The value hasn't been loaded from the cache yet */ - GIT_CVAR_NOT_CACHED = -1, + GIT_CONFIGMAP_NOT_CACHED = -1, /* core.safecrlf: false, 'fail', 'warn' */ GIT_SAFE_CRLF_FALSE = 0, @@ -89,34 +89,34 @@ GIT_EOL_DEFAULT = GIT_EOL_NATIVE, /* core.symlinks: bool */ - GIT_SYMLINKS_DEFAULT = GIT_CVAR_TRUE, + GIT_SYMLINKS_DEFAULT = GIT_CONFIGMAP_TRUE, /* core.ignorecase */ - GIT_IGNORECASE_DEFAULT = GIT_CVAR_FALSE, + GIT_IGNORECASE_DEFAULT = GIT_CONFIGMAP_FALSE, /* core.filemode */ - GIT_FILEMODE_DEFAULT = GIT_CVAR_TRUE, + GIT_FILEMODE_DEFAULT = GIT_CONFIGMAP_TRUE, /* core.ignorestat */ - GIT_IGNORESTAT_DEFAULT = GIT_CVAR_FALSE, + GIT_IGNORESTAT_DEFAULT = GIT_CONFIGMAP_FALSE, /* core.trustctime */ - GIT_TRUSTCTIME_DEFAULT = GIT_CVAR_TRUE, + GIT_TRUSTCTIME_DEFAULT = GIT_CONFIGMAP_TRUE, /* core.abbrev */ GIT_ABBREV_DEFAULT = 7, /* core.precomposeunicode */ - GIT_PRECOMPOSE_DEFAULT = GIT_CVAR_FALSE, + GIT_PRECOMPOSE_DEFAULT = GIT_CONFIGMAP_FALSE, /* core.safecrlf */ - GIT_SAFE_CRLF_DEFAULT = GIT_CVAR_FALSE, + GIT_SAFE_CRLF_DEFAULT = GIT_CONFIGMAP_FALSE, /* core.logallrefupdates */ - GIT_LOGALLREFUPDATES_FALSE = GIT_CVAR_FALSE, - GIT_LOGALLREFUPDATES_TRUE = GIT_CVAR_TRUE, + GIT_LOGALLREFUPDATES_FALSE = GIT_CONFIGMAP_FALSE, + GIT_LOGALLREFUPDATES_TRUE = GIT_CONFIGMAP_TRUE, GIT_LOGALLREFUPDATES_UNSET = 2, GIT_LOGALLREFUPDATES_ALWAYS = 3, GIT_LOGALLREFUPDATES_DEFAULT = GIT_LOGALLREFUPDATES_UNSET, /* core.protectHFS */ - GIT_PROTECTHFS_DEFAULT = GIT_CVAR_FALSE, + GIT_PROTECTHFS_DEFAULT = GIT_CONFIGMAP_FALSE, /* core.protectNTFS */ - GIT_PROTECTNTFS_DEFAULT = GIT_CVAR_TRUE, + GIT_PROTECTNTFS_DEFAULT = GIT_CONFIGMAP_TRUE, /* core.fsyncObjectFiles */ - GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CVAR_FALSE, -} git_cvar_value; + GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CONFIGMAP_FALSE, +} git_configmap_value; /* internal repository init flags */ enum { @@ -154,7 +154,7 @@ git_atomic attr_session_key; - git_cvar_value cvar_cache[GIT_CVAR_CACHE_MAX]; + git_configmap_value configmap_cache[GIT_CONFIGMAP_CACHE_MAX]; git_strmap *submodule_cache; }; @@ -166,25 +166,11 @@ int git_repository_head_tree(git_tree **tree, git_repository *repo); int git_repository_create_head(const char *git_dir, const char *ref_name); -/* - * Called for each HEAD. - * - * Can return either 0, causing the iteration over HEADs to - * continue, or a non-0 value causing the iteration to abort. The - * return value is passed back to the caller of - * `git_repository_foreach_head` - */ -typedef int (*git_repository_foreach_head_cb)(git_repository *repo, const char *path, void *payload); +typedef int (*git_repository_foreach_worktree_cb)(git_repository *, void *); -/* - * Iterate over repository and all worktree HEADs. - * - * This function will be called for the repository HEAD and for - * all HEADS of linked worktrees. For each HEAD, the callback is - * executed with the given payload. The return value equals the - * return value of the last executed callback function. - */ -int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload); +int git_repository_foreach_worktree(git_repository *repo, + git_repository_foreach_worktree_cb cb, + void *payload); /* * Weak pointers to repository internals. @@ -199,13 +185,13 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo); /* - * CVAR cache + * Configuration map cache * * Efficient access to the most used config variables of a repository. * The cache is cleared every time the config backend is replaced. */ -int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar); -void git_repository__cvar_cache_clear(git_repository *repo); +int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item); +void git_repository__configmap_lookup_cache_clear(git_repository *repo); GIT_INLINE(int) git_repository__ensure_not_bare( git_repository *repo, @@ -246,4 +232,10 @@ bool git_repository__reserved_names( git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs); +/* + * The default branch for the repository; the `init.defaultBranch` + * configuration option, if set, or `master` if it is not. + */ +int git_repository_initialbranch(git_buf *out, git_repository *repo); + #endif diff -Nru libgit2-0.28.5+dfsg.1/src/revert.c libgit2-1.1.0+dfsg.1/src/revert.c --- libgit2-0.28.5+dfsg.1/src/revert.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/revert.c 2020-10-12 18:53:06.000000000 +0000 @@ -224,9 +224,16 @@ return error; } -int git_revert_init_options(git_revert_options *opts, unsigned int version) +int git_revert_options_init(git_revert_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_revert_options, GIT_REVERT_OPTIONS_INIT); return 0; } + +#ifndef GIT_DEPRECATE_HARD +int git_revert_init_options(git_revert_options *opts, unsigned int version) +{ + return git_revert_options_init(opts, version); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/revparse.c libgit2-1.1.0+dfsg.1/src/revparse.c --- libgit2-0.28.5+dfsg.1/src/revparse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/revparse.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,11 +7,10 @@ #include "common.h" -#include - #include "buffer.h" #include "tree.h" #include "refdb.h" +#include "regexp.h" #include "git2.h" @@ -42,7 +41,7 @@ return maybe_sha_or_abbrev(out, repo, spec, speclen); } -static int build_regex(regex_t *regex, const char *pattern) +static int build_regex(git_regexp *regex, const char *pattern) { int error; @@ -51,13 +50,11 @@ return GIT_EINVALIDSPEC; } - error = p_regcomp(regex, pattern, REG_EXTENDED); + error = git_regexp_compile(regex, pattern, 0); if (!error) return 0; - error = git_error_set_regex(regex, error); - - regfree(regex); + git_regexp_dispose(regex); return error; } @@ -66,7 +63,7 @@ { const char *substr; int error; - regex_t regex; + git_regexp regex; substr = strstr(spec, "-g"); @@ -76,8 +73,8 @@ if (build_regex(®ex, ".+-[0-9]+-g[0-9a-fA-F]+") < 0) return -1; - error = regexec(®ex, spec, 0, NULL, 0); - regfree(®ex); + error = git_regexp_match(®ex, spec); + git_regexp_dispose(®ex); if (error) return GIT_ENOTFOUND; @@ -143,12 +140,11 @@ { git_reference *ref = NULL; git_reflog *reflog = NULL; - regex_t preg; + git_regexp preg; int error = -1; size_t i, numentries, cur; const git_reflog_entry *entry; const char *msg; - regmatch_t regexmatches[2]; git_buf buf = GIT_BUF_INIT; cur = position; @@ -168,12 +164,14 @@ numentries = git_reflog_entrycount(reflog); for (i = 0; i < numentries; i++) { + git_regmatch regexmatches[2]; + entry = git_reflog_entry_byindex(reflog, i); msg = git_reflog_entry_message(entry); if (!msg) continue; - if (regexec(&preg, msg, 2, regexmatches, 0)) + if (git_regexp_search(&preg, msg, 2, regexmatches) < 0) continue; cur--; @@ -181,7 +179,8 @@ if (cur > 0) continue; - git_buf_put(&buf, msg+regexmatches[1].rm_so, regexmatches[1].rm_eo - regexmatches[1].rm_so); + if ((git_buf_put(&buf, msg+regexmatches[1].start, regexmatches[1].end - regexmatches[1].start)) < 0) + goto cleanup; if ((error = git_reference_dwim(base_ref, repo, git_buf_cstr(&buf))) == 0) goto cleanup; @@ -199,7 +198,7 @@ cleanup: git_reference_free(ref); git_buf_dispose(&buf); - regfree(&preg); + git_regexp_dispose(&preg); git_reflog_free(reflog); return error; } @@ -448,7 +447,7 @@ return error; } -static int walk_and_search(git_object **out, git_revwalk *walk, regex_t *regex) +static int walk_and_search(git_object **out, git_revwalk *walk, git_regexp *regex) { int error; git_oid oid; @@ -460,7 +459,7 @@ if ((error < 0) && (error != GIT_ENOTFOUND)) return -1; - if (!regexec(regex, git_commit_message((git_commit*)obj), 0, NULL, 0)) { + if (!git_regexp_match(regex, git_commit_message((git_commit*)obj))) { *out = obj; return 0; } @@ -476,7 +475,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_oid *spec_oid, const char *pattern) { - regex_t preg; + git_regexp preg; git_revwalk *walk = NULL; int error; @@ -497,7 +496,7 @@ error = walk_and_search(out, walk, &preg); cleanup: - regfree(&preg); + git_regexp_dispose(&preg); git_revwalk_free(walk); return error; @@ -538,7 +537,8 @@ if (spec[*pos] == '\0') return GIT_EINVALIDSPEC; - git_buf_putc(buf, spec[(*pos)++]); + if (git_buf_putc(buf, spec[(*pos)++]) < 0) + return -1; } (*pos)++; @@ -586,7 +586,7 @@ *pos = end_ptr - spec; } - } while (spec[(*pos)] == kind && kind == '~'); + } while (spec[(*pos)] == kind && kind == '~'); *n = accumulated; @@ -660,7 +660,7 @@ return GIT_EINVALIDSPEC; } -int revparse__ext( +static int revparse( git_object **object_out, git_reference **reference_out, size_t *identifier_len_out, @@ -836,7 +836,7 @@ git_object *obj = NULL; git_reference *ref = NULL; - if ((error = revparse__ext(&obj, &ref, &identifier_len, repo, spec)) < 0) + if ((error = revparse(&obj, &ref, &identifier_len, repo, spec)) < 0) goto cleanup; *object_out = obj; diff -Nru libgit2-0.28.5+dfsg.1/src/revwalk.c libgit2-1.1.0+dfsg.1/src/revwalk.c --- libgit2-0.28.5+dfsg.1/src/revwalk.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/revwalk.c 2020-10-12 18:53:06.000000000 +0000 @@ -21,13 +21,10 @@ git_revwalk *walk, const git_oid *oid) { git_commit_list_node *commit; - size_t pos; - int ret; /* lookup and reserve space if not already present */ - pos = git_oidmap_lookup_index(walk->commits, oid); - if (git_oidmap_valid_index(walk->commits, pos)) - return git_oidmap_value_at(walk->commits, pos); + if ((commit = git_oidmap_get(walk->commits, oid)) != NULL) + return commit; commit = git_commit_list_alloc_node(walk); if (commit == NULL) @@ -35,14 +32,13 @@ git_oid_cpy(&commit->oid, oid); - pos = git_oidmap_put(walk->commits, &commit->oid, &ret); - assert(ret != 0); - git_oidmap_set_value_at(walk->commits, pos, commit); + if ((git_oidmap_set(walk->commits, &commit->oid, commit)) < 0) + return NULL; return commit; } -static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob) +int git_revwalk__push_commit(git_revwalk *walk, const git_oid *oid, const git_revwalk__push_options *opts) { git_oid commit_id; int error; @@ -58,11 +54,11 @@ if (error == GIT_ENOTFOUND || error == GIT_EINVALIDSPEC || error == GIT_EPEEL) { /* If this comes from e.g. push_glob("tags"), ignore this */ - if (from_glob) + if (opts->from_glob) return 0; git_error_set(GIT_ERROR_INVALID, "object is not a committish"); - return -1; + return error; } if (error < 0) return error; @@ -78,16 +74,18 @@ if (commit->uninteresting) return 0; - if (uninteresting) { + if (opts->uninteresting) { walk->limited = 1; walk->did_hide = 1; } else { walk->did_push = 1; } - commit->uninteresting = uninteresting; + commit->uninteresting = opts->uninteresting; list = walk->user_input; - if (git_commit_list_insert(commit, &list) == NULL) { + if ((opts->insert_by_date && + git_commit_list_insert_by_date(commit, &list) == NULL) || + git_commit_list_insert(commit, &list) == NULL) { git_error_set_oom(); return -1; } @@ -99,29 +97,36 @@ int git_revwalk_push(git_revwalk *walk, const git_oid *oid) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; + assert(walk && oid); - return push_commit(walk, oid, 0, false); + + return git_revwalk__push_commit(walk, oid, &opts); } int git_revwalk_hide(git_revwalk *walk, const git_oid *oid) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk && oid); - return push_commit(walk, oid, 1, false); + + opts.uninteresting = 1; + return git_revwalk__push_commit(walk, oid, &opts); } -static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob) +int git_revwalk__push_ref(git_revwalk *walk, const char *refname, const git_revwalk__push_options *opts) { git_oid oid; if (git_reference_name_to_id(&oid, walk->repo, refname) < 0) return -1; - return push_commit(walk, &oid, hide, from_glob); + return git_revwalk__push_commit(walk, &oid, opts); } -static int push_glob(git_revwalk *walk, const char *glob, int hide) +int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwalk__push_options *given_opts) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; int error = 0; git_buf buf = GIT_BUF_INIT; git_reference *ref; @@ -130,6 +135,9 @@ assert(walk && glob); + if (given_opts) + memcpy(&opts, given_opts, sizeof(opts)); + /* refs/ is implied if not given in the glob */ if (git__prefixcmp(glob, GIT_REFS_DIR) != 0) git_buf_joinpath(&buf, GIT_REFS_DIR, glob); @@ -145,8 +153,9 @@ if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0) goto out; + opts.from_glob = true; while ((error = git_reference_next(&ref, iter)) == 0) { - error = push_ref(walk, git_reference_name(ref), hide, true); + error = git_revwalk__push_ref(walk, git_reference_name(ref), &opts); git_reference_free(ref); if (error < 0) break; @@ -162,52 +171,74 @@ int git_revwalk_push_glob(git_revwalk *walk, const char *glob) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk && glob); - return push_glob(walk, glob, 0); + + return git_revwalk__push_glob(walk, glob, &opts); } int git_revwalk_hide_glob(git_revwalk *walk, const char *glob) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk && glob); - return push_glob(walk, glob, 1); + + opts.uninteresting = 1; + return git_revwalk__push_glob(walk, glob, &opts); } int git_revwalk_push_head(git_revwalk *walk) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk); - return push_ref(walk, GIT_HEAD_FILE, 0, false); + + return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts); } int git_revwalk_hide_head(git_revwalk *walk) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk); - return push_ref(walk, GIT_HEAD_FILE, 1, false); + + opts.uninteresting = 1; + return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts); } int git_revwalk_push_ref(git_revwalk *walk, const char *refname) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk && refname); - return push_ref(walk, refname, 0, false); + + return git_revwalk__push_ref(walk, refname, &opts); } int git_revwalk_push_range(git_revwalk *walk, const char *range) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; git_revspec revspec; int error = 0; if ((error = git_revparse(&revspec, walk->repo, range))) return error; + if (!revspec.to) { + git_error_set(GIT_ERROR_INVALID, "invalid revspec: range not provided"); + error = GIT_EINVALIDSPEC; + goto out; + } + if (revspec.flags & GIT_REVPARSE_MERGE_BASE) { /* TODO: support "..." */ git_error_set(GIT_ERROR_INVALID, "symmetric differences not implemented in revwalk"); - return GIT_EINVALIDSPEC; + error = GIT_EINVALIDSPEC; + goto out; } - if ((error = push_commit(walk, git_object_id(revspec.from), 1, false))) + opts.uninteresting = 1; + if ((error = git_revwalk__push_commit(walk, git_object_id(revspec.from), &opts))) goto out; - error = push_commit(walk, git_object_id(revspec.to), 0, false); + opts.uninteresting = 0; + error = git_revwalk__push_commit(walk, git_object_id(revspec.to), &opts); out: git_object_free(revspec.from); @@ -217,8 +248,10 @@ int git_revwalk_hide_ref(git_revwalk *walk, const char *refname) { + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; assert(walk && refname); - return push_ref(walk, refname, 1, false); + opts.uninteresting = 1; + return git_revwalk__push_ref(walk, refname, &opts); } static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit) @@ -626,13 +659,11 @@ git_revwalk *walk = git__calloc(1, sizeof(git_revwalk)); GIT_ERROR_CHECK_ALLOC(walk); - walk->commits = git_oidmap_alloc(); - GIT_ERROR_CHECK_ALLOC(walk->commits); - - if (git_pqueue_init(&walk->iterator_time, 0, 8, git_commit_list_time_cmp) < 0) + if (git_oidmap_new(&walk->commits) < 0 || + git_pqueue_init(&walk->iterator_time, 0, 8, git_commit_list_time_cmp) < 0 || + git_pool_init(&walk->commit_pool, COMMIT_ALLOC) < 0) return -1; - git_pool_init(&walk->commit_pool, COMMIT_ALLOC); walk->get_next = &revwalk_next_unsorted; walk->enqueue = &revwalk_enqueue_unsorted; @@ -667,7 +698,7 @@ return walk->repo; } -void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode) +int git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode) { assert(walk); @@ -686,11 +717,14 @@ if (walk->sorting != GIT_SORT_NONE) walk->limited = 1; + + return 0; } -void git_revwalk_simplify_first_parent(git_revwalk *walk) +int git_revwalk_simplify_first_parent(git_revwalk *walk) { walk->first_parent = 1; + return 0; } int git_revwalk_next(git_oid *oid, git_revwalk *walk) @@ -719,7 +753,7 @@ return error; } -void git_revwalk_reset(git_revwalk *walk) +int git_revwalk_reset(git_revwalk *walk) { git_commit_list_node *commit; @@ -744,6 +778,8 @@ walk->limited = 0; walk->did_push = walk->did_hide = 0; walk->sorting = GIT_SORT_NONE; + + return 0; } int git_revwalk_add_hide_cb( diff -Nru libgit2-0.28.5+dfsg.1/src/revwalk.h libgit2-1.1.0+dfsg.1/src/revwalk.h --- libgit2-0.28.5+dfsg.1/src/revwalk.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/revwalk.h 2020-10-12 18:53:06.000000000 +0000 @@ -50,4 +50,24 @@ git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid); +typedef struct { + int uninteresting; + int from_glob; + int insert_by_date; +} git_revwalk__push_options; + +#define GIT_REVWALK__PUSH_OPTIONS_INIT { 0 } + +int git_revwalk__push_commit(git_revwalk *walk, + const git_oid *oid, + const git_revwalk__push_options *opts); + +int git_revwalk__push_ref(git_revwalk *walk, + const char *refname, + const git_revwalk__push_options *opts); + +int git_revwalk__push_glob(git_revwalk *walk, + const char *glob, + const git_revwalk__push_options *given_opts); + #endif diff -Nru libgit2-0.28.5+dfsg.1/src/settings.c libgit2-1.1.0+dfsg.1/src/settings.c --- libgit2-0.28.5+dfsg.1/src/settings.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/settings.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,14 +25,17 @@ #include "refs.h" #include "index.h" #include "transports/smart.h" +#include "transports/http.h" #include "streams/openssl.h" #include "streams/mbedtls.h" -void git_libgit2_version(int *major, int *minor, int *rev) +int git_libgit2_version(int *major, int *minor, int *rev) { *major = LIBGIT2_VER_MAJOR; *minor = LIBGIT2_VER_MINOR; *rev = LIBGIT2_VER_REVISION; + + return 0; } int git_libgit2_features(void) @@ -56,7 +59,9 @@ /* Declarations for tuneable settings */ extern size_t git_mwindow__window_size; extern size_t git_mwindow__mapped_limit; +extern size_t git_mwindow__file_limit; extern size_t git_indexer__max_objects; +extern bool git_disable_pack_keep_file_checks; static int config_level_to_sysdir(int config_level) { @@ -120,6 +125,14 @@ *(va_arg(ap, size_t *)) = git_mwindow__mapped_limit; break; + case GIT_OPT_SET_MWINDOW_FILE_LIMIT: + git_mwindow__file_limit = va_arg(ap, size_t); + break; + + case GIT_OPT_GET_MWINDOW_FILE_LIMIT: + *(va_arg(ap, size_t *)) = git_mwindow__file_limit; + break; + case GIT_OPT_GET_SEARCH_PATH: if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) { git_buf *out = va_arg(ap, git_buf *); @@ -279,6 +292,14 @@ *(va_arg(ap, size_t *)) = git_indexer__max_objects; break; + case GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS: + git_disable_pack_keep_file_checks = (va_arg(ap, int) != 0); + break; + + case GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE: + git_http__expect_continue = (va_arg(ap, int) != 0); + break; + default: git_error_set(GIT_ERROR_INVALID, "invalid option key"); error = -1; diff -Nru libgit2-0.28.5+dfsg.1/src/sha1_lookup.c libgit2-1.1.0+dfsg.1/src/sha1_lookup.c --- libgit2-0.28.5+dfsg.1/src/sha1_lookup.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sha1_lookup.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "sha1_lookup.h" - -#include - -#include "oid.h" - -int sha1_position(const void *table, - size_t stride, - unsigned lo, unsigned hi, - const unsigned char *key) -{ - const unsigned char *base = table; - - while (lo < hi) { - unsigned mi = (lo + hi) / 2; - int cmp = git_oid__hashcmp(base + mi * stride, key); - - if (!cmp) - return mi; - - if (cmp > 0) - hi = mi; - else - lo = mi+1; - } - - return -((int)lo)-1; -} diff -Nru libgit2-0.28.5+dfsg.1/src/sha1_lookup.h libgit2-1.1.0+dfsg.1/src/sha1_lookup.h --- libgit2-0.28.5+dfsg.1/src/sha1_lookup.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sha1_lookup.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#ifndef INCLUDE_sha1_lookup_h__ -#define INCLUDE_sha1_lookup_h__ - -#include "common.h" - -#include - -int sha1_position(const void *table, - size_t stride, - unsigned lo, unsigned hi, - const unsigned char *key); - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/sortedcache.c libgit2-1.1.0+dfsg.1/src/sortedcache.c --- libgit2-0.28.5+dfsg.1/src/sortedcache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sortedcache.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,10 +25,9 @@ sc = git__calloc(1, alloclen); GIT_ERROR_CHECK_ALLOC(sc); - git_pool_init(&sc->pool, 1); - - if (git_vector_init(&sc->items, 4, item_cmp) < 0 || - git_strmap_alloc(&sc->map) < 0) + if (git_pool_init(&sc->pool, 1) < 0 || + git_vector_init(&sc->items, 4, item_cmp) < 0 || + git_strmap_new(&sc->map) < 0) goto fail; if (git_rwlock_init(&sc->lock)) { @@ -270,23 +269,19 @@ /* find and/or insert item, returning pointer to item data */ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) { - size_t pos; - int error = 0; - void *item; size_t keylen, itemlen; + int error = 0; char *item_key; + void *item; - pos = git_strmap_lookup_index(sc->map, key); - if (git_strmap_valid_index(sc->map, pos)) { - item = git_strmap_value_at(sc->map, pos); + if ((item = git_strmap_get(sc->map, key)) != NULL) goto done; - } keylen = strlen(key); itemlen = sc->item_path_offset + keylen + 1; itemlen = (itemlen + 7) & ~7; - if ((item = git_pool_mallocz(&sc->pool, (uint32_t)itemlen)) == NULL) { + if ((item = git_pool_mallocz(&sc->pool, itemlen)) == NULL) { /* don't use GIT_ERROR_CHECK_ALLOC b/c of lock */ error = -1; goto done; @@ -299,17 +294,11 @@ item_key = ((char *)item) + sc->item_path_offset; memcpy(item_key, key, keylen); - pos = git_strmap_put(sc->map, item_key, &error); - if (error < 0) + if ((error = git_strmap_set(sc->map, item_key, item)) < 0) goto done; - if (!error) - git_strmap_set_key_at(sc->map, pos, item_key); - git_strmap_set_value_at(sc->map, pos, item); - - error = git_vector_insert(&sc->items, item); - if (error < 0) - git_strmap_delete_at(sc->map, pos); + if ((error = git_vector_insert(&sc->items, item)) < 0) + git_strmap_delete(sc->map, item_key); done: if (out) @@ -320,10 +309,7 @@ /* lookup item by key */ void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key) { - size_t pos = git_strmap_lookup_index(sc->map, key); - if (git_strmap_valid_index(sc->map, pos)) - return git_strmap_value_at(sc->map, pos); - return NULL; + return git_strmap_get(sc->map, key); } /* find out how many items are in the cache */ @@ -371,9 +357,9 @@ int git_sortedcache_remove(git_sortedcache *sc, size_t pos) { char *item; - size_t mappos; - /* because of pool allocation, this can't actually remove the item, + /* + * Because of pool allocation, this can't actually remove the item, * but we can remove it from the items vector and the hash table. */ @@ -384,8 +370,7 @@ (void)git_vector_remove(&sc->items, pos); - mappos = git_strmap_lookup_index(sc->map, item + sc->item_path_offset); - git_strmap_delete_at(sc->map, mappos); + git_strmap_delete(sc->map, item + sc->item_path_offset); if (sc->free_item) sc->free_item(sc->free_item_payload, item); diff -Nru libgit2-0.28.5+dfsg.1/src/sortedcache.h libgit2-1.1.0+dfsg.1/src/sortedcache.h --- libgit2-0.28.5+dfsg.1/src/sortedcache.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sortedcache.h 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include "common.h" #include "util.h" -#include "fileops.h" +#include "futils.h" #include "vector.h" #include "thread-utils.h" #include "pool.h" diff -Nru libgit2-0.28.5+dfsg.1/src/stash.c libgit2-1.1.0+dfsg.1/src/stash.c --- libgit2-0.28.5+dfsg.1/src/stash.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/stash.c 2020-10-12 18:53:06.000000000 +0000 @@ -173,7 +173,7 @@ git_index *index, const char *path) { - git_index *repo_index; + git_index *repo_index = NULL; git_index_entry entry = {{0}}; struct stat st; int error; @@ -187,7 +187,7 @@ return error; git_index_entry__init_from_stat(&entry, &st, - (repo_index != NULL || !repo_index->distrust_filemode)); + (repo_index == NULL || !repo_index->distrust_filemode)); entry.path = path; @@ -398,28 +398,23 @@ git_commit *b_commit, git_commit *u_commit) { - int error = 0; - git_tree *w_tree = NULL, *i_tree = NULL; - git_index *i_index = NULL; - const git_commit *parents[] = { NULL, NULL, NULL }; - int ignorecase; + const git_commit *parents[] = { NULL, NULL, NULL }; + git_index *i_index = NULL, *r_index = NULL; + git_tree *w_tree = NULL; + int error = 0, ignorecase; parents[0] = b_commit; parents[1] = i_commit; parents[2] = u_commit; - if ((error = git_commit_tree(&i_tree, i_commit)) < 0) - goto cleanup; - - if ((error = git_index_new(&i_index)) < 0 || - (error = git_repository__cvar(&ignorecase, repo, GIT_CVAR_IGNORECASE)) < 0) + if ((error = git_repository_index(&r_index, repo) < 0) || + (error = git_index_new(&i_index)) < 0 || + (error = git_index__fill(i_index, &r_index->entries) < 0) || + (error = git_repository__configmap_lookup(&ignorecase, repo, GIT_CONFIGMAP_IGNORECASE)) < 0) goto cleanup; git_index__set_ignore_case(i_index, ignorecase); - if ((error = git_index_read_tree(i_index, i_tree)) < 0) - goto cleanup; - if ((error = build_workdir_tree(&w_tree, repo, i_index, b_commit)) < 0) goto cleanup; @@ -436,42 +431,39 @@ parents); cleanup: - git_tree_free(i_tree); git_tree_free(w_tree); git_index_free(i_index); + git_index_free(r_index); return error; } -static int prepare_worktree_commit_message( - git_buf* msg, - const char *user_message) +static int prepare_worktree_commit_message(git_buf *out, const char *user_message) { git_buf buf = GIT_BUF_INIT; - int error; - - if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0) - return error; - - git_buf_clear(msg); + int error = 0; - if (!user_message) - git_buf_printf(msg, "WIP on %s", git_buf_cstr(&buf)); - else { + if (!user_message) { + git_buf_printf(&buf, "WIP on %s", git_buf_cstr(out)); + } else { const char *colon; - if ((colon = strchr(git_buf_cstr(&buf), ':')) == NULL) + if ((colon = strchr(git_buf_cstr(out), ':')) == NULL) goto cleanup; - git_buf_puts(msg, "On "); - git_buf_put(msg, git_buf_cstr(&buf), colon - buf.ptr); - git_buf_printf(msg, ": %s\n", user_message); + git_buf_puts(&buf, "On "); + git_buf_put(&buf, git_buf_cstr(out), colon - out->ptr); + git_buf_printf(&buf, ": %s\n", user_message); } - error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0; + if (git_buf_oom(&buf)) { + error = -1; + goto cleanup; + } + + git_buf_swap(out, &buf); cleanup: git_buf_dispose(&buf); - return error; } @@ -502,10 +494,7 @@ return GIT_PASSTHROUGH; } -static int ensure_there_are_changes_to_stash( - git_repository *repo, - bool include_untracked_files, - bool include_ignored_files) +static int ensure_there_are_changes_to_stash(git_repository *repo, uint32_t flags) { int error; git_status_options opts = GIT_STATUS_OPTIONS_INIT; @@ -513,11 +502,11 @@ opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES; - if (include_untracked_files) + if (flags & GIT_STASH_INCLUDE_UNTRACKED) opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - if (include_ignored_files) + if (flags & GIT_STASH_INCLUDE_IGNORED) opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; @@ -532,20 +521,14 @@ return error; } -static int reset_index_and_workdir( - git_repository *repo, - git_commit *commit, - bool remove_untracked, - bool remove_ignored) +static int reset_index_and_workdir(git_repository *repo, git_commit *commit, uint32_t flags) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - if (remove_untracked) + if (flags & GIT_STASH_INCLUDE_UNTRACKED) opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_UNTRACKED; - - if (remove_ignored) + if (flags & GIT_STASH_INCLUDE_IGNORED) opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_IGNORED; return git_checkout_tree(repo, (git_object *)commit, &opts); @@ -571,31 +554,26 @@ if ((error = retrieve_base_commit_and_message(&b_commit, &msg, repo)) < 0) goto cleanup; - if ((error = ensure_there_are_changes_to_stash( - repo, - (flags & GIT_STASH_INCLUDE_UNTRACKED) != 0, - (flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0) + if ((error = ensure_there_are_changes_to_stash(repo, flags)) < 0) goto cleanup; if ((error = git_repository_index(&index, repo)) < 0) goto cleanup; - if ((error = commit_index( - &i_commit, repo, index, stasher, git_buf_cstr(&msg), b_commit)) < 0) + if ((error = commit_index(&i_commit, repo, index, stasher, + git_buf_cstr(&msg), b_commit)) < 0) goto cleanup; if ((flags & (GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)) && - (error = commit_untracked( - &u_commit, repo, stasher, git_buf_cstr(&msg), - i_commit, flags)) < 0) + (error = commit_untracked(&u_commit, repo, stasher, + git_buf_cstr(&msg), i_commit, flags)) < 0) goto cleanup; if ((error = prepare_worktree_commit_message(&msg, message)) < 0) goto cleanup; - if ((error = commit_worktree( - out, repo, stasher, git_buf_cstr(&msg), - i_commit, b_commit, u_commit)) < 0) + if ((error = commit_worktree(out, repo, stasher, git_buf_cstr(&msg), + i_commit, b_commit, u_commit)) < 0) goto cleanup; git_buf_rtrim(&msg); @@ -603,11 +581,8 @@ if ((error = update_reflog(out, repo, git_buf_cstr(&msg))) < 0) goto cleanup; - if ((error = reset_index_and_workdir( - repo, - ((flags & GIT_STASH_KEEP_INDEX) != 0) ? i_commit : b_commit, - (flags & GIT_STASH_INCLUDE_UNTRACKED) != 0, - (flags & GIT_STASH_INCLUDE_IGNORED) != 0)) < 0) + if ((error = reset_index_and_workdir(repo, (flags & GIT_STASH_KEEP_INDEX) ? i_commit : b_commit, + flags)) < 0) goto cleanup; cleanup: @@ -794,13 +769,20 @@ opts->checkout_options.their_label = "Stashed changes"; } -int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version) +int git_stash_apply_options_init(git_stash_apply_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_stash_apply_options, GIT_STASH_APPLY_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version) +{ + return git_stash_apply_options_init(opts, version); +} +#endif + #define NOTIFY_PROGRESS(opts, progress_type) \ do { \ if ((opts).progress_cb && \ diff -Nru libgit2-0.28.5+dfsg.1/src/status.c libgit2-1.1.0+dfsg.1/src/status.c --- libgit2-0.28.5+dfsg.1/src/status.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/status.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ #include "status.h" #include "git2.h" -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "vector.h" #include "tree.h" @@ -16,6 +16,7 @@ #include "repository.h" #include "ignore.h" #include "index.h" +#include "wildmatch.h" #include "git2/diff.h" #include "diff.h" @@ -85,15 +86,15 @@ /* if OIDs don't match, we might need to calculate them now to * discern between RENAMED vs RENAMED+MODIFED */ - if (git_oid_iszero(&idx2wd->old_file.id) && - diff->old_src == GIT_ITERATOR_TYPE_WORKDIR && + if (git_oid_is_zero(&idx2wd->old_file.id) && + diff->old_src == GIT_ITERATOR_WORKDIR && !git_diff__oid_for_file( &idx2wd->old_file.id, diff, idx2wd->old_file.path, idx2wd->old_file.mode, idx2wd->old_file.size)) idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; - if (git_oid_iszero(&idx2wd->new_file.id) && - diff->new_src == GIT_ITERATOR_TYPE_WORKDIR && + if (git_oid_is_zero(&idx2wd->new_file.id) && + diff->new_src == GIT_ITERATOR_WORKDIR && !git_diff__oid_for_file( &idx2wd->new_file.id, diff, idx2wd->new_file.path, idx2wd->new_file.mode, idx2wd->new_file.size)) @@ -280,7 +281,7 @@ if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 || (error = git_repository_index(&index, repo)) < 0) return error; - + if (opts != NULL && opts->baseline != NULL) { head = opts->baseline; } else { @@ -456,7 +457,7 @@ char *expected; unsigned int count; unsigned int status; - int fnm_flags; + int wildmatch_flags; int ambiguous; }; @@ -468,11 +469,11 @@ sfi->count++; sfi->status = status; - strcomp = (sfi->fnm_flags & FNM_CASEFOLD) ? git__strcasecmp : git__strcmp; + strcomp = (sfi->wildmatch_flags & WM_CASEFOLD) ? git__strcasecmp : git__strcmp; if (sfi->count > 1 || (strcomp(sfi->expected, path) != 0 && - p_fnmatch(sfi->expected, path, sfi->fnm_flags) != 0)) + wildmatch(sfi->expected, path, sfi->wildmatch_flags) != 0)) { sfi->ambiguous = true; return GIT_EAMBIGUOUS; /* git_error_set will be done by caller */ @@ -499,7 +500,7 @@ if ((sfi.expected = git__strdup(path)) == NULL) return -1; if (index->ignore_case) - sfi.fnm_flags = FNM_CASEFOLD; + sfi.wildmatch_flags = WM_CASEFOLD; opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED | @@ -540,13 +541,20 @@ return git_ignore_path_is_ignored(ignored, repo, path); } -int git_status_init_options(git_status_options *opts, unsigned int version) +int git_status_options_init(git_status_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_status_options, GIT_STATUS_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_status_init_options(git_status_options *opts, unsigned int version) +{ + return git_status_options_init(opts, version); +} +#endif + int git_status_list_get_perfdata( git_diff_perfdata *out, const git_status_list *status) { diff -Nru libgit2-0.28.5+dfsg.1/src/stdalloc.c libgit2-1.1.0+dfsg.1/src/stdalloc.c --- libgit2-0.28.5+dfsg.1/src/stdalloc.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/stdalloc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +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 "stdalloc.h" - -static void *stdalloc__malloc(size_t len, const char *file, int line) -{ - void *ptr = malloc(len); - - GIT_UNUSED(file); - GIT_UNUSED(line); - - if (!ptr) git_error_set_oom(); - return ptr; -} - -static void *stdalloc__calloc(size_t nelem, size_t elsize, const char *file, int line) -{ - void *ptr = calloc(nelem, elsize); - - GIT_UNUSED(file); - GIT_UNUSED(line); - - if (!ptr) git_error_set_oom(); - return ptr; -} - -static char *stdalloc__strdup(const char *str, const char *file, int line) -{ - char *ptr = strdup(str); - - GIT_UNUSED(file); - GIT_UNUSED(line); - - if (!ptr) git_error_set_oom(); - return ptr; -} - -static char *stdalloc__strndup(const char *str, size_t n, const char *file, int line) -{ - size_t length = 0, alloclength; - char *ptr; - - length = p_strnlen(str, n); - - if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) || - !(ptr = stdalloc__malloc(alloclength, file, line))) - return NULL; - - if (length) - memcpy(ptr, str, length); - - ptr[length] = '\0'; - - return ptr; -} - -static char *stdalloc__substrdup(const char *start, size_t n, const char *file, int line) -{ - char *ptr; - size_t alloclen; - - if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) || - !(ptr = stdalloc__malloc(alloclen, file, line))) - return NULL; - - memcpy(ptr, start, n); - ptr[n] = '\0'; - return ptr; -} - -static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line) -{ - void *new_ptr = realloc(ptr, size); - - GIT_UNUSED(file); - GIT_UNUSED(line); - - if (!new_ptr) git_error_set_oom(); - return new_ptr; -} - -static void *stdalloc__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line) -{ - size_t newsize; - - GIT_UNUSED(file); - GIT_UNUSED(line); - - return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ? - NULL : realloc(ptr, newsize); -} - -static void *stdalloc__mallocarray(size_t nelem, size_t elsize, const char *file, int line) -{ - return stdalloc__reallocarray(NULL, nelem, elsize, file, line); -} - -static void stdalloc__free(void *ptr) -{ - free(ptr); -} - -int git_stdalloc_init_allocator(git_allocator *allocator) -{ - allocator->gmalloc = stdalloc__malloc; - allocator->gcalloc = stdalloc__calloc; - allocator->gstrdup = stdalloc__strdup; - allocator->gstrndup = stdalloc__strndup; - allocator->gsubstrdup = stdalloc__substrdup; - allocator->grealloc = stdalloc__realloc; - allocator->greallocarray = stdalloc__reallocarray; - allocator->gmallocarray = stdalloc__mallocarray; - allocator->gfree = stdalloc__free; - return 0; -} diff -Nru libgit2-0.28.5+dfsg.1/src/stdalloc.h libgit2-1.1.0+dfsg.1/src/stdalloc.h --- libgit2-0.28.5+dfsg.1/src/stdalloc.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/stdalloc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +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_stdalloc_h__ -#define INCLUDE_stdalloc_h__ - -#include "alloc.h" - -#include "common.h" - -int git_stdalloc_init_allocator(git_allocator *allocator); - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/strarray.c libgit2-1.1.0+dfsg.1/src/strarray.c --- libgit2-0.28.5+dfsg.1/src/strarray.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/strarray.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * 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 "util.h" + +#include "common.h" + +int git_strarray_copy(git_strarray *tgt, const git_strarray *src) +{ + size_t i; + + assert(tgt && src); + + memset(tgt, 0, sizeof(*tgt)); + + if (!src->count) + return 0; + + tgt->strings = git__calloc(src->count, sizeof(char *)); + GIT_ERROR_CHECK_ALLOC(tgt->strings); + + for (i = 0; i < src->count; ++i) { + if (!src->strings[i]) + continue; + + tgt->strings[tgt->count] = git__strdup(src->strings[i]); + if (!tgt->strings[tgt->count]) { + git_strarray_dispose(tgt); + memset(tgt, 0, sizeof(*tgt)); + return -1; + } + + tgt->count++; + } + + return 0; +} + +void git_strarray_dispose(git_strarray *array) +{ + size_t i; + + if (array == NULL) + return; + + for (i = 0; i < array->count; ++i) + git__free(array->strings[i]); + + git__free(array->strings); + + memset(array, 0, sizeof(*array)); +} + +#ifndef GIT_DEPRECATE_HARD +void git_strarray_free(git_strarray *array) +{ + git_strarray_dispose(array); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/streams/openssl.c libgit2-1.1.0+dfsg.1/src/streams/openssl.c --- libgit2-0.28.5+dfsg.1/src/streams/openssl.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/streams/openssl.c 2020-10-12 18:53:06.000000000 +0000 @@ -156,7 +156,7 @@ lock = mode & CRYPTO_LOCK; if (lock) { - git_mutex_lock(&openssl_locks[n]); + (void)git_mutex_lock(&openssl_locks[n]); } else { git_mutex_unlock(&openssl_locks[n]); } @@ -196,16 +196,69 @@ } } +#ifdef VALGRIND +#ifdef OPENSSL_LEGACY_API +static void *git_openssl_malloc(size_t bytes) +{ + return git__calloc(1, bytes); +} + +static void *git_openssl_realloc(void *mem, size_t size) +{ + return git__realloc(mem, size); +} + +static void git_openssl_free(void *mem) +{ + return git__free(mem); +} +#else +static void *git_openssl_malloc(size_t bytes, const char *file, int line) +{ + GIT_UNUSED(file); + GIT_UNUSED(line); + return git__calloc(1, bytes); +} + +static void *git_openssl_realloc(void *mem, size_t size, const char *file, int line) +{ + GIT_UNUSED(file); + GIT_UNUSED(line); + return git__realloc(mem, size); +} + +static void git_openssl_free(void *mem, const char *file, int line) +{ + GIT_UNUSED(file); + GIT_UNUSED(line); + return git__free(mem); +} +#endif +#endif + int git_openssl_stream_global_init(void) { long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; const char *ciphers = git_libgit2__ssl_ciphers(); +#ifdef VALGRIND + static bool allocators_initialized = false; +#endif /* Older OpenSSL and MacOS OpenSSL doesn't have this */ #ifdef SSL_OP_NO_COMPRESSION ssl_opts |= SSL_OP_NO_COMPRESSION; #endif +#ifdef VALGRIND + /* Swap in our own allocator functions that initialize allocated memory */ + if (!allocators_initialized && + CRYPTO_set_mem_functions(git_openssl_malloc, + git_openssl_realloc, + git_openssl_free) != 1) + goto error; + allocators_initialized = true; +#endif + OPENSSL_init_ssl(0, NULL); /* @@ -310,7 +363,6 @@ static int bio_write(BIO *b, const char *buf, int len) { git_stream *io = (git_stream *) BIO_get_data(b); - return (int) git_stream_write(io, buf, len, 0); } @@ -603,15 +655,16 @@ static int openssl_certificate(git_cert **out, git_stream *stream) { openssl_stream *st = (openssl_stream *) stream; - int len; X509 *cert = SSL_get_peer_certificate(st->ssl); - unsigned char *guard, *encoded_cert; + unsigned char *guard, *encoded_cert = NULL; + int error, len; /* Retrieve the length of the certificate first */ len = i2d_X509(cert, NULL); if (len < 0) { git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information"); - return -1; + error = -1; + goto out; } encoded_cert = git__malloc(len); @@ -621,18 +674,23 @@ len = i2d_X509(cert, &guard); if (len < 0) { - git__free(encoded_cert); git_error_set(GIT_ERROR_NET, "failed to retrieve certificate information"); - return -1; + error = -1; + goto out; } st->cert_info.parent.cert_type = GIT_CERT_X509; st->cert_info.data = encoded_cert; st->cert_info.len = len; + encoded_cert = NULL; *out = &st->cert_info.parent; + error = 0; - return 0; +out: + git__free(encoded_cert); + X509_free(cert); + return error; } static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts) diff -Nru libgit2-0.28.5+dfsg.1/src/streams/registry.c libgit2-1.1.0+dfsg.1/src/streams/registry.c --- libgit2-0.28.5+dfsg.1/src/streams/registry.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/streams/registry.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,9 +5,10 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include "git2/errors.h" - #include "common.h" + +#include "streams/registry.h" + #include "global.h" #include "streams/tls.h" #include "streams/mbedtls.h" @@ -100,7 +101,7 @@ return 0; } - +#ifndef GIT_DEPRECATE_HARD int git_stream_register_tls( int GIT_CALLBACK(ctor)(git_stream **out, const char *host, const char *port)) { @@ -116,3 +117,4 @@ return git_stream_register(GIT_STREAM_TLS, NULL); } } +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/streams/socket.c libgit2-1.1.0+dfsg.1/src/streams/socket.c --- libgit2-0.28.5+dfsg.1/src/streams/socket.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/streams/socket.c 2020-10-12 18:53:06.000000000 +0000 @@ -138,7 +138,7 @@ errno = 0; if ((written = p_send(st->s, data, len, flags)) < 0) { - net_set_error("Error sending data"); + net_set_error("error sending data"); return -1; } @@ -151,7 +151,7 @@ git_socket_stream *st = (git_socket_stream *) stream; if ((ret = p_recv(st->s, data, len, 0)) < 0) - net_set_error("Error receiving socket data"); + net_set_error("error receiving socket data"); return ret; } diff -Nru libgit2-0.28.5+dfsg.1/src/strmap.c libgit2-1.1.0+dfsg.1/src/strmap.c --- libgit2-0.28.5+dfsg.1/src/strmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/strmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -18,12 +18,10 @@ __KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal) -int git_strmap_alloc(git_strmap **map) +int git_strmap_new(git_strmap **out) { - if ((*map = kh_init(str)) == NULL) { - git_error_set_oom(); - return -1; - } + *out = kh_init(str); + GIT_ERROR_CHECK_ALLOC(*out); return 0; } @@ -38,110 +36,65 @@ kh_clear(str, map); } -size_t git_strmap_num_entries(git_strmap *map) +size_t git_strmap_size(git_strmap *map) { return kh_size(map); } -size_t git_strmap_lookup_index(git_strmap *map, const char *key) -{ - return kh_get(str, map, key); -} - -int git_strmap_valid_index(git_strmap *map, size_t idx) -{ - return idx != kh_end(map); -} - -int git_strmap_exists(git_strmap *map, const char *key) -{ - return kh_get(str, map, key) != kh_end(map); -} - -int git_strmap_has_data(git_strmap *map, size_t idx) -{ - return kh_exist(map, idx); -} - -const char *git_strmap_key(git_strmap *map, size_t idx) -{ - return kh_key(map, idx); -} - -void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key) -{ - kh_val(map, idx) = key; -} - -void *git_strmap_value_at(git_strmap *map, size_t idx) +void *git_strmap_get(git_strmap *map, const char *key) { + size_t idx = kh_get(str, map, key); + if (idx == kh_end(map) || !kh_exist(map, idx)) + return NULL; return kh_val(map, idx); } -void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value) -{ - kh_val(map, idx) = value; -} - -void git_strmap_delete_at(git_strmap *map, size_t idx) +int git_strmap_set(git_strmap *map, const char *key, void *value) { - kh_del(str, map, idx); -} + size_t idx; + int rval; -int git_strmap_put(git_strmap *map, const char *key, int *err) -{ - return kh_put(str, map, key, err); -} + idx = kh_put(str, map, key, &rval); + if (rval < 0) + return -1; -void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval) -{ - khiter_t idx = kh_put(str, map, key, rval); + if (rval == 0) + kh_key(map, idx) = key; - if ((*rval) >= 0) { - if ((*rval) == 0) - kh_key(map, idx) = key; - kh_val(map, idx) = value; - } -} + kh_val(map, idx) = value; -void git_strmap_delete(git_strmap *map, const char *key) -{ - khiter_t idx = git_strmap_lookup_index(map, key); - if (git_strmap_valid_index(map, idx)) - git_strmap_delete_at(map, idx); + return 0; } -size_t git_strmap_begin(git_strmap *map) +int git_strmap_delete(git_strmap *map, const char *key) { - GIT_UNUSED(map); + khiter_t idx = kh_get(str, map, key); + if (idx == kh_end(map)) + return GIT_ENOTFOUND; + kh_del(str, map, idx); return 0; } -size_t git_strmap_end(git_strmap *map) +int git_strmap_exists(git_strmap *map, const char *key) { - return map->n_buckets; + return kh_get(str, map, key) != kh_end(map); } -int git_strmap_next( - void **data, - size_t* iter, - git_strmap *map) +int git_strmap_iterate(void **value, git_strmap *map, size_t *iter, const char **key) { - if (!map) - return GIT_ERROR; + size_t i = *iter; - while (*iter != git_strmap_end(map)) { - if (!(git_strmap_has_data(map, *iter))) { - ++(*iter); - continue; - } + while (i < map->n_buckets && !kh_exist(map, i)) + i++; - *data = git_strmap_value_at(map, *iter); + if (i >= map->n_buckets) + return GIT_ITEROVER; - ++(*iter); + if (key) + *key = kh_key(map, i); + if (value) + *value = kh_val(map, i); + *iter = ++i; - return GIT_OK; - } - - return GIT_ITEROVER; + return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/strmap.h libgit2-1.1.0+dfsg.1/src/strmap.h --- libgit2-0.28.5+dfsg.1/src/strmap.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/strmap.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,51 +9,123 @@ #include "common.h" +/** A map with C strings as key. */ typedef struct kh_str_s git_strmap; -int git_strmap_alloc(git_strmap **map); +/** + * Allocate a new string map. + * + * @param out Pointer to the map that shall be allocated. + * @return 0 on success, an error code if allocation has failed. + */ +int git_strmap_new(git_strmap **out); + +/** + * Free memory associated with the map. + * + * Note that this function will _not_ free keys or values added + * to this map. + * + * @param map Pointer to the map that is to be free'd. May be + * `NULL`. + */ void git_strmap_free(git_strmap *map); -void git_strmap_clear(git_strmap *map); - -size_t git_strmap_num_entries(git_strmap *map); -size_t git_strmap_lookup_index(git_strmap *map, const char *key); -int git_strmap_valid_index(git_strmap *map, size_t idx); +/** + * Clear all entries from the map. + * + * This function will remove all entries from the associated map. + * Memory associated with it will not be released, though. + * + * @param map Pointer to the map that shall be cleared. May be + * `NULL`. + */ +void git_strmap_clear(git_strmap *map); +/** + * Return the number of elements in the map. + * + * @parameter map map containing the elements + * @return number of elements in the map + */ +size_t git_strmap_size(git_strmap *map); + +/** + * Return value associated with the given key. + * + * @param map map to search key in + * @param key key to search for + * @return value associated with the given key or NULL if the key was not found + */ +void *git_strmap_get(git_strmap *map, const char *key); + +/** + * Set the entry for key to value. + * + * If the map has no corresponding entry for the given key, a new + * entry will be created with the given value. If an entry exists + * already, its value will be updated to match the given value. + * + * @param map map to create new entry in + * @param key key to set + * @param value value to associate the key with; may be NULL + * @return zero if the key was successfully set, a negative error + * code otherwise + */ +int git_strmap_set(git_strmap *map, const char *key, void *value); + +/** + * Delete an entry from the map. + * + * Delete the given key and its value from the map. If no such + * key exists, this will do nothing. + * + * @param map map to delete key in + * @param key key to delete + * @return `0` if the key has been deleted, GIT_ENOTFOUND if no + * such key was found, a negative code in case of an + * error + */ +int git_strmap_delete(git_strmap *map, const char *key); + +/** + * Check whether a key exists in the given map. + * + * @param map map to query for the key + * @param key key to search for + * @return 0 if the key has not been found, 1 otherwise + */ int git_strmap_exists(git_strmap *map, const char *key); -int git_strmap_has_data(git_strmap *map, size_t idx); -const char *git_strmap_key(git_strmap *map, size_t idx); -void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key); -void *git_strmap_value_at(git_strmap *map, size_t idx); -void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value); -void git_strmap_delete_at(git_strmap *map, size_t idx); - -int git_strmap_put(git_strmap *map, const char *key, int *err); -void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval); -void git_strmap_delete(git_strmap *map, const char *key); - -#define git_strmap_foreach(h, kvar, vvar, code) { size_t __i; \ - for (__i = git_strmap_begin(h); __i != git_strmap_end(h); ++__i) { \ - if (!git_strmap_has_data(h,__i)) continue; \ - (kvar) = git_strmap_key(h,__i); \ - (vvar) = git_strmap_value_at(h,__i); \ +/** + * Iterate over entries of the map. + * + * This functions allows to iterate over all key-value entries of + * the map. The current position is stored in the `iter` variable + * and should be initialized to `0` before the first call to this + * function. + * + * @param map map to iterate over + * @param value pointer to the variable where to store the current + * value. May be NULL. + * @param iter iterator storing the current position. Initialize + * with zero previous to the first call. + * @param key pointer to the variable where to store the current + * key. May be NULL. + * @return `0` if the next entry was correctly retrieved. + * GIT_ITEROVER if no entries are left. A negative error + * code otherwise. + */ +int git_strmap_iterate(void **value, git_strmap *map, size_t *iter, const char **key); + +#define git_strmap_foreach(h, kvar, vvar, code) { size_t __i = 0; \ + while (git_strmap_iterate((void **) &(vvar), h, &__i, &(kvar)) == 0) { \ code; \ } } -#define git_strmap_foreach_value(h, vvar, code) { size_t __i; \ - for (__i = git_strmap_begin(h); __i != git_strmap_end(h); ++__i) { \ - if (!git_strmap_has_data(h,__i)) continue; \ - (vvar) = git_strmap_value_at(h,__i); \ +#define git_strmap_foreach_value(h, vvar, code) { size_t __i = 0; \ + while (git_strmap_iterate((void **) &(vvar), h, &__i, NULL) == 0) { \ code; \ } } -size_t git_strmap_begin(git_strmap *map); -size_t git_strmap_end(git_strmap *map); - -int git_strmap_next( - void **data, - size_t *iter, - git_strmap *map); - #endif diff -Nru libgit2-0.28.5+dfsg.1/src/submodule.c libgit2-1.1.0+dfsg.1/src/submodule.c --- libgit2-0.28.5+dfsg.1/src/submodule.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/submodule.c 2020-10-12 18:53:06.000000000 +0000 @@ -23,31 +23,32 @@ #include "path.h" #include "index.h" #include "worktree.h" +#include "clone.h" #define GIT_MODULES_FILE ".gitmodules" -static git_cvar_map _sm_update_map[] = { - {GIT_CVAR_STRING, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT}, - {GIT_CVAR_STRING, "rebase", GIT_SUBMODULE_UPDATE_REBASE}, - {GIT_CVAR_STRING, "merge", GIT_SUBMODULE_UPDATE_MERGE}, - {GIT_CVAR_STRING, "none", GIT_SUBMODULE_UPDATE_NONE}, - {GIT_CVAR_FALSE, NULL, GIT_SUBMODULE_UPDATE_NONE}, - {GIT_CVAR_TRUE, NULL, GIT_SUBMODULE_UPDATE_CHECKOUT}, +static git_configmap _sm_update_map[] = { + {GIT_CONFIGMAP_STRING, "checkout", GIT_SUBMODULE_UPDATE_CHECKOUT}, + {GIT_CONFIGMAP_STRING, "rebase", GIT_SUBMODULE_UPDATE_REBASE}, + {GIT_CONFIGMAP_STRING, "merge", GIT_SUBMODULE_UPDATE_MERGE}, + {GIT_CONFIGMAP_STRING, "none", GIT_SUBMODULE_UPDATE_NONE}, + {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_UPDATE_NONE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_UPDATE_CHECKOUT}, }; -static git_cvar_map _sm_ignore_map[] = { - {GIT_CVAR_STRING, "none", GIT_SUBMODULE_IGNORE_NONE}, - {GIT_CVAR_STRING, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED}, - {GIT_CVAR_STRING, "dirty", GIT_SUBMODULE_IGNORE_DIRTY}, - {GIT_CVAR_STRING, "all", GIT_SUBMODULE_IGNORE_ALL}, - {GIT_CVAR_FALSE, NULL, GIT_SUBMODULE_IGNORE_NONE}, - {GIT_CVAR_TRUE, NULL, GIT_SUBMODULE_IGNORE_ALL}, +static git_configmap _sm_ignore_map[] = { + {GIT_CONFIGMAP_STRING, "none", GIT_SUBMODULE_IGNORE_NONE}, + {GIT_CONFIGMAP_STRING, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED}, + {GIT_CONFIGMAP_STRING, "dirty", GIT_SUBMODULE_IGNORE_DIRTY}, + {GIT_CONFIGMAP_STRING, "all", GIT_SUBMODULE_IGNORE_ALL}, + {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_IGNORE_NONE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_IGNORE_ALL}, }; -static git_cvar_map _sm_recurse_map[] = { - {GIT_CVAR_STRING, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND}, - {GIT_CVAR_FALSE, NULL, GIT_SUBMODULE_RECURSE_NO}, - {GIT_CVAR_TRUE, NULL, GIT_SUBMODULE_RECURSE_YES}, +static git_configmap _sm_recurse_map[] = { + {GIT_CONFIGMAP_STRING, "on-demand", GIT_SUBMODULE_RECURSE_ONDEMAND}, + {GIT_CONFIGMAP_FALSE, NULL, GIT_SUBMODULE_RECURSE_NO}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_SUBMODULE_RECURSE_YES}, }; enum { @@ -197,12 +198,11 @@ git_config_entry *entry; git_buf buf = GIT_BUF_INIT; git_strmap *names; - int rval, isvalid; - int error = 0; + int isvalid, error; *out = NULL; - if ((error = git_strmap_alloc(&names)) < 0) + if ((error = git_strmap_new(&names)) < 0) goto out; if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0) @@ -230,8 +230,7 @@ if (!isvalid) continue; - git_strmap_insert(names, git__strdup(entry->value), git_buf_detach(&buf), &rval); - if (rval < 0) { + if ((error = git_strmap_set(names, git__strdup(entry->value), git_buf_detach(&buf))) < 0) { git_error_set(GIT_ERROR_NOMEMORY, "error inserting submodule into hash table"); error = -1; goto out; @@ -267,10 +266,9 @@ } if (repo->submodule_cache != NULL) { - size_t pos = git_strmap_lookup_index(repo->submodule_cache, name); - if (git_strmap_valid_index(repo->submodule_cache, pos)) { + if ((sm = git_strmap_get(repo->submodule_cache, name)) != NULL) { if (out) { - *out = git_strmap_value_at(repo->submodule_cache, pos); + *out = sm; GIT_REFCOUNT_INC(*out); } return 0; @@ -395,30 +393,21 @@ static int submodule_get_or_create(git_submodule **out, git_repository *repo, git_strmap *map, const char *name) { - int error = 0; - size_t pos; git_submodule *sm = NULL; + int error; - pos = git_strmap_lookup_index(map, name); - if (git_strmap_valid_index(map, pos)) { - sm = git_strmap_value_at(map, pos); + if ((sm = git_strmap_get(map, name)) != NULL) goto done; - } /* if the submodule doesn't exist yet in the map, create it */ if ((error = submodule_alloc(&sm, repo, name)) < 0) return error; - pos = git_strmap_put(map, sm->name, &error); - /* nobody can beat us to adding it */ - assert(error != 0); - if (error < 0) { + if ((error = git_strmap_set(map, sm->name, sm)) < 0) { git_submodule_free(sm); return error; } - git_strmap_set_value_at(map, pos, sm); - done: GIT_REFCOUNT_INC(sm); *out = sm; @@ -439,26 +428,18 @@ goto done; while (!(error = git_iterator_advance(&entry, i))) { - size_t pos = git_strmap_lookup_index(map, entry->path); git_submodule *sm; - if (git_strmap_valid_index(map, pos)) { - sm = git_strmap_value_at(map, pos); - + if ((sm = git_strmap_get(map, entry->path)) != NULL) { if (S_ISGITLINK(entry->mode)) submodule_update_from_index_entry(sm, entry); else sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - size_t name_pos; const char *name; - name_pos = git_strmap_lookup_index(names, entry->path); - if (git_strmap_valid_index(names, name_pos)) { - name = git_strmap_value_at(names, name_pos); - } else { + if ((name = git_strmap_get(names, entry->path)) == NULL) name = entry->path; - } if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name)) { submodule_update_from_index_entry(sm, entry); @@ -491,26 +472,18 @@ goto done; while (!(error = git_iterator_advance(&entry, i))) { - size_t pos = git_strmap_lookup_index(map, entry->path); git_submodule *sm; - if (git_strmap_valid_index(map, pos)) { - sm = git_strmap_value_at(map, pos); - + if ((sm = git_strmap_get(map, entry->path)) != NULL) { if (S_ISGITLINK(entry->mode)) submodule_update_from_head_data(sm, entry->mode, &entry->id); else sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - size_t name_pos; const char *name; - name_pos = git_strmap_lookup_index(names, entry->path); - if (git_strmap_valid_index(names, name_pos)) { - name = git_strmap_value_at(names, name_pos); - } else { + if ((name = git_strmap_get(names, entry->path)) == NULL) name = entry->path; - } if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name)) { submodule_update_from_head_data( @@ -618,14 +591,14 @@ return -1; } - if ((error = git_strmap_alloc(&submodules)) < 0) + if ((error = git_strmap_new(&submodules)) < 0) return error; if ((error = git_submodule__map(repo, submodules)) < 0) goto done; if (!(error = git_vector_init( - &snapshot, git_strmap_num_entries(submodules), submodule_cmp))) { + &snapshot, git_strmap_size(submodules), submodule_cmp))) { git_strmap_foreach_value(submodules, sm, { if ((error = git_vector_insert(&snapshot, sm)) < 0) @@ -843,6 +816,64 @@ return error; } +static int clone_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) +{ + GIT_UNUSED(url); + GIT_UNUSED(payload); + return git_remote_lookup(out, repo, name); +} + +static int clone_return_repo(git_repository **out, const char *path, int bare, void *payload) +{ + git_submodule *sm = payload; + + GIT_UNUSED(path); + GIT_UNUSED(bare); + return git_submodule_open(out, sm); +} + +int git_submodule_clone(git_repository **out, git_submodule *submodule, const git_submodule_update_options *given_opts) +{ + int error; + git_repository *clone; + git_buf rel_path = GIT_BUF_INIT; + git_submodule_update_options sub_opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; + git_clone_options opts = GIT_CLONE_OPTIONS_INIT; + + assert(submodule); + + if (given_opts) + memcpy(&sub_opts, given_opts, sizeof(sub_opts)); + + GIT_ERROR_CHECK_VERSION(&sub_opts, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options"); + + memcpy(&opts.checkout_opts, &sub_opts.checkout_opts, sizeof(sub_opts.checkout_opts)); + memcpy(&opts.fetch_opts, &sub_opts.fetch_opts, sizeof(sub_opts.fetch_opts)); + opts.repository_cb = clone_return_repo; + opts.repository_cb_payload = submodule; + opts.remote_cb = clone_return_origin; + opts.remote_cb_payload = submodule; + + git_buf_puts(&rel_path, git_repository_workdir(git_submodule_owner(submodule))); + git_buf_joinpath(&rel_path, git_buf_cstr(&rel_path), git_submodule_path(submodule)); + + GIT_ERROR_CHECK_ALLOC_BUF(&rel_path); + + error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts); + if (error < 0) + goto cleanup; + + if (!out) + git_repository_free(clone); + else + *out = clone; + +cleanup: + git_buf_dispose(&rel_path); + + return error; +} + int git_submodule_add_finalize(git_submodule *sm) { int error; @@ -927,7 +958,7 @@ return error; } -const char *git_submodule_update_to_str(git_submodule_update_t update) +static const char *submodule_update_to_str(git_submodule_update_t update) { int i; for (i = 0; i < (int)ARRAY_SIZE(_sm_update_map); ++i) @@ -1017,9 +1048,9 @@ return error; } -static int write_mapped_var(git_repository *repo, const char *name, git_cvar_map *maps, size_t nmaps, const char *var, int ival) +static int write_mapped_var(git_repository *repo, const char *name, git_configmap *maps, size_t nmaps, const char *var, int ival) { - git_cvar_t type; + git_configmap_t type; const char *val; if (git_config_lookup_map_enum(&type, &val, maps, nmaps, ival) < 0) { @@ -1027,7 +1058,7 @@ return -1; } - if (type == GIT_CVAR_TRUE) + if (type == GIT_CONFIGMAP_TRUE) val = "true"; return write_var(repo, name, var, val); @@ -1202,13 +1233,20 @@ return submodule_repo_create(out, sm->repo, path); } -int git_submodule_update_init_options(git_submodule_update_options *opts, unsigned int version) +int git_submodule_update_options_init(git_submodule_update_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE( opts, version, git_submodule_update_options, GIT_SUBMODULE_UPDATE_OPTIONS_INIT); return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_submodule_update_init_options(git_submodule_update_options *opts, unsigned int version) +{ + return git_submodule_update_options_init(opts, version); +} +#endif + int git_submodule_update(git_submodule *sm, int init, git_submodule_update_options *_update_options) { int error; @@ -1365,7 +1403,7 @@ /* write "submodule.NAME.update" if not default */ val = (sm->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ? - NULL : git_submodule_update_to_str(sm->update); + NULL : submodule_update_to_str(sm->update); if ((error = git_buf_printf(&key, "submodule.%s.update", sm->name)) < 0 || (error = git_config__update_entry( @@ -1384,50 +1422,46 @@ int git_submodule_sync(git_submodule *sm) { - int error = 0; - git_config *cfg = NULL; - git_buf key = GIT_BUF_INIT; + git_buf key = GIT_BUF_INIT, url = GIT_BUF_INIT, remote_name = GIT_BUF_INIT; git_repository *smrepo = NULL; + git_config *cfg = NULL; + int error = 0; if (!sm->url) { - git_error_set(GIT_ERROR_SUBMODULE, - "no URL configured for submodule '%s'", sm->name); + git_error_set(GIT_ERROR_SUBMODULE, "no URL configured for submodule '%s'", sm->name); return -1; } /* copy URL over to config only if it already exists */ + if ((error = git_repository_config__weakptr(&cfg, sm->repo)) < 0 || + (error = git_buf_printf(&key, "submodule.%s.url", sm->name)) < 0 || + (error = git_submodule_resolve_url(&url, sm->repo, sm->url)) < 0 || + (error = git_config__update_entry(cfg, key.ptr, url.ptr, true, true)) < 0) + goto out; - if (!(error = git_repository_config__weakptr(&cfg, sm->repo)) && - !(error = git_buf_printf(&key, "submodule.%s.url", sm->name))) - error = git_config__update_entry(cfg, key.ptr, sm->url, true, true); + if (!(sm->flags & GIT_SUBMODULE_STATUS_IN_WD)) + goto out; /* if submodule exists in the working directory, update remote url */ + if ((error = git_submodule_open(&smrepo, sm)) < 0 || + (error = git_repository_config__weakptr(&cfg, smrepo)) < 0) + goto out; - if (!error && - (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0 && - !(error = git_submodule_open(&smrepo, sm))) - { - git_buf remote_name = GIT_BUF_INIT; - - if ((error = git_repository_config__weakptr(&cfg, smrepo)) < 0) - /* return error from reading submodule config */; - else if ((error = lookup_head_remote_key(&remote_name, smrepo)) < 0) { - git_error_clear(); - error = git_buf_sets(&key, "remote.origin.url"); - } else { - error = git_buf_join3( - &key, '.', "remote", remote_name.ptr, "url"); - git_buf_dispose(&remote_name); - } - - if (!error) - error = git_config__update_entry(cfg, key.ptr, sm->url, true, false); - - git_repository_free(smrepo); + if (lookup_head_remote_key(&remote_name, smrepo) == 0) { + if ((error = git_buf_join3(&key, '.', "remote", remote_name.ptr, "url")) < 0) + goto out; + } else if ((error = git_buf_sets(&key, "remote.origin.url")) < 0) { + goto out; } - git_buf_dispose(&key); + if ((error = git_config__update_entry(cfg, key.ptr, url.ptr, true, false)) < 0) + goto out; +out: + git_repository_free(smrepo); + git_buf_dispose(&remote_name); + git_buf_dispose(&key); + git_buf_dispose(&url); return error; } @@ -1570,43 +1604,40 @@ int git_submodule_reload(git_submodule *sm, int force) { - int error = 0, isvalid; - git_config *mods; + git_config *mods = NULL; + int error; GIT_UNUSED(force); assert(sm); - isvalid = git_submodule_name_is_valid(sm->repo, sm->name, 0); - if (isvalid <= 0) { + if ((error = git_submodule_name_is_valid(sm->repo, sm->name, 0)) <= 0) /* This should come with a warning, but we've no API for that */ - return isvalid; - } + goto out; - if (!git_repository_is_bare(sm->repo)) { - /* refresh config data */ - if ((error = gitmodules_snapshot(&mods, sm->repo)) < 0 && error != GIT_ENOTFOUND) - return error; - if (mods != NULL) { - error = submodule_read_config(sm, mods); - git_config_free(mods); + if (git_repository_is_bare(sm->repo)) + goto out; - if (error < 0) - return error; - } + /* refresh config data */ + if ((error = gitmodules_snapshot(&mods, sm->repo)) < 0 && error != GIT_ENOTFOUND) + goto out; - /* refresh wd data */ - sm->flags &= - ~(GIT_SUBMODULE_STATUS_IN_WD | - GIT_SUBMODULE_STATUS__WD_OID_VALID | - GIT_SUBMODULE_STATUS__WD_FLAGS); + if (mods != NULL && (error = submodule_read_config(sm, mods)) < 0) + goto out; - error = submodule_load_from_wd_lite(sm); - } + /* refresh wd data */ + sm->flags &= + ~(GIT_SUBMODULE_STATUS_IN_WD | + GIT_SUBMODULE_STATUS__WD_OID_VALID | + GIT_SUBMODULE_STATUS__WD_FLAGS); - if (error == 0 && (error = submodule_update_index(sm)) == 0) - error = submodule_update_head(sm); + if ((error = submodule_load_from_wd_lite(sm)) < 0 || + (error = submodule_update_index(sm)) < 0 || + (error = submodule_update_head(sm)) < 0) + goto out; +out: + git_config_free(mods); return error; } @@ -1809,7 +1840,7 @@ return 0; } -int git_submodule_parse_recurse(git_submodule_recurse_t *out, const char *value) +static int submodule_parse_recurse(git_submodule_recurse_t *out, const char *value) { int val; @@ -1905,7 +1936,7 @@ if ((error = get_value(&value, cfg, &key, sm->name, "fetchRecurseSubmodules")) == 0) { in_config = 1; - if ((error = git_submodule_parse_recurse(&sm->fetch_recurse, value)) < 0) + if ((error = submodule_parse_recurse(&sm->fetch_recurse, value)) < 0) goto cleanup; sm->fetch_recurse_default = sm->fetch_recurse; } else if (error != GIT_ENOTFOUND) { @@ -1935,7 +1966,6 @@ { lfc_data *data = payload; const char *namestart, *property; - size_t pos; git_strmap *map = data->map; git_buf name = GIT_BUF_INIT; git_submodule *sm; @@ -1967,8 +1997,7 @@ * a new submodule, load the config and insert it. If it's * already inserted, we've already loaded it, so we skip. */ - pos = git_strmap_lookup_index(map, name.ptr); - if (git_strmap_valid_index(map, pos)) { + if (git_strmap_exists(map, name.ptr)) { error = 0; goto done; } @@ -1981,9 +2010,7 @@ goto done; } - git_strmap_insert(map, sm->name, sm, &error); - assert(error != 0); - if (error < 0) + if ((error = git_strmap_set(map, sm->name, sm)) < 0) goto done; error = 0; @@ -2136,7 +2163,7 @@ int error = lookup_head_remote(remote, repo); /* if that failed, use 'origin' instead */ - if (error == GIT_ENOTFOUND) + if (error == GIT_ENOTFOUND || error == GIT_EUNBORNBRANCH) error = git_remote_lookup(remote, repo, "origin"); if (error == GIT_ENOTFOUND) diff -Nru libgit2-0.28.5+dfsg.1/src/submodule.h libgit2-1.1.0+dfsg.1/src/submodule.h --- libgit2-0.28.5+dfsg.1/src/submodule.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/submodule.h 2020-10-12 18:53:06.000000000 +0000 @@ -11,7 +11,7 @@ #include "git2/submodule.h" #include "git2/repository.h" -#include "fileops.h" +#include "futils.h" /* Notes: * diff -Nru libgit2-0.28.5+dfsg.1/src/sysdir.c libgit2-1.1.0+dfsg.1/src/sysdir.c --- libgit2-0.28.5+dfsg.1/src/sysdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sysdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -216,25 +216,6 @@ return 0; } -int git_sysdir_get_str( - char *out, - size_t outlen, - git_sysdir_t which) -{ - const git_buf *path = NULL; - - GIT_ERROR_CHECK_ERROR(git_sysdir_check_selector(which)); - GIT_ERROR_CHECK_ERROR(git_sysdir_get(&path, which)); - - if (!out || path->size >= outlen) { - git_error_set(GIT_ERROR_NOMEMORY, "buffer is too short for the path"); - return GIT_EBUFS; - } - - git_buf_copy_cstr(out, outlen, path); - return 0; -} - #define PATH_MAGIC "$PATH" int git_sysdir_set(git_sysdir_t which, const char *search_path) @@ -317,8 +298,11 @@ } done: + if (name) + git_error_set(GIT_ERROR_OS, "the %s file '%s' doesn't exist", label, name); + else + git_error_set(GIT_ERROR_OS, "the %s directory doesn't exist", label); git_buf_dispose(path); - git_error_set(GIT_ERROR_OS, "the %s file '%s' doesn't exist", label, name); return GIT_ENOTFOUND; } diff -Nru libgit2-0.28.5+dfsg.1/src/sysdir.h libgit2-1.1.0+dfsg.1/src/sysdir.h --- libgit2-0.28.5+dfsg.1/src/sysdir.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/sysdir.h 2020-10-12 18:53:06.000000000 +0000 @@ -94,17 +94,6 @@ extern int git_sysdir_get(const git_buf **out, git_sysdir_t which); /** - * Get search path into a preallocated buffer - * - * @param out String buffer to write into - * @param outlen Size of string buffer - * @param which Which search path to return - * @return 0 on success, GIT_EBUFS if out is too small, <0 on other failure - */ - -extern int git_sysdir_get_str(char *out, size_t outlen, git_sysdir_t which); - -/** * Set search paths for global/system/xdg files * * The first occurrence of the magic string "$PATH" in the new value will diff -Nru libgit2-0.28.5+dfsg.1/src/tag.c libgit2-1.1.0+dfsg.1/src/tag.c --- libgit2-0.28.5+dfsg.1/src/tag.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/tag.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,6 +10,7 @@ #include "commit.h" #include "signature.h" #include "message.h" +#include "wildmatch.h" #include "git2/object.h" #include "git2/repository.h" #include "git2/signature.h" @@ -327,7 +328,7 @@ return git_tag_create__internal(oid, repo, tag_name, target, NULL, NULL, allow_ref_overwrite, 0); } -int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite) +int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite) { git_tag tag; int error; @@ -475,7 +476,7 @@ GIT_UNUSED(oid); if (!*filter->pattern || - p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0) + wildmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0) { char *matched = git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN); GIT_ERROR_CHECK_ALLOC(matched); @@ -520,3 +521,12 @@ { return git_object_peel(tag_target, (const git_object *)tag, GIT_OBJECT_ANY); } + +/* Deprecated Functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite) +{ + return git_tag_create_from_buffer(oid, repo, buffer, allow_ref_overwrite); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/thread-utils.h libgit2-1.1.0+dfsg.1/src/thread-utils.h --- libgit2-0.28.5+dfsg.1/src/thread-utils.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/thread-utils.h 2020-10-12 18:53:06.000000000 +0000 @@ -7,12 +7,30 @@ #ifndef INCLUDE_thread_utils_h__ #define INCLUDE_thread_utils_h__ -#if defined(__GNUC__) && defined(GIT_THREADS) +#if defined(GIT_THREADS) + +#if defined(__clang__) + +# if (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 1)) +# error Atomic primitives do not exist on this version of clang; configure libgit2 with -DTHREADSAFE=OFF +# else +# define GIT_BUILTIN_ATOMIC +# endif + +#elif defined(__GNUC__) + # if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)) # error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF +# elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +# define GIT_BUILTIN_ATOMIC +# else +# define GIT_BUILTIN_SYNC # endif + #endif +#endif /* GIT_THREADS */ + /* Common operations even if threading has been disabled */ typedef struct { #if defined(GIT_WIN32) @@ -26,21 +44,25 @@ typedef struct { #if defined(GIT_WIN32) - __int64 val; + volatile __int64 val; #else - int64_t val; + volatile int64_t val; #endif } git_atomic64; typedef git_atomic64 git_atomic_ssize; +#define git_atomic_ssize_set git_atomic64_set #define git_atomic_ssize_add git_atomic64_add +#define git_atomic_ssize_get git_atomic64_get #else typedef git_atomic git_atomic_ssize; +#define git_atomic_ssize_set git_atomic_set #define git_atomic_ssize_add git_atomic_add +#define git_atomic_ssize_get git_atomic_get #endif @@ -56,7 +78,9 @@ { #if defined(GIT_WIN32) InterlockedExchange(&a->val, (LONG)val); -#elif defined(__GNUC__) +#elif defined(GIT_BUILTIN_ATOMIC) + __atomic_store_n(&a->val, val, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) __sync_lock_test_and_set(&a->val, val); #else # error "Unsupported architecture for atomic operations" @@ -67,7 +91,9 @@ { #if defined(GIT_WIN32) return InterlockedIncrement(&a->val); -#elif defined(__GNUC__) +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_add_fetch(&a->val, 1, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) return __sync_add_and_fetch(&a->val, 1); #else # error "Unsupported architecture for atomic operations" @@ -78,7 +104,9 @@ { #if defined(GIT_WIN32) return InterlockedExchangeAdd(&a->val, addend); -#elif defined(__GNUC__) +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) return __sync_add_and_fetch(&a->val, addend); #else # error "Unsupported architecture for atomic operations" @@ -89,25 +117,45 @@ { #if defined(GIT_WIN32) return InterlockedDecrement(&a->val); -#elif defined(__GNUC__) +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_sub_fetch(&a->val, 1, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) return __sync_sub_and_fetch(&a->val, 1); #else # error "Unsupported architecture for atomic operations" #endif } +GIT_INLINE(int) git_atomic_get(git_atomic *a) +{ +#if defined(GIT_WIN32) + return (int)InterlockedCompareExchange(&a->val, 0, 0); +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_load_n(&a->val, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) + return __sync_val_compare_and_swap(&a->val, 0, 0); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + GIT_INLINE(void *) git___compare_and_swap( void * volatile *ptr, void *oldval, void *newval) { - volatile void *foundval; #if defined(GIT_WIN32) + volatile void *foundval; foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval); -#elif defined(__GNUC__) + return (foundval == oldval) ? oldval : newval; +#elif defined(GIT_BUILTIN_ATOMIC) + bool success = __atomic_compare_exchange(ptr, &oldval, &newval, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return success ? oldval : newval; +#elif defined(GIT_BUILTIN_SYNC) + volatile void *foundval; foundval = __sync_val_compare_and_swap(ptr, oldval, newval); + return (foundval == oldval) ? oldval : newval; #else # error "Unsupported architecture for atomic operations" #endif - return (foundval == oldval) ? oldval : newval; } GIT_INLINE(volatile void *) git___swap( @@ -115,8 +163,30 @@ { #if defined(GIT_WIN32) return InterlockedExchangePointer(ptr, newval); -#else +#elif defined(GIT_BUILTIN_ATOMIC) + void * volatile foundval; + __atomic_exchange(ptr, &newval, &foundval, __ATOMIC_SEQ_CST); + return foundval; +#elif defined(GIT_BUILTIN_SYNC) return __sync_lock_test_and_set(ptr, newval); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + +GIT_INLINE(volatile void *) git___load(void * volatile *ptr) +{ +#if defined(GIT_WIN32) + void *newval = NULL, *oldval = NULL; + volatile void *foundval = NULL; + foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval); + return foundval; +#elif defined(GIT_BUILTIN_ATOMIC) + return (volatile void *)__atomic_load_n(ptr, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) + return (volatile void *)__sync_val_compare_and_swap(ptr, 0, 0); +#else +# error "Unsupported architecture for atomic operations" #endif } @@ -126,13 +196,41 @@ { #if defined(GIT_WIN32) return InterlockedExchangeAdd64(&a->val, addend); -#elif defined(__GNUC__) +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_add_fetch(&a->val, addend, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) return __sync_add_and_fetch(&a->val, addend); #else # error "Unsupported architecture for atomic operations" #endif } +GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val) +{ +#if defined(GIT_WIN32) + InterlockedExchange64(&a->val, val); +#elif defined(GIT_BUILTIN_ATOMIC) + __atomic_store_n(&a->val, val, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) + __sync_lock_test_and_set(&a->val, val); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + +GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a) +{ +#if defined(GIT_WIN32) + return (int64_t)InterlockedCompareExchange64(&a->val, 0, 0); +#elif defined(GIT_BUILTIN_ATOMIC) + return __atomic_load_n(&a->val, __ATOMIC_SEQ_CST); +#elif defined(GIT_BUILTIN_SYNC) + return __sync_val_compare_and_swap(&a->val, 0, 0); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + #endif #else @@ -190,6 +288,11 @@ return --a->val; } +GIT_INLINE(int) git_atomic_get(git_atomic *a) +{ + return (int)a->val; +} + GIT_INLINE(void *) git___compare_and_swap( void * volatile *ptr, void *oldval, void *newval) { @@ -216,15 +319,20 @@ return a->val; } -#endif - -#endif +GIT_INLINE(void) git_atomic64_set(git_atomic64 *a, int64_t val) +{ + a->val = val; +} -GIT_INLINE(int) git_atomic_get(git_atomic *a) +GIT_INLINE(int64_t) git_atomic64_get(git_atomic64 *a) { - return (int)a->val; + return (int64_t)a->val; } +#endif + +#endif + /* Atomically replace oldval with newval * @return oldval if it was replaced or newval if it was not */ @@ -233,14 +341,24 @@ #define git__swap(ptr, val) (void *)git___swap((void * volatile *)&ptr, val) +#define git__load(ptr) (void *)git___load((void * volatile *)&ptr) + extern int git_online_cpus(void); -#if defined(GIT_THREADS) && defined(_MSC_VER) -# define GIT_MEMORY_BARRIER MemoryBarrier() -#elif defined(GIT_THREADS) -# define GIT_MEMORY_BARRIER __sync_synchronize() +#if defined(GIT_THREADS) + +# if defined(GIT_WIN32) +# define GIT_MEMORY_BARRIER MemoryBarrier() +# elif defined(GIT_BUILTIN_ATOMIC) +# define GIT_MEMORY_BARRIER __atomic_thread_fence(__ATOMIC_SEQ_CST) +# elif defined(GIT_BUILTIN_SYNC) +# define GIT_MEMORY_BARRIER __sync_synchronize() +# endif + #else + # define GIT_MEMORY_BARRIER /* noop */ + #endif #endif diff -Nru libgit2-0.28.5+dfsg.1/src/trace.c libgit2-1.1.0+dfsg.1/src/trace.c --- libgit2-0.28.5+dfsg.1/src/trace.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/trace.c 2020-10-12 18:53:06.000000000 +0000 @@ -17,7 +17,7 @@ #endif -int git_trace_set(git_trace_level_t level, git_trace_callback callback) +int git_trace_set(git_trace_level_t level, git_trace_cb callback) { #ifdef GIT_TRACE assert(level == 0 || callback != NULL); diff -Nru libgit2-0.28.5+dfsg.1/src/trace.h libgit2-1.1.0+dfsg.1/src/trace.h --- libgit2-0.28.5+dfsg.1/src/trace.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/trace.h 2020-10-12 18:53:06.000000000 +0000 @@ -16,7 +16,7 @@ struct git_trace_data { git_trace_level_t level; - git_trace_callback callback; + git_trace_cb callback; }; extern struct git_trace_data git_trace__data; @@ -25,7 +25,7 @@ git_trace_level_t level, const char *fmt, ...) { - git_trace_callback callback = git_trace__data.callback; + git_trace_cb callback = git_trace__data.callback; git_buf message = GIT_BUF_INIT; va_list ap; @@ -56,7 +56,7 @@ GIT_UNUSED(fmt); } -#define git_trace_level() ((void)0) +#define git_trace_level() ((git_trace_level_t)0) #define git_trace git_trace__null #endif diff -Nru libgit2-0.28.5+dfsg.1/src/trailer.c libgit2-1.1.0+dfsg.1/src/trailer.c --- libgit2-0.28.5+dfsg.1/src/trailer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/trailer.c 2020-10-12 18:53:06.000000000 +0000 @@ -42,15 +42,19 @@ } /* - * Return the position of the start of the last line. If len is 0, return -1. + * Return the position of the start of the last line. If len is 0, return 0. */ -static int last_line(const char *buf, size_t len) +static bool last_line(size_t *out, const char *buf, size_t len) { - int i; + size_t i; + + *out = 0; + if (len == 0) - return -1; + return false; if (len == 1) - return 0; + return true; + /* * Skip the last character (in addition to the null terminator), * because if the last character is a newline, it is considered as part @@ -58,31 +62,37 @@ */ i = len - 2; - for (; i >= 0; i--) { - if (buf[i] == '\n') - return i + 1; + for (; i > 0; i--) { + if (buf[i] == '\n') { + *out = i + 1; + return true; + } } - return 0; + return true; } /* * If the given line is of the form - * "..." or "...", return the - * location of the separator. Otherwise, return -1. The optional whitespace - * is allowed there primarily to allow things like "Bug #43" where is - * "Bug" and is "#". + * "..." or "...", sets out + * to the location of the separator and returns true. Otherwise, returns + * false. The optional whitespace is allowed there primarily to allow things + * like "Bug #43" where is "Bug" and is "#". * - * The separator-starts-line case (in which this function returns 0) is - * distinguished from the non-well-formed-line case (in which this function - * returns -1) because some callers of this function need such a distinction. + * The separator-starts-line case (in which this function returns true and + * sets out to 0) is distinguished from the non-well-formed-line case (in + * which this function returns false) because some callers of this function + * need such a distinction. */ -static int find_separator(const char *line, const char *separators) +static bool find_separator(size_t *out, const char *line, const char *separators) { int whitespace_found = 0; const char *c; for (c = line; *c; c++) { - if (strchr(separators, *c)) - return c - line; + if (strchr(separators, *c)) { + *out = c - line; + return true; + } + if (!whitespace_found && (isalnum(*c) || *c == '-')) continue; if (c != line && (*c == ' ' || *c == '\t')) { @@ -91,7 +101,7 @@ } break; } - return -1; + return false; } /* @@ -104,10 +114,9 @@ * Returns the number of bytes from the tail to ignore, to be fed as * the second parameter to append_signoff(). */ -static int ignore_non_trailer(const char *buf, size_t len) +static size_t ignore_non_trailer(const char *buf, size_t len) { - int boc = 0; - size_t bol = 0; + size_t boc = 0, bol = 0; int in_old_conflicts_block = 0; size_t cutoff = len; @@ -144,7 +153,7 @@ * Return the position of the start of the patch or the length of str if there * is no patch in the message. */ -static int find_patch_start(const char *str) +static size_t find_patch_start(const char *str) { const char *s; @@ -160,10 +169,11 @@ * Return the position of the first trailer line or len if there are no * trailers. */ -static int find_trailer_start(const char *buf, size_t len) +static size_t find_trailer_start(const char *buf, size_t len) { const char *s; - int end_of_title, l, only_spaces = 1; + size_t end_of_title, l; + int only_spaces = 1; int recognized_prefix = 0, trailer_lines = 0, non_trailer_lines = 0; /* * Number of possible continuation lines encountered. This will be @@ -189,12 +199,11 @@ * trailers, or (ii) contains at least one Git-generated trailer and * consists of at least 25% trailers. */ - for (l = last_line(buf, len); - l >= end_of_title; - l = last_line(buf, l)) { + l = len; + while (last_line(&l, buf, l) && l >= end_of_title) { const char *bol = buf + l; const char *const *p; - int separator_pos; + size_t separator_pos = 0; if (bol[0] == COMMENT_LINE_CHAR) { non_trailer_lines += possible_continuation_lines; @@ -223,7 +232,7 @@ } } - separator_pos = find_separator(bol, TRAILER_SEPARATORS); + find_separator(&separator_pos, bol, TRAILER_SEPARATORS); if (separator_pos >= 1 && !isspace(bol[0])) { trailer_lines++; possible_continuation_lines = 0; @@ -244,7 +253,7 @@ } /* Return the position of the end of the trailers. */ -static int find_trailer_end(const char *buf, size_t len) +static size_t find_trailer_end(const char *buf, size_t len) { return len - ignore_non_trailer(buf, len); } @@ -258,6 +267,9 @@ size_t trailer_len = trailer_end - trailer_start; char *buffer = git__malloc(trailer_len + 1); + if (buffer == NULL) + return NULL; + memcpy(buffer, message + trailer_start, trailer_len); buffer[trailer_len] = 0; @@ -293,6 +305,8 @@ size_t trailer_len; char *trailer = extract_trailer_block(message, &trailer_len); + if (trailer == NULL) + return -1; for (ptr = trailer;;) { switch (state) { diff -Nru libgit2-0.28.5+dfsg.1/src/transaction.c libgit2-1.1.0+dfsg.1/src/transaction.c --- libgit2-0.28.5+dfsg.1/src/transaction.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transaction.c 2020-10-12 18:53:06.000000000 +0000 @@ -76,7 +76,8 @@ assert(out && repo); - git_pool_init(&pool, 1); + if ((error = git_pool_init(&pool, 1)) < 0) + goto on_error; tx = git_pool_mallocz(&pool, sizeof(git_transaction)); if (!tx) { @@ -84,7 +85,7 @@ goto on_error; } - if ((error = git_strmap_alloc(&tx->locks)) < 0) { + if ((error = git_strmap_new(&tx->locks)) < 0) { error = -1; goto on_error; } @@ -119,8 +120,7 @@ if ((error = git_refdb_lock(&node->payload, tx->db, refname)) < 0) return error; - git_strmap_insert(tx->locks, node->name, node, &error); - if (error < 0) + if ((error = git_strmap_set(tx->locks, node->name, node)) < 0) goto cleanup; return 0; @@ -134,16 +134,12 @@ static int find_locked(transaction_node **out, git_transaction *tx, const char *refname) { transaction_node *node; - size_t pos; - pos = git_strmap_lookup_index(tx->locks, refname); - if (!git_strmap_valid_index(tx->locks, pos)) { + if ((node = git_strmap_get(tx->locks, refname)) == NULL) { git_error_set(GIT_ERROR_REFERENCE, "the specified reference is not locked"); return GIT_ENOTFOUND; } - node = git_strmap_value_at(tx->locks, pos); - *out = node; return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth.c libgit2-1.1.0+dfsg.1/src/transports/auth.c --- libgit2-0.28.5+dfsg.1/src/transports/auth.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,32 +9,31 @@ #include "git2.h" #include "buffer.h" +#include "git2/sys/credential.h" static int basic_next_token( git_buf *out, git_http_auth_context *ctx, - const char *header_name, - git_cred *c) + git_credential *c) { - git_cred_userpass_plaintext *cred; + git_credential_userpass_plaintext *cred; git_buf raw = GIT_BUF_INIT; int error = -1; GIT_UNUSED(ctx); - if (c->credtype != GIT_CREDTYPE_USERPASS_PLAINTEXT) { + if (c->credtype != GIT_CREDENTIAL_USERPASS_PLAINTEXT) { git_error_set(GIT_ERROR_INVALID, "invalid credential type for basic auth"); goto on_error; } - cred = (git_cred_userpass_plaintext *)c; + cred = (git_credential_userpass_plaintext *)c; git_buf_printf(&raw, "%s:%s", cred->username, cred->password); if (git_buf_oom(&raw) || - git_buf_printf(out, "%s: Basic ", header_name) < 0 || - git_buf_encode_base64(out, git_buf_cstr(&raw), raw.size) < 0 || - git_buf_puts(out, "\r\n") < 0) + git_buf_puts(out, "Basic ") < 0 || + git_buf_encode_base64(out, git_buf_cstr(&raw), raw.size) < 0) goto on_error; error = 0; @@ -48,28 +47,30 @@ } static git_http_auth_context basic_context = { - GIT_AUTHTYPE_BASIC, - GIT_CREDTYPE_USERPASS_PLAINTEXT, + GIT_HTTP_AUTH_BASIC, + GIT_CREDENTIAL_USERPASS_PLAINTEXT, + 0, NULL, basic_next_token, + NULL, NULL }; int git_http_auth_basic( - git_http_auth_context **out, const gitno_connection_data *connection_data) + git_http_auth_context **out, const git_net_url *url) { - GIT_UNUSED(connection_data); + GIT_UNUSED(url); *out = &basic_context; return 0; } int git_http_auth_dummy( - git_http_auth_context **out, const gitno_connection_data *connection_data) + git_http_auth_context **out, const git_net_url *url) { - GIT_UNUSED(connection_data); + GIT_UNUSED(url); *out = NULL; - return 0; + return GIT_PASSTHROUGH; } diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth.h libgit2-1.1.0+dfsg.1/src/transports/auth.h --- libgit2-0.28.5+dfsg.1/src/transports/auth.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth.h 2020-10-12 18:53:06.000000000 +0000 @@ -14,24 +14,31 @@ #include "netops.h" typedef enum { - GIT_AUTHTYPE_BASIC = 1, - GIT_AUTHTYPE_NEGOTIATE = 2, -} git_http_authtype_t; + GIT_HTTP_AUTH_BASIC = 1, + GIT_HTTP_AUTH_NEGOTIATE = 2, + GIT_HTTP_AUTH_NTLM = 4, +} git_http_auth_t; typedef struct git_http_auth_context git_http_auth_context; struct git_http_auth_context { /** Type of scheme */ - git_http_authtype_t type; + git_http_auth_t type; /** Supported credentials */ - git_credtype_t credtypes; + git_credential_t credtypes; + + /** Connection affinity or request affinity */ + unsigned connection_affinity : 1; /** Sets the challenge on the authentication context */ int (*set_challenge)(git_http_auth_context *ctx, const char *challenge); /** Gets the next authentication token from the context */ - int (*next_token)(git_buf *out, git_http_auth_context *ctx, const char *header_name, git_cred *cred); + int (*next_token)(git_buf *out, git_http_auth_context *ctx, git_credential *cred); + + /** Examines if all tokens have been presented. */ + int (*is_complete)(git_http_auth_context *ctx); /** Frees the authentication context */ void (*free)(git_http_auth_context *ctx); @@ -39,26 +46,26 @@ typedef struct { /** Type of scheme */ - git_http_authtype_t type; + git_http_auth_t type; /** Name of the scheme (as used in the Authorization header) */ const char *name; /** Credential types this scheme supports */ - git_credtype_t credtypes; + git_credential_t credtypes; /** Function to initialize an authentication context */ int (*init_context)( git_http_auth_context **out, - const gitno_connection_data *connection_data); + const git_net_url *url); } git_http_auth_scheme; int git_http_auth_dummy( git_http_auth_context **out, - const gitno_connection_data *connection_data); + const git_net_url *url); int git_http_auth_basic( git_http_auth_context **out, - const gitno_connection_data *connection_data); + const git_net_url *url); #endif diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth_negotiate.c libgit2-1.1.0+dfsg.1/src/transports/auth_negotiate.c --- libgit2-0.28.5+dfsg.1/src/transports/auth_negotiate.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth_negotiate.c 2020-10-12 18:53:06.000000000 +0000 @@ -7,14 +7,19 @@ #include "auth_negotiate.h" -#ifdef GIT_GSSAPI +#if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK) #include "git2.h" #include "buffer.h" #include "auth.h" +#include "git2/sys/credential.h" +#ifdef GIT_GSSFRAMEWORK +#import +#elif defined(GIT_GSSAPI) #include #include +#endif static gss_OID_desc negotiate_oid_spnego = { 6, (void *) "\x2b\x06\x01\x05\x05\x02" }; @@ -70,11 +75,26 @@ return 0; } +static void negotiate_context_dispose(http_auth_negotiate_context *ctx) +{ + OM_uint32 status_minor; + + if (ctx->gss_context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context( + &status_minor, &ctx->gss_context, GSS_C_NO_BUFFER); + ctx->gss_context = GSS_C_NO_CONTEXT; + } + + git_buf_dispose(&ctx->target); + + git__free(ctx->challenge); + ctx->challenge = NULL; +} + static int negotiate_next_token( git_buf *buf, git_http_auth_context *c, - const char *header_name, - git_cred *cred) + git_credential *cred) { http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c; OM_uint32 status_major, status_minor; @@ -88,7 +108,7 @@ size_t challenge_len; int error = 0; - assert(buf && ctx && ctx->configured && cred && cred->credtype == GIT_CREDTYPE_DEFAULT); + assert(buf && ctx && ctx->configured && cred && cred->credtype == GIT_CREDENTIAL_DEFAULT); if (ctx->complete) return 0; @@ -101,18 +121,20 @@ if (GSS_ERROR(status_major)) { negotiate_err_set(status_major, status_minor, - "Could not parse principal"); + "could not parse principal"); error = -1; goto done; } challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0; - if (challenge_len < 9) { - git_error_set(GIT_ERROR_NET, "no negotiate challenge sent from server"); + if (challenge_len < 9 || memcmp(ctx->challenge, "Negotiate", 9) != 0) { + git_error_set(GIT_ERROR_NET, "server did not request negotiate"); error = -1; goto done; - } else if (challenge_len > 9) { + } + + if (challenge_len > 9) { if (git_buf_decode_base64(&input_buf, ctx->challenge + 10, challenge_len - 10) < 0) { git_error_set(GIT_ERROR_NET, "invalid negotiate challenge from server"); @@ -124,14 +146,12 @@ input_token.length = input_buf.size; input_token_ptr = &input_token; } else if (ctx->gss_context != GSS_C_NO_CONTEXT) { - git_error_set(GIT_ERROR_NET, "could not restart authentication"); - error = -1; - goto done; + negotiate_context_dispose(ctx); } mech = &negotiate_oid_spnego; - if (GSS_ERROR(status_major = gss_init_sec_context( + status_major = gss_init_sec_context( &status_minor, GSS_C_NO_CREDENTIAL, &ctx->gss_context, @@ -144,21 +164,29 @@ NULL, &output_token, NULL, - NULL))) { - negotiate_err_set(status_major, status_minor, "Negotiate failure"); + NULL); + + if (GSS_ERROR(status_major)) { + negotiate_err_set(status_major, status_minor, "negotiate failure"); error = -1; goto done; } /* This message merely told us auth was complete; we do not respond. */ if (status_major == GSS_S_COMPLETE) { + negotiate_context_dispose(ctx); ctx->complete = 1; goto done; } - git_buf_printf(buf, "%s: Negotiate ", header_name); + if (output_token.length == 0) { + git_error_set(GIT_ERROR_NET, "GSSAPI did not return token"); + error = -1; + goto done; + } + + git_buf_puts(buf, "Negotiate "); git_buf_encode_base64(buf, output_token.value, output_token.length); - git_buf_puts(buf, "\r\n"); if (git_buf_oom(buf)) error = -1; @@ -170,20 +198,20 @@ return error; } -static void negotiate_context_free(git_http_auth_context *c) +static int negotiate_is_complete(git_http_auth_context *c) { http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c; - OM_uint32 status_minor; - if (ctx->gss_context != GSS_C_NO_CONTEXT) { - gss_delete_sec_context( - &status_minor, &ctx->gss_context, GSS_C_NO_BUFFER); - ctx->gss_context = GSS_C_NO_CONTEXT; - } + assert(ctx); - git_buf_dispose(&ctx->target); + return (ctx->complete == 1); +} - git__free(ctx->challenge); +static void negotiate_context_free(git_http_auth_context *c) +{ + http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c; + + negotiate_context_dispose(ctx); ctx->configured = 0; ctx->complete = 0; @@ -194,7 +222,7 @@ static int negotiate_init_context( http_auth_negotiate_context *ctx, - const gitno_connection_data *connection_data) + const git_net_url *url) { OM_uint32 status_major, status_minor; gss_OID item, *oid; @@ -202,8 +230,9 @@ size_t i; /* Query supported mechanisms looking for SPNEGO) */ - if (GSS_ERROR(status_major = - gss_indicate_mechs(&status_minor, &mechanism_list))) { + status_major = gss_indicate_mechs(&status_minor, &mechanism_list); + + if (GSS_ERROR(status_major)) { negotiate_err_set(status_major, status_minor, "could not query mechanisms"); return -1; @@ -235,7 +264,7 @@ } git_buf_puts(&ctx->target, "HTTP@"); - git_buf_puts(&ctx->target, connection_data->host); + git_buf_puts(&ctx->target, url->host); if (git_buf_oom(&ctx->target)) return -1; @@ -248,7 +277,7 @@ int git_http_auth_negotiate( git_http_auth_context **out, - const gitno_connection_data *connection_data) + const git_net_url *url) { http_auth_negotiate_context *ctx; @@ -257,15 +286,17 @@ ctx = git__calloc(1, sizeof(http_auth_negotiate_context)); GIT_ERROR_CHECK_ALLOC(ctx); - if (negotiate_init_context(ctx, connection_data) < 0) { + if (negotiate_init_context(ctx, url) < 0) { git__free(ctx); return -1; } - ctx->parent.type = GIT_AUTHTYPE_NEGOTIATE; - ctx->parent.credtypes = GIT_CREDTYPE_DEFAULT; + ctx->parent.type = GIT_HTTP_AUTH_NEGOTIATE; + ctx->parent.credtypes = GIT_CREDENTIAL_DEFAULT; + ctx->parent.connection_affinity = 1; ctx->parent.set_challenge = negotiate_set_challenge; ctx->parent.next_token = negotiate_next_token; + ctx->parent.is_complete = negotiate_is_complete; ctx->parent.free = negotiate_context_free; *out = (git_http_auth_context *)ctx; diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth_negotiate.h libgit2-1.1.0+dfsg.1/src/transports/auth_negotiate.h --- libgit2-0.28.5+dfsg.1/src/transports/auth_negotiate.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth_negotiate.h 2020-10-12 18:53:06.000000000 +0000 @@ -12,11 +12,11 @@ #include "git2.h" #include "auth.h" -#ifdef GIT_GSSAPI +#if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK) extern int git_http_auth_negotiate( git_http_auth_context **out, - const gitno_connection_data *connection_data); + const git_net_url *url); #else diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth_ntlm.c libgit2-1.1.0+dfsg.1/src/transports/auth_ntlm.c --- libgit2-0.28.5+dfsg.1/src/transports/auth_ntlm.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth_ntlm.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,223 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2.h" +#include "common.h" +#include "buffer.h" +#include "auth.h" +#include "auth_ntlm.h" +#include "git2/sys/credential.h" + +#ifdef GIT_NTLM + +#include "ntlm.h" + +typedef struct { + git_http_auth_context parent; + ntlm_client *ntlm; + char *challenge; + bool complete; +} http_auth_ntlm_context; + +static int ntlm_set_challenge( + git_http_auth_context *c, + const char *challenge) +{ + http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c; + + assert(ctx && challenge); + + git__free(ctx->challenge); + + ctx->challenge = git__strdup(challenge); + GIT_ERROR_CHECK_ALLOC(ctx->challenge); + + return 0; +} + +static int ntlm_set_credentials(http_auth_ntlm_context *ctx, git_credential *_cred) +{ + git_credential_userpass_plaintext *cred; + const char *sep, *username; + char *domain = NULL, *domainuser = NULL; + int error = 0; + + assert(_cred->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT); + cred = (git_credential_userpass_plaintext *)_cred; + + if ((sep = strchr(cred->username, '\\')) != NULL) { + domain = git__strndup(cred->username, (sep - cred->username)); + GIT_ERROR_CHECK_ALLOC(domain); + + domainuser = git__strdup(sep + 1); + GIT_ERROR_CHECK_ALLOC(domainuser); + + username = domainuser; + } else { + username = cred->username; + } + + if (ntlm_client_set_credentials(ctx->ntlm, + username, domain, cred->password) < 0) { + git_error_set(GIT_ERROR_NET, "could not set credentials: %s", + ntlm_client_errmsg(ctx->ntlm)); + error = -1; + goto done; + } + +done: + git__free(domain); + git__free(domainuser); + return error; +} + +static int ntlm_next_token( + git_buf *buf, + git_http_auth_context *c, + git_credential *cred) +{ + http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c; + git_buf input_buf = GIT_BUF_INIT; + const unsigned char *msg; + size_t challenge_len, msg_len; + int error = -1; + + assert(buf && ctx && ctx->ntlm); + + challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0; + + if (ctx->complete) + ntlm_client_reset(ctx->ntlm); + + /* + * Set us complete now since it's the default case; the one + * incomplete case (successfully created a client request) + * will explicitly set that it requires a second step. + */ + ctx->complete = true; + + if (cred && ntlm_set_credentials(ctx, cred) != 0) + goto done; + + if (challenge_len < 4) { + git_error_set(GIT_ERROR_NET, "no ntlm challenge sent from server"); + goto done; + } else if (challenge_len == 4) { + if (memcmp(ctx->challenge, "NTLM", 4) != 0) { + git_error_set(GIT_ERROR_NET, "server did not request NTLM"); + goto done; + } + + if (ntlm_client_negotiate(&msg, &msg_len, ctx->ntlm) != 0) { + git_error_set(GIT_ERROR_NET, "ntlm authentication failed: %s", + ntlm_client_errmsg(ctx->ntlm)); + goto done; + } + + ctx->complete = false; + } else { + if (memcmp(ctx->challenge, "NTLM ", 5) != 0) { + git_error_set(GIT_ERROR_NET, "challenge from server was not NTLM"); + goto done; + } + + if (git_buf_decode_base64(&input_buf, + ctx->challenge + 5, challenge_len - 5) < 0) { + git_error_set(GIT_ERROR_NET, "invalid NTLM challenge from server"); + goto done; + } + + if (ntlm_client_set_challenge(ctx->ntlm, + (const unsigned char *)input_buf.ptr, input_buf.size) != 0) { + git_error_set(GIT_ERROR_NET, "ntlm challenge failed: %s", + ntlm_client_errmsg(ctx->ntlm)); + goto done; + } + + if (ntlm_client_response(&msg, &msg_len, ctx->ntlm) != 0) { + git_error_set(GIT_ERROR_NET, "ntlm authentication failed: %s", + ntlm_client_errmsg(ctx->ntlm)); + goto done; + } + } + + git_buf_puts(buf, "NTLM "); + git_buf_encode_base64(buf, (const char *)msg, msg_len); + + if (git_buf_oom(buf)) + goto done; + + error = 0; + +done: + git_buf_dispose(&input_buf); + return error; +} + +static int ntlm_is_complete(git_http_auth_context *c) +{ + http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c; + + assert(ctx); + return (ctx->complete == true); +} + +static void ntlm_context_free(git_http_auth_context *c) +{ + http_auth_ntlm_context *ctx = (http_auth_ntlm_context *)c; + + ntlm_client_free(ctx->ntlm); + git__free(ctx->challenge); + git__free(ctx); +} + +static int ntlm_init_context( + http_auth_ntlm_context *ctx, + const git_net_url *url) +{ + GIT_UNUSED(url); + + if ((ctx->ntlm = ntlm_client_init(NTLM_CLIENT_DEFAULTS)) == NULL) { + git_error_set_oom(); + return -1; + } + + return 0; +} + +int git_http_auth_ntlm( + git_http_auth_context **out, + const git_net_url *url) +{ + http_auth_ntlm_context *ctx; + + GIT_UNUSED(url); + + *out = NULL; + + ctx = git__calloc(1, sizeof(http_auth_ntlm_context)); + GIT_ERROR_CHECK_ALLOC(ctx); + + if (ntlm_init_context(ctx, url) < 0) { + git__free(ctx); + return -1; + } + + ctx->parent.type = GIT_HTTP_AUTH_NTLM; + ctx->parent.credtypes = GIT_CREDENTIAL_USERPASS_PLAINTEXT; + ctx->parent.connection_affinity = 1; + ctx->parent.set_challenge = ntlm_set_challenge; + ctx->parent.next_token = ntlm_next_token; + ctx->parent.is_complete = ntlm_is_complete; + ctx->parent.free = ntlm_context_free; + + *out = (git_http_auth_context *)ctx; + + return 0; +} + +#endif /* GIT_NTLM */ diff -Nru libgit2-0.28.5+dfsg.1/src/transports/auth_ntlm.h libgit2-1.1.0+dfsg.1/src/transports/auth_ntlm.h --- libgit2-0.28.5+dfsg.1/src/transports/auth_ntlm.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/auth_ntlm.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * 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_transports_auth_ntlm_h__ +#define INCLUDE_transports_auth_ntlm_h__ + +#include "git2.h" +#include "auth.h" + +/* NTLM requires a full request/challenge/response */ +#define GIT_AUTH_STEPS_NTLM 2 + +#ifdef GIT_NTLM + +#if defined(GIT_OPENSSL) +# define CRYPT_OPENSSL +#elif defined(GIT_MBEDTLS) +# define CRYPT_MBEDTLS +#elif defined(GIT_SECURE_TRANSPORT) +# define CRYPT_COMMONCRYPTO +#endif + +extern int git_http_auth_ntlm( + git_http_auth_context **out, + const git_net_url *url); + +#else + +#define git_http_auth_ntlm git_http_auth_dummy + +#endif /* GIT_NTLM */ + +#endif + diff -Nru libgit2-0.28.5+dfsg.1/src/transports/cred.c libgit2-1.1.0+dfsg.1/src/transports/cred.c --- libgit2-0.28.5+dfsg.1/src/transports/cred.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/cred.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,390 +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 "cred.h" - -#include "git2.h" -#include "smart.h" -#include "git2/cred_helpers.h" - -static int git_cred_ssh_key_type_new( - git_cred **cred, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase, - git_credtype_t credtype); - -int git_cred_has_username(git_cred *cred) -{ - if (cred->credtype == GIT_CREDTYPE_DEFAULT) - return 0; - - return 1; -} - -const char *git_cred__username(git_cred *cred) -{ - switch (cred->credtype) { - case GIT_CREDTYPE_USERNAME: - { - git_cred_username *c = (git_cred_username *) cred; - return c->username; - } - case GIT_CREDTYPE_USERPASS_PLAINTEXT: - { - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *) cred; - return c->username; - } - case GIT_CREDTYPE_SSH_KEY: - case GIT_CREDTYPE_SSH_MEMORY: - { - git_cred_ssh_key *c = (git_cred_ssh_key *) cred; - return c->username; - } - case GIT_CREDTYPE_SSH_CUSTOM: - { - git_cred_ssh_custom *c = (git_cred_ssh_custom *) cred; - return c->username; - } - case GIT_CREDTYPE_SSH_INTERACTIVE: - { - git_cred_ssh_interactive *c = (git_cred_ssh_interactive *) cred; - return c->username; - } - - default: - return NULL; - } -} - -static void plaintext_free(struct git_cred *cred) -{ - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - - git__free(c->username); - - /* Zero the memory which previously held the password */ - if (c->password) { - size_t pass_len = strlen(c->password); - git__memzero(c->password, pass_len); - git__free(c->password); - } - - git__free(c); -} - -int git_cred_userpass_plaintext_new( - git_cred **cred, - const char *username, - const char *password) -{ - git_cred_userpass_plaintext *c; - - assert(cred && username && password); - - c = git__malloc(sizeof(git_cred_userpass_plaintext)); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = GIT_CREDTYPE_USERPASS_PLAINTEXT; - c->parent.free = plaintext_free; - c->username = git__strdup(username); - - if (!c->username) { - git__free(c); - return -1; - } - - c->password = git__strdup(password); - - if (!c->password) { - git__free(c->username); - git__free(c); - return -1; - } - - *cred = &c->parent; - return 0; -} - -static void ssh_key_free(struct git_cred *cred) -{ - git_cred_ssh_key *c = - (git_cred_ssh_key *)cred; - - git__free(c->username); - - if (c->privatekey) { - /* Zero the memory which previously held the private key */ - size_t key_len = strlen(c->privatekey); - git__memzero(c->privatekey, key_len); - git__free(c->privatekey); - } - - if (c->passphrase) { - /* Zero the memory which previously held the passphrase */ - size_t pass_len = strlen(c->passphrase); - git__memzero(c->passphrase, pass_len); - git__free(c->passphrase); - } - - if (c->publickey) { - /* Zero the memory which previously held the public key */ - size_t key_len = strlen(c->publickey); - git__memzero(c->publickey, key_len); - git__free(c->publickey); - } - - git__free(c); -} - -static void ssh_interactive_free(struct git_cred *cred) -{ - git_cred_ssh_interactive *c = (git_cred_ssh_interactive *)cred; - - git__free(c->username); - - git__free(c); -} - -static void ssh_custom_free(struct git_cred *cred) -{ - git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred; - - git__free(c->username); - - if (c->publickey) { - /* Zero the memory which previously held the publickey */ - size_t key_len = strlen(c->publickey); - git__memzero(c->publickey, key_len); - git__free(c->publickey); - } - - git__free(c); -} - -static void default_free(struct git_cred *cred) -{ - git_cred_default *c = (git_cred_default *)cred; - - git__free(c); -} - -static void username_free(struct git_cred *cred) -{ - git__free(cred); -} - -int git_cred_ssh_key_new( - git_cred **cred, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ - return git_cred_ssh_key_type_new( - cred, - username, - publickey, - privatekey, - passphrase, - GIT_CREDTYPE_SSH_KEY); -} - -int git_cred_ssh_key_memory_new( - git_cred **cred, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase) -{ -#ifdef GIT_SSH_MEMORY_CREDENTIALS - return git_cred_ssh_key_type_new( - cred, - username, - publickey, - privatekey, - passphrase, - GIT_CREDTYPE_SSH_MEMORY); -#else - GIT_UNUSED(cred); - GIT_UNUSED(username); - GIT_UNUSED(publickey); - GIT_UNUSED(privatekey); - GIT_UNUSED(passphrase); - - git_error_set(GIT_ERROR_INVALID, - "this version of libgit2 was not built with ssh memory credentials."); - return -1; -#endif -} - -static int git_cred_ssh_key_type_new( - git_cred **cred, - const char *username, - const char *publickey, - const char *privatekey, - const char *passphrase, - git_credtype_t credtype) -{ - git_cred_ssh_key *c; - - assert(username && cred && privatekey); - - c = git__calloc(1, sizeof(git_cred_ssh_key)); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = credtype; - c->parent.free = ssh_key_free; - - c->username = git__strdup(username); - GIT_ERROR_CHECK_ALLOC(c->username); - - c->privatekey = git__strdup(privatekey); - GIT_ERROR_CHECK_ALLOC(c->privatekey); - - if (publickey) { - c->publickey = git__strdup(publickey); - GIT_ERROR_CHECK_ALLOC(c->publickey); - } - - if (passphrase) { - c->passphrase = git__strdup(passphrase); - GIT_ERROR_CHECK_ALLOC(c->passphrase); - } - - *cred = &c->parent; - return 0; -} - -int git_cred_ssh_interactive_new( - git_cred **out, - const char *username, - git_cred_ssh_interactive_callback prompt_callback, - void *payload) -{ - git_cred_ssh_interactive *c; - - assert(out && username && prompt_callback); - - c = git__calloc(1, sizeof(git_cred_ssh_interactive)); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = GIT_CREDTYPE_SSH_INTERACTIVE; - c->parent.free = ssh_interactive_free; - - c->username = git__strdup(username); - GIT_ERROR_CHECK_ALLOC(c->username); - - c->prompt_callback = prompt_callback; - c->payload = payload; - - *out = &c->parent; - return 0; -} - -int git_cred_ssh_key_from_agent(git_cred **cred, const char *username) { - git_cred_ssh_key *c; - - assert(username && cred); - - c = git__calloc(1, sizeof(git_cred_ssh_key)); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = GIT_CREDTYPE_SSH_KEY; - c->parent.free = ssh_key_free; - - c->username = git__strdup(username); - GIT_ERROR_CHECK_ALLOC(c->username); - - c->privatekey = NULL; - - *cred = &c->parent; - return 0; -} - -int git_cred_ssh_custom_new( - git_cred **cred, - const char *username, - const char *publickey, - size_t publickey_len, - git_cred_sign_callback sign_callback, - void *payload) -{ - git_cred_ssh_custom *c; - - assert(username && cred); - - c = git__calloc(1, sizeof(git_cred_ssh_custom)); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = GIT_CREDTYPE_SSH_CUSTOM; - c->parent.free = ssh_custom_free; - - c->username = git__strdup(username); - GIT_ERROR_CHECK_ALLOC(c->username); - - if (publickey_len > 0) { - c->publickey = git__malloc(publickey_len); - GIT_ERROR_CHECK_ALLOC(c->publickey); - - memcpy(c->publickey, publickey, publickey_len); - } - - c->publickey_len = publickey_len; - c->sign_callback = sign_callback; - c->payload = payload; - - *cred = &c->parent; - return 0; -} - -int git_cred_default_new(git_cred **cred) -{ - git_cred_default *c; - - assert(cred); - - c = git__calloc(1, sizeof(git_cred_default)); - GIT_ERROR_CHECK_ALLOC(c); - - c->credtype = GIT_CREDTYPE_DEFAULT; - c->free = default_free; - - *cred = c; - return 0; -} - -int git_cred_username_new(git_cred **cred, const char *username) -{ - git_cred_username *c; - size_t len, allocsize; - - assert(cred); - - len = strlen(username); - - GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, sizeof(git_cred_username), len); - GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, allocsize, 1); - c = git__malloc(allocsize); - GIT_ERROR_CHECK_ALLOC(c); - - c->parent.credtype = GIT_CREDTYPE_USERNAME; - c->parent.free = username_free; - memcpy(c->username, username, len + 1); - - *cred = (git_cred *) c; - return 0; -} - -void git_cred_free(git_cred *cred) -{ - if (!cred) - return; - - cred->free(cred); -} diff -Nru libgit2-0.28.5+dfsg.1/src/transports/credential.c libgit2-1.1.0+dfsg.1/src/transports/credential.c --- libgit2-0.28.5+dfsg.1/src/transports/credential.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/credential.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,478 @@ +/* + * 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 "common.h" + +#include "git2/credential.h" +#include "git2/sys/credential.h" +#include "git2/credential_helpers.h" + +static int git_credential_ssh_key_type_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credential_t credtype); + +int git_credential_has_username(git_credential *cred) +{ + if (cred->credtype == GIT_CREDENTIAL_DEFAULT) + return 0; + + return 1; +} + +const char *git_credential_get_username(git_credential *cred) +{ + switch (cred->credtype) { + case GIT_CREDENTIAL_USERNAME: + { + git_credential_username *c = (git_credential_username *) cred; + return c->username; + } + case GIT_CREDENTIAL_USERPASS_PLAINTEXT: + { + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_KEY: + case GIT_CREDENTIAL_SSH_MEMORY: + { + git_credential_ssh_key *c = (git_credential_ssh_key *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_CUSTOM: + { + git_credential_ssh_custom *c = (git_credential_ssh_custom *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_INTERACTIVE: + { + git_credential_ssh_interactive *c = (git_credential_ssh_interactive *) cred; + return c->username; + } + + default: + return NULL; + } +} + +static void plaintext_free(struct git_credential *cred) +{ + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred; + + git__free(c->username); + + /* Zero the memory which previously held the password */ + if (c->password) { + size_t pass_len = strlen(c->password); + git__memzero(c->password, pass_len); + git__free(c->password); + } + + git__free(c); +} + +int git_credential_userpass_plaintext_new( + git_credential **cred, + const char *username, + const char *password) +{ + git_credential_userpass_plaintext *c; + + assert(cred && username && password); + + c = git__malloc(sizeof(git_credential_userpass_plaintext)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_USERPASS_PLAINTEXT; + c->parent.free = plaintext_free; + c->username = git__strdup(username); + + if (!c->username) { + git__free(c); + return -1; + } + + c->password = git__strdup(password); + + if (!c->password) { + git__free(c->username); + git__free(c); + return -1; + } + + *cred = &c->parent; + return 0; +} + +static void ssh_key_free(struct git_credential *cred) +{ + git_credential_ssh_key *c = + (git_credential_ssh_key *)cred; + + git__free(c->username); + + if (c->privatekey) { + /* Zero the memory which previously held the private key */ + size_t key_len = strlen(c->privatekey); + git__memzero(c->privatekey, key_len); + git__free(c->privatekey); + } + + if (c->passphrase) { + /* Zero the memory which previously held the passphrase */ + size_t pass_len = strlen(c->passphrase); + git__memzero(c->passphrase, pass_len); + git__free(c->passphrase); + } + + if (c->publickey) { + /* Zero the memory which previously held the public key */ + size_t key_len = strlen(c->publickey); + git__memzero(c->publickey, key_len); + git__free(c->publickey); + } + + git__free(c); +} + +static void ssh_interactive_free(struct git_credential *cred) +{ + git_credential_ssh_interactive *c = (git_credential_ssh_interactive *)cred; + + git__free(c->username); + + git__free(c); +} + +static void ssh_custom_free(struct git_credential *cred) +{ + git_credential_ssh_custom *c = (git_credential_ssh_custom *)cred; + + git__free(c->username); + + if (c->publickey) { + /* Zero the memory which previously held the publickey */ + size_t key_len = strlen(c->publickey); + git__memzero(c->publickey, key_len); + git__free(c->publickey); + } + + git__free(c); +} + +static void default_free(struct git_credential *cred) +{ + git_credential_default *c = (git_credential_default *)cred; + + git__free(c); +} + +static void username_free(struct git_credential *cred) +{ + git__free(cred); +} + +int git_credential_ssh_key_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDENTIAL_SSH_KEY); +} + +int git_credential_ssh_key_memory_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ +#ifdef GIT_SSH_MEMORY_CREDENTIALS + return git_credential_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDENTIAL_SSH_MEMORY); +#else + GIT_UNUSED(cred); + GIT_UNUSED(username); + GIT_UNUSED(publickey); + GIT_UNUSED(privatekey); + GIT_UNUSED(passphrase); + + git_error_set(GIT_ERROR_INVALID, + "this version of libgit2 was not built with ssh memory credentials."); + return -1; +#endif +} + +static int git_credential_ssh_key_type_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credential_t credtype) +{ + git_credential_ssh_key *c; + + assert(username && cred && privatekey); + + c = git__calloc(1, sizeof(git_credential_ssh_key)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = credtype; + c->parent.free = ssh_key_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->privatekey = git__strdup(privatekey); + GIT_ERROR_CHECK_ALLOC(c->privatekey); + + if (publickey) { + c->publickey = git__strdup(publickey); + GIT_ERROR_CHECK_ALLOC(c->publickey); + } + + if (passphrase) { + c->passphrase = git__strdup(passphrase); + GIT_ERROR_CHECK_ALLOC(c->passphrase); + } + + *cred = &c->parent; + return 0; +} + +int git_credential_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload) +{ + git_credential_ssh_interactive *c; + + assert(out && username && prompt_callback); + + c = git__calloc(1, sizeof(git_credential_ssh_interactive)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_INTERACTIVE; + c->parent.free = ssh_interactive_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->prompt_callback = prompt_callback; + c->payload = payload; + + *out = &c->parent; + return 0; +} + +int git_credential_ssh_key_from_agent(git_credential **cred, const char *username) { + git_credential_ssh_key *c; + + assert(username && cred); + + c = git__calloc(1, sizeof(git_credential_ssh_key)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_KEY; + c->parent.free = ssh_key_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->privatekey = NULL; + + *cred = &c->parent; + return 0; +} + +int git_credential_ssh_custom_new( + git_credential **cred, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload) +{ + git_credential_ssh_custom *c; + + assert(username && cred); + + c = git__calloc(1, sizeof(git_credential_ssh_custom)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_CUSTOM; + c->parent.free = ssh_custom_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + if (publickey_len > 0) { + c->publickey = git__malloc(publickey_len); + GIT_ERROR_CHECK_ALLOC(c->publickey); + + memcpy(c->publickey, publickey, publickey_len); + } + + c->publickey_len = publickey_len; + c->sign_callback = sign_callback; + c->payload = payload; + + *cred = &c->parent; + return 0; +} + +int git_credential_default_new(git_credential **cred) +{ + git_credential_default *c; + + assert(cred); + + c = git__calloc(1, sizeof(git_credential_default)); + GIT_ERROR_CHECK_ALLOC(c); + + c->credtype = GIT_CREDENTIAL_DEFAULT; + c->free = default_free; + + *cred = c; + return 0; +} + +int git_credential_username_new(git_credential **cred, const char *username) +{ + git_credential_username *c; + size_t len, allocsize; + + assert(cred); + + len = strlen(username); + + GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, sizeof(git_credential_username), len); + GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, allocsize, 1); + c = git__malloc(allocsize); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_USERNAME; + c->parent.free = username_free; + memcpy(c->username, username, len + 1); + + *cred = (git_credential *) c; + return 0; +} + +void git_credential_free(git_credential *cred) +{ + if (!cred) + return; + + cred->free(cred); +} + +/* Deprecated credential functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_cred_has_username(git_credential *cred) +{ + return git_credential_has_username(cred); +} + +const char *git_cred_get_username(git_credential *cred) +{ + return git_credential_get_username(cred); +} + +int git_cred_userpass_plaintext_new( + git_credential **out, + const char *username, + const char *password) +{ + return git_credential_userpass_plaintext_new(out,username, password); +} + +int git_cred_default_new(git_credential **out) +{ + return git_credential_default_new(out); +} + +int git_cred_username_new(git_credential **out, const char *username) +{ + return git_credential_username_new(out, username); +} + +int git_cred_ssh_key_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_new(out, username, + publickey, privatekey, passphrase); +} + +int git_cred_ssh_key_memory_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_memory_new(out, username, + publickey, privatekey, passphrase); +} + +int git_cred_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload) +{ + return git_credential_ssh_interactive_new(out, username, + prompt_callback, payload); +} + +int git_cred_ssh_key_from_agent( + git_credential **out, + const char *username) +{ + return git_credential_ssh_key_from_agent(out, username); +} + +int git_cred_ssh_custom_new( + git_credential **out, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload) +{ + return git_credential_ssh_custom_new(out, username, + publickey, publickey_len, sign_callback, payload); +} + +void git_cred_free(git_credential *cred) +{ + git_credential_free(cred); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/transports/credential_helpers.c libgit2-1.1.0+dfsg.1/src/transports/credential_helpers.c --- libgit2-0.28.5+dfsg.1/src/transports/credential_helpers.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/credential_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * 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 "common.h" + +#include "git2/credential_helpers.h" + +int git_credential_userpass( + git_credential **cred, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload) +{ + git_credential_userpass_payload *userpass = (git_credential_userpass_payload*)payload; + const char *effective_username = NULL; + + GIT_UNUSED(url); + + if (!userpass || !userpass->password) return -1; + + /* Username resolution: a username can be passed with the URL, the + * credentials payload, or both. Here's what we do. Note that if we get + * this far, we know that any password the url may contain has already + * failed at least once, so we ignore it. + * + * | Payload | URL | Used | + * +-------------+----------+-----------+ + * | yes | no | payload | + * | yes | yes | payload | + * | no | yes | url | + * | no | no | FAIL | + */ + if (userpass->username) + effective_username = userpass->username; + else if (user_from_url) + effective_username = user_from_url; + else + return -1; + + if (GIT_CREDENTIAL_USERNAME & allowed_types) + return git_credential_username_new(cred, effective_username); + + if ((GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) == 0 || + git_credential_userpass_plaintext_new(cred, effective_username, userpass->password) < 0) + return -1; + + return 0; +} + +/* Deprecated credential functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_cred_userpass( + git_credential **out, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload) +{ + return git_credential_userpass(out, url, user_from_url, + allowed_types, payload); +} +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/transports/cred.h libgit2-1.1.0+dfsg.1/src/transports/cred.h --- libgit2-0.28.5+dfsg.1/src/transports/cred.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/cred.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +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_transports_cred_h__ -#define INCLUDE_transports_cred_h__ - -#include "common.h" - -#include "git2/transport.h" - -const char *git_cred__username(git_cred *cred); - -#endif diff -Nru libgit2-0.28.5+dfsg.1/src/transports/cred_helpers.c libgit2-1.1.0+dfsg.1/src/transports/cred_helpers.c --- libgit2-0.28.5+dfsg.1/src/transports/cred_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/cred_helpers.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +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 "common.h" - -#include "git2/cred_helpers.h" - -int git_cred_userpass( - git_cred **cred, - const char *url, - const char *user_from_url, - unsigned int allowed_types, - void *payload) -{ - git_cred_userpass_payload *userpass = (git_cred_userpass_payload*)payload; - const char *effective_username = NULL; - - GIT_UNUSED(url); - - if (!userpass || !userpass->password) return -1; - - /* Username resolution: a username can be passed with the URL, the - * credentials payload, or both. Here's what we do. Note that if we get - * this far, we know that any password the url may contain has already - * failed at least once, so we ignore it. - * - * | Payload | URL | Used | - * +-------------+----------+-----------+ - * | yes | no | payload | - * | yes | yes | payload | - * | no | yes | url | - * | no | no | FAIL | - */ - if (userpass->username) - effective_username = userpass->username; - else if (user_from_url) - effective_username = user_from_url; - else - return -1; - - if (GIT_CREDTYPE_USERNAME & allowed_types) - return git_cred_username_new(cred, effective_username); - - if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || - git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0) - return -1; - - return 0; -} diff -Nru libgit2-0.28.5+dfsg.1/src/transports/git.c libgit2-1.1.0+dfsg.1/src/transports/git.c --- libgit2-0.28.5+dfsg.1/src/transports/git.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/git.c 2020-10-12 18:53:06.000000000 +0000 @@ -192,8 +192,9 @@ const char *url, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; + git_net_url urldata = GIT_NET_URL_INIT; const char *stream_url = url; + const char *host, *port; git_proto_stream *s; int error; @@ -202,17 +203,15 @@ if (!git__prefixcmp(url, prefix_git)) stream_url += strlen(prefix_git); - if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0) + if ((error = git_net_url_parse(&urldata, url)) < 0) return error; - error = git_proto_stream_alloc(t, stream_url, cmd_uploadpack, host, port, stream); + host = urldata.host; + port = urldata.port ? urldata.port : GIT_DEFAULT_PORT; - git__free(host); - git__free(port); - git__free(path); - git__free(user); - git__free(pass); + error = git_proto_stream_alloc(t, stream_url, cmd_uploadpack, host, port, stream); + git_net_url_dispose(&urldata); if (error < 0) { git_proto_stream_free(*stream); @@ -251,7 +250,7 @@ const char *url, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; + git_net_url urldata = GIT_NET_URL_INIT; const char *stream_url = url; git_proto_stream *s; int error; @@ -260,16 +259,12 @@ if (!git__prefixcmp(url, prefix_git)) stream_url += strlen(prefix_git); - if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0) + if ((error = git_net_url_parse(&urldata, url)) < 0) return error; - error = git_proto_stream_alloc(t, stream_url, cmd_receivepack, host, port, stream); + error = git_proto_stream_alloc(t, stream_url, cmd_receivepack, urldata.host, urldata.port, stream); - git__free(host); - git__free(port); - git__free(path); - git__free(user); - git__free(pass); + git_net_url_dispose(&urldata); if (error < 0) { git_proto_stream_free(*stream); diff -Nru libgit2-0.28.5+dfsg.1/src/transports/http.c libgit2-1.1.0+dfsg.1/src/transports/http.c --- libgit2-0.28.5+dfsg.1/src/transports/http.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/http.c 2020-10-12 18:53:06.000000000 +0000 @@ -12,1363 +12,635 @@ #include "git2.h" #include "http_parser.h" #include "buffer.h" +#include "net.h" #include "netops.h" #include "global.h" #include "remote.h" +#include "git2/sys/credential.h" #include "smart.h" #include "auth.h" #include "http.h" #include "auth_negotiate.h" +#include "auth_ntlm.h" +#include "trace.h" #include "streams/tls.h" #include "streams/socket.h" +#include "httpclient.h" -git_http_auth_scheme auth_schemes[] = { - { GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate }, - { GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic }, -}; - -static const char *upload_pack_service = "upload-pack"; -static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack"; -static const char *upload_pack_service_url = "/git-upload-pack"; -static const char *receive_pack_service = "receive-pack"; -static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive-pack"; -static const char *receive_pack_service_url = "/git-receive-pack"; -static const char *get_verb = "GET"; -static const char *post_verb = "POST"; +bool git_http__expect_continue = false; -#define AUTH_HEADER_SERVER "Authorization" -#define AUTH_HEADER_PROXY "Proxy-Authorization" - -#define SERVER_TYPE_REMOTE "remote" -#define SERVER_TYPE_PROXY "proxy" - -#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport) +typedef enum { + HTTP_STATE_NONE = 0, + HTTP_STATE_SENDING_REQUEST, + HTTP_STATE_RECEIVING_RESPONSE, + HTTP_STATE_DONE +} http_state; -#define PARSE_ERROR_GENERIC -1 -#define PARSE_ERROR_REPLAY -2 -/** Look at the user field */ -#define PARSE_ERROR_EXT -3 - -#define CHUNK_SIZE 4096 - -enum last_cb { - NONE, - FIELD, - VALUE -}; +typedef struct { + git_http_method method; + const char *url; + const char *request_type; + const char *response_type; + unsigned chunked : 1; +} http_service; typedef struct { git_smart_subtransport_stream parent; - const char *service; - const char *service_url; - char *redirect_url; - const char *verb; - char *chunk_buffer; - unsigned chunk_buffer_len; - unsigned sent_request : 1, - received_response : 1, - chunked : 1; + const http_service *service; + http_state state; + unsigned replay_count; } http_stream; typedef struct { - gitno_connection_data url; - git_stream *stream; + git_net_url url; - git_cred *cred; - git_cred *url_cred; - - git_vector auth_challenges; - git_vector auth_contexts; + git_credential *cred; + unsigned auth_schemetypes; + unsigned url_cred_presented : 1; } http_server; typedef struct { git_smart_subtransport parent; transport_smart *owner; - git_stream *gitserver_stream; - bool connected; http_server server; - http_server proxy; - char *proxy_url; - git_proxy_options proxy_opts; - /* Parser structures */ - http_parser parser; - http_parser_settings settings; - gitno_buffer parse_buffer; - git_buf parse_header_name; - git_buf parse_header_value; - char parse_buffer_data[NETIO_BUFSIZE]; - char *content_type; - char *content_length; - char *location; - enum last_cb last_cb; - int parse_error; - int error; - unsigned parse_finished : 1, - replay_count : 3; + git_http_client *http_client; } http_subtransport; -typedef struct { - http_stream *s; - http_subtransport *t; +static const http_service upload_pack_ls_service = { + GIT_HTTP_METHOD_GET, "/info/refs?service=git-upload-pack", + NULL, + "application/x-git-upload-pack-advertisement", + 0 +}; +static const http_service upload_pack_service = { + GIT_HTTP_METHOD_POST, "/git-upload-pack", + "application/x-git-upload-pack-request", + "application/x-git-upload-pack-result", + 0 +}; +static const http_service receive_pack_ls_service = { + GIT_HTTP_METHOD_GET, "/info/refs?service=git-receive-pack", + NULL, + "application/x-git-receive-pack-advertisement", + 0 +}; +static const http_service receive_pack_service = { + GIT_HTTP_METHOD_POST, "/git-receive-pack", + "application/x-git-receive-pack-request", + "application/x-git-receive-pack-result", + 1 +}; - /* Target buffer details from read() */ - char *buffer; - size_t buf_size; - size_t *bytes_read; -} parser_context; +#define SERVER_TYPE_REMOTE "remote" +#define SERVER_TYPE_PROXY "proxy" + +#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport) -static bool credtype_match(git_http_auth_scheme *scheme, void *data) +static int apply_url_credentials( + git_credential **cred, + unsigned int allowed_types, + const char *username, + const char *password) { - unsigned int credtype = *(unsigned int *)data; + if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) + return git_credential_userpass_plaintext_new(cred, username, password); + + if ((allowed_types & GIT_CREDENTIAL_DEFAULT) && *username == '\0' && *password == '\0') + return git_credential_default_new(cred); - return !!(scheme->credtypes & credtype); + return GIT_PASSTHROUGH; } -static bool challenge_match(git_http_auth_scheme *scheme, void *data) +GIT_INLINE(void) free_cred(git_credential **cred) { - const char *scheme_name = scheme->name; - const char *challenge = (const char *)data; - size_t scheme_len; - - scheme_len = strlen(scheme_name); - return (strncasecmp(challenge, scheme_name, scheme_len) == 0 && - (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' ')); + if (*cred) { + git_credential_free(*cred); + (*cred) = NULL; + } } -static int auth_context_match( - git_http_auth_context **out, +static int handle_auth( http_server *server, - bool (*scheme_match)(git_http_auth_scheme *scheme, void *data), - void *data) + const char *server_type, + const char *url, + unsigned int allowed_schemetypes, + unsigned int allowed_credtypes, + git_credential_acquire_cb callback, + void *callback_payload) { - git_http_auth_scheme *scheme = NULL; - git_http_auth_context *context = NULL, *c; - size_t i; + int error = 1; - *out = NULL; + if (server->cred) + free_cred(&server->cred); - for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) { - if (scheme_match(&auth_schemes[i], data)) { - scheme = &auth_schemes[i]; - break; - } + /* Start with URL-specified credentials, if there were any. */ + if ((allowed_credtypes & GIT_CREDENTIAL_USERPASS_PLAINTEXT) && + !server->url_cred_presented && + server->url.username && + server->url.password) { + error = apply_url_credentials(&server->cred, allowed_credtypes, server->url.username, server->url.password); + server->url_cred_presented = 1; + + /* treat GIT_PASSTHROUGH as if callback isn't set */ + if (error == GIT_PASSTHROUGH) + error = 1; } - if (!scheme) - return 0; + if (error > 0 && callback) { + error = callback(&server->cred, url, server->url.username, allowed_credtypes, callback_payload); - /* See if authentication has already started for this scheme */ - git_vector_foreach(&server->auth_contexts, i, c) { - if (c->type == scheme->type) { - context = c; - break; - } + /* treat GIT_PASSTHROUGH as if callback isn't set */ + if (error == GIT_PASSTHROUGH) + error = 1; } - if (!context) { - if (scheme->init_context(&context, &server->url) < 0) - return -1; - else if (!context) - return 0; - else if (git_vector_insert(&server->auth_contexts, context) < 0) - return -1; + if (error > 0) { + git_error_set(GIT_ERROR_HTTP, "%s authentication required but no callback set", server_type); + error = -1; } - *out = context; + if (!error) + server->auth_schemetypes = allowed_schemetypes; - return 0; + return error; } -static int apply_credentials( - git_buf *buf, - http_server *server, - const char *header_name) +GIT_INLINE(int) handle_remote_auth( + http_stream *stream, + git_http_response *response) { - git_cred *cred = server->cred; - git_http_auth_context *context; - - /* Apply the credentials given to us in the URL */ - if (!cred && server->url.user && server->url.pass) { - if (!server->url_cred && - git_cred_userpass_plaintext_new(&server->url_cred, - server->url.user, server->url.pass) < 0) - return -1; + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); - cred = server->url_cred; - } - - if (!cred) - return 0; - - /* Get or create a context for the best scheme for this cred type */ - if (auth_context_match(&context, server, - credtype_match, &cred->credtype) < 0) + if (response->server_auth_credtypes == 0) { + git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support"); return -1; + } - if (!context) - return 0; - - return context->next_token(buf, context, header_name, cred); + /* Otherwise, prompt for credentials. */ + return handle_auth( + &transport->server, + SERVER_TYPE_REMOTE, + transport->owner->url, + response->server_auth_schemetypes, + response->server_auth_credtypes, + transport->owner->cred_acquire_cb, + transport->owner->cred_acquire_payload); } -static int gen_request( - git_buf *buf, - http_stream *s, - size_t content_length) +GIT_INLINE(int) handle_proxy_auth( + http_stream *stream, + git_http_response *response) { - http_subtransport *t = OWNING_SUBTRANSPORT(s); - const char *path = t->server.url.path ? t->server.url.path : "/"; - size_t i; - - if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) - git_buf_printf(buf, "%s %s://%s:%s%s%s HTTP/1.1\r\n", - s->verb, - t->server.url.use_ssl ? "https" : "http", - t->server.url.host, - t->server.url.port, - path, s->service_url); - else - git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", - s->verb, path, s->service_url); - - git_buf_puts(buf, "User-Agent: "); - git_http__user_agent(buf); - git_buf_puts(buf, "\r\n"); - git_buf_printf(buf, "Host: %s", t->server.url.host); - if (strcmp(t->server.url.port, gitno__default_port(&t->server.url)) != 0) { - git_buf_printf(buf, ":%s", t->server.url.port); - } - git_buf_puts(buf, "\r\n"); - - if (s->chunked || content_length > 0) { - git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service); - git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", s->service); - - if (s->chunked) - git_buf_puts(buf, "Transfer-Encoding: chunked\r\n"); - else - git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length); - } else - git_buf_puts(buf, "Accept: */*\r\n"); - - for (i = 0; i < t->owner->custom_headers.count; i++) { - if (t->owner->custom_headers.strings[i]) - git_buf_printf(buf, "%s\r\n", t->owner->custom_headers.strings[i]); - } - - /* Apply proxy and server credentials to the request */ - if (t->proxy_opts.type != GIT_PROXY_NONE && - apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0) - return -1; - - if (apply_credentials(buf, &t->server, AUTH_HEADER_SERVER) < 0) - return -1; + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); - git_buf_puts(buf, "\r\n"); - - if (git_buf_oom(buf)) + if (response->proxy_auth_credtypes == 0) { + git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support"); return -1; - - return 0; -} - -static int parse_authenticate_response( - http_server *server, - int *allowed_types) -{ - git_http_auth_context *context; - char *challenge; - size_t i; - - git_vector_foreach(&server->auth_challenges, i, challenge) { - if (auth_context_match(&context, server, - challenge_match, challenge) < 0) - return -1; - else if (!context) - continue; - - if (context->set_challenge && - context->set_challenge(context, challenge) < 0) - return -1; - - *allowed_types |= context->credtypes; } - return 0; + /* Otherwise, prompt for credentials. */ + return handle_auth( + &transport->proxy, + SERVER_TYPE_PROXY, + transport->owner->proxy.url, + response->server_auth_schemetypes, + response->proxy_auth_credtypes, + transport->owner->proxy.credentials, + transport->owner->proxy.payload); } -static int on_header_ready(http_subtransport *t) + +static int handle_response( + bool *complete, + http_stream *stream, + git_http_response *response, + bool allow_replay) { - git_buf *name = &t->parse_header_name; - git_buf *value = &t->parse_header_value; + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + int error; - if (!strcasecmp("Content-Type", git_buf_cstr(name))) { - if (t->content_type) { - git_error_set(GIT_ERROR_NET, "multiple Content-Type headers"); - return -1; - } + *complete = false; - t->content_type = git__strdup(git_buf_cstr(value)); - GIT_ERROR_CHECK_ALLOC(t->content_type); - } - else if (!strcasecmp("Content-Length", git_buf_cstr(name))) { - if (t->content_length) { - git_error_set(GIT_ERROR_NET, "multiple Content-Length headers"); + if (allow_replay && git_http_response_is_redirect(response)) { + if (!response->location) { + git_error_set(GIT_ERROR_HTTP, "redirect without location"); return -1; } - t->content_length = git__strdup(git_buf_cstr(value)); - GIT_ERROR_CHECK_ALLOC(t->content_length); - } - else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) { - char *dup = git__strdup(git_buf_cstr(value)); - GIT_ERROR_CHECK_ALLOC(dup); - - if (git_vector_insert(&t->proxy.auth_challenges, dup) < 0) - return -1; - } - else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) { - char *dup = git__strdup(git_buf_cstr(value)); - GIT_ERROR_CHECK_ALLOC(dup); - - if (git_vector_insert(&t->server.auth_challenges, dup) < 0) - return -1; - } - else if (!strcasecmp("Location", git_buf_cstr(name))) { - if (t->location) { - git_error_set(GIT_ERROR_NET, "multiple Location headers"); + if (git_net_url_apply_redirect(&transport->server.url, response->location, stream->service->url) < 0) { return -1; } - t->location = git__strdup(git_buf_cstr(value)); - GIT_ERROR_CHECK_ALLOC(t->location); - } - - return 0; -} - -static int on_header_field(http_parser *parser, const char *str, size_t len) -{ - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - - /* Both parse_header_name and parse_header_value are populated - * and ready for consumption */ - if (VALUE == t->last_cb) - if (on_header_ready(t) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - if (NONE == t->last_cb || VALUE == t->last_cb) - git_buf_clear(&t->parse_header_name); - - if (git_buf_put(&t->parse_header_name, str, len) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - t->last_cb = FIELD; - return 0; -} - -static int on_header_value(http_parser *parser, const char *str, size_t len) -{ - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - - assert(NONE != t->last_cb); - - if (FIELD == t->last_cb) - git_buf_clear(&t->parse_header_value); - - if (git_buf_put(&t->parse_header_value, str, len) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - t->last_cb = VALUE; - return 0; -} - -GIT_INLINE(void) free_cred(git_cred **cred) -{ - if (*cred) { - git_cred_free(*cred); - (*cred) = NULL; - } -} - -static int on_auth_required( - git_cred **creds, - http_parser *parser, - const char *url, - const char *type, - git_cred_acquire_cb callback, - void *callback_payload, - const char *username, - int allowed_types) -{ - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - int ret; - - if (!allowed_types) { - git_error_set(GIT_ERROR_NET, "%s requested authentication but did not negotiate mechanisms", type); - t->parse_error = PARSE_ERROR_GENERIC; - return t->parse_error; - } - - if (callback) { - free_cred(creds); - ret = callback(creds, url, username, allowed_types, callback_payload); - - if (ret == GIT_PASSTHROUGH) { - /* treat GIT_PASSTHROUGH as if callback isn't set */ - } else if (ret < 0) { - t->error = ret; - t->parse_error = PARSE_ERROR_EXT; - return t->parse_error; - } else { - assert(*creds); - - if (!((*creds)->credtype & allowed_types)) { - git_error_set(GIT_ERROR_NET, "%s credential provider returned an invalid cred type", type); - t->parse_error = PARSE_ERROR_GENERIC; - return t->parse_error; - } - - /* Successfully acquired a credential. */ - t->parse_error = PARSE_ERROR_REPLAY; - return 0; - } + return 0; + } else if (git_http_response_is_redirect(response)) { + git_error_set(GIT_ERROR_HTTP, "unexpected redirect"); + return -1; } - git_error_set(GIT_ERROR_NET, "%s authentication required but no callback set", - type); - t->parse_error = PARSE_ERROR_GENERIC; - return t->parse_error; -} - -static int on_headers_complete(http_parser *parser) -{ - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - http_stream *s = ctx->s; - git_buf buf = GIT_BUF_INIT; - int proxy_auth_types = 0, server_auth_types = 0; - - /* Enforce a reasonable cap on the number of replays */ - if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) { - git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays"); - return t->parse_error = PARSE_ERROR_GENERIC; - } - - /* Both parse_header_name and parse_header_value are populated - * and ready for consumption. */ - if (VALUE == t->last_cb) - if (on_header_ready(t) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - /* - * Capture authentication headers for the proxy or final endpoint, - * these may be 407/401 (authentication is not complete) or a 200 - * (informing us that auth has completed). - */ - if (parse_authenticate_response(&t->proxy, &proxy_auth_types) < 0 || - parse_authenticate_response(&t->server, &server_auth_types) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - /* Check for a proxy authentication failure. */ - if (parser->status_code == 407 && get_verb == s->verb) - return on_auth_required(&t->proxy.cred, - parser, - t->proxy_opts.url, - SERVER_TYPE_PROXY, - t->proxy_opts.credentials, - t->proxy_opts.payload, - t->proxy.url.user, - proxy_auth_types); - - /* Check for an authentication failure. */ - if (parser->status_code == 401 && get_verb == s->verb) - return on_auth_required(&t->server.cred, - parser, - t->owner->url, - SERVER_TYPE_REMOTE, - t->owner->cred_acquire_cb, - t->owner->cred_acquire_payload, - t->server.url.user, - server_auth_types); - - /* Check for a redirect. - * Right now we only permit a redirect to the same hostname. */ - if ((parser->status_code == 301 || - parser->status_code == 302 || - (parser->status_code == 303 && get_verb == s->verb) || - parser->status_code == 307 || - parser->status_code == 308) && - t->location) { - - if (gitno_connection_data_from_url(&t->server.url, t->location, s->service_url) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - /* Set the redirect URL on the stream. This is a transfer of - * ownership of the memory. */ - if (s->redirect_url) - git__free(s->redirect_url); + /* If we're in the middle of challenge/response auth, continue. */ + if (allow_replay && response->resend_credentials) { + return 0; + } else if (allow_replay && response->status == GIT_HTTP_STATUS_UNAUTHORIZED) { + if ((error = handle_remote_auth(stream, response)) < 0) + return error; - s->redirect_url = t->location; - t->location = NULL; + return git_http_client_skip_body(transport->http_client); + } else if (allow_replay && response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) { + if ((error = handle_proxy_auth(stream, response)) < 0) + return error; - t->connected = 0; - t->parse_error = PARSE_ERROR_REPLAY; - return 0; + return git_http_client_skip_body(transport->http_client); + } else if (response->status == GIT_HTTP_STATUS_UNAUTHORIZED || + response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) { + git_error_set(GIT_ERROR_HTTP, "unexpected authentication failure"); + return -1; } - /* Check for a 200 HTTP status code. */ - if (parser->status_code != 200) { - git_error_set(GIT_ERROR_NET, - "unexpected HTTP status code: %d", - parser->status_code); - return t->parse_error = PARSE_ERROR_GENERIC; + if (response->status != GIT_HTTP_STATUS_OK) { + git_error_set(GIT_ERROR_HTTP, "unexpected http status code: %d", response->status); + return -1; } /* The response must contain a Content-Type header. */ - if (!t->content_type) { - git_error_set(GIT_ERROR_NET, "no Content-Type header in response"); - return t->parse_error = PARSE_ERROR_GENERIC; + if (!response->content_type) { + git_error_set(GIT_ERROR_HTTP, "no content-type header in response"); + return -1; } /* The Content-Type header must match our expectation. */ - if (get_verb == s->verb) - git_buf_printf(&buf, - "application/x-git-%s-advertisement", - ctx->s->service); - else - git_buf_printf(&buf, - "application/x-git-%s-result", - ctx->s->service); - - if (git_buf_oom(&buf)) - return t->parse_error = PARSE_ERROR_GENERIC; - - if (strcmp(t->content_type, git_buf_cstr(&buf))) { - git_buf_dispose(&buf); - git_error_set(GIT_ERROR_NET, - "invalid Content-Type: %s", - t->content_type); - return t->parse_error = PARSE_ERROR_GENERIC; + if (strcmp(response->content_type, stream->service->response_type) != 0) { + git_error_set(GIT_ERROR_HTTP, "invalid content-type: '%s'", response->content_type); + return -1; } - git_buf_dispose(&buf); - + *complete = true; + stream->state = HTTP_STATE_RECEIVING_RESPONSE; return 0; } -static int on_message_complete(http_parser *parser) +static int lookup_proxy( + bool *out_use, + http_subtransport *transport) { - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; + const char *proxy; + git_remote *remote; + bool use_ssl; + char *config = NULL; + int error = 0; - t->parse_finished = 1; - - return 0; -} + *out_use = false; + git_net_url_dispose(&transport->proxy.url); -static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len) -{ - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - - /* If our goal is to replay the request (either an auth failure or - * a redirect) then don't bother buffering since we're ignoring the - * content anyway. - */ - if (t->parse_error == PARSE_ERROR_REPLAY) - return 0; - - /* If there's no buffer set, we're explicitly ignoring the body. */ - if (ctx->buffer) { - if (ctx->buf_size < len) { - git_error_set(GIT_ERROR_NET, "can't fit data in the buffer"); - return t->parse_error = PARSE_ERROR_GENERIC; - } - - memcpy(ctx->buffer, str, len); - ctx->buffer += len; - ctx->buf_size -= len; - } - - *(ctx->bytes_read) += len; - - return 0; -} + switch (transport->owner->proxy.type) { + case GIT_PROXY_SPECIFIED: + proxy = transport->owner->proxy.url; + break; -static void clear_parser_state(http_subtransport *t) -{ - http_parser_init(&t->parser, HTTP_RESPONSE); - gitno_buffer_setup_fromstream(t->server.stream, - &t->parse_buffer, - t->parse_buffer_data, - sizeof(t->parse_buffer_data)); + case GIT_PROXY_AUTO: + remote = transport->owner->owner; + use_ssl = !strcmp(transport->server.url.scheme, "https"); - t->last_cb = NONE; - t->parse_error = 0; - t->parse_finished = 0; + error = git_remote__get_http_proxy(remote, use_ssl, &config); - git_buf_dispose(&t->parse_header_name); - git_buf_init(&t->parse_header_name, 0); + if (error || !config) + goto done; - git_buf_dispose(&t->parse_header_value); - git_buf_init(&t->parse_header_value, 0); + proxy = config; + break; - git__free(t->content_type); - t->content_type = NULL; + default: + return 0; + } - git__free(t->content_length); - t->content_length = NULL; + if (!proxy || + (error = git_net_url_parse(&transport->proxy.url, proxy)) < 0) + goto done; - git__free(t->location); - t->location = NULL; + *out_use = true; - git_vector_free_deep(&t->proxy.auth_challenges); - git_vector_free_deep(&t->server.auth_challenges); +done: + git__free(config); + return error; } -static int write_chunk(git_stream *io, const char *buffer, size_t len) +static int generate_request( + git_net_url *url, + git_http_request *request, + http_stream *stream, + size_t len) { - git_buf buf = GIT_BUF_INIT; - - /* Chunk header */ - git_buf_printf(&buf, "%" PRIxZ "\r\n", len); + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + bool use_proxy = false; + int error; - if (git_buf_oom(&buf)) - return -1; + if ((error = git_net_url_joinpath(url, + &transport->server.url, stream->service->url)) < 0 || + (error = lookup_proxy(&use_proxy, transport)) < 0) + return error; - if (git_stream__write_full(io, buf.ptr, buf.size, 0) < 0) { - git_buf_dispose(&buf); - return -1; + request->method = stream->service->method; + request->url = url; + request->credentials = transport->server.cred; + request->proxy = use_proxy ? &transport->proxy.url : NULL; + request->proxy_credentials = transport->proxy.cred; + request->custom_headers = &transport->owner->custom_headers; + + if (stream->service->method == GIT_HTTP_METHOD_POST) { + request->chunked = stream->service->chunked; + request->content_length = stream->service->chunked ? 0 : len; + request->content_type = stream->service->request_type; + request->accept = stream->service->response_type; + request->expect_continue = git_http__expect_continue; } - git_buf_dispose(&buf); - - /* Chunk body */ - if (len > 0 && git_stream__write_full(io, buffer, len, 0) < 0) - return -1; - - /* Chunk footer */ - if (git_stream__write_full(io, "\r\n", 2, 0) < 0) - return -1; - return 0; } -static int load_proxy_config(http_subtransport *t) +/* + * Read from an HTTP transport - for the first invocation of this function + * (ie, when stream->state == HTTP_STATE_NONE), we'll send a GET request + * to the remote host. We will stream that data back on all subsequent + * calls. + */ +static int http_stream_read( + git_smart_subtransport_stream *s, + char *buffer, + size_t buffer_size, + size_t *out_len) { + http_stream *stream = (http_stream *)s; + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + git_net_url url = GIT_NET_URL_INIT; + git_net_url proxy_url = GIT_NET_URL_INIT; + git_http_request request = {0}; + git_http_response response = {0}; + bool complete; int error; - switch (t->owner->proxy.type) { - case GIT_PROXY_NONE: - return 0; - - case GIT_PROXY_AUTO: - git__free(t->proxy_url); - t->proxy_url = NULL; - - git_proxy_init_options(&t->proxy_opts, GIT_PROXY_OPTIONS_VERSION); - - if ((error = git_remote__get_http_proxy(t->owner->owner, - !!t->server.url.use_ssl, &t->proxy_url)) < 0) - return error; + *out_len = 0; - if (!t->proxy_url) - return 0; + if (stream->state == HTTP_STATE_NONE) { + stream->state = HTTP_STATE_SENDING_REQUEST; + stream->replay_count = 0; + } - t->proxy_opts.type = GIT_PROXY_SPECIFIED; - t->proxy_opts.url = t->proxy_url; - t->proxy_opts.credentials = t->owner->proxy.credentials; - t->proxy_opts.certificate_check = t->owner->proxy.certificate_check; - t->proxy_opts.payload = t->owner->proxy.payload; - break; + /* + * Formulate the URL, send the request and read the response + * headers. Some of the request body may also be read. + */ + while (stream->state == HTTP_STATE_SENDING_REQUEST && + stream->replay_count < GIT_HTTP_REPLAY_MAX) { + git_net_url_dispose(&url); + git_net_url_dispose(&proxy_url); + git_http_response_dispose(&response); + + if ((error = generate_request(&url, &request, stream, 0)) < 0 || + (error = git_http_client_send_request( + transport->http_client, &request)) < 0 || + (error = git_http_client_read_response( + &response, transport->http_client)) < 0 || + (error = handle_response(&complete, stream, &response, true)) < 0) + goto done; - case GIT_PROXY_SPECIFIED: - memcpy(&t->proxy_opts, &t->owner->proxy, sizeof(git_proxy_options)); - break; + if (complete) + break; - default: - assert(0); - return -1; + stream->replay_count++; } - if ((error = gitno_connection_data_from_url(&t->proxy.url, t->proxy_opts.url, NULL)) < 0) - return error; - - if (t->proxy.url.use_ssl) { - git_error_set(GIT_ERROR_NET, "SSL connections to proxy are not supported"); - return -1; + if (stream->state == HTTP_STATE_SENDING_REQUEST) { + git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays"); + error = -1; + goto done; } - return error; -} + assert (stream->state == HTTP_STATE_RECEIVING_RESPONSE); -static int check_certificate( - git_stream *stream, - gitno_connection_data *url, - int is_valid, - git_transport_certificate_check_cb cert_cb, - void *cert_cb_payload) -{ - git_cert *cert; - git_error_state last_error = {0}; - int error; - - if ((error = git_stream_certificate(&cert, stream)) < 0) - return error; + error = git_http_client_read_body(transport->http_client, buffer, buffer_size); - git_error_state_capture(&last_error, GIT_ECERTIFICATE); - - error = cert_cb(cert, is_valid, url->host, cert_cb_payload); - - if (error == GIT_PASSTHROUGH && !is_valid) - return git_error_state_restore(&last_error); - else if (error == GIT_PASSTHROUGH) + if (error > 0) { + *out_len = error; error = 0; - else if (error && !git_error_last()) - git_error_set(GIT_ERROR_NET, "user rejected certificate for %s", url->host); - - git_error_state_free(&last_error); - return error; -} - -static int stream_connect( - git_stream *stream, - gitno_connection_data *url, - git_transport_certificate_check_cb cert_cb, - void *cb_payload) -{ - int error; - - GIT_ERROR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream"); - - error = git_stream_connect(stream); - - if (error && error != GIT_ECERTIFICATE) - return error; + } - if (git_stream_is_encrypted(stream) && cert_cb != NULL) - error = check_certificate(stream, url, !error, cert_cb, cb_payload); +done: + git_net_url_dispose(&url); + git_net_url_dispose(&proxy_url); + git_http_response_dispose(&response); return error; } -static int gen_connect_req(git_buf *buf, http_subtransport *t) +static bool needs_probe(http_stream *stream) { - git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n", - t->server.url.host, t->server.url.port); - - git_buf_puts(buf, "User-Agent: "); - git_http__user_agent(buf); - git_buf_puts(buf, "\r\n"); - - git_buf_printf(buf, "Host: %s\r\n", t->proxy.url.host); + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); - if (apply_credentials(buf, &t->proxy, AUTH_HEADER_PROXY) < 0) - return -1; - - git_buf_puts(buf, "\r\n"); - - return git_buf_oom(buf) ? -1 : 0; + return (transport->server.auth_schemetypes == GIT_HTTP_AUTH_NTLM || + transport->server.auth_schemetypes == GIT_HTTP_AUTH_NEGOTIATE); } -static int proxy_headers_complete(http_parser *parser) +static int send_probe(http_stream *stream) { - parser_context *ctx = (parser_context *) parser->data; - http_subtransport *t = ctx->t; - int proxy_auth_types = 0; - - /* Enforce a reasonable cap on the number of replays */ - if (t->replay_count++ >= GIT_HTTP_REPLAY_MAX) { - git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays"); - return t->parse_error = PARSE_ERROR_GENERIC; - } + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + git_http_client *client = transport->http_client; + const char *probe = "0000"; + size_t len = 4; + git_net_url url = GIT_NET_URL_INIT; + git_http_request request = {0}; + git_http_response response = {0}; + bool complete = false; + size_t step, steps = 1; + int error; - /* Both parse_header_name and parse_header_value are populated - * and ready for consumption. */ - if (VALUE == t->last_cb) - if (on_header_ready(t) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; + /* NTLM requires a full challenge/response */ + if (transport->server.auth_schemetypes == GIT_HTTP_AUTH_NTLM) + steps = GIT_AUTH_STEPS_NTLM; /* - * Capture authentication headers for the proxy or final endpoint, - * these may be 407/401 (authentication is not complete) or a 200 - * (informing us that auth has completed). + * Send at most two requests: one without any authentication to see + * if we get prompted to authenticate. If we do, send a second one + * with the first authentication message. The final authentication + * message with the response will occur with the *actual* POST data. */ - if (parse_authenticate_response(&t->proxy, &proxy_auth_types) < 0) - return t->parse_error = PARSE_ERROR_GENERIC; - - /* Check for a proxy authentication failure. */ - if (parser->status_code == 407) - return on_auth_required(&t->proxy.cred, - parser, - t->proxy_opts.url, - SERVER_TYPE_PROXY, - t->proxy_opts.credentials, - t->proxy_opts.payload, - t->proxy.url.user, - proxy_auth_types); - - if (parser->status_code != 200) { - git_error_set(GIT_ERROR_NET, "unexpected status code from proxy: %d", - parser->status_code); - return t->parse_error = PARSE_ERROR_GENERIC; + for (step = 0; step < steps && !complete; step++) { + git_net_url_dispose(&url); + git_http_response_dispose(&response); + + if ((error = generate_request(&url, &request, stream, len)) < 0 || + (error = git_http_client_send_request(client, &request)) < 0 || + (error = git_http_client_send_body(client, probe, len)) < 0 || + (error = git_http_client_read_response(&response, client)) < 0 || + (error = git_http_client_skip_body(client)) < 0 || + (error = handle_response(&complete, stream, &response, true)) < 0) + goto done; } - if (!t->content_length || strcmp(t->content_length, "0") == 0) - t->parse_finished = 1; - - return 0; +done: + git_http_response_dispose(&response); + git_net_url_dispose(&url); + return error; } -static int proxy_connect( - git_stream **out, git_stream *proxy_stream, http_subtransport *t) +/* +* Write to an HTTP transport - for the first invocation of this function +* (ie, when stream->state == HTTP_STATE_NONE), we'll send a POST request +* to the remote host. If we're sending chunked data, then subsequent calls +* will write the additional data given in the buffer. If we're not chunking, +* then the caller should have given us all the data in the original call. +* The caller should call http_stream_read_response to get the result. +*/ +static int http_stream_write( + git_smart_subtransport_stream *s, + const char *buffer, + size_t len) { - git_buf request = GIT_BUF_INIT; - static http_parser_settings proxy_parser_settings = {0}; - size_t bytes_read = 0, bytes_parsed; - parser_context ctx; + http_stream *stream = GIT_CONTAINER_OF(s, http_stream, parent); + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + git_net_url url = GIT_NET_URL_INIT; + git_http_request request = {0}; + git_http_response response = {0}; int error; - /* Use the parser settings only to parser headers. */ - proxy_parser_settings.on_header_field = on_header_field; - proxy_parser_settings.on_header_value = on_header_value; - proxy_parser_settings.on_headers_complete = proxy_headers_complete; - proxy_parser_settings.on_message_complete = on_message_complete; - -replay: - clear_parser_state(t); - - gitno_buffer_setup_fromstream(proxy_stream, - &t->parse_buffer, - t->parse_buffer_data, - sizeof(t->parse_buffer_data)); + while (stream->state == HTTP_STATE_NONE && + stream->replay_count < GIT_HTTP_REPLAY_MAX) { - if ((error = gen_connect_req(&request, t)) < 0) - goto done; - - if ((error = git_stream__write_full(proxy_stream, request.ptr, - request.size, 0)) < 0) - goto done; - - git_buf_dispose(&request); - - while (!bytes_read && !t->parse_finished) { - t->parse_buffer.offset = 0; - - if ((error = gitno_recv(&t->parse_buffer)) < 0) - goto done; + git_net_url_dispose(&url); + git_http_response_dispose(&response); /* - * This call to http_parser_execute will invoke the on_* - * callbacks. Since we don't care about the body of the response, - * we can set our buffer to NULL. + * If we're authenticating with a connection-based mechanism + * (NTLM, Kerberos), send a "probe" packet. Servers SHOULD + * authenticate an entire keep-alive connection, so ideally + * we should not need to authenticate but some servers do + * not support this. By sending a probe packet, we'll be + * able to follow up with a second POST using the actual + * data (and, in the degenerate case, the authentication + * header as well). */ - ctx.t = t; - ctx.s = NULL; - ctx.buffer = NULL; - ctx.buf_size = 0; - ctx.bytes_read = &bytes_read; - - /* Set the context, call the parser, then unset the context. */ - t->parser.data = &ctx; - - bytes_parsed = http_parser_execute(&t->parser, - &proxy_parser_settings, t->parse_buffer.data, t->parse_buffer.offset); - - t->parser.data = NULL; - - /* Ensure that we didn't get a redirect; unsupported. */ - if (t->location) { - git_error_set(GIT_ERROR_NET, "proxy server sent unsupported redirect during CONNECT"); - error = -1; + if (needs_probe(stream) && (error = send_probe(stream)) < 0) goto done; - } - - /* Replay the request with authentication headers. */ - if (PARSE_ERROR_REPLAY == t->parse_error) - goto replay; - if (t->parse_error < 0) { - error = t->parse_error == PARSE_ERROR_EXT ? PARSE_ERROR_EXT : -1; + /* Send the regular POST request. */ + if ((error = generate_request(&url, &request, stream, len)) < 0 || + (error = git_http_client_send_request( + transport->http_client, &request)) < 0) goto done; - } - if (bytes_parsed != t->parse_buffer.offset) { - git_error_set(GIT_ERROR_NET, - "HTTP parser error: %s", - http_errno_description((enum http_errno)t->parser.http_errno)); - error = -1; - goto done; + if (request.expect_continue && + git_http_client_has_response(transport->http_client)) { + bool complete; + + /* + * If we got a response to an expect/continue, then + * it's something other than a 100 and we should + * deal with the response somehow. + */ + if ((error = git_http_client_read_response(&response, transport->http_client)) < 0 || + (error = handle_response(&complete, stream, &response, true)) < 0) + goto done; + } else { + stream->state = HTTP_STATE_SENDING_REQUEST; } - } - - if ((error = git_tls_stream_wrap(out, proxy_stream, t->server.url.host)) == 0) - error = stream_connect(*out, &t->server.url, - t->owner->certificate_check_cb, - t->owner->message_cb_payload); - - /* - * Since we've connected via a HTTPS proxy tunnel, we don't behave - * as if we have an HTTP proxy. - */ - t->proxy_opts.type = GIT_PROXY_NONE; - t->replay_count = 0; - -done: - return error; -} - -static int http_connect(http_subtransport *t) -{ - gitno_connection_data *url; - git_stream *proxy_stream = NULL, *stream = NULL; - git_transport_certificate_check_cb cert_cb; - void *cb_payload; - int error; - - if (t->connected && - http_should_keep_alive(&t->parser) && - t->parse_finished) - return 0; - - if ((error = load_proxy_config(t)) < 0) - return error; - - if (t->server.stream) { - git_stream_close(t->server.stream); - git_stream_free(t->server.stream); - t->server.stream = NULL; - } - if (t->proxy.stream) { - git_stream_close(t->proxy.stream); - git_stream_free(t->proxy.stream); - t->proxy.stream = NULL; - } - - t->connected = 0; - - if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) { - url = &t->proxy.url; - cert_cb = t->proxy_opts.certificate_check; - cb_payload = t->proxy_opts.payload; - } else { - url = &t->server.url; - cert_cb = t->owner->certificate_check_cb; - cb_payload = t->owner->message_cb_payload; + stream->replay_count++; } - if (url->use_ssl) - error = git_tls_stream_new(&stream, url->host, url->port); - else - error = git_socket_stream_new(&stream, url->host, url->port); - - if (error < 0) - goto on_error; - - if ((error = stream_connect(stream, url, cert_cb, cb_payload)) < 0) - goto on_error; - - /* - * At this point we have a connection to the remote server or to - * a proxy. If it's a proxy and the remote server is actually - * an HTTPS connection, then we need to build a CONNECT tunnel. - */ - if (t->proxy_opts.type == GIT_PROXY_SPECIFIED && - t->server.url.use_ssl) { - proxy_stream = stream; - stream = NULL; - - if ((error = proxy_connect(&stream, proxy_stream, t)) < 0) - goto on_error; + if (stream->state == HTTP_STATE_NONE) { + git_error_set(GIT_ERROR_HTTP, + "too many redirects or authentication replays"); + error = -1; + goto done; } - t->proxy.stream = proxy_stream; - t->server.stream = stream; - t->connected = 1; - t->replay_count = 0; - return 0; + assert(stream->state == HTTP_STATE_SENDING_REQUEST); -on_error: - if (stream) { - git_stream_close(stream); - git_stream_free(stream); - } - - if (proxy_stream) { - git_stream_close(proxy_stream); - git_stream_free(proxy_stream); - } + error = git_http_client_send_body(transport->http_client, buffer, len); +done: + git_http_response_dispose(&response); + git_net_url_dispose(&url); return error; } -static int http_stream_read( - git_smart_subtransport_stream *stream, +/* +* Read from an HTTP transport after it has been written to. This is the +* response from a POST request made by http_stream_write. +*/ +static int http_stream_read_response( + git_smart_subtransport_stream *s, char *buffer, - size_t buf_size, - size_t *bytes_read) + size_t buffer_size, + size_t *out_len) { - http_stream *s = (http_stream *)stream; - http_subtransport *t = OWNING_SUBTRANSPORT(s); - parser_context ctx; - size_t bytes_parsed; - -replay: - *bytes_read = 0; - - assert(t->connected); - - if (!s->sent_request) { - git_buf request = GIT_BUF_INIT; - - clear_parser_state(t); - - if (gen_request(&request, s, 0) < 0) - return -1; - - if (git_stream__write_full(t->server.stream, request.ptr, - request.size, 0) < 0) { - git_buf_dispose(&request); - return -1; - } - - git_buf_dispose(&request); - - s->sent_request = 1; - } - - if (!s->received_response) { - if (s->chunked) { - assert(s->verb == post_verb); - - /* Flush, if necessary */ - if (s->chunk_buffer_len > 0 && - write_chunk(t->server.stream, - s->chunk_buffer, s->chunk_buffer_len) < 0) - return -1; - - s->chunk_buffer_len = 0; - - /* Write the final chunk. */ - if (git_stream__write_full(t->server.stream, - "0\r\n\r\n", 5, 0) < 0) - return -1; - } - - s->received_response = 1; - } - - while (!*bytes_read && !t->parse_finished) { - size_t data_offset; - int error; - - /* - * Make the parse_buffer think it's as full of data as - * the buffer, so it won't try to recv more data than - * we can put into it. - * - * data_offset is the actual data offset from which we - * should tell the parser to start reading. - */ - if (buf_size >= t->parse_buffer.len) { - t->parse_buffer.offset = 0; - } else { - t->parse_buffer.offset = t->parse_buffer.len - buf_size; - } - - data_offset = t->parse_buffer.offset; - - if (gitno_recv(&t->parse_buffer) < 0) - return -1; - - /* This call to http_parser_execute will result in invocations of the - * on_* family of callbacks. The most interesting of these is - * on_body_fill_buffer, which is called when data is ready to be copied - * into the target buffer. We need to marshal the buffer, buf_size, and - * bytes_read parameters to this callback. */ - ctx.t = t; - ctx.s = s; - ctx.buffer = buffer; - ctx.buf_size = buf_size; - ctx.bytes_read = bytes_read; - - /* Set the context, call the parser, then unset the context. */ - t->parser.data = &ctx; - - bytes_parsed = http_parser_execute(&t->parser, - &t->settings, - t->parse_buffer.data + data_offset, - t->parse_buffer.offset - data_offset); - - t->parser.data = NULL; - - /* If there was a handled authentication failure, then parse_error - * will have signaled us that we should replay the request. */ - if (PARSE_ERROR_REPLAY == t->parse_error) { - s->sent_request = 0; - - if ((error = http_connect(t)) < 0) - return error; - - goto replay; - } - - if (t->parse_error == PARSE_ERROR_EXT) { - return t->error; - } - - if (t->parse_error < 0) - return -1; - - if (bytes_parsed != t->parse_buffer.offset - data_offset) { - git_error_set(GIT_ERROR_NET, - "HTTP parser error: %s", - http_errno_description((enum http_errno)t->parser.http_errno)); - return -1; - } - } - - return 0; -} - -static int http_stream_write_chunked( - git_smart_subtransport_stream *stream, - const char *buffer, - size_t len) -{ - http_stream *s = (http_stream *)stream; - http_subtransport *t = OWNING_SUBTRANSPORT(s); - - assert(t->connected); - - /* Send the request, if necessary */ - if (!s->sent_request) { - git_buf request = GIT_BUF_INIT; - - clear_parser_state(t); - - if (gen_request(&request, s, 0) < 0) - return -1; - - if (git_stream__write_full(t->server.stream, request.ptr, - request.size, 0) < 0) { - git_buf_dispose(&request); - return -1; - } - - git_buf_dispose(&request); - - s->sent_request = 1; - } + http_stream *stream = (http_stream *)s; + http_subtransport *transport = OWNING_SUBTRANSPORT(stream); + git_http_client *client = transport->http_client; + git_http_response response = {0}; + bool complete; + int error; - if (len > CHUNK_SIZE) { - /* Flush, if necessary */ - if (s->chunk_buffer_len > 0) { - if (write_chunk(t->server.stream, - s->chunk_buffer, s->chunk_buffer_len) < 0) - return -1; + *out_len = 0; - s->chunk_buffer_len = 0; - } + if (stream->state == HTTP_STATE_SENDING_REQUEST) { + if ((error = git_http_client_read_response(&response, client)) < 0 || + (error = handle_response(&complete, stream, &response, false)) < 0) + goto done; - /* Write chunk directly */ - if (write_chunk(t->server.stream, buffer, len) < 0) - return -1; - } - else { - /* Append as much to the buffer as we can */ - int count = min(CHUNK_SIZE - s->chunk_buffer_len, len); - - if (!s->chunk_buffer) - s->chunk_buffer = git__malloc(CHUNK_SIZE); - - memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count); - s->chunk_buffer_len += count; - buffer += count; - len -= count; - - /* Is the buffer full? If so, then flush */ - if (CHUNK_SIZE == s->chunk_buffer_len) { - if (write_chunk(t->server.stream, - s->chunk_buffer, s->chunk_buffer_len) < 0) - return -1; - - s->chunk_buffer_len = 0; - - if (len > 0) { - memcpy(s->chunk_buffer, buffer, len); - s->chunk_buffer_len = len; - } - } + assert(complete); + stream->state = HTTP_STATE_RECEIVING_RESPONSE; } - return 0; -} + error = git_http_client_read_body(client, buffer, buffer_size); -static int http_stream_write_single( - git_smart_subtransport_stream *stream, - const char *buffer, - size_t len) -{ - http_stream *s = (http_stream *)stream; - http_subtransport *t = OWNING_SUBTRANSPORT(s); - git_buf request = GIT_BUF_INIT; - - assert(t->connected); - - if (s->sent_request) { - git_error_set(GIT_ERROR_NET, "subtransport configured for only one write"); - return -1; + if (error > 0) { + *out_len = error; + error = 0; } - clear_parser_state(t); - - if (gen_request(&request, s, len) < 0) - return -1; - - if (git_stream__write_full(t->server.stream, request.ptr, request.size, 0) < 0) - goto on_error; - - if (len && git_stream__write_full(t->server.stream, buffer, len, 0) < 0) - goto on_error; - - git_buf_dispose(&request); - s->sent_request = 1; - - return 0; - -on_error: - git_buf_dispose(&request); - return -1; +done: + git_http_response_dispose(&response); + return error; } static void http_stream_free(git_smart_subtransport_stream *stream) { - http_stream *s = (http_stream *)stream; - - if (s->chunk_buffer) - git__free(s->chunk_buffer); - - if (s->redirect_url) - git__free(s->redirect_url); - + http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent); git__free(s); } -static int http_stream_alloc(http_subtransport *t, - git_smart_subtransport_stream **stream) -{ - http_stream *s; - - if (!stream) - return -1; - - s = git__calloc(sizeof(http_stream), 1); - GIT_ERROR_CHECK_ALLOC(s); - - s->parent.subtransport = &t->parent; - s->parent.read = http_stream_read; - s->parent.write = http_stream_write_single; - s->parent.free = http_stream_free; - - *stream = (git_smart_subtransport_stream *)s; - return 0; -} - -static int http_uploadpack_ls( - http_subtransport *t, - git_smart_subtransport_stream **stream) -{ - http_stream *s; - - if (http_stream_alloc(t, stream) < 0) - return -1; - - s = (http_stream *)*stream; - - s->service = upload_pack_service; - s->service_url = upload_pack_ls_service_url; - s->verb = get_verb; - - return 0; -} - -static int http_uploadpack( - http_subtransport *t, - git_smart_subtransport_stream **stream) -{ - http_stream *s; - - if (http_stream_alloc(t, stream) < 0) - return -1; - - s = (http_stream *)*stream; - - s->service = upload_pack_service; - s->service_url = upload_pack_service_url; - s->verb = post_verb; - - return 0; -} - -static int http_receivepack_ls( - http_subtransport *t, - git_smart_subtransport_stream **stream) -{ - http_stream *s; - - if (http_stream_alloc(t, stream) < 0) - return -1; - - s = (http_stream *)*stream; - - s->service = receive_pack_service; - s->service_url = receive_pack_ls_service_url; - s->verb = get_verb; - - return 0; -} - -static int http_receivepack( - http_subtransport *t, - git_smart_subtransport_stream **stream) +static const http_service *select_service(git_smart_service_t action) { - http_stream *s; - - if (http_stream_alloc(t, stream) < 0) - return -1; - - s = (http_stream *)*stream; - - /* Use Transfer-Encoding: chunked for this request */ - s->chunked = 1; - s->parent.write = http_stream_write_chunked; - - s->service = receive_pack_service; - s->service_url = receive_pack_service_url; - s->verb = post_verb; + switch (action) { + case GIT_SERVICE_UPLOADPACK_LS: + return &upload_pack_ls_service; + case GIT_SERVICE_UPLOADPACK: + return &upload_pack_service; + case GIT_SERVICE_RECEIVEPACK_LS: + return &receive_pack_ls_service; + case GIT_SERVICE_RECEIVEPACK: + return &receive_pack_service; + } - return 0; + return NULL; } static int http_action( - git_smart_subtransport_stream **stream, - git_smart_subtransport *subtransport, + git_smart_subtransport_stream **out, + git_smart_subtransport *t, const char *url, git_smart_service_t action) { - http_subtransport *t = (http_subtransport *)subtransport; - int ret; + http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent); + http_stream *stream; + const http_service *service; + int error; - assert(stream); + assert(out && t); + + *out = NULL; /* * If we've seen a redirect then preserve the location that we've @@ -1377,121 +649,89 @@ * have redirected us from HTTP->HTTPS and is using an auth mechanism * that would be insecure in plaintext (eg, HTTP Basic). */ - if ((!t->server.url.host || !t->server.url.port || !t->server.url.path) && - (ret = gitno_connection_data_from_url(&t->server.url, url, NULL)) < 0) - return ret; + if (!git_net_url_valid(&transport->server.url) && + (error = git_net_url_parse(&transport->server.url, url)) < 0) + return error; - assert(t->server.url.host && t->server.url.port && t->server.url.path); + if ((service = select_service(action)) == NULL) { + git_error_set(GIT_ERROR_HTTP, "invalid action"); + return -1; + } - if ((ret = http_connect(t)) < 0) - return ret; + stream = git__calloc(sizeof(http_stream), 1); + GIT_ERROR_CHECK_ALLOC(stream); - switch (action) { - case GIT_SERVICE_UPLOADPACK_LS: - return http_uploadpack_ls(t, stream); + if (!transport->http_client) { + git_http_client_options opts = {0}; - case GIT_SERVICE_UPLOADPACK: - return http_uploadpack(t, stream); + opts.server_certificate_check_cb = transport->owner->certificate_check_cb; + opts.server_certificate_check_payload = transport->owner->message_cb_payload; + opts.proxy_certificate_check_cb = transport->owner->proxy.certificate_check; + opts.proxy_certificate_check_payload = transport->owner->proxy.payload; - case GIT_SERVICE_RECEIVEPACK_LS: - return http_receivepack_ls(t, stream); - - case GIT_SERVICE_RECEIVEPACK: - return http_receivepack(t, stream); + if (git_http_client_new(&transport->http_client, &opts) < 0) + return -1; } - *stream = NULL; - return -1; -} - -static void free_auth_contexts(git_vector *contexts) -{ - git_http_auth_context *context; - size_t i; + stream->service = service; + stream->parent.subtransport = &transport->parent; - git_vector_foreach(contexts, i, context) { - if (context->free) - context->free(context); + if (service->method == GIT_HTTP_METHOD_GET) { + stream->parent.read = http_stream_read; + } else { + stream->parent.write = http_stream_write; + stream->parent.read = http_stream_read_response; } - git_vector_clear(contexts); + stream->parent.free = http_stream_free; + + *out = (git_smart_subtransport_stream *)stream; + return 0; } -static int http_close(git_smart_subtransport *subtransport) +static int http_close(git_smart_subtransport *t) { - http_subtransport *t = (http_subtransport *) subtransport; + http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent); - clear_parser_state(t); + free_cred(&transport->server.cred); + free_cred(&transport->proxy.cred); - t->connected = 0; + transport->server.url_cred_presented = false; + transport->proxy.url_cred_presented = false; - if (t->server.stream) { - git_stream_close(t->server.stream); - git_stream_free(t->server.stream); - t->server.stream = NULL; - } - - if (t->proxy.stream) { - git_stream_close(t->proxy.stream); - git_stream_free(t->proxy.stream); - t->proxy.stream = NULL; - } - - free_cred(&t->server.cred); - free_cred(&t->server.url_cred); - free_cred(&t->proxy.cred); - free_cred(&t->proxy.url_cred); - - free_auth_contexts(&t->server.auth_contexts); - free_auth_contexts(&t->proxy.auth_contexts); - - gitno_connection_data_free_ptrs(&t->server.url); - memset(&t->server.url, 0x0, sizeof(gitno_connection_data)); - - gitno_connection_data_free_ptrs(&t->proxy.url); - memset(&t->proxy.url, 0x0, sizeof(gitno_connection_data)); - - git__free(t->proxy_url); - t->proxy_url = NULL; + git_net_url_dispose(&transport->server.url); + git_net_url_dispose(&transport->proxy.url); return 0; } -static void http_free(git_smart_subtransport *subtransport) +static void http_free(git_smart_subtransport *t) { - http_subtransport *t = (http_subtransport *) subtransport; + http_subtransport *transport = GIT_CONTAINER_OF(t, http_subtransport, parent); - http_close(subtransport); + git_http_client_free(transport->http_client); - git_vector_free(&t->server.auth_contexts); - git_vector_free(&t->proxy.auth_contexts); - git__free(t); + http_close(t); + git__free(transport); } int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner, void *param) { - http_subtransport *t; + http_subtransport *transport; GIT_UNUSED(param); - if (!out) - return -1; + assert(out); - t = git__calloc(sizeof(http_subtransport), 1); - GIT_ERROR_CHECK_ALLOC(t); + transport = git__calloc(sizeof(http_subtransport), 1); + GIT_ERROR_CHECK_ALLOC(transport); - t->owner = (transport_smart *)owner; - t->parent.action = http_action; - t->parent.close = http_close; - t->parent.free = http_free; - - t->settings.on_header_field = on_header_field; - t->settings.on_header_value = on_header_value; - t->settings.on_headers_complete = on_headers_complete; - t->settings.on_body = on_body_fill_buffer; - t->settings.on_message_complete = on_message_complete; + transport->owner = (transport_smart *)owner; + transport->parent.action = http_action; + transport->parent.close = http_close; + transport->parent.free = http_free; - *out = (git_smart_subtransport *) t; + *out = (git_smart_subtransport *) transport; return 0; } diff -Nru libgit2-0.28.5+dfsg.1/src/transports/httpclient.c libgit2-1.1.0+dfsg.1/src/transports/httpclient.c --- libgit2-0.28.5+dfsg.1/src/transports/httpclient.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/httpclient.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,1547 @@ +/* + * 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 "common.h" +#include "git2.h" +#include "http_parser.h" +#include "vector.h" +#include "trace.h" +#include "global.h" +#include "httpclient.h" +#include "http.h" +#include "auth.h" +#include "auth_negotiate.h" +#include "auth_ntlm.h" +#include "git2/sys/credential.h" +#include "net.h" +#include "stream.h" +#include "streams/socket.h" +#include "streams/tls.h" +#include "auth.h" + +static git_http_auth_scheme auth_schemes[] = { + { GIT_HTTP_AUTH_NEGOTIATE, "Negotiate", GIT_CREDENTIAL_DEFAULT, git_http_auth_negotiate }, + { GIT_HTTP_AUTH_NTLM, "NTLM", GIT_CREDENTIAL_USERPASS_PLAINTEXT, git_http_auth_ntlm }, + { GIT_HTTP_AUTH_BASIC, "Basic", GIT_CREDENTIAL_USERPASS_PLAINTEXT, git_http_auth_basic }, +}; + +/* + * Use a 16kb read buffer to match the maximum size of a TLS packet. This + * is critical for compatibility with SecureTransport, which will always do + * a network read on every call, even if it has data buffered to return to + * you. That buffered data may be the _end_ of a keep-alive response, so + * if SecureTransport performs another network read, it will wait until the + * server ultimately times out before it returns that buffered data to you. + * Since SecureTransport only reads a single TLS packet at a time, by + * calling it with a read buffer that is the maximum size of a TLS packet, + * we ensure that it will never buffer. + */ +#define GIT_READ_BUFFER_SIZE (16 * 1024) + +typedef struct { + git_net_url url; + git_stream *stream; + + git_vector auth_challenges; + git_http_auth_context *auth_context; +} git_http_server; + +typedef enum { + PROXY = 1, + SERVER +} git_http_server_t; + +typedef enum { + NONE = 0, + SENDING_REQUEST, + SENDING_BODY, + SENT_REQUEST, + HAS_EARLY_RESPONSE, + READING_RESPONSE, + READING_BODY, + DONE +} http_client_state; + +/* Parser state */ +typedef enum { + PARSE_HEADER_NONE = 0, + PARSE_HEADER_NAME, + PARSE_HEADER_VALUE, + PARSE_HEADER_COMPLETE +} parse_header_state; + +typedef enum { + PARSE_STATUS_OK, + PARSE_STATUS_NO_OUTPUT, + PARSE_STATUS_ERROR +} parse_status; + +typedef struct { + git_http_client *client; + git_http_response *response; + + /* Temporary buffers to avoid extra mallocs */ + git_buf parse_header_name; + git_buf parse_header_value; + + /* Parser state */ + int error; + parse_status parse_status; + + /* Headers parsing */ + parse_header_state parse_header_state; + + /* Body parsing */ + char *output_buf; /* Caller's output buffer */ + size_t output_size; /* Size of caller's output buffer */ + size_t output_written; /* Bytes we've written to output buffer */ +} http_parser_context; + +/* HTTP client connection */ +struct git_http_client { + git_http_client_options opts; + + /* Are we writing to the proxy or server, and state of the client. */ + git_http_server_t current_server; + http_client_state state; + + http_parser parser; + + git_http_server server; + git_http_server proxy; + + unsigned request_count; + unsigned connected : 1, + proxy_connected : 1, + keepalive : 1, + request_chunked : 1; + + /* Temporary buffers to avoid extra mallocs */ + git_buf request_msg; + git_buf read_buf; + + /* A subset of information from the request */ + size_t request_body_len, + request_body_remain; + + /* + * When state == HAS_EARLY_RESPONSE, the response of our proxy + * that we have buffered and will deliver during read_response. + */ + git_http_response early_response; +}; + +bool git_http_response_is_redirect(git_http_response *response) +{ + return (response->status == GIT_HTTP_MOVED_PERMANENTLY || + response->status == GIT_HTTP_FOUND || + response->status == GIT_HTTP_SEE_OTHER || + response->status == GIT_HTTP_TEMPORARY_REDIRECT || + response->status == GIT_HTTP_PERMANENT_REDIRECT); +} + +void git_http_response_dispose(git_http_response *response) +{ + assert(response); + + git__free(response->content_type); + git__free(response->location); + + memset(response, 0, sizeof(git_http_response)); +} + +static int on_header_complete(http_parser *parser) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + git_http_client *client = ctx->client; + git_http_response *response = ctx->response; + + git_buf *name = &ctx->parse_header_name; + git_buf *value = &ctx->parse_header_value; + + if (!strcasecmp("Content-Type", name->ptr)) { + if (response->content_type) { + git_error_set(GIT_ERROR_HTTP, + "multiple content-type headers"); + return -1; + } + + response->content_type = + git__strndup(value->ptr, value->size); + GIT_ERROR_CHECK_ALLOC(ctx->response->content_type); + } else if (!strcasecmp("Content-Length", name->ptr)) { + int64_t len; + + if (response->content_length) { + git_error_set(GIT_ERROR_HTTP, + "multiple content-length headers"); + return -1; + } + + if (git__strntol64(&len, value->ptr, value->size, + NULL, 10) < 0 || len < 0) { + git_error_set(GIT_ERROR_HTTP, + "invalid content-length"); + return -1; + } + + response->content_length = (size_t)len; + } else if (!strcasecmp("Transfer-Encoding", name->ptr) && + !strcasecmp("chunked", value->ptr)) { + ctx->response->chunked = 1; + } else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) { + char *dup = git__strndup(value->ptr, value->size); + GIT_ERROR_CHECK_ALLOC(dup); + + if (git_vector_insert(&client->proxy.auth_challenges, dup) < 0) + return -1; + } else if (!strcasecmp("WWW-Authenticate", name->ptr)) { + char *dup = git__strndup(value->ptr, value->size); + GIT_ERROR_CHECK_ALLOC(dup); + + if (git_vector_insert(&client->server.auth_challenges, dup) < 0) + return -1; + } else if (!strcasecmp("Location", name->ptr)) { + if (response->location) { + git_error_set(GIT_ERROR_HTTP, + "multiple location headers"); + return -1; + } + + response->location = git__strndup(value->ptr, value->size); + GIT_ERROR_CHECK_ALLOC(response->location); + } + + return 0; +} + +static int on_header_field(http_parser *parser, const char *str, size_t len) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + + switch (ctx->parse_header_state) { + /* + * We last saw a header value, process the name/value pair and + * get ready to handle this new name. + */ + case PARSE_HEADER_VALUE: + if (on_header_complete(parser) < 0) + return ctx->parse_status = PARSE_STATUS_ERROR; + + git_buf_clear(&ctx->parse_header_name); + git_buf_clear(&ctx->parse_header_value); + /* Fall through */ + + case PARSE_HEADER_NONE: + case PARSE_HEADER_NAME: + ctx->parse_header_state = PARSE_HEADER_NAME; + + if (git_buf_put(&ctx->parse_header_name, str, len) < 0) + return ctx->parse_status = PARSE_STATUS_ERROR; + + break; + + default: + git_error_set(GIT_ERROR_HTTP, + "header name seen at unexpected time"); + return ctx->parse_status = PARSE_STATUS_ERROR; + } + + return 0; +} + +static int on_header_value(http_parser *parser, const char *str, size_t len) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + + switch (ctx->parse_header_state) { + case PARSE_HEADER_NAME: + case PARSE_HEADER_VALUE: + ctx->parse_header_state = PARSE_HEADER_VALUE; + + if (git_buf_put(&ctx->parse_header_value, str, len) < 0) + return ctx->parse_status = PARSE_STATUS_ERROR; + + break; + + default: + git_error_set(GIT_ERROR_HTTP, + "header value seen at unexpected time"); + return ctx->parse_status = PARSE_STATUS_ERROR; + } + + return 0; +} + +GIT_INLINE(bool) challenge_matches_scheme( + const char *challenge, + git_http_auth_scheme *scheme) +{ + const char *scheme_name = scheme->name; + size_t scheme_len = strlen(scheme_name); + + if (!strncasecmp(challenge, scheme_name, scheme_len) && + (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' ')) + return true; + + return false; +} + +static git_http_auth_scheme *scheme_for_challenge(const char *challenge) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) { + if (challenge_matches_scheme(challenge, &auth_schemes[i])) + return &auth_schemes[i]; + } + + return NULL; +} + +GIT_INLINE(void) collect_authinfo( + unsigned int *schemetypes, + unsigned int *credtypes, + git_vector *challenges) +{ + git_http_auth_scheme *scheme; + const char *challenge; + size_t i; + + *schemetypes = 0; + *credtypes = 0; + + git_vector_foreach(challenges, i, challenge) { + if ((scheme = scheme_for_challenge(challenge)) != NULL) { + *schemetypes |= scheme->type; + *credtypes |= scheme->credtypes; + } + } +} + +static int resend_needed(git_http_client *client, git_http_response *response) +{ + git_http_auth_context *auth_context; + + if (response->status == GIT_HTTP_STATUS_UNAUTHORIZED && + (auth_context = client->server.auth_context) && + auth_context->is_complete && + !auth_context->is_complete(auth_context)) + return 1; + + if (response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED && + (auth_context = client->proxy.auth_context) && + auth_context->is_complete && + !auth_context->is_complete(auth_context)) + return 1; + + return 0; +} + +static int on_headers_complete(http_parser *parser) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + + /* Finalize the last seen header */ + switch (ctx->parse_header_state) { + case PARSE_HEADER_VALUE: + if (on_header_complete(parser) < 0) + return ctx->parse_status = PARSE_STATUS_ERROR; + + /* Fall through */ + + case PARSE_HEADER_NONE: + ctx->parse_header_state = PARSE_HEADER_COMPLETE; + break; + + default: + git_error_set(GIT_ERROR_HTTP, + "header completion at unexpected time"); + return ctx->parse_status = PARSE_STATUS_ERROR; + } + + ctx->response->status = parser->status_code; + ctx->client->keepalive = http_should_keep_alive(parser); + + /* Prepare for authentication */ + collect_authinfo(&ctx->response->server_auth_schemetypes, + &ctx->response->server_auth_credtypes, + &ctx->client->server.auth_challenges); + collect_authinfo(&ctx->response->proxy_auth_schemetypes, + &ctx->response->proxy_auth_credtypes, + &ctx->client->proxy.auth_challenges); + + ctx->response->resend_credentials = resend_needed(ctx->client, + ctx->response); + + /* Stop parsing. */ + http_parser_pause(parser, 1); + + if (ctx->response->content_type || ctx->response->chunked) + ctx->client->state = READING_BODY; + else + ctx->client->state = DONE; + + return 0; +} + +static int on_body(http_parser *parser, const char *buf, size_t len) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + size_t max_len; + + /* Saw data when we expected not to (eg, in consume_response_body) */ + if (ctx->output_buf == NULL && ctx->output_size == 0) { + ctx->parse_status = PARSE_STATUS_NO_OUTPUT; + return 0; + } + + assert(ctx->output_size >= ctx->output_written); + + max_len = min(ctx->output_size - ctx->output_written, len); + max_len = min(max_len, INT_MAX); + + memcpy(ctx->output_buf + ctx->output_written, buf, max_len); + ctx->output_written += max_len; + + return 0; +} + +static int on_message_complete(http_parser *parser) +{ + http_parser_context *ctx = (http_parser_context *) parser->data; + + ctx->client->state = DONE; + return 0; +} + +GIT_INLINE(int) stream_write( + git_http_server *server, + const char *data, + size_t len) +{ + git_trace(GIT_TRACE_TRACE, + "Sending request:\n%.*s", (int)len, data); + + return git_stream__write_full(server->stream, data, len, 0); +} + +GIT_INLINE(int) client_write_request(git_http_client *client) +{ + git_stream *stream = client->current_server == PROXY ? + client->proxy.stream : client->server.stream; + + git_trace(GIT_TRACE_TRACE, + "Sending request:\n%.*s", + (int)client->request_msg.size, client->request_msg.ptr); + + return git_stream__write_full(stream, + client->request_msg.ptr, + client->request_msg.size, + 0); +} + +static const char *name_for_method(git_http_method method) +{ + switch (method) { + case GIT_HTTP_METHOD_GET: + return "GET"; + case GIT_HTTP_METHOD_POST: + return "POST"; + case GIT_HTTP_METHOD_CONNECT: + return "CONNECT"; + } + + return NULL; +} + +/* + * Find the scheme that is suitable for the given credentials, based on the + * server's auth challenges. + */ +static bool best_scheme_and_challenge( + git_http_auth_scheme **scheme_out, + const char **challenge_out, + git_vector *challenges, + git_credential *credentials) +{ + const char *challenge; + size_t i, j; + + for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) { + git_vector_foreach(challenges, j, challenge) { + git_http_auth_scheme *scheme = &auth_schemes[i]; + + if (challenge_matches_scheme(challenge, scheme) && + (scheme->credtypes & credentials->credtype)) { + *scheme_out = scheme; + *challenge_out = challenge; + return true; + } + } + } + + return false; +} + +/* + * Find the challenge from the server for our current auth context. + */ +static const char *challenge_for_context( + git_vector *challenges, + git_http_auth_context *auth_ctx) +{ + const char *challenge; + size_t i, j; + + for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) { + if (auth_schemes[i].type == auth_ctx->type) { + git_http_auth_scheme *scheme = &auth_schemes[i]; + + git_vector_foreach(challenges, j, challenge) { + if (challenge_matches_scheme(challenge, scheme)) + return challenge; + } + } + } + + return NULL; +} + +static const char *init_auth_context( + git_http_server *server, + git_vector *challenges, + git_credential *credentials) +{ + git_http_auth_scheme *scheme; + const char *challenge; + int error; + + if (!best_scheme_and_challenge(&scheme, &challenge, challenges, credentials)) { + git_error_set(GIT_ERROR_HTTP, "could not find appropriate mechanism for credentials"); + return NULL; + } + + error = scheme->init_context(&server->auth_context, &server->url); + + if (error == GIT_PASSTHROUGH) { + git_error_set(GIT_ERROR_HTTP, "'%s' authentication is not supported", scheme->name); + return NULL; + } + + return challenge; +} + +static void free_auth_context(git_http_server *server) +{ + if (!server->auth_context) + return; + + if (server->auth_context->free) + server->auth_context->free(server->auth_context); + + server->auth_context = NULL; +} + +static int apply_credentials( + git_buf *buf, + git_http_server *server, + const char *header_name, + git_credential *credentials) +{ + git_http_auth_context *auth = server->auth_context; + git_vector *challenges = &server->auth_challenges; + const char *challenge; + git_buf token = GIT_BUF_INIT; + int error = 0; + + /* We've started a new request without creds; free the context. */ + if (auth && !credentials) { + free_auth_context(server); + return 0; + } + + /* We haven't authenticated, nor were we asked to. Nothing to do. */ + if (!auth && !git_vector_length(challenges)) + return 0; + + if (!auth) { + challenge = init_auth_context(server, challenges, credentials); + auth = server->auth_context; + + if (!challenge || !auth) { + error = -1; + goto done; + } + } else if (auth->set_challenge) { + challenge = challenge_for_context(challenges, auth); + } + + if (auth->set_challenge && challenge && + (error = auth->set_challenge(auth, challenge)) < 0) + goto done; + + if ((error = auth->next_token(&token, auth, credentials)) < 0) + goto done; + + if (auth->is_complete && auth->is_complete(auth)) { + /* + * If we're done with an auth mechanism with connection affinity, + * we don't need to send any more headers and can dispose the context. + */ + if (auth->connection_affinity) + free_auth_context(server); + } else if (!token.size) { + git_error_set(GIT_ERROR_HTTP, "failed to respond to authentication challenge"); + error = -1; + goto done; + } + + if (token.size > 0) + error = git_buf_printf(buf, "%s: %s\r\n", header_name, token.ptr); + +done: + git_buf_dispose(&token); + return error; +} + +GIT_INLINE(int) apply_server_credentials( + git_buf *buf, + git_http_client *client, + git_http_request *request) +{ + return apply_credentials(buf, + &client->server, + "Authorization", + request->credentials); +} + +GIT_INLINE(int) apply_proxy_credentials( + git_buf *buf, + git_http_client *client, + git_http_request *request) +{ + return apply_credentials(buf, + &client->proxy, + "Proxy-Authorization", + request->proxy_credentials); +} + +static int generate_connect_request( + git_http_client *client, + git_http_request *request) +{ + git_buf *buf; + int error; + + git_buf_clear(&client->request_msg); + buf = &client->request_msg; + + git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n", + client->server.url.host, client->server.url.port); + + git_buf_puts(buf, "User-Agent: "); + git_http__user_agent(buf); + git_buf_puts(buf, "\r\n"); + + git_buf_printf(buf, "Host: %s\r\n", client->proxy.url.host); + + if ((error = apply_proxy_credentials(buf, client, request) < 0)) + return -1; + + git_buf_puts(buf, "\r\n"); + + return git_buf_oom(buf) ? -1 : 0; +} + +static int generate_request( + git_http_client *client, + git_http_request *request) +{ + git_buf *buf; + size_t i; + int error; + + assert(client && request); + + git_buf_clear(&client->request_msg); + buf = &client->request_msg; + + /* GET|POST path HTTP/1.1 */ + git_buf_puts(buf, name_for_method(request->method)); + git_buf_putc(buf, ' '); + + if (request->proxy && strcmp(request->url->scheme, "https")) + git_net_url_fmt(buf, request->url); + else + git_net_url_fmt_path(buf, request->url); + + git_buf_puts(buf, " HTTP/1.1\r\n"); + + git_buf_puts(buf, "User-Agent: "); + git_http__user_agent(buf); + git_buf_puts(buf, "\r\n"); + + git_buf_printf(buf, "Host: %s", request->url->host); + + if (!git_net_url_is_default_port(request->url)) + git_buf_printf(buf, ":%s", request->url->port); + + git_buf_puts(buf, "\r\n"); + + if (request->accept) + git_buf_printf(buf, "Accept: %s\r\n", request->accept); + else + git_buf_puts(buf, "Accept: */*\r\n"); + + if (request->content_type) + git_buf_printf(buf, "Content-Type: %s\r\n", + request->content_type); + + if (request->chunked) + git_buf_puts(buf, "Transfer-Encoding: chunked\r\n"); + + if (request->content_length > 0) + git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", + request->content_length); + + if (request->expect_continue) + git_buf_printf(buf, "Expect: 100-continue\r\n"); + + if ((error = apply_server_credentials(buf, client, request)) < 0 || + (error = apply_proxy_credentials(buf, client, request)) < 0) + return error; + + if (request->custom_headers) { + for (i = 0; i < request->custom_headers->count; i++) { + const char *hdr = request->custom_headers->strings[i]; + + if (hdr) + git_buf_printf(buf, "%s\r\n", hdr); + } + } + + git_buf_puts(buf, "\r\n"); + + if (git_buf_oom(buf)) + return -1; + + return 0; +} + +static int check_certificate( + git_stream *stream, + git_net_url *url, + int is_valid, + git_transport_certificate_check_cb cert_cb, + void *cert_cb_payload) +{ + git_cert *cert; + git_error_state last_error = {0}; + int error; + + if ((error = git_stream_certificate(&cert, stream)) < 0) + return error; + + git_error_state_capture(&last_error, GIT_ECERTIFICATE); + + error = cert_cb(cert, is_valid, url->host, cert_cb_payload); + + if (error == GIT_PASSTHROUGH && !is_valid) + return git_error_state_restore(&last_error); + else if (error == GIT_PASSTHROUGH) + error = 0; + else if (error && !git_error_last()) + git_error_set(GIT_ERROR_HTTP, + "user rejected certificate for %s", url->host); + + git_error_state_free(&last_error); + return error; +} + +static int server_connect_stream( + git_http_server *server, + git_transport_certificate_check_cb cert_cb, + void *cb_payload) +{ + int error; + + GIT_ERROR_CHECK_VERSION(server->stream, GIT_STREAM_VERSION, "git_stream"); + + error = git_stream_connect(server->stream); + + if (error && error != GIT_ECERTIFICATE) + return error; + + if (git_stream_is_encrypted(server->stream) && cert_cb != NULL) + error = check_certificate(server->stream, &server->url, !error, + cert_cb, cb_payload); + + return error; +} + +static void reset_auth_connection(git_http_server *server) +{ + /* + * If we've authenticated and we're doing "normal" + * authentication with a request affinity (Basic, Digest) + * then we want to _keep_ our context, since authentication + * survives even through non-keep-alive connections. If + * we've authenticated and we're doing connection-based + * authentication (NTLM, Negotiate) - indicated by the presence + * of an `is_complete` callback - then we need to restart + * authentication on a new connection. + */ + + if (server->auth_context && + server->auth_context->connection_affinity) + free_auth_context(server); +} + +/* + * Updates the server data structure with the new URL; returns 1 if the server + * has changed and we need to reconnect, returns 0 otherwise. + */ +GIT_INLINE(int) server_setup_from_url( + git_http_server *server, + git_net_url *url) +{ + if (!server->url.scheme || strcmp(server->url.scheme, url->scheme) || + !server->url.host || strcmp(server->url.host, url->host) || + !server->url.port || strcmp(server->url.port, url->port)) { + git__free(server->url.scheme); + git__free(server->url.host); + git__free(server->url.port); + + server->url.scheme = git__strdup(url->scheme); + GIT_ERROR_CHECK_ALLOC(server->url.scheme); + + server->url.host = git__strdup(url->host); + GIT_ERROR_CHECK_ALLOC(server->url.host); + + server->url.port = git__strdup(url->port); + GIT_ERROR_CHECK_ALLOC(server->url.port); + + return 1; + } + + return 0; +} + +static void reset_parser(git_http_client *client) +{ + http_parser_init(&client->parser, HTTP_RESPONSE); +} + +static int setup_hosts( + git_http_client *client, + git_http_request *request) +{ + int ret, diff = 0; + + assert(client && request && request->url); + + if ((ret = server_setup_from_url(&client->server, request->url)) < 0) + return ret; + + diff |= ret; + + if (request->proxy && + (ret = server_setup_from_url(&client->proxy, request->proxy)) < 0) + return ret; + + diff |= ret; + + if (diff) { + free_auth_context(&client->server); + free_auth_context(&client->proxy); + + client->connected = 0; + } + + return 0; +} + +GIT_INLINE(int) server_create_stream(git_http_server *server) +{ + git_net_url *url = &server->url; + + if (strcasecmp(url->scheme, "https") == 0) + return git_tls_stream_new(&server->stream, url->host, url->port); + else if (strcasecmp(url->scheme, "http") == 0) + return git_socket_stream_new(&server->stream, url->host, url->port); + + git_error_set(GIT_ERROR_HTTP, "unknown http scheme '%s'", url->scheme); + return -1; +} + +GIT_INLINE(void) save_early_response( + git_http_client *client, + git_http_response *response) +{ + /* Buffer the response so we can return it in read_response */ + client->state = HAS_EARLY_RESPONSE; + + memcpy(&client->early_response, response, sizeof(git_http_response)); + memset(response, 0, sizeof(git_http_response)); +} + +static int proxy_connect( + git_http_client *client, + git_http_request *request) +{ + git_http_response response = {0}; + int error; + + if (!client->proxy_connected || !client->keepalive) { + git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s:%s", + client->proxy.url.host, client->proxy.url.port); + + if ((error = server_create_stream(&client->proxy)) < 0 || + (error = server_connect_stream(&client->proxy, + client->opts.proxy_certificate_check_cb, + client->opts.proxy_certificate_check_payload)) < 0) + goto done; + + client->proxy_connected = 1; + } + + client->current_server = PROXY; + client->state = SENDING_REQUEST; + + if ((error = generate_connect_request(client, request)) < 0 || + (error = client_write_request(client)) < 0) + goto done; + + client->state = SENT_REQUEST; + + if ((error = git_http_client_read_response(&response, client)) < 0 || + (error = git_http_client_skip_body(client)) < 0) + goto done; + + assert(client->state == DONE); + + if (response.status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) { + save_early_response(client, &response); + + error = GIT_RETRY; + goto done; + } else if (response.status != GIT_HTTP_STATUS_OK) { + git_error_set(GIT_ERROR_HTTP, "proxy returned unexpected status: %d", response.status); + error = -1; + goto done; + } + + reset_parser(client); + client->state = NONE; + +done: + git_http_response_dispose(&response); + return error; +} + +static int server_connect(git_http_client *client) +{ + git_net_url *url = &client->server.url; + git_transport_certificate_check_cb cert_cb; + void *cert_payload; + int error; + + client->current_server = SERVER; + + if (client->proxy.stream) + error = git_tls_stream_wrap(&client->server.stream, client->proxy.stream, url->host); + else + error = server_create_stream(&client->server); + + if (error < 0) + goto done; + + cert_cb = client->opts.server_certificate_check_cb; + cert_payload = client->opts.server_certificate_check_payload; + + error = server_connect_stream(&client->server, cert_cb, cert_payload); + +done: + return error; +} + +GIT_INLINE(void) close_stream(git_http_server *server) +{ + if (server->stream) { + git_stream_close(server->stream); + git_stream_free(server->stream); + server->stream = NULL; + } +} + +static int http_client_connect( + git_http_client *client, + git_http_request *request) +{ + bool use_proxy = false; + int error; + + if ((error = setup_hosts(client, request)) < 0) + goto on_error; + + /* We're connected to our destination server; no need to reconnect */ + if (client->connected && client->keepalive && + (client->state == NONE || client->state == DONE)) + return 0; + + client->connected = 0; + client->request_count = 0; + + close_stream(&client->server); + reset_auth_connection(&client->server); + + reset_parser(client); + + /* Reconnect to the proxy if necessary. */ + use_proxy = client->proxy.url.host && + !strcmp(client->server.url.scheme, "https"); + + if (use_proxy) { + if (!client->proxy_connected || !client->keepalive || + (client->state != NONE && client->state != DONE)) { + close_stream(&client->proxy); + reset_auth_connection(&client->proxy); + + client->proxy_connected = 0; + } + + if ((error = proxy_connect(client, request)) < 0) + goto on_error; + } + + git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s:%s", + client->server.url.host, client->server.url.port); + + if ((error = server_connect(client)) < 0) + goto on_error; + + client->connected = 1; + return error; + +on_error: + if (error != GIT_RETRY) + close_stream(&client->proxy); + + close_stream(&client->server); + return error; +} + +GIT_INLINE(int) client_read(git_http_client *client) +{ + http_parser_context *parser_context = client->parser.data; + git_stream *stream; + char *buf = client->read_buf.ptr + client->read_buf.size; + size_t max_len; + ssize_t read_len; + + stream = client->current_server == PROXY ? + client->proxy.stream : client->server.stream; + + /* + * We use a git_buf for convenience, but statically allocate it and + * don't resize. Limit our consumption to INT_MAX since calling + * functions use an int return type to return number of bytes read. + */ + max_len = client->read_buf.asize - client->read_buf.size; + max_len = min(max_len, INT_MAX); + + if (parser_context->output_size) + max_len = min(max_len, parser_context->output_size); + + if (max_len == 0) { + git_error_set(GIT_ERROR_HTTP, "no room in output buffer"); + return -1; + } + + read_len = git_stream_read(stream, buf, max_len); + + if (read_len >= 0) { + client->read_buf.size += read_len; + + git_trace(GIT_TRACE_TRACE, "Received:\n%.*s", + (int)read_len, buf); + } + + return (int)read_len; +} + +static bool parser_settings_initialized; +static http_parser_settings parser_settings; + +GIT_INLINE(http_parser_settings *) http_client_parser_settings(void) +{ + if (!parser_settings_initialized) { + parser_settings.on_header_field = on_header_field; + parser_settings.on_header_value = on_header_value; + parser_settings.on_headers_complete = on_headers_complete; + parser_settings.on_body = on_body; + parser_settings.on_message_complete = on_message_complete; + + parser_settings_initialized = true; + } + + return &parser_settings; +} + +GIT_INLINE(int) client_read_and_parse(git_http_client *client) +{ + http_parser *parser = &client->parser; + http_parser_context *ctx = (http_parser_context *) parser->data; + unsigned char http_errno; + int read_len; + size_t parsed_len; + + /* + * If we have data in our read buffer, that means we stopped early + * when parsing headers. Use the data in the read buffer instead of + * reading more from the socket. + */ + if (!client->read_buf.size && (read_len = client_read(client)) < 0) + return read_len; + + parsed_len = http_parser_execute(parser, + http_client_parser_settings(), + client->read_buf.ptr, + client->read_buf.size); + http_errno = client->parser.http_errno; + + if (parsed_len > INT_MAX) { + git_error_set(GIT_ERROR_HTTP, "unexpectedly large parse"); + return -1; + } + + if (ctx->parse_status == PARSE_STATUS_ERROR) { + client->connected = 0; + return ctx->error ? ctx->error : -1; + } + + /* + * If we finished reading the headers or body, we paused parsing. + * Otherwise the parser will start filling the body, or even parse + * a new response if the server pipelined us multiple responses. + * (This can happen in response to an expect/continue request, + * where the server gives you a 100 and 200 simultaneously.) + */ + if (http_errno == HPE_PAUSED) { + /* + * http-parser has a "feature" where it will not deliver the + * final byte when paused in a callback. Consume that byte. + * https://github.com/nodejs/http-parser/issues/97 + */ + assert(client->read_buf.size > parsed_len); + + http_parser_pause(parser, 0); + + parsed_len += http_parser_execute(parser, + http_client_parser_settings(), + client->read_buf.ptr + parsed_len, + 1); + } + + /* Most failures will be reported in http_errno */ + else if (parser->http_errno != HPE_OK) { + git_error_set(GIT_ERROR_HTTP, "http parser error: %s", + http_errno_description(http_errno)); + return -1; + } + + /* Otherwise we should have consumed the entire buffer. */ + else if (parsed_len != client->read_buf.size) { + git_error_set(GIT_ERROR_HTTP, + "http parser did not consume entire buffer: %s", + http_errno_description(http_errno)); + return -1; + } + + /* recv returned 0, the server hung up on us */ + else if (!parsed_len) { + git_error_set(GIT_ERROR_HTTP, "unexpected EOF"); + return -1; + } + + git_buf_consume_bytes(&client->read_buf, parsed_len); + + return (int)parsed_len; +} + +/* + * See if we've consumed the entire response body. If the client was + * reading the body but did not consume it entirely, it's possible that + * they knew that the stream had finished (in a git response, seeing a + * final flush) and stopped reading. But if the response was chunked, + * we may have not consumed the final chunk marker. Consume it to + * ensure that we don't have it waiting in our socket. If there's + * more than just a chunk marker, close the connection. + */ +static void complete_response_body(git_http_client *client) +{ + http_parser_context parser_context = {0}; + + /* If we're not keeping alive, don't bother. */ + if (!client->keepalive) { + client->connected = 0; + goto done; + } + + parser_context.client = client; + client->parser.data = &parser_context; + + /* If there was an error, just close the connection. */ + if (client_read_and_parse(client) < 0 || + parser_context.error != HPE_OK || + (parser_context.parse_status != PARSE_STATUS_OK && + parser_context.parse_status != PARSE_STATUS_NO_OUTPUT)) { + git_error_clear(); + client->connected = 0; + } + +done: + git_buf_clear(&client->read_buf); +} + +int git_http_client_send_request( + git_http_client *client, + git_http_request *request) +{ + git_http_response response = {0}; + int error = -1; + + assert(client && request); + + /* If the client did not finish reading, clean up the stream. */ + if (client->state == READING_BODY) + complete_response_body(client); + + /* If we're waiting for proxy auth, don't sending more requests. */ + if (client->state == HAS_EARLY_RESPONSE) + return 0; + + if (git_trace_level() >= GIT_TRACE_DEBUG) { + git_buf url = GIT_BUF_INIT; + git_net_url_fmt(&url, request->url); + git_trace(GIT_TRACE_DEBUG, "Sending %s request to %s", + name_for_method(request->method), + url.ptr ? url.ptr : ""); + git_buf_dispose(&url); + } + + if ((error = http_client_connect(client, request)) < 0 || + (error = generate_request(client, request)) < 0 || + (error = client_write_request(client)) < 0) + goto done; + + client->state = SENT_REQUEST; + + if (request->expect_continue) { + if ((error = git_http_client_read_response(&response, client)) < 0 || + (error = git_http_client_skip_body(client)) < 0) + goto done; + + error = 0; + + if (response.status != GIT_HTTP_STATUS_CONTINUE) { + save_early_response(client, &response); + goto done; + } + } + + if (request->content_length || request->chunked) { + client->state = SENDING_BODY; + client->request_body_len = request->content_length; + client->request_body_remain = request->content_length; + client->request_chunked = request->chunked; + } + + reset_parser(client); + +done: + if (error == GIT_RETRY) + error = 0; + + git_http_response_dispose(&response); + return error; +} + +bool git_http_client_has_response(git_http_client *client) +{ + return (client->state == HAS_EARLY_RESPONSE || + client->state > SENT_REQUEST); +} + +int git_http_client_send_body( + git_http_client *client, + const char *buffer, + size_t buffer_len) +{ + git_http_server *server; + git_buf hdr = GIT_BUF_INIT; + int error; + + assert(client); + + /* If we're waiting for proxy auth, don't sending more requests. */ + if (client->state == HAS_EARLY_RESPONSE) + return 0; + + if (client->state != SENDING_BODY) { + git_error_set(GIT_ERROR_HTTP, "client is in invalid state"); + return -1; + } + + if (!buffer_len) + return 0; + + server = &client->server; + + if (client->request_body_len) { + assert(buffer_len <= client->request_body_remain); + + if ((error = stream_write(server, buffer, buffer_len)) < 0) + goto done; + + client->request_body_remain -= buffer_len; + } else { + if ((error = git_buf_printf(&hdr, "%" PRIxZ "\r\n", buffer_len)) < 0 || + (error = stream_write(server, hdr.ptr, hdr.size)) < 0 || + (error = stream_write(server, buffer, buffer_len)) < 0 || + (error = stream_write(server, "\r\n", 2)) < 0) + goto done; + } + +done: + git_buf_dispose(&hdr); + return error; +} + +static int complete_request(git_http_client *client) +{ + int error = 0; + + assert(client && client->state == SENDING_BODY); + + if (client->request_body_len && client->request_body_remain) { + git_error_set(GIT_ERROR_HTTP, "truncated write"); + error = -1; + } else if (client->request_chunked) { + error = stream_write(&client->server, "0\r\n\r\n", 5); + } + + client->state = SENT_REQUEST; + return error; +} + +int git_http_client_read_response( + git_http_response *response, + git_http_client *client) +{ + http_parser_context parser_context = {0}; + int error; + + assert(response && client); + + if (client->state == SENDING_BODY) { + if ((error = complete_request(client)) < 0) + goto done; + } + + if (client->state == HAS_EARLY_RESPONSE) { + memcpy(response, &client->early_response, sizeof(git_http_response)); + memset(&client->early_response, 0, sizeof(git_http_response)); + client->state = DONE; + return 0; + } + + if (client->state != SENT_REQUEST) { + git_error_set(GIT_ERROR_HTTP, "client is in invalid state"); + error = -1; + goto done; + } + + git_http_response_dispose(response); + + if (client->current_server == PROXY) { + git_vector_free_deep(&client->proxy.auth_challenges); + } else if(client->current_server == SERVER) { + git_vector_free_deep(&client->server.auth_challenges); + } + + client->state = READING_RESPONSE; + client->keepalive = 0; + client->parser.data = &parser_context; + + parser_context.client = client; + parser_context.response = response; + + while (client->state == READING_RESPONSE) { + if ((error = client_read_and_parse(client)) < 0) + goto done; + } + + assert(client->state == READING_BODY || client->state == DONE); + +done: + git_buf_dispose(&parser_context.parse_header_name); + git_buf_dispose(&parser_context.parse_header_value); + + return error; +} + +int git_http_client_read_body( + git_http_client *client, + char *buffer, + size_t buffer_size) +{ + http_parser_context parser_context = {0}; + int error = 0; + + if (client->state == DONE) + return 0; + + if (client->state != READING_BODY) { + git_error_set(GIT_ERROR_HTTP, "client is in invalid state"); + return -1; + } + + /* + * Now we'll read from the socket and http_parser will pipeline the + * data directly to the client. + */ + + parser_context.client = client; + parser_context.output_buf = buffer; + parser_context.output_size = buffer_size; + + client->parser.data = &parser_context; + + /* + * Clients expect to get a non-zero amount of data from us, + * so we either block until we have data to return, until we + * hit EOF or there's an error. Do this in a loop, since we + * may end up reading only some stream metadata (like chunk + * information). + */ + while (!parser_context.output_written) { + error = client_read_and_parse(client); + + if (error <= 0) + goto done; + + if (client->state == DONE) + break; + } + + assert(parser_context.output_written <= INT_MAX); + error = (int)parser_context.output_written; + +done: + if (error < 0) + client->connected = 0; + + return error; +} + +int git_http_client_skip_body(git_http_client *client) +{ + http_parser_context parser_context = {0}; + int error; + + if (client->state == DONE) + return 0; + + if (client->state != READING_BODY) { + git_error_set(GIT_ERROR_HTTP, "client is in invalid state"); + return -1; + } + + parser_context.client = client; + client->parser.data = &parser_context; + + do { + error = client_read_and_parse(client); + + if (parser_context.error != HPE_OK || + (parser_context.parse_status != PARSE_STATUS_OK && + parser_context.parse_status != PARSE_STATUS_NO_OUTPUT)) { + git_error_set(GIT_ERROR_HTTP, + "unexpected data handled in callback"); + error = -1; + } + } while (!error); + + if (error < 0) + client->connected = 0; + + return error; +} + +/* + * Create an http_client capable of communicating with the given remote + * host. + */ +int git_http_client_new( + git_http_client **out, + git_http_client_options *opts) +{ + git_http_client *client; + + assert(out); + + client = git__calloc(1, sizeof(git_http_client)); + GIT_ERROR_CHECK_ALLOC(client); + + git_buf_init(&client->read_buf, GIT_READ_BUFFER_SIZE); + GIT_ERROR_CHECK_ALLOC(client->read_buf.ptr); + + if (opts) + memcpy(&client->opts, opts, sizeof(git_http_client_options)); + + *out = client; + return 0; +} + +GIT_INLINE(void) http_server_close(git_http_server *server) +{ + if (server->stream) { + git_stream_close(server->stream); + git_stream_free(server->stream); + server->stream = NULL; + } + + git_net_url_dispose(&server->url); + + git_vector_free_deep(&server->auth_challenges); + free_auth_context(server); +} + +static void http_client_close(git_http_client *client) +{ + http_server_close(&client->server); + http_server_close(&client->proxy); + + git_buf_dispose(&client->request_msg); + + client->state = 0; + client->request_count = 0; + client->connected = 0; + client->keepalive = 0; +} + +void git_http_client_free(git_http_client *client) +{ + if (!client) + return; + + http_client_close(client); + git_buf_dispose(&client->read_buf); + git__free(client); +} diff -Nru libgit2-0.28.5+dfsg.1/src/transports/httpclient.h libgit2-1.1.0+dfsg.1/src/transports/httpclient.h --- libgit2-0.28.5+dfsg.1/src/transports/httpclient.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/httpclient.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * 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_transports_httpclient_h__ +#define INCLUDE_transports_httpclient_h__ + +#include "common.h" +#include "net.h" + +#define GIT_HTTP_STATUS_CONTINUE 100 +#define GIT_HTTP_STATUS_OK 200 +#define GIT_HTTP_MOVED_PERMANENTLY 301 +#define GIT_HTTP_FOUND 302 +#define GIT_HTTP_SEE_OTHER 303 +#define GIT_HTTP_TEMPORARY_REDIRECT 307 +#define GIT_HTTP_PERMANENT_REDIRECT 308 +#define GIT_HTTP_STATUS_UNAUTHORIZED 401 +#define GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED 407 + +typedef struct git_http_client git_http_client; + +/** Method for the HTTP request */ +typedef enum { + GIT_HTTP_METHOD_GET, + GIT_HTTP_METHOD_POST, + GIT_HTTP_METHOD_CONNECT +} git_http_method; + +/** An HTTP request */ +typedef struct { + git_http_method method; /**< Method for the request */ + git_net_url *url; /**< Full request URL */ + git_net_url *proxy; /**< Proxy to use */ + + /* Headers */ + const char *accept; /**< Contents of the Accept header */ + const char *content_type; /**< Content-Type header (for POST) */ + git_credential *credentials; /**< Credentials to authenticate with */ + git_credential *proxy_credentials; /**< Credentials for proxy */ + git_strarray *custom_headers; /**< Additional headers to deliver */ + + /* To POST a payload, either set content_length OR set chunked. */ + size_t content_length; /**< Length of the POST body */ + unsigned chunked : 1, /**< Post with chunking */ + expect_continue : 1; /**< Use expect/continue negotiation */ +} git_http_request; + +typedef struct { + int status; + + /* Headers */ + char *content_type; + size_t content_length; + char *location; + + /* Authentication headers */ + unsigned server_auth_schemetypes; /**< Schemes requested by remote */ + unsigned server_auth_credtypes; /**< Supported cred types for remote */ + + unsigned proxy_auth_schemetypes; /**< Schemes requested by proxy */ + unsigned proxy_auth_credtypes; /**< Supported cred types for proxy */ + + unsigned chunked : 1, /**< Response body is chunked */ + resend_credentials : 1; /**< Resend with authentication */ +} git_http_response; + +typedef struct { + /** Certificate check callback for the remote */ + git_transport_certificate_check_cb server_certificate_check_cb; + void *server_certificate_check_payload; + + /** Certificate check callback for the proxy */ + git_transport_certificate_check_cb proxy_certificate_check_cb; + void *proxy_certificate_check_payload; +} git_http_client_options; + +/** + * Create a new httpclient instance with the given options. + * + * @param out pointer to receive the new instance + * @param opts options to create the client with or NULL for defaults + */ +extern int git_http_client_new( + git_http_client **out, + git_http_client_options *opts); + +/* + * Sends a request to the host specified by the request URL. If the + * method is POST, either the the content_length or the chunked flag must + * be specified. The body should be provided in subsequent calls to + * git_http_client_send_body. + * + * @param client the client to write the request to + * @param request the request to send + */ +extern int git_http_client_send_request( + git_http_client *client, + git_http_request *request); + +/* + * After sending a request, there may already be a response to read -- + * either because there was a non-continue response to an expect: continue + * request, or because the server pipelined a response to us before we even + * sent the request. Examine the state. + * + * @param client the client to examine + * @return true if there's already a response to read, false otherwise + */ +extern bool git_http_client_has_response(git_http_client *client); + +/** + * Sends the given buffer to the remote as part of the request body. The + * request must have specified either a content_length or the chunked flag. + * + * @param client the client to write the request body to + * @param buffer the request body + * @param buffer_len number of bytes of the buffer to send + */ +extern int git_http_client_send_body( + git_http_client *client, + const char *buffer, + size_t buffer_len); + +/** + * Reads the headers of a response to a request. This will consume the + * entirety of the headers of a response from the server. The body (if any) + * can be read by calling git_http_client_read_body. Callers must free + * the response with git_http_response_dispose. + * + * @param response pointer to the response object to fill + * @param client the client to read the response from + */ +extern int git_http_client_read_response( + git_http_response *response, + git_http_client *client); + +/** + * Reads some or all of the body of a response. At most buffer_size (or + * INT_MAX) bytes will be read and placed into the buffer provided. The + * number of bytes read will be returned, or 0 to indicate that the end of + * the body has been read. + * + * @param client the client to read the response from + * @param buffer pointer to the buffer to fill + * @param buffer_size the maximum number of bytes to read + * @return the number of bytes read, 0 on end of body, or error code + */ +extern int git_http_client_read_body( + git_http_client *client, + char *buffer, + size_t buffer_size); + +/** + * Reads all of the (remainder of the) body of the response and ignores it. + * None of the data from the body will be returned to the caller. + * + * @param client the client to read the response from + * @return 0 or an error code + */ +extern int git_http_client_skip_body(git_http_client *client); + +/** + * Examines the status code of the response to determine if it is a + * redirect of any type (eg, 301, 302, etc). + * + * @param response the response to inspect + * @return true if the response is a redirect, false otherwise + */ +extern bool git_http_response_is_redirect(git_http_response *response); + +/** + * Frees any memory associated with the response. + * + * @param response the response to free + */ +extern void git_http_response_dispose(git_http_response *response); + +/** + * Frees any memory associated with the client. If any sockets are open, + * they will be closed. + * + * @param client the client to free + */ +extern void git_http_client_free(git_http_client *client); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/transports/http.h libgit2-1.1.0+dfsg.1/src/transports/http.h --- libgit2-0.28.5+dfsg.1/src/transports/http.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/http.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,8 +9,11 @@ #define INCLUDE_transports_http_h__ #include "buffer.h" +#include "httpclient.h" -#define GIT_HTTP_REPLAY_MAX 7 +#define GIT_HTTP_REPLAY_MAX 15 + +extern bool git_http__expect_continue; GIT_INLINE(int) git_http__user_agent(git_buf *buf) { diff -Nru libgit2-0.28.5+dfsg.1/src/transports/local.c libgit2-1.1.0+dfsg.1/src/transports/local.c --- libgit2-0.28.5+dfsg.1/src/transports/local.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/local.c 2020-10-12 18:53:06.000000000 +0000 @@ -185,12 +185,12 @@ } t->have_refs = 1; - git_strarray_free(&ref_names); + git_strarray_dispose(&ref_names); return 0; on_error: git_vector_free(&t->refs); - git_strarray_free(&ref_names); + git_strarray_dispose(&ref_names); return -1; } @@ -201,7 +201,7 @@ static int local_connect( git_transport *transport, const char *url, - git_cred_acquire_cb cred_acquire_cb, + git_credential_acquire_cb cred_acquire_cb, void *cred_acquire_payload, const git_proxy_options *proxy, int direction, int flags) @@ -309,7 +309,7 @@ if (lref[0] != '\0') { /* Create or update a ref */ error = git_reference_create(NULL, remote_repo, rref, loid, - !git_oid_iszero(roid), NULL); + !git_oid_is_zero(roid), NULL); } else { /* Delete a ref */ if ((error = git_reference_lookup(&remote_ref, remote_repo, rref)) < 0) { @@ -325,7 +325,7 @@ return error; } -static int transfer_to_push_transfer(const git_transfer_progress *stats, void *payload) +static int transfer_to_push_transfer(const git_indexer_progress *stats, void *payload) { const git_remote_callbacks *cbs = payload; @@ -460,8 +460,8 @@ } typedef struct foreach_data { - git_transfer_progress *stats; - git_transfer_progress_cb progress_cb; + git_indexer_progress *stats; + git_indexer_progress_cb progress_cb; void *progress_payload; git_odb_writepack *writepack; } foreach_data; @@ -501,7 +501,7 @@ if (git_buf_oom(&progress_info)) return -1; - error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload); + error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload); git_buf_dispose(&progress_info); return error; @@ -533,8 +533,8 @@ static int local_download_pack( git_transport *transport, git_repository *repo, - git_transfer_progress *stats, - git_transfer_progress_cb progress_cb, + git_indexer_progress *stats, + git_indexer_progress_cb progress_cb, void *progress_payload) { transport_local *t = (transport_local*)transport; @@ -588,7 +588,7 @@ goto cleanup; if (t->progress_cb && - (error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0) + (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0) goto cleanup; /* Walk the objects, building a packfile */ @@ -602,7 +602,7 @@ goto cleanup; if (t->progress_cb && - (error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0) + (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0) goto cleanup; if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0) diff -Nru libgit2-0.28.5+dfsg.1/src/transports/smart.c libgit2-1.1.0+dfsg.1/src/transports/smart.c --- libgit2-0.28.5+dfsg.1/src/transports/smart.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/smart.c 2020-10-12 18:53:06.000000000 +0000 @@ -63,7 +63,7 @@ git_transport_certificate_check_cb certificate_check_cb, void *message_cb_payload) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); t->progress_cb = progress_cb; t->error_cb = error_cb; @@ -73,7 +73,7 @@ return 0; } -static int http_header_name_length(const char *http_header) +static size_t http_header_name_length(const char *http_header) { const char *colon = strchr(http_header, ':'); if (!colon) @@ -84,7 +84,7 @@ static bool is_malformed_http_header(const char *http_header) { const char *c; - int name_len; + size_t name_len; /* Disallow \r and \n */ c = strchr(http_header, '\r'); @@ -114,7 +114,7 @@ static bool is_forbidden_custom_header(const char *custom_header) { unsigned long i; - int name_len = http_header_name_length(custom_header); + size_t name_len = http_header_name_length(custom_header); /* Disallow headers that we set */ for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++) @@ -128,11 +128,11 @@ git_transport *transport, const git_strarray *custom_headers) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); size_t i; if (t->custom_headers.count) - git_strarray_free(&t->custom_headers); + git_strarray_dispose(&t->custom_headers); if (!custom_headers) return 0; @@ -206,13 +206,13 @@ static int git_smart__connect( git_transport *transport, const char *url, - git_cred_acquire_cb cred_acquire_cb, + git_credential_acquire_cb cred_acquire_cb, void *cred_acquire_payload, const git_proxy_options *proxy, int direction, int flags) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); git_smart_subtransport_stream *stream; int error; git_pkt *pkt; @@ -286,7 +286,7 @@ if ((error = git_smart__detect_caps(first, &t->caps, &symrefs)) == 0) { /* If the only ref in the list is capabilities^{} with OID_ZERO, remove it */ if (1 == t->refs.length && !strcmp(first->head.name, "capabilities^{}") && - git_oid_iszero(&first->head.oid)) { + git_oid_is_zero(&first->head.oid)) { git_vector_clear(&t->refs); git_pkt_free((git_pkt *)first); } @@ -315,7 +315,7 @@ static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); if (!t->have_refs) { git_error_set(GIT_ERROR_NET, "the transport has not yet loaded the refs"); @@ -330,7 +330,7 @@ int git_smart__negotiation_step(git_transport *transport, void *data, size_t len) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); git_smart_subtransport_stream *stream; int error; @@ -387,21 +387,21 @@ static void git_smart__cancel(git_transport *transport) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); git_atomic_set(&t->cancelled, 1); } static int git_smart__is_connected(git_transport *transport) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); return t->connected; } static int git_smart__read_flags(git_transport *transport, int *flags) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); *flags = t->flags; @@ -410,7 +410,7 @@ static int git_smart__close(git_transport *transport) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); git_vector *common = &t->common; unsigned int i; git_pkt *p; @@ -447,7 +447,7 @@ static void git_smart__free(git_transport *transport) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); git_vector *refs = &t->refs; unsigned int i; git_pkt *p; @@ -465,7 +465,7 @@ git_vector_free(refs); git__free((char *)t->proxy.url); - git_strarray_free(&t->custom_headers); + git_strarray_dispose(&t->custom_headers); git__free(t); } @@ -479,7 +479,7 @@ int git_transport_smart_certificate_check(git_transport *transport, git_cert *cert, int valid, const char *hostname) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); assert(transport && cert && hostname); @@ -489,9 +489,9 @@ return t->certificate_check_cb(cert, valid, hostname, t->message_cb_payload); } -int git_transport_smart_credentials(git_cred **out, git_transport *transport, const char *user, int methods) +int git_transport_smart_credentials(git_credential **out, git_transport *transport, const char *user, int methods) { - transport_smart *t = (transport_smart *)transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); assert(out && transport); @@ -503,7 +503,7 @@ int git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport) { - transport_smart *t = (transport_smart *) transport; + transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent); return git_proxy_options_dup(out, &t->proxy); } diff -Nru libgit2-0.28.5+dfsg.1/src/transports/smart.h libgit2-1.1.0+dfsg.1/src/transports/smart.h --- libgit2-0.28.5+dfsg.1/src/transports/smart.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/smart.h 2020-10-12 18:53:06.000000000 +0000 @@ -137,7 +137,7 @@ git_transport parent; git_remote *owner; char *url; - git_cred_acquire_cb cred_acquire_cb; + git_credential_acquire_cb cred_acquire_cb; void *cred_acquire_payload; git_proxy_options proxy; int direction; @@ -177,8 +177,8 @@ int git_smart__download_pack( git_transport *transport, git_repository *repo, - git_transfer_progress *stats, - git_transfer_progress_cb progress_cb, + git_indexer_progress *stats, + git_indexer_progress_cb progress_cb, void *progress_payload); /* smart.c */ diff -Nru libgit2-0.28.5+dfsg.1/src/transports/smart_protocol.c libgit2-1.1.0+dfsg.1/src/transports/smart_protocol.c --- libgit2-0.28.5+dfsg.1/src/transports/smart_protocol.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/smart_protocol.c 2020-10-12 18:53:06.000000000 +0000 @@ -17,6 +17,7 @@ #include "pack-objects.h" #include "remote.h" #include "util.h" +#include "revwalk.h" #define NETWORK_XFER_THRESHOLD (100*1024) /* The minimal interval between progress updates (in seconds). */ @@ -270,50 +271,6 @@ return 0; } -static int fetch_setup_walk(git_revwalk **out, git_repository *repo) -{ - git_revwalk *walk = NULL; - git_strarray refs; - unsigned int i; - git_reference *ref = NULL; - int error; - - if ((error = git_reference_list(&refs, repo)) < 0) - return error; - - if ((error = git_revwalk_new(&walk, repo)) < 0) - return error; - - git_revwalk_sorting(walk, GIT_SORT_TIME); - - for (i = 0; i < refs.count; ++i) { - git_reference_free(ref); - ref = NULL; - - /* No tags */ - if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR)) - continue; - - if ((error = git_reference_lookup(&ref, repo, refs.strings[i])) < 0) - goto on_error; - - if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) - continue; - - if ((error = git_revwalk_push(walk, git_reference_target(ref))) < 0) - goto on_error; - } - - *out = walk; - -on_error: - if (error) - git_revwalk_free(walk); - git_reference_free(ref); - git_strarray_free(&refs); - return error; -} - static int wait_while_ack(gitno_buffer *buf) { int error; @@ -347,6 +304,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count) { transport_smart *t = (transport_smart *)transport; + git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; gitno_buffer *buf = &t->buffer; git_buf data = GIT_BUF_INIT; git_revwalk *walk = NULL; @@ -358,7 +316,11 @@ if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) return error; - if ((error = fetch_setup_walk(&walk, repo)) < 0) + if ((error = git_revwalk_new(&walk, repo)) < 0) + goto on_error; + + opts.insert_by_date = 1; + if ((error = git_revwalk__push_glob(walk, "refs/*", &opts)) < 0) goto on_error; /* @@ -409,7 +371,7 @@ } else if (pkt_type == GIT_PKT_NAK) { continue; } else { - git_error_set(GIT_ERROR_NET, "Unexpected pkt type"); + git_error_set(GIT_ERROR_NET, "unexpected pkt type"); error = -1; goto on_error; } @@ -477,7 +439,7 @@ return error; if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) { - git_error_set(GIT_ERROR_NET, "Unexpected pkt type"); + git_error_set(GIT_ERROR_NET, "unexpected pkt type"); return -1; } } else { @@ -492,13 +454,13 @@ return error; } -static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_transfer_progress *stats) +static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_indexer_progress *stats) { int recvd; do { if (t->cancelled.val) { - git_error_set(GIT_ERROR_NET, "The fetch was cancelled by the user"); + git_error_set(GIT_ERROR_NET, "the fetch was cancelled by the user"); return GIT_EUSER; } @@ -519,9 +481,9 @@ struct network_packetsize_payload { - git_transfer_progress_cb callback; + git_indexer_progress_cb callback; void *payload; - git_transfer_progress *stats; + git_indexer_progress *stats; size_t last_fired_bytes; }; @@ -546,8 +508,8 @@ int git_smart__download_pack( git_transport *transport, git_repository *repo, - git_transfer_progress *stats, - git_transfer_progress_cb transfer_progress_cb, + git_indexer_progress *stats, + git_indexer_progress_cb progress_cb, void *progress_payload) { transport_smart *t = (transport_smart *)transport; @@ -557,10 +519,10 @@ int error = 0; struct network_packetsize_payload npp = {0}; - memset(stats, 0, sizeof(git_transfer_progress)); + memset(stats, 0, sizeof(git_indexer_progress)); - if (transfer_progress_cb) { - npp.callback = transfer_progress_cb; + if (progress_cb) { + npp.callback = progress_cb; npp.payload = progress_payload; npp.stats = stats; t->packetsize_cb = &network_packetsize; @@ -573,7 +535,7 @@ } if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || - ((error = git_odb_write_pack(&writepack, odb, transfer_progress_cb, progress_payload)) != 0)) + ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)) goto done; /* @@ -604,7 +566,14 @@ } else if (pkt->type == GIT_PKT_PROGRESS) { if (t->progress_cb) { git_pkt_progress *p = (git_pkt_progress *) pkt; - error = t->progress_cb(p->data, p->len, t->message_cb_payload); + + if (p->len > INT_MAX) { + git_error_set(GIT_ERROR_NET, "oversized progress message"); + error = GIT_ERROR; + goto done; + } + + error = t->progress_cb(p->data, (int)p->len, t->message_cb_payload); } } else if (pkt->type == GIT_PKT_DATA) { git_pkt_data *p = (git_pkt_data *) pkt; @@ -626,7 +595,7 @@ } while (1); /* - * Trailing execution of transfer_progress_cb, if necessary... + * Trailing execution of progress_cb, if necessary... * Only the callback through the npp datastructure currently * updates the last_fired_bytes value. It is possible that * progress has already been reported with the correct @@ -645,7 +614,7 @@ done: if (writepack) writepack->free(writepack); - if (transfer_progress_cb) { + if (progress_cb) { t->packetsize_cb = NULL; t->packetsize_payload = NULL; } @@ -839,7 +808,14 @@ case GIT_PKT_PROGRESS: if (transport->progress_cb) { git_pkt_progress *p = (git_pkt_progress *) pkt; - error = transport->progress_cb(p->data, p->len, transport->message_cb_payload); + + if (p->len > INT_MAX) { + git_error_set(GIT_ERROR_NET, "oversized progress message"); + error = GIT_ERROR; + goto done; + } + + error = transport->progress_cb(p->data, (int)p->len, transport->message_cb_payload); } break; default: @@ -855,7 +831,7 @@ if (data_pkt_buf.size > 0) { /* If there was data remaining in the pack data buffer, * then the server sent a partial pkt-line */ - git_error_set(GIT_ERROR_NET, "Incomplete pack data pkt-line"); + git_error_set(GIT_ERROR_NET, "incomplete pack data pkt-line"); error = GIT_ERROR; } goto done; @@ -963,7 +939,7 @@ /* Remove any refs which we updated to have a zero OID. */ git_vector_rforeach(refs, i, ref) { - if (git_oid_iszero(&ref->head.oid)) { + if (git_oid_is_zero(&ref->head.oid)) { git_vector_remove(refs, i); git_pkt_free((git_pkt *)ref); } @@ -978,7 +954,7 @@ { git_smart_subtransport_stream *stream; git_packbuilder *pb; - git_push_transfer_progress cb; + git_push_transfer_progress_cb cb; void *cb_payload; size_t last_bytes; double last_progress_report_time; diff -Nru libgit2-0.28.5+dfsg.1/src/transports/ssh.c libgit2-1.1.0+dfsg.1/src/transports/ssh.c --- libgit2-0.28.5+dfsg.1/src/transports/ssh.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/ssh.c 2020-10-12 18:53:06.000000000 +0000 @@ -14,11 +14,14 @@ #include "global.h" #include "git2.h" #include "buffer.h" +#include "net.h" #include "netops.h" #include "smart.h" -#include "cred.h" #include "streams/socket.h" +#include "git2/credential.h" +#include "git2/sys/credential.h" + #ifdef GIT_SSH #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) @@ -42,7 +45,7 @@ git_smart_subtransport parent; transport_smart *owner; ssh_stream *current_stream; - git_cred *cred; + git_credential *cred; char *cmd_uploadpack; char *cmd_receivepack; } ssh_subtransport; @@ -132,7 +135,7 @@ size_t *bytes_read) { int rc; - ssh_stream *s = (ssh_stream *)stream; + ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent); *bytes_read = 0; @@ -170,7 +173,7 @@ const char *buffer, size_t len) { - ssh_stream *s = (ssh_stream *)stream; + ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent); size_t off = 0; ssize_t ret = 0; @@ -196,7 +199,7 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) { - ssh_stream *s = (ssh_stream *)stream; + ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent); ssh_subtransport *t; if (!stream) @@ -258,8 +261,7 @@ } static int git_ssh_extract_url_parts( - char **host, - char **username, + git_net_url *urldata, const char *url) { char *colon, *at; @@ -271,11 +273,11 @@ at = strchr(url, '@'); if (at) { start = at + 1; - *username = git__substrdup(url, at - url); - GIT_ERROR_CHECK_ALLOC(*username); + urldata->username = git__substrdup(url, at - url); + GIT_ERROR_CHECK_ALLOC(urldata->username); } else { start = url; - *username = NULL; + urldata->username = NULL; } if (colon == NULL || (colon < start)) { @@ -283,13 +285,13 @@ return -1; } - *host = git__substrdup(start, colon - start); - GIT_ERROR_CHECK_ALLOC(*host); + urldata->host = git__substrdup(start, colon - start); + GIT_ERROR_CHECK_ALLOC(urldata->host); return 0; } -static int ssh_agent_auth(LIBSSH2_SESSION *session, git_cred_ssh_key *c) { +static int ssh_agent_auth(LIBSSH2_SESSION *session, git_credential_ssh_key *c) { int rc = LIBSSH2_ERROR_NONE; struct libssh2_agent_publickey *curr, *prev = NULL; @@ -344,21 +346,21 @@ } static int _git_ssh_authenticate_session( - LIBSSH2_SESSION* session, - git_cred* cred) + LIBSSH2_SESSION *session, + git_credential *cred) { int rc; do { git_error_clear(); switch (cred->credtype) { - case GIT_CREDTYPE_USERPASS_PLAINTEXT: { - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; + case GIT_CREDENTIAL_USERPASS_PLAINTEXT: { + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred; rc = libssh2_userauth_password(session, c->username, c->password); break; } - case GIT_CREDTYPE_SSH_KEY: { - git_cred_ssh_key *c = (git_cred_ssh_key *)cred; + case GIT_CREDENTIAL_SSH_KEY: { + git_credential_ssh_key *c = (git_credential_ssh_key *)cred; if (c->privatekey) rc = libssh2_userauth_publickey_fromfile( @@ -369,17 +371,17 @@ break; } - case GIT_CREDTYPE_SSH_CUSTOM: { - git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred; + case GIT_CREDENTIAL_SSH_CUSTOM: { + git_credential_ssh_custom *c = (git_credential_ssh_custom *)cred; rc = libssh2_userauth_publickey( session, c->username, (const unsigned char *)c->publickey, c->publickey_len, c->sign_callback, &c->payload); break; } - case GIT_CREDTYPE_SSH_INTERACTIVE: { + case GIT_CREDENTIAL_SSH_INTERACTIVE: { void **abstract = libssh2_session_abstract(session); - git_cred_ssh_interactive *c = (git_cred_ssh_interactive *)cred; + git_credential_ssh_interactive *c = (git_credential_ssh_interactive *)cred; /* ideally, we should be able to set this by calling * libssh2_session_init_ex() instead of libssh2_session_init(). @@ -399,8 +401,8 @@ break; } #ifdef GIT_SSH_MEMORY_CREDENTIALS - case GIT_CREDTYPE_SSH_MEMORY: { - git_cred_ssh_key *c = (git_cred_ssh_key *)cred; + case GIT_CREDENTIAL_SSH_MEMORY: { + git_credential_ssh_key *c = (git_credential_ssh_key *)cred; assert(c->username); assert(c->privatekey); @@ -436,10 +438,10 @@ return 0; } -static int request_creds(git_cred **out, ssh_subtransport *t, const char *user, int auth_methods) +static int request_creds(git_credential **out, ssh_subtransport *t, const char *user, int auth_methods) { int error, no_callback = 0; - git_cred *cred = NULL; + git_credential *cred = NULL; if (!t->owner->cred_acquire_cb) { no_callback = 1; @@ -479,7 +481,7 @@ { int rc = 0; LIBSSH2_SESSION* s; - git_socket_stream *socket = (git_socket_stream *) io; + git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent); assert(session); @@ -506,18 +508,19 @@ return 0; } +#define SSH_DEFAULT_PORT "22" + static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; - const char *default_port="22"; + git_net_url urldata = GIT_NET_URL_INIT; int auth_methods, error = 0; size_t i; ssh_stream *s; - git_cred *cred = NULL; + git_credential *cred = NULL; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; @@ -535,19 +538,22 @@ const char *p = ssh_prefixes[i]; if (!git__prefixcmp(url, p)) { - if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) + if ((error = git_net_url_parse(&urldata, url)) < 0) goto done; goto post_extract; } } - if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) + if ((error = git_ssh_extract_url_parts(&urldata, url)) < 0) goto done; - port = git__strdup(default_port); - GIT_ERROR_CHECK_ALLOC(port); + + if (urldata.port == NULL) + urldata.port = git__strdup(SSH_DEFAULT_PORT); + + GIT_ERROR_CHECK_ALLOC(urldata.port); post_extract: - if ((error = git_socket_stream_new(&s->io, host, port)) < 0 || + if ((error = git_socket_stream_new(&s->io, urldata.host, urldata.port)) < 0 || (error = git_stream_connect(s->io)) < 0) goto done; @@ -560,6 +566,14 @@ cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2; +#ifdef LIBSSH2_HOSTKEY_HASH_SHA256 + key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256); + if (key != NULL) { + cert.type |= GIT_CERT_SSH_SHA256; + memcpy(&cert.hash_sha256, key, 32); + } +#endif + key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); if (key != NULL) { cert.type |= GIT_CERT_SSH_SHA1; @@ -583,7 +597,7 @@ cert_ptr = &cert; - error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload); + error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, urldata.host, t->owner->message_cb_payload); if (error < 0 && error != GIT_PASSTHROUGH) { if (!git_error_last()) @@ -594,21 +608,21 @@ } /* we need the username to ask for auth methods */ - if (!user) { - if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0) + if (!urldata.username) { + if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0) goto done; - user = git__strdup(((git_cred_username *) cred)->username); + urldata.username = git__strdup(((git_credential_username *) cred)->username); cred->free(cred); cred = NULL; - if (!user) + if (!urldata.username) goto done; - } else if (user && pass) { - if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0) + } else if (urldata.username && urldata.password) { + if ((error = git_credential_userpass_plaintext_new(&cred, urldata.username, urldata.password)) < 0) goto done; } - if ((error = list_auth_methods(&auth_methods, session, user)) < 0) + if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0) goto done; error = GIT_EAUTH; @@ -622,16 +636,24 @@ cred = NULL; } - if ((error = request_creds(&cred, t, user, auth_methods)) < 0) + if ((error = request_creds(&cred, t, urldata.username, auth_methods)) < 0) goto done; - if (strcmp(user, git_cred__username(cred))) { + if (strcmp(urldata.username, git_credential_get_username(cred))) { git_error_set(GIT_ERROR_SSH, "username does not match previous request"); error = -1; goto done; } error = _git_ssh_authenticate_session(session, cred); + + if (error == GIT_EAUTH) { + /* refresh auth methods */ + if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0) + goto done; + else + error = GIT_EAUTH; + } } if (error < 0) @@ -662,11 +684,7 @@ if (cred) cred->free(cred); - git__free(host); - git__free(port); - git__free(path); - git__free(user); - git__free(pass); + git_net_url_dispose(&urldata); return error; } @@ -730,7 +748,7 @@ const char *url, git_smart_service_t action) { - ssh_subtransport *t = (ssh_subtransport *) subtransport; + ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent); switch (action) { case GIT_SERVICE_UPLOADPACK_LS: @@ -752,7 +770,7 @@ static int _ssh_close(git_smart_subtransport *subtransport) { - ssh_subtransport *t = (ssh_subtransport *) subtransport; + ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent); assert(!t->current_stream); @@ -763,7 +781,7 @@ static void _ssh_free(git_smart_subtransport *subtransport) { - ssh_subtransport *t = (ssh_subtransport *) subtransport; + ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent); assert(!t->current_stream); @@ -796,23 +814,23 @@ ptr++; if (!git__prefixcmp(ptr, SSH_AUTH_PUBLICKEY)) { - *out |= GIT_CREDTYPE_SSH_KEY; - *out |= GIT_CREDTYPE_SSH_CUSTOM; + *out |= GIT_CREDENTIAL_SSH_KEY; + *out |= GIT_CREDENTIAL_SSH_CUSTOM; #ifdef GIT_SSH_MEMORY_CREDENTIALS - *out |= GIT_CREDTYPE_SSH_MEMORY; + *out |= GIT_CREDENTIAL_SSH_MEMORY; #endif ptr += strlen(SSH_AUTH_PUBLICKEY); continue; } if (!git__prefixcmp(ptr, SSH_AUTH_PASSWORD)) { - *out |= GIT_CREDTYPE_USERPASS_PLAINTEXT; + *out |= GIT_CREDENTIAL_USERPASS_PLAINTEXT; ptr += strlen(SSH_AUTH_PASSWORD); continue; } if (!git__prefixcmp(ptr, SSH_AUTH_KEYBOARD_INTERACTIVE)) { - *out |= GIT_CREDTYPE_SSH_INTERACTIVE; + *out |= GIT_CREDENTIAL_SSH_INTERACTIVE; ptr += strlen(SSH_AUTH_KEYBOARD_INTERACTIVE); continue; } diff -Nru libgit2-0.28.5+dfsg.1/src/transports/winhttp.c libgit2-1.1.0+dfsg.1/src/transports/winhttp.c --- libgit2-0.28.5+dfsg.1/src/transports/winhttp.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/transports/winhttp.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,6 +19,7 @@ #include "repository.h" #include "global.h" #include "http.h" +#include "git2/sys/credential.h" #include #include @@ -40,18 +41,28 @@ #define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0 #endif -#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS_1_1 +#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 # define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 0x00000200 #endif -#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS_1_2 +#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 # define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 0x00000800 #endif +#ifndef WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 +# define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 0x00002000 +#endif + #ifndef HTTP_STATUS_PERMANENT_REDIRECT # define HTTP_STATUS_PERMANENT_REDIRECT 308 #endif +#ifndef DWORD_MAX +# define DWORD_MAX 0xffffffff +#endif + +bool git_http__expect_continue = false; + static const char *prefix_https = "https://"; static const char *upload_pack_service = "upload-pack"; static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack"; @@ -105,23 +116,43 @@ } winhttp_stream; typedef struct { + git_net_url url; + git_credential *cred; + int auth_mechanisms; + bool url_cred_presented; +} winhttp_server; + +typedef struct { git_smart_subtransport parent; transport_smart *owner; - gitno_connection_data connection_data; - gitno_connection_data proxy_connection_data; - git_cred *cred; - git_cred *url_cred; - git_cred *proxy_cred; - int auth_mechanisms; + + winhttp_server server; + winhttp_server proxy; + HINTERNET session; HINTERNET connection; } winhttp_subtransport; -static int _apply_userpass_credential(HINTERNET request, DWORD target, DWORD scheme, git_cred *cred) +static int apply_userpass_credentials(HINTERNET request, DWORD target, int mechanisms, git_credential *cred) { - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - wchar_t *user, *pass; + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred; + wchar_t *user = NULL, *pass = NULL; int user_len = 0, pass_len = 0, error = 0; + DWORD native_scheme; + + if (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) { + native_scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE; + } else if (mechanisms & GIT_WINHTTP_AUTH_NTLM) { + native_scheme = WINHTTP_AUTH_SCHEME_NTLM; + } else if (mechanisms & GIT_WINHTTP_AUTH_DIGEST) { + native_scheme = WINHTTP_AUTH_SCHEME_DIGEST; + } else if (mechanisms & GIT_WINHTTP_AUTH_BASIC) { + native_scheme = WINHTTP_AUTH_SCHEME_BASIC; + } else { + git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme"); + error = -1; + goto done; + } if ((error = user_len = git__utf8_to_16_alloc(&user, c->username)) < 0) goto done; @@ -129,7 +160,7 @@ if ((error = pass_len = git__utf8_to_16_alloc(&pass, c->password)) < 0) goto done; - if (!WinHttpSetCredentials(request, target, scheme, user, pass, NULL)) { + if (!WinHttpSetCredentials(request, target, native_scheme, user, pass, NULL)) { git_error_set(GIT_ERROR_OS, "failed to set credentials"); error = -1; } @@ -147,81 +178,62 @@ return error; } -static int apply_userpass_credential_proxy(HINTERNET request, git_cred *cred, int mechanisms) +static int apply_default_credentials(HINTERNET request, DWORD target, int mechanisms) { - if (GIT_WINHTTP_AUTH_DIGEST & mechanisms) { - return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY, - WINHTTP_AUTH_SCHEME_DIGEST, cred); - } - - return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY, - WINHTTP_AUTH_SCHEME_BASIC, cred); -} - -static int apply_userpass_credential(HINTERNET request, int mechanisms, git_cred *cred) -{ - DWORD native_scheme; + DWORD autologon_level = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW; + DWORD native_scheme = 0; - if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) || - (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE)) { + if ((mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) != 0) { + native_scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE; + } else if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) != 0) { native_scheme = WINHTTP_AUTH_SCHEME_NTLM; - } else if (mechanisms & GIT_WINHTTP_AUTH_BASIC) { - native_scheme = WINHTTP_AUTH_SCHEME_BASIC; } else { - git_error_set(GIT_ERROR_NET, "invalid authentication scheme"); + git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme"); return -1; } - return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_SERVER, - native_scheme, cred); -} - -static int apply_default_credentials(HINTERNET request, int mechanisms) -{ - /* Either the caller explicitly requested that default credentials be passed, - * or our fallback credential callback was invoked and checked that the target - * URI was in the appropriate Internet Explorer security zone. By setting this - * flag, we guarantee that the credentials are delivered by WinHTTP. The default - * is "medium" which applies to the intranet and sounds like it would correspond - * to Internet Explorer security zones, but in fact does not. */ - DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW; - DWORD native_scheme = 0; - - if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) != 0) - native_scheme = WINHTTP_AUTH_SCHEME_NTLM; - - if ((mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) != 0) - native_scheme = WINHTTP_AUTH_SCHEME_NEGOTIATE; - - if (!native_scheme) { - git_error_set(GIT_ERROR_NET, "invalid authentication scheme"); + /* + * Autologon policy must be "low" to use default creds. + * This is safe as the user has explicitly requested it. + */ + if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &autologon_level, sizeof(DWORD))) { + git_error_set(GIT_ERROR_OS, "could not configure logon policy"); return -1; } - if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD))) - return -1; - - if (!WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_SERVER, native_scheme, NULL, NULL, NULL)) + if (!WinHttpSetCredentials(request, target, native_scheme, NULL, NULL, NULL)) { + git_error_set(GIT_ERROR_OS, "could not configure credentials"); return -1; + } return 0; } -static int fallback_cred_acquire_cb( - git_cred **cred, - const char *url, - const char *username_from_url, +static int acquire_url_cred( + git_credential **cred, unsigned int allowed_types, - void *payload) + const char *username, + const char *password) { - int error = 1; + if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) + return git_credential_userpass_plaintext_new(cred, username, password); + + if ((allowed_types & GIT_CREDENTIAL_DEFAULT) && *username == '\0' && *password == '\0') + return git_credential_default_new(cred); - GIT_UNUSED(username_from_url); - GIT_UNUSED(payload); + return 1; +} + +static int acquire_fallback_cred( + git_credential **cred, + const char *url, + unsigned int allowed_types) +{ + int error = 1; /* If the target URI supports integrated Windows authentication * as an authentication mechanism */ - if (GIT_CREDTYPE_DEFAULT & allowed_types) { + if (GIT_CREDENTIAL_DEFAULT & allowed_types) { wchar_t *wide_url; HRESULT hCoInitResult; @@ -245,21 +257,21 @@ (URLZONE_LOCAL_MACHINE == dwZone || URLZONE_INTRANET == dwZone || URLZONE_TRUSTED == dwZone)) { - git_cred *existing = *cred; + git_credential *existing = *cred; if (existing) existing->free(existing); /* Then use default Windows credentials to authenticate this request */ - error = git_cred_default_new(cred); + error = git_credential_default_new(cred); } pISM->lpVtbl->Release(pISM); } - if (SUCCEEDED(hCoInitResult)) - /* Only unitialize if the call to CoInitializeEx was successful. */ - CoUninitialize(); + /* Only unitialize if the call to CoInitializeEx was successful. */ + if (SUCCEEDED(hCoInitResult)) + CoUninitialize(); } git__free(wide_url); @@ -279,12 +291,12 @@ /* If there is no override, we should fail if WinHTTP doesn't think it's fine */ if (t->owner->certificate_check_cb == NULL && !valid) { if (!git_error_last()) - git_error_set(GIT_ERROR_NET, "unknown certificate check failure"); + git_error_set(GIT_ERROR_HTTP, "unknown certificate check failure"); return GIT_ECERTIFICATE; } - if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl) + if (t->owner->certificate_check_cb == NULL || git__strcmp(t->server.url.scheme, "https") != 0) return 0; if (!WinHttpQueryOption(s->request, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert_ctx, &cert_ctx_size)) { @@ -296,14 +308,14 @@ cert.parent.cert_type = GIT_CERT_X509; cert.data = cert_ctx->pbCertEncoded; cert.len = cert_ctx->cbCertEncoded; - error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->connection_data.host, t->owner->message_cb_payload); + error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->server.url.host, t->owner->message_cb_payload); CertFreeCertificateContext(cert_ctx); if (error == GIT_PASSTHROUGH) error = valid ? 0 : GIT_ECERTIFICATE; if (error < 0 && !git_error_last()) - git_error_set(GIT_ERROR_NET, "user cancelled certificate check"); + git_error_set(GIT_ERROR_HTTP, "user cancelled certificate check"); return error; } @@ -333,8 +345,25 @@ s->sent_request = 0; } -#define SCHEME_HTTP "http://" -#define SCHEME_HTTPS "https://" +static int apply_credentials( + HINTERNET request, + git_net_url *url, + int target, + git_credential *creds, + int mechanisms) +{ + int error = 0; + + GIT_UNUSED(url); + + /* If we have creds, just apply them */ + if (creds && creds->credtype == GIT_CREDENTIAL_USERPASS_PLAINTEXT) + error = apply_userpass_credentials(request, target, mechanisms, creds); + else if (creds && creds->credtype == GIT_CREDENTIAL_DEFAULT) + error = apply_default_credentials(request, target, mechanisms); + + return error; +} static int winhttp_stream_connect(winhttp_stream *s) { @@ -348,11 +377,17 @@ unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; + DWORD autologon_policy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH; + + const char *service_url = s->service_url; size_t i; const git_proxy_options *proxy_opts; + /* If path already ends in /, remove the leading slash from service_url */ + if ((git__suffixcmp(t->server.url.path, "/") == 0) && (git__prefixcmp(service_url, "/") == 0)) + service_url++; /* Prepare URL */ - git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url); + git_buf_printf(&buf, "%s%s", t->server.url.path, service_url); if (git_buf_oom(&buf)) return -1; @@ -371,13 +406,17 @@ NULL, WINHTTP_NO_REFERER, types, - t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0); + git__strcmp(t->server.url.scheme, "https") == 0 ? WINHTTP_FLAG_SECURE : 0); if (!s->request) { git_error_set(GIT_ERROR_OS, "failed to open request"); goto on_error; } + /* Never attempt default credentials; we'll provide them explicitly. */ + if (!WinHttpSetOption(s->request, WINHTTP_OPTION_AUTOLOGON_POLICY, &autologon_policy, sizeof(DWORD))) + return -1; + if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { git_error_set(GIT_ERROR_OS, "failed to set timeouts for WinHTTP"); goto on_error; @@ -386,7 +425,7 @@ proxy_opts = &t->owner->proxy; if (proxy_opts->type == GIT_PROXY_AUTO) { /* Set proxy if necessary */ - if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0) + if (git_remote__get_http_proxy(t->owner->owner, (strcmp(t->server.url.scheme, "https") == 0), &proxy_url) < 0) goto on_error; } else if (proxy_opts->type == GIT_PROXY_SPECIFIED) { @@ -399,38 +438,24 @@ WINHTTP_PROXY_INFO proxy_info; wchar_t *proxy_wide; - if (!git__prefixcmp(proxy_url, SCHEME_HTTP)) { - t->proxy_connection_data.use_ssl = false; - } else if (!git__prefixcmp(proxy_url, SCHEME_HTTPS)) { - t->proxy_connection_data.use_ssl = true; - } else { - git_error_set(GIT_ERROR_NET, "invalid URL: '%s'", proxy_url); - return -1; - } + git_net_url_dispose(&t->proxy.url); - gitno_connection_data_free_ptrs(&t->proxy_connection_data); - - if ((error = gitno_extract_url_parts(&t->proxy_connection_data.host, &t->proxy_connection_data.port, NULL, - &t->proxy_connection_data.user, &t->proxy_connection_data.pass, proxy_url, NULL)) < 0) + if ((error = git_net_url_parse(&t->proxy.url, proxy_url)) < 0) goto on_error; - if (t->proxy_connection_data.user && t->proxy_connection_data.pass) { - if (t->proxy_cred) { - t->proxy_cred->free(t->proxy_cred); - } - - if ((error = git_cred_userpass_plaintext_new(&t->proxy_cred, t->proxy_connection_data.user, t->proxy_connection_data.pass)) < 0) - goto on_error; + if (strcmp(t->proxy.url.scheme, "http") != 0 && strcmp(t->proxy.url.scheme, "https") != 0) { + git_error_set(GIT_ERROR_HTTP, "invalid URL: '%s'", proxy_url); + error = -1; + goto on_error; } - if (t->proxy_connection_data.use_ssl) - git_buf_PUTS(&processed_url, SCHEME_HTTPS); - else - git_buf_PUTS(&processed_url, SCHEME_HTTP); + git_buf_puts(&processed_url, t->proxy.url.scheme); + git_buf_PUTS(&processed_url, "://"); + + git_buf_puts(&processed_url, t->proxy.url.host); - git_buf_puts(&processed_url, t->proxy_connection_data.host); - if (t->proxy_connection_data.port) - git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port); + if (!git_net_url_is_default_port(&t->proxy.url)) + git_buf_printf(&processed_url, ":%s", t->proxy.url.port); if (git_buf_oom(&processed_url)) { error = -1; @@ -458,13 +483,8 @@ git__free(proxy_wide); - if (t->proxy_cred) { - if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) { - if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred, t->auth_mechanisms)) < 0) - goto on_error; - } - } - + if ((error = apply_credentials(s->request, &t->proxy.url, WINHTTP_AUTH_TARGET_PROXY, t->proxy.cred, t->proxy.auth_mechanisms)) < 0) + goto on_error; } /* Disable WinHTTP redirects so we can handle them manually. Why, you ask? @@ -475,6 +495,7 @@ &disable_redirects, sizeof(disable_redirects))) { git_error_set(GIT_ERROR_OS, "failed to disable redirects"); + error = -1; goto on_error; } @@ -547,33 +568,16 @@ } /* If requested, disable certificate validation */ - if (t->connection_data.use_ssl) { + if (strcmp(t->server.url.scheme, "https") == 0) { int flags; if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0) goto on_error; } - /* If we have a credential on the subtransport, apply it to the request */ - if (t->cred && - t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT && - apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0) - goto on_error; - else if (t->cred && - t->cred->credtype == GIT_CREDTYPE_DEFAULT && - apply_default_credentials(s->request, t->auth_mechanisms) < 0) + if ((error = apply_credentials(s->request, &t->server.url, WINHTTP_AUTH_TARGET_SERVER, t->server.cred, t->server.auth_mechanisms)) < 0) goto on_error; - /* If no other credentials have been applied and the URL has username and - * password, use those */ - if (!t->cred && t->connection_data.user && t->connection_data.pass) { - if (!t->url_cred && - git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0) - goto on_error; - if (apply_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, t->url_cred) < 0) - goto on_error; - } - /* We've done everything up to calling WinHttpSendRequest. */ error = 0; @@ -588,9 +592,9 @@ } static int parse_unauthorized_response( - HINTERNET request, int *allowed_types, - int *allowed_mechanisms) + int *allowed_mechanisms, + HINTERNET request) { DWORD supported, first, target; @@ -606,23 +610,23 @@ } if (WINHTTP_AUTH_SCHEME_NTLM & supported) { - *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; - *allowed_types |= GIT_CREDTYPE_DEFAULT; + *allowed_types |= GIT_CREDENTIAL_USERPASS_PLAINTEXT; + *allowed_types |= GIT_CREDENTIAL_DEFAULT; *allowed_mechanisms |= GIT_WINHTTP_AUTH_NTLM; } if (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported) { - *allowed_types |= GIT_CREDTYPE_DEFAULT; + *allowed_types |= GIT_CREDENTIAL_DEFAULT; *allowed_mechanisms |= GIT_WINHTTP_AUTH_NEGOTIATE; } if (WINHTTP_AUTH_SCHEME_BASIC & supported) { - *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; + *allowed_types |= GIT_CREDENTIAL_USERPASS_PLAINTEXT; *allowed_mechanisms |= GIT_WINHTTP_AUTH_BASIC; } if (WINHTTP_AUTH_SCHEME_DIGEST & supported) { - *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; + *allowed_types |= GIT_CREDENTIAL_USERPASS_PLAINTEXT; *allowed_mechanisms |= GIT_WINHTTP_AUTH_DIGEST; } @@ -703,27 +707,31 @@ { DWORD status; + GIT_UNUSED(connection); + GIT_UNUSED(ctx); + GIT_UNUSED(info_len); + if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) return; status = *((DWORD *)info); if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)) - git_error_set(GIT_ERROR_NET, "SSL certificate issued for different common name"); + git_error_set(GIT_ERROR_HTTP, "SSL certificate issued for different common name"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) - git_error_set(GIT_ERROR_NET, "SSL certificate has expired"); + git_error_set(GIT_ERROR_HTTP, "SSL certificate has expired"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)) - git_error_set(GIT_ERROR_NET, "SSL certificate signed by unknown CA"); + git_error_set(GIT_ERROR_HTTP, "SSL certificate signed by unknown CA"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)) - git_error_set(GIT_ERROR_NET, "SSL certificate is invalid"); + git_error_set(GIT_ERROR_HTTP, "SSL certificate is invalid"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)) - git_error_set(GIT_ERROR_NET, "certificate revocation check failed"); + git_error_set(GIT_ERROR_HTTP, "certificate revocation check failed"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)) - git_error_set(GIT_ERROR_NET, "SSL certificate was revoked"); + git_error_set(GIT_ERROR_HTTP, "SSL certificate was revoked"); else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR)) - git_error_set(GIT_ERROR_NET, "security libraries could not be loaded"); + git_error_set(GIT_ERROR_HTTP, "security libraries could not be loaded"); else - git_error_set(GIT_ERROR_NET, "unknown security error %lu", status); + git_error_set(GIT_ERROR_HTTP, "unknown security error %lu", status); } static int winhttp_connect( @@ -739,18 +747,19 @@ DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | - WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2; + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 | + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3; t->session = NULL; t->connection = NULL; /* Prepare port */ - if (git__strntol32(&port, t->connection_data.port, - strlen(t->connection_data.port), NULL, 10) < 0) + if (git__strntol32(&port, t->server.url.port, + strlen(t->server.url.port), NULL, 10) < 0) return -1; /* Prepare host */ - if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) { + if (git__utf8_to_16_alloc(&wide_host, t->server.url.host) < 0) { git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters"); return -1; } @@ -784,14 +793,20 @@ } /* - * Do a best-effort attempt to enable TLS 1.2 but allow this to - * fail; if TLS 1.2 support is not available for some reason, + * Do a best-effort attempt to enable TLS 1.3 and 1.2 but allow this to + * fail; if TLS 1.2 or 1.3 support is not available for some reason, * ignore the failure (it will keep the default protocols). */ - WinHttpSetOption(t->session, + if (WinHttpSetOption(t->session, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, - sizeof(protocols)); + sizeof(protocols)) == FALSE) { + protocols &= ~WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3; + WinHttpSetOption(t->session, + WINHTTP_OPTION_SECURE_PROTOCOLS, + &protocols, + sizeof(protocols)); + } if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { git_error_set(GIT_ERROR_OS, "failed to set timeouts for WinHTTP"); @@ -828,13 +843,18 @@ return error; } -static int do_send_request(winhttp_stream *s, size_t len, int ignore_length) +static int do_send_request(winhttp_stream *s, size_t len, bool chunked) { int attempts; bool success; + if (len > DWORD_MAX) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return -1; + } + for (attempts = 0; attempts < 5; attempts++) { - if (ignore_length) { + if (chunked) { success = WinHttpSendRequest(s->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, @@ -843,7 +863,7 @@ success = WinHttpSendRequest(s->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, - len, 0); + (DWORD)len, 0); } if (success || GetLastError() != (DWORD)SEC_E_BUFFER_TOO_SMALL) @@ -853,13 +873,13 @@ return success ? 0 : -1; } -static int send_request(winhttp_stream *s, size_t len, int ignore_length) +static int send_request(winhttp_stream *s, size_t len, bool chunked) { int request_failed = 0, cert_valid = 1, error = 0; DWORD ignore_flags; git_error_clear(); - if ((error = do_send_request(s, len, ignore_length)) < 0) { + if ((error = do_send_request(s, len, chunked)) < 0) { if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) { git_error_set(GIT_ERROR_OS, "failed to send request"); return -1; @@ -888,12 +908,65 @@ return -1; } - if ((error = do_send_request(s, len, ignore_length)) < 0) + if ((error = do_send_request(s, len, chunked)) < 0) git_error_set(GIT_ERROR_OS, "failed to send request with unchecked certificate"); return error; } +static int acquire_credentials( + HINTERNET request, + winhttp_server *server, + const char *url_str, + git_credential_acquire_cb cred_cb, + void *cred_cb_payload) +{ + int allowed_types; + int error = 1; + + if (parse_unauthorized_response(&allowed_types, &server->auth_mechanisms, request) < 0) + return -1; + + if (allowed_types) { + git_credential_free(server->cred); + server->cred = NULL; + + /* Start with URL-specified credentials, if there were any. */ + if (!server->url_cred_presented && server->url.username && server->url.password) { + error = acquire_url_cred(&server->cred, allowed_types, server->url.username, server->url.password); + server->url_cred_presented = 1; + + if (error < 0) + return error; + } + + /* Next use the user-defined callback, if there is one. */ + if (error > 0 && cred_cb) { + error = cred_cb(&server->cred, url_str, server->url.username, allowed_types, cred_cb_payload); + + /* Treat GIT_PASSTHROUGH as though git_credential_acquire_cb isn't set */ + if (error == GIT_PASSTHROUGH) + error = 1; + else if (error < 0) + return error; + } + + /* Finally, invoke the fallback default credential lookup. */ + if (error > 0) { + error = acquire_fallback_cred(&server->cred, url_str, allowed_types); + + if (error < 0) + return error; + } + } + + /* + * No error occurred but we could not find appropriate credentials. + * This behaves like a pass-through. + */ + return error; +} + static int winhttp_stream_read( git_smart_subtransport_stream *stream, char *buffer, @@ -909,7 +982,7 @@ replay: /* Enforce a reasonable cap on the number of replays */ if (replay_count++ >= GIT_HTTP_REPLAY_MAX) { - git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays"); + git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays"); return -1; } @@ -924,7 +997,7 @@ if (!s->sent_request) { - if ((error = send_request(s, s->post_body_len, 0)) < 0) + if ((error = send_request(s, s->post_body_len, false)) < 0) return error; s->sent_request = 1; @@ -960,6 +1033,7 @@ } buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE); + GIT_ERROR_CHECK_ALLOC(buffer); while (len > 0) { DWORD bytes_written; @@ -1067,7 +1141,7 @@ if (!git__prefixcmp_icase(location8, prefix_https)) { /* Upgrade to secure connection; disconnect and start over */ - if (gitno_connection_data_from_url(&t->connection_data, location8, s->service_url) < 0) { + if (git_net_url_apply_redirect(&t->server.url, location8, s->service_url) < 0) { git__free(location8); return -1; } @@ -1082,72 +1156,39 @@ goto replay; } - /* Handle proxy authentication failures */ - if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) { - int allowed_types; - - if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0) - return -1; - - /* TODO: extract the username from the url, no payload? */ - if (t->owner->proxy.credentials) { - int cred_error = 1; - cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, t->owner->proxy.payload); - - if (cred_error < 0) - return cred_error; - } - - winhttp_stream_close(s); - goto replay; - } - /* Handle authentication failures */ - if (HTTP_STATUS_DENIED == status_code && get_verb == s->verb) { - int allowed_types; - - if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0) - return -1; - - if (allowed_types) { - int cred_error = 1; - - git_cred_free(t->cred); - t->cred = NULL; - /* Start with the user-supplied credential callback, if present */ - if (t->owner->cred_acquire_cb) { - cred_error = t->owner->cred_acquire_cb(&t->cred, t->owner->url, - t->connection_data.user, allowed_types, t->owner->cred_acquire_payload); - - /* Treat GIT_PASSTHROUGH as though git_cred_acquire_cb isn't set */ - if (cred_error == GIT_PASSTHROUGH) - cred_error = 1; - else if (cred_error < 0) - return cred_error; - } - - /* Invoke the fallback credentials acquisition callback if necessary */ - if (cred_error > 0) { - cred_error = fallback_cred_acquire_cb(&t->cred, t->owner->url, - t->connection_data.user, allowed_types, NULL); - - if (cred_error < 0) - return cred_error; - } + if (status_code == HTTP_STATUS_DENIED) { + int error = acquire_credentials(s->request, + &t->server, + t->owner->url, + t->owner->cred_acquire_cb, + t->owner->cred_acquire_payload); - if (!cred_error) { - assert(t->cred); - - winhttp_stream_close(s); + if (error < 0) { + return error; + } else if (!error) { + assert(t->server.cred); + winhttp_stream_close(s); + goto replay; + } + } else if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) { + int error = acquire_credentials(s->request, + &t->proxy, + t->owner->proxy.url, + t->owner->proxy.credentials, + t->owner->proxy.payload); - /* Successfully acquired a credential */ - goto replay; - } + if (error < 0) { + return error; + } else if (!error) { + assert(t->proxy.cred); + winhttp_stream_close(s); + goto replay; } } if (HTTP_STATUS_OK != status_code) { - git_error_set(GIT_ERROR_NET, "request failed with status code: %lu", status_code); + git_error_set(GIT_ERROR_HTTP, "request failed with status code: %lu", status_code); return -1; } @@ -1174,7 +1215,7 @@ } if (wcscmp(expected_content_type, content_type)) { - git_error_set(GIT_ERROR_NET, "received unexpected content-type"); + git_error_set(GIT_ERROR_HTTP, "received unexpected content-type"); return -1; } @@ -1209,11 +1250,11 @@ /* This implementation of write permits only a single call. */ if (s->sent_request) { - git_error_set(GIT_ERROR_NET, "subtransport configured for only one write"); + git_error_set(GIT_ERROR_HTTP, "subtransport configured for only one write"); return -1; } - if ((error = send_request(s, len, 0)) < 0) + if ((error = send_request(s, len, false)) < 0) return error; s->sent_request = 1; @@ -1240,12 +1281,12 @@ if (RPC_S_OK != status && RPC_S_UUID_LOCAL_ONLY != status && RPC_S_UUID_NO_ADDRESS != status) { - git_error_set(GIT_ERROR_NET, "unable to generate name for temp file"); + git_error_set(GIT_ERROR_HTTP, "unable to generate name for temp file"); return -1; } if (buffer_len_cch < UUID_LENGTH_CCH + 1) { - git_error_set(GIT_ERROR_NET, "buffer too small for name of temp file"); + git_error_set(GIT_ERROR_HTTP, "buffer too small for name of temp file"); return -1; } @@ -1352,7 +1393,7 @@ return -1; } - if ((error = send_request(s, 0, 1)) < 0) + if ((error = send_request(s, 0, true)) < 0) return error; s->sent_request = 1; @@ -1375,8 +1416,10 @@ /* Append as much to the buffer as we can */ int count = (int)min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, len); - if (!s->chunk_buffer) + if (!s->chunk_buffer) { s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE); + GIT_ERROR_CHECK_ALLOC(s->chunk_buffer); + } memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count); s->chunk_buffer_len += count; @@ -1501,7 +1544,7 @@ int ret = -1; if (!t->connection) - if ((ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0 || + if ((ret = git_net_url_parse(&t->server.url, url)) < 0 || (ret = winhttp_connect(t)) < 0) return ret; @@ -1543,24 +1586,17 @@ { winhttp_subtransport *t = (winhttp_subtransport *)subtransport; - gitno_connection_data_free_ptrs(&t->connection_data); - memset(&t->connection_data, 0x0, sizeof(gitno_connection_data)); - gitno_connection_data_free_ptrs(&t->proxy_connection_data); - memset(&t->proxy_connection_data, 0x0, sizeof(gitno_connection_data)); - - if (t->cred) { - t->cred->free(t->cred); - t->cred = NULL; - } + git_net_url_dispose(&t->server.url); + git_net_url_dispose(&t->proxy.url); - if (t->proxy_cred) { - t->proxy_cred->free(t->proxy_cred); - t->proxy_cred = NULL; + if (t->server.cred) { + t->server.cred->free(t->server.cred); + t->server.cred = NULL; } - if (t->url_cred) { - t->url_cred->free(t->url_cred); - t->url_cred = NULL; + if (t->proxy.cred) { + t->proxy.cred->free(t->proxy.cred); + t->proxy.cred = NULL; } return winhttp_close_connection(t); diff -Nru libgit2-0.28.5+dfsg.1/src/tree.c libgit2-1.1.0+dfsg.1/src/tree.c --- libgit2-0.28.5+dfsg.1/src/tree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/tree.c 2020-10-12 18:53:06.000000000 +0000 @@ -10,7 +10,7 @@ #include "commit.h" #include "git2/repository.h" #include "git2/object.h" -#include "fileops.h" +#include "futils.h" #include "tree-cache.h" #include "index.h" @@ -340,11 +340,11 @@ return tree->entries.size; } -unsigned int git_treebuilder_entrycount(git_treebuilder *bld) +size_t git_treebuilder_entrycount(git_treebuilder *bld) { assert(bld); - return git_strmap_num_entries(bld->map); + return git_strmap_size(bld->map); } static int tree_error(const char *str, const char *path) @@ -479,7 +479,7 @@ if (!valid_entry_name(repo, filename)) return tree_error("failed to insert entry: invalid name for a tree entry", filename); - if (git_oid_iszero(id)) + if (git_oid_is_zero(id)) return tree_error("failed to insert entry: invalid null OID", filename); if (filemode != GIT_FILEMODE_COMMIT && @@ -507,8 +507,7 @@ entry->attr = (uint16_t)filemode; - git_strmap_insert(bld->map, entry->filename, entry, &error); - if (error < 0) { + if ((error = git_strmap_set(bld->map, entry->filename, entry)) < 0) { git_tree_entry_free(entry); git_error_set(GIT_ERROR_TREE, "failed to append entry %s to the tree builder", filename); return -1; @@ -688,7 +687,7 @@ bld->repo = repo; - if (git_strmap_alloc(&bld->map) < 0) { + if (git_strmap_new(&bld->map) < 0) { git__free(bld); return -1; } @@ -723,24 +722,19 @@ { git_tree_entry *entry; int error; - size_t pos; assert(bld && id && filename); if ((error = check_entry(bld->repo, filename, id, filemode)) < 0) return error; - pos = git_strmap_lookup_index(bld->map, filename); - if (git_strmap_valid_index(bld->map, pos)) { - entry = git_strmap_value_at(bld->map, pos); + if ((entry = git_strmap_get(bld->map, filename)) != NULL) { git_oid_cpy((git_oid *) entry->oid, id); } else { entry = alloc_entry(filename, strlen(filename), id); GIT_ERROR_CHECK_ALLOC(entry); - git_strmap_insert(bld->map, entry->filename, entry, &error); - - if (error < 0) { + if ((error = git_strmap_set(bld->map, entry->filename, entry)) < 0) { git_tree_entry_free(entry); git_error_set(GIT_ERROR_TREE, "failed to insert %s", filename); return -1; @@ -757,16 +751,8 @@ static git_tree_entry *treebuilder_get(git_treebuilder *bld, const char *filename) { - git_tree_entry *entry = NULL; - size_t pos; - assert(bld && filename); - - pos = git_strmap_lookup_index(bld->map, filename); - if (git_strmap_valid_index(bld->map, pos)) - entry = git_strmap_value_at(bld->map, pos); - - return entry; + return git_strmap_get(bld->map, filename); } const git_tree_entry *git_treebuilder_get(git_treebuilder *bld, const char *filename) @@ -811,7 +797,7 @@ git_buf_clear(tree); - entrycount = git_strmap_num_entries(bld->map); + entrycount = git_strmap_size(bld->map); if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0) goto out; @@ -848,7 +834,7 @@ return error; } -void git_treebuilder_filter( +int git_treebuilder_filter( git_treebuilder *bld, git_treebuilder_filter_cb filter, void *payload) @@ -864,9 +850,11 @@ git_tree_entry_free(entry); } }); + + return 0; } -void git_treebuilder_clear(git_treebuilder *bld) +int git_treebuilder_clear(git_treebuilder *bld) { git_tree_entry *e; @@ -874,6 +862,8 @@ git_strmap_foreach_value(bld->map, e, git_tree_entry_free(e)); git_strmap_clear(bld->map); + + return 0; } void git_treebuilder_free(git_treebuilder *bld) diff -Nru libgit2-0.28.5+dfsg.1/src/tree-cache.c libgit2-1.1.0+dfsg.1/src/tree-cache.c --- libgit2-0.28.5+dfsg.1/src/tree-cache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/tree-cache.c 2020-10-12 18:53:06.000000000 +0000 @@ -120,12 +120,14 @@ /* Parse children: */ if (tree->children_count > 0) { - unsigned int i; + size_t i, bufsize; - tree->children = git_pool_malloc(pool, tree->children_count * sizeof(git_tree_cache *)); + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&bufsize, tree->children_count, sizeof(git_tree_cache*)); + + tree->children = git_pool_malloc(pool, bufsize); GIT_ERROR_CHECK_ALLOC(tree->children); - memset(tree->children, 0x0, tree->children_count * sizeof(git_tree_cache *)); + memset(tree->children, 0x0, bufsize); for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, pool) < 0) @@ -160,7 +162,7 @@ static int read_tree_recursive(git_tree_cache *cache, const git_tree *tree, git_pool *pool) { git_repository *repo; - size_t i, j, nentries, ntrees; + size_t i, j, nentries, ntrees, alloc_size; int error; repo = git_tree_owner(tree); @@ -182,8 +184,10 @@ ntrees++; } + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloc_size, ntrees, sizeof(git_tree_cache *)); + cache->children_count = ntrees; - cache->children = git_pool_mallocz(pool, ntrees * sizeof(git_tree_cache *)); + cache->children = git_pool_mallocz(pool, alloc_size); GIT_ERROR_CHECK_ALLOC(cache->children); j = 0; @@ -232,11 +236,14 @@ int git_tree_cache_new(git_tree_cache **out, const char *name, git_pool *pool) { - size_t name_len; + size_t name_len, alloc_size; git_tree_cache *tree; name_len = strlen(name); - tree = git_pool_malloc(pool, sizeof(git_tree_cache) + name_len + 1); + + GIT_ERROR_CHECK_ALLOC_ADD3(&alloc_size, sizeof(git_tree_cache), name_len, 1); + + tree = git_pool_malloc(pool, alloc_size); GIT_ERROR_CHECK_ALLOC(tree); memset(tree, 0x0, sizeof(git_tree_cache)); diff -Nru libgit2-0.28.5+dfsg.1/src/unix/map.c libgit2-1.1.0+dfsg.1/src/unix/map.c --- libgit2-0.28.5+dfsg.1/src/unix/map.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/unix/map.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,7 +32,7 @@ return git__page_size(alignment); } -int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset) +int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset) { int mprot = PROT_READ; int mflag = 0; diff -Nru libgit2-0.28.5+dfsg.1/src/unix/posix.h libgit2-1.1.0+dfsg.1/src/unix/posix.h --- libgit2-0.28.5+dfsg.1/src/unix/posix.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/unix/posix.h 2020-10-12 18:53:06.000000000 +0000 @@ -59,14 +59,26 @@ #define p_strcasecmp(s1, s2) strcasecmp(s1, s2) #define p_strncasecmp(s1, s2, c) strncasecmp(s1, s2, c) #define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a) -#define p_snprintf(b, c, ...) snprintf(b, c, __VA_ARGS__) +#define p_snprintf snprintf #define p_mkstemp(p) mkstemp(p) #define p_chdir(p) chdir(p) -#define p_chmod(p,m) chmod(p, m) #define p_rmdir(p) rmdir(p) #define p_access(p,m) access(p,m) #define p_ftruncate(fd, sz) ftruncate(fd, sz) +/* + * Pre-Android 5 did not implement a virtual filesystem atop FAT + * partitions for Unix permissions, which causes chmod to fail. However, + * Unix permissions have no effect on Android anyway as file permissions + * are not actually managed this way, so treating it as a no-op across + * all Android is safe. + */ +#ifdef __ANDROID__ +# define p_chmod(p,m) 0 +#else +# define p_chmod(p,m) chmod(p, m) +#endif + /* see win32/posix.h for explanation about why this exists */ #define p_lstat_posixly(p,b) lstat(p,b) @@ -89,14 +101,4 @@ # define p_futimes futimes #endif -#ifdef GIT_USE_REGCOMP_L -#include -GIT_INLINE(int) p_regcomp(regex_t *preg, const char *pattern, int cflags) -{ - return regcomp_l(preg, pattern, cflags, (locale_t) 0); -} -#else -# define p_regcomp regcomp -#endif - #endif diff -Nru libgit2-0.28.5+dfsg.1/src/userdiff.h libgit2-1.1.0+dfsg.1/src/userdiff.h --- libgit2-0.28.5+dfsg.1/src/userdiff.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/userdiff.h 2020-10-12 18:53:06.000000000 +0000 @@ -7,6 +7,8 @@ #ifndef INCLUDE_userdiff_h__ #define INCLUDE_userdiff_h__ +#include "regexp.h" + /* * This file isolates the built in diff driver function name patterns. * Most of these patterns are taken from Git (with permission from the @@ -29,7 +31,7 @@ #define PATTERNS(NAME, FN_PATS, WORD_PAT) \ { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, 0 } #define IPATTERN(NAME, FN_PATS, WORD_PAT) \ - { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, REG_ICASE } + { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, GIT_REGEXP_ICASE } /* * The table of diff driver patterns diff -Nru libgit2-0.28.5+dfsg.1/src/util.c libgit2-1.1.0+dfsg.1/src/util.c --- libgit2-0.28.5+dfsg.1/src/util.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/util.c 2020-10-12 18:53:06.000000000 +0000 @@ -22,52 +22,6 @@ # include #endif -void git_strarray_free(git_strarray *array) -{ - size_t i; - - if (array == NULL) - return; - - for (i = 0; i < array->count; ++i) - git__free(array->strings[i]); - - git__free(array->strings); - - memset(array, 0, sizeof(*array)); -} - -int git_strarray_copy(git_strarray *tgt, const git_strarray *src) -{ - size_t i; - - assert(tgt && src); - - memset(tgt, 0, sizeof(*tgt)); - - if (!src->count) - return 0; - - tgt->strings = git__calloc(src->count, sizeof(char *)); - GIT_ERROR_CHECK_ALLOC(tgt->strings); - - for (i = 0; i < src->count; ++i) { - if (!src->strings[i]) - continue; - - tgt->strings[tgt->count] = git__strdup(src->strings[i]); - if (!tgt->strings[tgt->count]) { - git_strarray_free(tgt); - memset(tgt, 0, sizeof(*tgt)); - return -1; - } - - tgt->count++; - } - - return 0; -} - int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base) { const char *p; @@ -192,7 +146,7 @@ tmp_int = tmp_long & 0xFFFFFFFF; if (tmp_int != tmp_long) { - int len = tmp_endptr - nptr; + int len = (int)(tmp_endptr - nptr); git_error_set(GIT_ERROR_INVALID, "failed to convert: '%.*s' is too large", len, nptr); return -1; } @@ -204,13 +158,6 @@ return error; } -int git__strcmp(const char *a, const char *b) -{ - while (*a && *b && *a == *b) - ++a, ++b; - return (int)(*(const unsigned char *)a) - (int)(*(const unsigned char *)b); -} - int git__strcasecmp(const char *a, const char *b) { while (*a && *b && git__tolower(*a) == git__tolower(*b)) @@ -240,15 +187,6 @@ return cmp; } -int git__strncmp(const char *a, const char *b, size_t sz) -{ - while (sz && *a && *b && *a == *b) - --sz, ++a, ++b; - if (!sz) - return 0; - return (int)(*(const unsigned char *)a) - (int)(*(const unsigned char *)b); -} - int git__strncasecmp(const char *a, const char *b, size_t sz) { int al, bl; @@ -301,7 +239,18 @@ int git__prefixcmp(const char *str, const char *prefix) { - return prefixcmp(str, SIZE_MAX, prefix, false); + unsigned char s, p; + + while (1) { + p = *prefix++; + s = *str++; + + if (!p) + return 0; + + if (s != p) + return s - p; + } } int git__prefixncmp(const char *str, size_t str_n, const char *prefix) @@ -429,35 +378,48 @@ last_line = (len % LINE_WIDTH); for (i = 0; i < line_count; ++i) { + printf("%08" PRIxZ " ", (i * LINE_WIDTH)); + line = buffer + (i * LINE_WIDTH); - for (j = 0; j < LINE_WIDTH; ++j, ++line) - printf("%02X ", (unsigned char)*line & 0xFF); + for (j = 0; j < LINE_WIDTH; ++j, ++line) { + printf("%02x ", (unsigned char)*line & 0xFF); + + if (j == (LINE_WIDTH / 2)) + printf(" "); + } - printf("| "); + printf(" |"); line = buffer + (i * LINE_WIDTH); for (j = 0; j < LINE_WIDTH; ++j, ++line) printf("%c", (*line >= 32 && *line <= 126) ? *line : '.'); - printf("\n"); + printf("|\n"); } if (last_line > 0) { + printf("%08" PRIxZ " ", (line_count * LINE_WIDTH)); line = buffer + (line_count * LINE_WIDTH); - for (j = 0; j < last_line; ++j, ++line) - printf("%02X ", (unsigned char)*line & 0xFF); + for (j = 0; j < last_line; ++j, ++line) { + printf("%02x ", (unsigned char)*line & 0xFF); + if (j == (LINE_WIDTH / 2)) + printf(" "); + } + + if (j < (LINE_WIDTH / 2)) + printf(" "); for (j = 0; j < (LINE_WIDTH - last_line); ++j) - printf(" "); + printf(" "); - printf("| "); + printf(" |"); line = buffer + (line_count * LINE_WIDTH); for (j = 0; j < last_line; ++j, ++line) printf("%c", (*line >= 32 && *line <= 126) ? *line : '.'); - printf("\n"); + printf("|\n"); } printf("\n"); @@ -724,6 +686,37 @@ } #endif + +#if !defined(HAVE_QSORT_R_BSD) && \ + !defined(HAVE_QSORT_R_GNU) && \ + !defined(HAVE_QSORT_S) +static void swap(uint8_t *a, uint8_t *b, size_t elsize) +{ + char tmp[256]; + + while (elsize) { + size_t n = elsize < sizeof(tmp) ? elsize : sizeof(tmp); + memcpy(tmp, a + elsize - n, n); + memcpy(a + elsize - n, b + elsize - n, n); + memcpy(b + elsize - n, tmp, n); + elsize -= n; + } +} + +static void insertsort( + void *els, size_t nel, size_t elsize, + git__sort_r_cmp cmp, void *payload) +{ + uint8_t *base = els; + uint8_t *end = base + nel * elsize; + uint8_t *i, *j; + + for (i = base + elsize; i < end; i += elsize) + for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize) + swap(j, j - elsize, elsize); +} +#endif + void git__qsort_r( void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload) { @@ -736,33 +729,10 @@ git__qsort_r_glue glue = { cmp, payload }; qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue); #else - git__insertsort_r(els, nel, elsize, NULL, cmp, payload); + insertsort(els, nel, elsize, cmp, payload); #endif } -void git__insertsort_r( - void *els, size_t nel, size_t elsize, void *swapel, - git__sort_r_cmp cmp, void *payload) -{ - uint8_t *base = els; - uint8_t *end = base + nel * elsize; - uint8_t *i, *j; - bool freeswap = !swapel; - - if (freeswap) - swapel = git__malloc(elsize); - - for (i = base + elsize; i < end; i += elsize) - for (j = i; j > base && cmp(j, j - elsize, payload) < 0; j -= elsize) { - memcpy(swapel, j, elsize); - memcpy(j, j - elsize, elsize); - memcpy(j - elsize, swapel, elsize); - } - - if (freeswap) - git__free(swapel); -} - /* * git__utf8_iterate is taken from the utf8proc project, * http://www.public-software-group.org/utf8proc @@ -807,23 +777,23 @@ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; -int git__utf8_charlen(const uint8_t *str, int str_len) +static int util_utf8_charlen(const uint8_t *str, size_t str_len) { - int length, i; + size_t length, i; length = utf8proc_utf8class[str[0]]; if (!length) return -1; - if (str_len >= 0 && length > str_len) - return -str_len; + if (str_len > 0 && length > str_len) + return -1; for (i = 1; i < length; i++) { if ((str[i] & 0xC0) != 0x80) - return -i; + return -1; } - return length; + return (int)length; } int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst) @@ -832,7 +802,7 @@ int32_t uc = -1; *dst = -1; - length = git__utf8_charlen(str, str_len); + length = util_utf8_charlen(str, str_len); if (length < 0) return -1; @@ -864,17 +834,12 @@ return length; } -double git_time_monotonic(void) -{ - return git__timer(); -} - size_t git__utf8_valid_buf_length(const uint8_t *str, size_t str_len) { size_t offset = 0; while (offset < str_len) { - int length = git__utf8_charlen(str + offset, str_len - offset); + int length = util_utf8_charlen(str + offset, str_len - offset); if (length < 0) break; diff -Nru libgit2-0.28.5+dfsg.1/src/util.h libgit2-1.1.0+dfsg.1/src/util.h --- libgit2-0.28.5+dfsg.1/src/util.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/util.h 2020-10-12 18:53:06.000000000 +0000 @@ -30,6 +30,17 @@ # define max(a,b) ((a) > (b) ? (a) : (b)) #endif +#if defined(__GNUC__) +# define GIT_CONTAINER_OF(ptr, type, member) \ + __builtin_choose_expr( \ + __builtin_offsetof(type, member) == 0 && \ + __builtin_types_compatible_p(typeof(&((type *) 0)->member), typeof(ptr)), \ + ((type *) (ptr)), \ + (void)0) +#else +# define GIT_CONTAINER_OF(ptr, type, member) (type *)(ptr) +#endif + #define GIT_DATE_RFC2822_SZ 32 /** @@ -126,10 +137,6 @@ extern void git__qsort_r( void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload); -extern void git__insertsort_r( - void *els, size_t nel, size_t elsize, void *swapel, - git__sort_r_cmp cmp, void *payload); - /** * @param position If non-NULL, this will be set to the position where the * element is or would be inserted if not found. @@ -150,12 +157,13 @@ void *payload, size_t *position); +#define git__strcmp strcmp +#define git__strncmp strncmp + extern int git__strcmp_cb(const void *a, const void *b); extern int git__strcasecmp_cb(const void *a, const void *b); -extern int git__strcmp(const char *a, const char *b); extern int git__strcasecmp(const char *a, const char *b); -extern int git__strncmp(const char *a, const char *b, size_t sz); extern int git__strncasecmp(const char *a, const char *b, size_t sz); extern int git__strcasesort_cmp(const char *a, const char *b); @@ -178,10 +186,10 @@ } #define GIT_REFCOUNT_OWN(r, o) { \ - (r)->rc.owner = o; \ + (void)git__swap((r)->rc.owner, o); \ } -#define GIT_REFCOUNT_OWNER(r) ((r)->rc.owner) +#define GIT_REFCOUNT_OWNER(r) git__load((r)->rc.owner) #define GIT_REFCOUNT_VAL(r) git_atomic_get((r)->rc.refcount) @@ -349,22 +357,9 @@ GIT_INLINE(double) git__timer(void) { - /* We need the initial tick count to detect if the tick - * count has rolled over. */ - static DWORD initial_tick_count = 0; - - /* GetTickCount returns the number of milliseconds that have + /* GetTickCount64 returns the number of milliseconds that have * elapsed since the system was started. */ - DWORD count = GetTickCount(); - - if(initial_tick_count == 0) { - initial_tick_count = count; - } else if (count < initial_tick_count) { - /* The tick count has rolled over - adjust for it. */ - count = (0xFFFFFFFF - initial_tick_count) + count; - } - - return (double) count / (double) 1000; + return (double) GetTickCount64() / (double) 1000; } #elif __APPLE__ diff -Nru libgit2-0.28.5+dfsg.1/src/wildmatch.c libgit2-1.1.0+dfsg.1/src/wildmatch.c --- libgit2-0.28.5+dfsg.1/src/wildmatch.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/wildmatch.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,320 @@ +/* + * 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. + * + * Do shell-style pattern matching for ?, \, [], and * characters. + * It is 8bit clean. + * + * Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. + * Rich $alz is now . + * + * Modified by Wayne Davison to special-case '/' matching, to make '**' + * work differently than '*', and to fix the character-class code. + * + * Imported from git.git. + */ + +#include "wildmatch.h" + +#define GIT_SPACE 0x01 +#define GIT_DIGIT 0x02 +#define GIT_ALPHA 0x04 +#define GIT_GLOB_SPECIAL 0x08 +#define GIT_REGEX_SPECIAL 0x10 +#define GIT_PATHSPEC_MAGIC 0x20 +#define GIT_CNTRL 0x40 +#define GIT_PUNCT 0x80 + +enum { + S = GIT_SPACE, + A = GIT_ALPHA, + D = GIT_DIGIT, + G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */ + R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | */ + P = GIT_PATHSPEC_MAGIC, /* other non-alnum, except for ] and } */ + X = GIT_CNTRL, + U = GIT_PUNCT, + Z = GIT_CNTRL | GIT_SPACE +}; + +static const unsigned char sane_ctype[256] = { + X, X, X, X, X, X, X, X, X, Z, Z, X, X, Z, X, X, /* 0.. 15 */ + X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 16.. 31 */ + S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */ + D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */ + P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ + A, A, A, A, A, A, A, A, A, A, A, G, G, U, R, P, /* 80.. 95 */ + P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ + A, A, A, A, A, A, A, A, A, A, A, R, R, U, P, X, /* 112..127 */ + /* Nothing in the 128.. range */ +}; + +#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) +#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL) + +typedef unsigned char uchar; + +/* What character marks an inverted character class? */ +#define NEGATE_CLASS '!' +#define NEGATE_CLASS2 '^' + +#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \ + && *(class) == *(litmatch) \ + && strncmp((char*)class, litmatch, len) == 0) + +#if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +#else +# define ISASCII(c) isascii(c) +#endif + +#ifdef isblank +# define ISBLANK(c) (ISASCII(c) && isblank(c)) +#else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#endif + +#ifdef isgraph +# define ISGRAPH(c) (ISASCII(c) && isgraph(c)) +#else +# define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c)) +#endif + +#define ISPRINT(c) (ISASCII(c) && isprint(c)) +#define ISDIGIT(c) (ISASCII(c) && isdigit(c)) +#define ISALNUM(c) (ISASCII(c) && isalnum(c)) +#define ISALPHA(c) (ISASCII(c) && isalpha(c)) +#define ISCNTRL(c) (ISASCII(c) && iscntrl(c)) +#define ISLOWER(c) (ISASCII(c) && islower(c)) +#define ISPUNCT(c) (ISASCII(c) && ispunct(c)) +#define ISSPACE(c) (ISASCII(c) && isspace(c)) +#define ISUPPER(c) (ISASCII(c) && isupper(c)) +#define ISXDIGIT(c) (ISASCII(c) && isxdigit(c)) + +/* Match pattern "p" against "text" */ +static int dowild(const uchar *p, const uchar *text, unsigned int flags) +{ + uchar p_ch; + const uchar *pattern = p; + + for ( ; (p_ch = *p) != '\0'; text++, p++) { + int matched, match_slash, negated; + uchar t_ch, prev_ch; + if ((t_ch = *text) == '\0' && p_ch != '*') + return WM_ABORT_ALL; + if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) + t_ch = tolower(t_ch); + if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) + p_ch = tolower(p_ch); + switch (p_ch) { + case '\\': + /* Literal match with following character. Note that the test + * in "default" handles the p[1] == '\0' failure case. */ + p_ch = *++p; + /* FALLTHROUGH */ + default: + if (t_ch != p_ch) + return WM_NOMATCH; + continue; + case '?': + /* Match anything but '/'. */ + if ((flags & WM_PATHNAME) && t_ch == '/') + return WM_NOMATCH; + continue; + case '*': + if (*++p == '*') { + const uchar *prev_p = p - 2; + while (*++p == '*') {} + if (!(flags & WM_PATHNAME)) + /* without WM_PATHNAME, '*' == '**' */ + match_slash = 1; + else if ((prev_p < pattern || *prev_p == '/') && + (*p == '\0' || *p == '/' || + (p[0] == '\\' && p[1] == '/'))) { + /* + * Assuming we already match 'foo/' and are at + * , just assume it matches + * nothing and go ahead match the rest of the + * pattern with the remaining string. This + * helps make foo/<*><*>/bar (<> because + * otherwise it breaks C comment syntax) match + * both foo/bar and foo/a/bar. + */ + if (p[0] == '/' && + dowild(p + 1, text, flags) == WM_MATCH) + return WM_MATCH; + match_slash = 1; + } else /* WM_PATHNAME is set */ + match_slash = 0; + } else + /* without WM_PATHNAME, '*' == '**' */ + match_slash = flags & WM_PATHNAME ? 0 : 1; + if (*p == '\0') { + /* Trailing "**" matches everything. Trailing "*" matches + * only if there are no more slash characters. */ + if (!match_slash) { + if (strchr((char*)text, '/') != NULL) + return WM_NOMATCH; + } + return WM_MATCH; + } else if (!match_slash && *p == '/') { + /* + * _one_ asterisk followed by a slash + * with WM_PATHNAME matches the next + * directory + */ + const char *slash = strchr((char*)text, '/'); + if (!slash) + return WM_NOMATCH; + text = (const uchar*)slash; + /* the slash is consumed by the top-level for loop */ + break; + } + while (1) { + if (t_ch == '\0') + break; + /* + * Try to advance faster when an asterisk is + * followed by a literal. We know in this case + * that the string before the literal + * must belong to "*". + * If match_slash is false, do not look past + * the first slash as it cannot belong to '*'. + */ + if (!is_glob_special(*p)) { + p_ch = *p; + if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) + p_ch = tolower(p_ch); + while ((t_ch = *text) != '\0' && + (match_slash || t_ch != '/')) { + if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) + t_ch = tolower(t_ch); + if (t_ch == p_ch) + break; + text++; + } + if (t_ch != p_ch) + return WM_NOMATCH; + } + if ((matched = dowild(p, text, flags)) != WM_NOMATCH) { + if (!match_slash || matched != WM_ABORT_TO_STARSTAR) + return matched; + } else if (!match_slash && t_ch == '/') + return WM_ABORT_TO_STARSTAR; + t_ch = *++text; + } + return WM_ABORT_ALL; + case '[': + p_ch = *++p; +#ifdef NEGATE_CLASS2 + if (p_ch == NEGATE_CLASS2) + p_ch = NEGATE_CLASS; +#endif + /* Assign literal 1/0 because of "matched" comparison. */ + negated = p_ch == NEGATE_CLASS ? 1 : 0; + if (negated) { + /* Inverted character class. */ + p_ch = *++p; + } + prev_ch = 0; + matched = 0; + do { + if (!p_ch) + return WM_ABORT_ALL; + if (p_ch == '\\') { + p_ch = *++p; + if (!p_ch) + return WM_ABORT_ALL; + if (t_ch == p_ch) + matched = 1; + } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') { + p_ch = *++p; + if (p_ch == '\\') { + p_ch = *++p; + if (!p_ch) + return WM_ABORT_ALL; + } + if (t_ch <= p_ch && t_ch >= prev_ch) + matched = 1; + else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) { + uchar t_ch_upper = toupper(t_ch); + if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch) + matched = 1; + } + p_ch = 0; /* This makes "prev_ch" get set to 0. */ + } else if (p_ch == '[' && p[1] == ':') { + const uchar *s; + int i; + for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/ + if (!p_ch) + return WM_ABORT_ALL; + i = (int)(p - s - 1); + if (i < 0 || p[-1] != ':') { + /* Didn't find ":]", so treat like a normal set. */ + p = s - 2; + p_ch = '['; + if (t_ch == p_ch) + matched = 1; + continue; + } + if (CC_EQ(s,i, "alnum")) { + if (ISALNUM(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "alpha")) { + if (ISALPHA(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "blank")) { + if (ISBLANK(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "cntrl")) { + if (ISCNTRL(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "digit")) { + if (ISDIGIT(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "graph")) { + if (ISGRAPH(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "lower")) { + if (ISLOWER(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "print")) { + if (ISPRINT(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "punct")) { + if (ISPUNCT(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "space")) { + if (ISSPACE(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "upper")) { + if (ISUPPER(t_ch)) + matched = 1; + else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) + matched = 1; + } else if (CC_EQ(s,i, "xdigit")) { + if (ISXDIGIT(t_ch)) + matched = 1; + } else /* malformed [:class:] string */ + return WM_ABORT_ALL; + p_ch = 0; /* This makes "prev_ch" get set to 0. */ + } else if (t_ch == p_ch) + matched = 1; + } while (prev_ch = p_ch, (p_ch = *++p) != ']'); + if (matched == negated || + ((flags & WM_PATHNAME) && t_ch == '/')) + return WM_NOMATCH; + continue; + } + } + + return *text ? WM_NOMATCH : WM_MATCH; +} + +/* Match the "pattern" against the "text" string. */ +int wildmatch(const char *pattern, const char *text, unsigned int flags) +{ + return dowild((const uchar*)pattern, (const uchar*)text, flags); +} diff -Nru libgit2-0.28.5+dfsg.1/src/wildmatch.h libgit2-1.1.0+dfsg.1/src/wildmatch.h --- libgit2-0.28.5+dfsg.1/src/wildmatch.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/wildmatch.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,23 @@ +/* + * 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_wildmatch_h__ +#define INCLUDE_wildmatch_h__ + +#include "common.h" + +#define WM_CASEFOLD 1 +#define WM_PATHNAME 2 + +#define WM_NOMATCH 1 +#define WM_MATCH 0 +#define WM_ABORT_ALL -1 +#define WM_ABORT_TO_STARSTAR -2 + +int wildmatch(const char *pattern, const char *text, unsigned int flags); + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/win32/git2.rc libgit2-1.1.0+dfsg.1/src/win32/git2.rc --- libgit2-0.28.5+dfsg.1/src/win32/git2.rc 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/git2.rc 2020-10-12 18:53:06.000000000 +0000 @@ -2,14 +2,29 @@ #include "../../include/git2/version.h" #ifndef LIBGIT2_FILENAME -# define LIBGIT2_FILENAME "git2" +# ifdef __GNUC__ +# define LIBGIT2_FILENAME git2 +# else +# define LIBGIT2_FILENAME "git2" +# endif #endif #ifndef LIBGIT2_COMMENTS # define LIBGIT2_COMMENTS "For more information visit http://libgit2.github.com/" #endif +#ifdef __GNUC__ +# define _STR(x) #x +# define STR(x) _STR(x) +#else +# define STR(x) x +#endif + +#ifdef __GNUC__ +VS_VERSION_INFO VERSIONINFO +#else VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE +#endif FILEVERSION LIBGIT2_VER_MAJOR,LIBGIT2_VER_MINOR,LIBGIT2_VER_REVISION,LIBGIT2_VER_PATCH PRODUCTVERSION LIBGIT2_VER_MAJOR,LIBGIT2_VER_MINOR,LIBGIT2_VER_REVISION,LIBGIT2_VER_PATCH FILEFLAGSMASK VS_FFI_FILEFLAGSMASK @@ -29,9 +44,9 @@ BEGIN VALUE "FileDescription", "libgit2 - the Git linkable library\0" VALUE "FileVersion", LIBGIT2_VERSION "\0" - VALUE "InternalName", LIBGIT2_FILENAME ".dll\0" + VALUE "InternalName", STR(LIBGIT2_FILENAME) ".dll\0" VALUE "LegalCopyright", "Copyright (C) the libgit2 contributors. All rights reserved.\0" - VALUE "OriginalFilename", LIBGIT2_FILENAME ".dll\0" + VALUE "OriginalFilename", STR(LIBGIT2_FILENAME) ".dll\0" VALUE "ProductName", "libgit2\0" VALUE "ProductVersion", LIBGIT2_VERSION "\0" VALUE "Comments", LIBGIT2_COMMENTS "\0" diff -Nru libgit2-0.28.5+dfsg.1/src/win32/map.c libgit2-1.1.0+dfsg.1/src/win32/map.c --- libgit2-0.28.5+dfsg.1/src/win32/map.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/map.c 2020-10-12 18:53:06.000000000 +0000 @@ -50,7 +50,7 @@ return 0; } -int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset) +int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset) { HANDLE fh = (HANDLE)_get_osfhandle(fd); DWORD alignment = get_allocation_granularity(); @@ -58,8 +58,8 @@ DWORD view_prot = 0; DWORD off_low = 0; DWORD off_hi = 0; - git_off_t page_start; - git_off_t page_offset; + off64_t page_start; + off64_t page_offset; GIT_MMAP_VALIDATE(out, len, prot, flags); @@ -99,8 +99,6 @@ return -1; } - assert(sizeof(git_off_t) == 8); - off_low = (DWORD)(page_start); off_hi = (DWORD)(page_start >> 32); out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len); diff -Nru libgit2-0.28.5+dfsg.1/src/win32/path_w32.c libgit2-1.1.0+dfsg.1/src/win32/path_w32.c --- libgit2-0.28.5+dfsg.1/src/win32/path_w32.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/path_w32.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,6 +25,9 @@ #define path__is_unc(p) \ (((p)[0] == '\\' && (p)[1] == '\\') || ((p)[0] == '/' && (p)[1] == '/')) +#define path__startswith_slash(p) \ + ((p)[0] == '\\' || (p)[0] == '/') + GIT_INLINE(int) path__cwd(wchar_t *path, int size) { int len; @@ -140,14 +143,24 @@ *to = L'\0'; - return (to - path); + if ((to - path) > INT_MAX) { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return -1; + } + + return (int)(to - path); } -int git_win32_path__cwd(wchar_t *out, size_t len) +static int win32_path_cwd(wchar_t *out, size_t len) { int cwd_len; - if ((cwd_len = path__cwd(out, len)) < 0) + if (len > INT_MAX) { + errno = ENAMETOOLONG; + return -1; + } + + if ((cwd_len = path__cwd(out, (int)len)) < 0) return -1; /* UNC paths */ @@ -211,7 +224,7 @@ goto on_error; } /* Absolute paths omitting the drive letter */ - else if (src[0] == '\\' || src[0] == '/') { + else if (path__startswith_slash(src)) { if (path__cwd(dest, MAX_PATH) < 0) goto on_error; @@ -228,7 +241,7 @@ else { int cwd_len; - if ((cwd_len = git_win32_path__cwd(dest, MAX_PATH)) < 0) + if ((cwd_len = win32_path_cwd(dest, MAX_PATH)) < 0) goto on_error; dest[cwd_len++] = L'\\'; @@ -247,6 +260,30 @@ return -1; } +int git_win32_path_relative_from_utf8(git_win32_path out, const char *src) +{ + wchar_t *dest = out, *p; + int len; + + /* Handle absolute paths */ + if (git_path_is_absolute(src) || + path__is_nt_namespace(src) || + path__is_unc(src) || + path__startswith_slash(src)) { + return git_win32_path_from_utf8(out, src); + } + + if ((len = git__utf8_to_16(dest, MAX_PATH, src)) < 0) + return -1; + + for (p = dest; p < (dest + len); p++) { + if (*p == L'/') + *p = L'\\'; + } + + return len; +} + int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src) { char *out = dest; diff -Nru libgit2-0.28.5+dfsg.1/src/win32/path_w32.h libgit2-1.1.0+dfsg.1/src/win32/path_w32.h --- libgit2-0.28.5+dfsg.1/src/win32/path_w32.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/path_w32.h 2020-10-12 18:53:06.000000000 +0000 @@ -8,45 +8,28 @@ #define INCLUDE_win32_path_w32_h__ #include "common.h" - #include "vector.h" -/* - * Provides a large enough buffer to support Windows paths: MAX_PATH is - * 260, corresponding to a maximum path length of 259 characters plus a - * NULL terminator. Prefixing with "\\?\" adds 4 characters, but if the - * original was a UNC path, then we turn "\\server\share" into - * "\\?\UNC\server\share". So we replace the first two characters with - * 8 characters, a net gain of 6, so the maximum length is MAX_PATH+6. - */ -#define GIT_WIN_PATH_UTF16 MAX_PATH+6 - -/* Maximum size of a UTF-8 Win32 path. We remove the "\\?\" or "\\?\UNC\" - * prefixes for presentation, bringing us back to 259 (non-NULL) - * characters. UTF-8 does have 4-byte sequences, but they are encoded in - * UTF-16 using surrogate pairs, which takes up the space of two characters. - * Two characters in the range U+0800 -> U+FFFF take up more space in UTF-8 - * (6 bytes) than one surrogate pair (4 bytes). - */ -#define GIT_WIN_PATH_UTF8 (259 * 3 + 1) - -/* - * The length of a Windows "shortname", for 8.3 compatibility. +/** + * Create a Win32 path (in UCS-2 format) from a UTF-8 string. If the given + * path is relative, then it will be turned into an absolute path by having + * the current working directory prepended. + * + * @param dest The buffer to receive the wide string. + * @param src The UTF-8 string to convert. + * @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure */ -#define GIT_WIN_PATH_SHORTNAME 13 - -/* Win32 path types */ -typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; -typedef char git_win32_utf8_path[GIT_WIN_PATH_UTF8]; +extern int git_win32_path_from_utf8(git_win32_path dest, const char *src); /** - * Create a Win32 path (in UCS-2 format) from a UTF-8 string. + * Create a Win32 path (in UCS-2 format) from a UTF-8 string. If the given + * path is relative, then it will not be turned into an absolute path. * * @param dest The buffer to receive the wide string. * @param src The UTF-8 string to convert. * @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure */ -extern int git_win32_path_from_utf8(git_win32_path dest, const char *src); +extern int git_win32_path_relative_from_utf8(git_win32_path dest, const char *src); /** * Canonicalize a Win32 UCS-2 path so that it is suitable for delivery to the @@ -55,6 +38,9 @@ * canonical (always backslashes, never forward slashes) and process any * directory entries of '.' or '..'. * + * Note that this is intended to be used on absolute Windows paths, those + * that start with `C:\`, `\\server\share`, `\\?\`, etc. + * * This processes the buffer in place. * * @param path The buffer to process diff -Nru libgit2-0.28.5+dfsg.1/src/win32/posix.h libgit2-1.1.0+dfsg.1/src/win32/posix.h --- libgit2-0.28.5+dfsg.1/src/win32/posix.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/posix.h 2020-10-12 18:53:06.000000000 +0000 @@ -47,7 +47,7 @@ extern int p_chmod(const char* path, mode_t mode); extern int p_rmdir(const char* path); extern int p_access(const char* path, mode_t mode); -extern int p_ftruncate(int fd, git_off_t size); +extern int p_ftruncate(int fd, off64_t size); /* p_lstat is almost but not quite POSIX correct. Specifically, the use of * ENOTDIR is wrong, in that it does not mean precisely that a non-directory @@ -60,7 +60,4 @@ extern struct tm * p_localtime_r(const time_t *timer, struct tm *result); extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result); -/* Use the bundled regcomp */ -#define p_regcomp regcomp - #endif diff -Nru libgit2-0.28.5+dfsg.1/src/win32/posix_w32.c libgit2-1.1.0+dfsg.1/src/win32/posix_w32.c --- libgit2-0.28.5+dfsg.1/src/win32/posix_w32.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/posix_w32.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ #include "common.h" #include "../posix.h" -#include "../fileops.h" +#include "../futils.h" #include "path.h" #include "path_w32.h" #include "utf-conv.h" @@ -210,7 +210,7 @@ * We now take a "git_off_t" rather than "long" because * files may be longer than 2Gb. */ -int p_ftruncate(int fd, git_off_t size) +int p_ftruncate(int fd, off64_t size) { if (size < 0) { errno = EINVAL; @@ -251,9 +251,25 @@ GIT_INLINE(int) unlink_once(const wchar_t *path) { + DWORD error; + if (DeleteFileW(path)) return 0; + if ((error = GetLastError()) == ERROR_ACCESS_DENIED) { + WIN32_FILE_ATTRIBUTE_DATA fdata; + if (!GetFileAttributesExW(path, GetFileExInfoStandard, &fdata) || + !(fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) || + !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + goto out; + + if (RemoveDirectoryW(path)) + return 0; + } + +out: + SetLastError(error); + if (last_error_retryable()) return GIT_RETRY; @@ -398,18 +414,44 @@ return (int)bufsiz; } +static bool target_is_dir(const char *target, const char *path) +{ + git_buf resolved = GIT_BUF_INIT; + git_win32_path resolved_w; + bool isdir = true; + + if (git_path_is_absolute(target)) + git_win32_path_from_utf8(resolved_w, target); + else if (git_path_dirname_r(&resolved, path) < 0 || + git_path_apply_relative(&resolved, target) < 0 || + git_win32_path_from_utf8(resolved_w, resolved.ptr) < 0) + goto out; + + isdir = GetFileAttributesW(resolved_w) & FILE_ATTRIBUTE_DIRECTORY; + +out: + git_buf_dispose(&resolved); + return isdir; +} + int p_symlink(const char *target, const char *path) { git_win32_path target_w, path_w; DWORD dwFlags; + /* + * Convert both target and path to Windows-style paths. Note that we do + * not want to use `git_win32_path_from_utf8` for converting the target, + * as that function will automatically pre-pend the current working + * directory in case the path is not absolute. As Git will instead use + * relative symlinks, this is not someting we want. + */ if (git_win32_path_from_utf8(path_w, path) < 0 || - git__utf8_to_16(target_w, MAX_PATH, target) < 0) + git_win32_path_relative_from_utf8(target_w, target) < 0) return -1; dwFlags = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; - - if (GetFileAttributesW(target_w) & FILE_ATTRIBUTE_DIRECTORY) + if (target_is_dir(target, path)) dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY; if (!CreateSymbolicLinkW(path_w, target_w, dwFlags)) diff -Nru libgit2-0.28.5+dfsg.1/src/win32/precompiled.h libgit2-1.1.0+dfsg.1/src/win32/precompiled.h --- libgit2-0.28.5+dfsg.1/src/win32/precompiled.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/precompiled.h 2020-10-12 18:53:06.000000000 +0000 @@ -13,8 +13,6 @@ #include #include -#include - #include #include #ifdef GIT_THREADS diff -Nru libgit2-0.28.5+dfsg.1/src/win32/thread.c libgit2-1.1.0+dfsg.1/src/win32/thread.c --- libgit2-0.28.5+dfsg.1/src/win32/thread.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/thread.c 2020-10-12 18:53:06.000000000 +0000 @@ -40,15 +40,15 @@ HMODULE hModule = GetModuleHandleW(L"kernel32"); if (hModule) { - win32_srwlock_initialize = (win32_srwlock_fn) + win32_srwlock_initialize = (win32_srwlock_fn)(void *) GetProcAddress(hModule, "InitializeSRWLock"); - win32_srwlock_acquire_shared = (win32_srwlock_fn) + win32_srwlock_acquire_shared = (win32_srwlock_fn)(void *) GetProcAddress(hModule, "AcquireSRWLockShared"); - win32_srwlock_release_shared = (win32_srwlock_fn) + win32_srwlock_release_shared = (win32_srwlock_fn)(void *) GetProcAddress(hModule, "ReleaseSRWLockShared"); - win32_srwlock_acquire_exclusive = (win32_srwlock_fn) + win32_srwlock_acquire_exclusive = (win32_srwlock_fn)(void *) GetProcAddress(hModule, "AcquireSRWLockExclusive"); - win32_srwlock_release_exclusive = (win32_srwlock_fn) + win32_srwlock_release_exclusive = (win32_srwlock_fn)(void *) GetProcAddress(hModule, "ReleaseSRWLockExclusive"); } diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_buffer.c libgit2-1.1.0+dfsg.1/src/win32/w32_buffer.c --- libgit2-0.28.5+dfsg.1/src/win32/w32_buffer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_buffer.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,13 +25,17 @@ int utf8_len, utf8_write_len; size_t new_size; - if (!len_w) + if (!len_w) { return 0; + } else if (len_w > INT_MAX) { + git_error_set_oom(); + return -1; + } assert(string_w); /* Measure the string necessary for conversion */ - if ((utf8_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, NULL, 0, NULL, NULL)) == 0) + if ((utf8_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string_w, (int)len_w, NULL, 0, NULL, NULL)) == 0) return 0; assert(utf8_len > 0); @@ -43,7 +47,7 @@ return -1; if ((utf8_write_len = WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, &buf->ptr[buf->size], utf8_len, NULL, NULL)) == 0) + CP_UTF8, WC_ERR_INVALID_CHARS, string_w, (int)len_w, &buf->ptr[buf->size], utf8_len, NULL, NULL)) == 0) return handle_wc_error(); assert(utf8_write_len == utf8_len); diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_common.h libgit2-1.1.0+dfsg.1/src/win32/w32_common.h --- libgit2-0.28.5+dfsg.1/src/win32/w32_common.h 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_common.h 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * 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_win32_w32_common_h__ +#define INCLUDE_win32_w32_common_h__ + +/* + * Provides a large enough buffer to support Windows paths: MAX_PATH is + * 260, corresponding to a maximum path length of 259 characters plus a + * NULL terminator. Prefixing with "\\?\" adds 4 characters, but if the + * original was a UNC path, then we turn "\\server\share" into + * "\\?\UNC\server\share". So we replace the first two characters with + * 8 characters, a net gain of 6, so the maximum length is MAX_PATH+6. + */ +#define GIT_WIN_PATH_UTF16 MAX_PATH+6 + +/* Maximum size of a UTF-8 Win32 path. We remove the "\\?\" or "\\?\UNC\" + * prefixes for presentation, bringing us back to 259 (non-NULL) + * characters. UTF-8 does have 4-byte sequences, but they are encoded in + * UTF-16 using surrogate pairs, which takes up the space of two characters. + * Two characters in the range U+0800 -> U+FFFF take up more space in UTF-8 + * (6 bytes) than one surrogate pair (4 bytes). + */ +#define GIT_WIN_PATH_UTF8 (259 * 3 + 1) + +/* + * The length of a Windows "shortname", for 8.3 compatibility. + */ +#define GIT_WIN_PATH_SHORTNAME 13 + +/* Win32 path types */ +typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; +typedef char git_win32_utf8_path[GIT_WIN_PATH_UTF8]; + +#endif diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_crtdbg_stacktrace.c libgit2-1.1.0+dfsg.1/src/win32/w32_crtdbg_stacktrace.c --- libgit2-0.28.5+dfsg.1/src/win32/w32_crtdbg_stacktrace.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_crtdbg_stacktrace.c 2020-10-12 18:53:06.000000000 +0000 @@ -71,99 +71,6 @@ static unsigned int g_checkpoint_id = 0; /* to better label leak checkpoints */ static bool g_transient_leaks_since_mark = false; /* payload for hook */ -static void *crtdbg__malloc(size_t len, const char *file, int line) -{ - void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); - if (!ptr) git_error_set_oom(); - return ptr; -} - -static void *crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line) -{ - void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); - if (!ptr) git_error_set_oom(); - return ptr; -} - -static char *crtdbg__strdup(const char *str, const char *file, int line) -{ - char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); - if (!ptr) git_error_set_oom(); - return ptr; -} - -static char *crtdbg__strndup(const char *str, size_t n, const char *file, int line) -{ - size_t length = 0, alloclength; - char *ptr; - - length = p_strnlen(str, n); - - if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) || - !(ptr = crtdbg__malloc(alloclength, file, line))) - return NULL; - - if (length) - memcpy(ptr, str, length); - - ptr[length] = '\0'; - - return ptr; -} - -static char *crtdbg__substrdup(const char *start, size_t n, const char *file, int line) -{ - char *ptr; - size_t alloclen; - - if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) || - !(ptr = crtdbg__malloc(alloclen, file, line))) - return NULL; - - memcpy(ptr, start, n); - ptr[n] = '\0'; - return ptr; -} - -static void *crtdbg__realloc(void *ptr, size_t size, const char *file, int line) -{ - void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); - if (!new_ptr) git_error_set_oom(); - return new_ptr; -} - -static void *crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line) -{ - size_t newsize; - - return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ? - NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line); -} - -static void *crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line) -{ - return crtdbg__reallocarray(NULL, nelem, elsize, file, line); -} - -static void crtdbg__free(void *ptr) -{ - free(ptr); -} - -int git_win32_crtdbg_init_allocator(git_allocator *allocator) -{ - allocator->gmalloc = crtdbg__malloc; - allocator->gcalloc = crtdbg__calloc; - allocator->gstrdup = crtdbg__strdup; - allocator->gstrndup = crtdbg__strndup; - allocator->gsubstrdup = crtdbg__substrdup; - allocator->grealloc = crtdbg__realloc; - allocator->greallocarray = crtdbg__reallocarray; - allocator->gmallocarray = crtdbg__mallocarray; - allocator->gfree = crtdbg__free; - return 0; -} - /** * Compare function for bsearch on g_cs_index table. */ diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_crtdbg_stacktrace.h libgit2-1.1.0+dfsg.1/src/win32/w32_crtdbg_stacktrace.h --- libgit2-0.28.5+dfsg.1/src/win32/w32_crtdbg_stacktrace.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_crtdbg_stacktrace.h 2020-10-12 18:53:06.000000000 +0000 @@ -43,8 +43,6 @@ * startup. See tests/main.c for an example. */ -int git_win32_crtdbg_init_allocator(git_allocator *allocator); - /** * Initialize our memory leak tracking and de-dup data structures. * This should ONLY be called by git_libgit2_init(). diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_stack.c libgit2-1.1.0+dfsg.1/src/win32/w32_stack.c --- libgit2-0.28.5+dfsg.1/src/win32/w32_stack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_stack.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,11 +13,6 @@ #include "win32/posix.h" #include "hash.h" -/** - * This is supposedly defined in WinBase.h (from Windows.h) but there were linker issues. - */ -USHORT WINAPI RtlCaptureStackBackTrace(ULONG, ULONG, PVOID*, PULONG); - static bool g_win32_stack_initialized = false; static HANDLE g_win32_stack_process = INVALID_HANDLE_VALUE; static git_win32__stack__aux_cb_alloc g_aux_cb_alloc = NULL; @@ -81,7 +76,7 @@ } int git_win32__stack_format( - char *pbuf, int buf_len, + char *pbuf, size_t buf_len, const git_win32__stack__raw_data *pdata, const char *prefix, const char *suffix) { @@ -96,10 +91,10 @@ } s; IMAGEHLP_LINE64 line; - int buf_used = 0; + size_t buf_used = 0; unsigned int k; char detail[MY_MAX_FILENAME * 2]; /* filename plus space for function name and formatting */ - int detail_len; + size_t detail_len; if (!g_win32_stack_initialized) { git_error_set(GIT_ERROR_INVALID, "git_win32_stack not initialized."); @@ -176,7 +171,7 @@ } int git_win32__stack( - char * pbuf, int buf_len, + char * pbuf, size_t buf_len, int skip, const char *prefix, const char *suffix) { diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_stack.h libgit2-1.1.0+dfsg.1/src/win32/w32_stack.h --- libgit2-0.28.5+dfsg.1/src/win32/w32_stack.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_stack.h 2020-10-12 18:53:06.000000000 +0000 @@ -38,7 +38,7 @@ * @param aux_msg A buffer where a formatted message should be written. * @param aux_msg_len The size of the buffer. */ -typedef void (*git_win32__stack__aux_cb_lookup)(unsigned int aux_id, char *aux_msg, unsigned int aux_msg_len); +typedef void (*git_win32__stack__aux_cb_lookup)(unsigned int aux_id, char *aux_msg, size_t aux_msg_len); /** * Register an "aux" data provider to augment our C stacktrace data. @@ -116,7 +116,7 @@ * @param suffix String written after each frame; defaults to "\n". */ int git_win32__stack_format( - char *pbuf, int buf_len, + char *pbuf, size_t buf_len, const git_win32__stack__raw_data *pdata, const char *prefix, const char *suffix); @@ -132,7 +132,7 @@ * @param suffix String written after each frame; defaults to "\n". */ int git_win32__stack( - char * pbuf, int buf_len, + char * pbuf, size_t buf_len, int skip, const char *prefix, const char *suffix); diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_util.c libgit2-1.1.0+dfsg.1/src/win32/w32_util.c --- libgit2-0.28.5+dfsg.1/src/win32/w32_util.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_util.c 2020-10-12 18:53:06.000000000 +0000 @@ -93,3 +93,34 @@ *out = (attrs & FILE_ATTRIBUTE_HIDDEN) ? true : false; return 0; } + +int git_win32__file_attribute_to_stat( + struct stat *st, + const WIN32_FILE_ATTRIBUTE_DATA *attrdata, + const wchar_t *path) +{ + git_win32__stat_init(st, + attrdata->dwFileAttributes, + attrdata->nFileSizeHigh, + attrdata->nFileSizeLow, + attrdata->ftCreationTime, + attrdata->ftLastAccessTime, + attrdata->ftLastWriteTime); + + if (attrdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && path) { + git_win32_path target; + + if (git_win32_path_readlink_w(target, path) >= 0) { + st->st_mode = (st->st_mode & ~S_IFMT) | S_IFLNK; + + /* st_size gets the UTF-8 length of the target name, in bytes, + * not counting the NULL terminator */ + if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) { + git_error_set(GIT_ERROR_OS, "could not convert reparse point name for '%ls'", path); + return -1; + } + } + } + + return 0; +} diff -Nru libgit2-0.28.5+dfsg.1/src/win32/w32_util.h libgit2-1.1.0+dfsg.1/src/win32/w32_util.h --- libgit2-0.28.5+dfsg.1/src/win32/w32_util.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/win32/w32_util.h 2020-10-12 18:53:06.000000000 +0000 @@ -59,6 +59,11 @@ */ extern int git_win32__hidden(bool *hidden, const char *path); +extern int git_win32__file_attribute_to_stat( + struct stat *st, + const WIN32_FILE_ATTRIBUTE_DATA *attrdata, + const wchar_t *path); + /** * Converts a FILETIME structure to a struct timespec. * @@ -115,7 +120,7 @@ st->st_uid = 0; st->st_nlink = 1; st->st_mode = mode; - st->st_size = ((git_off_t)nFileSizeHigh << 32) + nFileSizeLow; + st->st_size = ((int64_t)nFileSizeHigh << 32) + nFileSizeLow; st->st_dev = _getdrive() - 1; st->st_rdev = st->st_dev; git_win32__filetime_to_timespec(&ftLastAccessTime, &(st->st_atim)); @@ -136,35 +141,4 @@ fileinfo->ftLastWriteTime); } -GIT_INLINE(int) git_win32__file_attribute_to_stat( - struct stat *st, - const WIN32_FILE_ATTRIBUTE_DATA *attrdata, - const wchar_t *path) -{ - git_win32__stat_init(st, - attrdata->dwFileAttributes, - attrdata->nFileSizeHigh, - attrdata->nFileSizeLow, - attrdata->ftCreationTime, - attrdata->ftLastAccessTime, - attrdata->ftLastWriteTime); - - if (attrdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && path) { - git_win32_path target; - - if (git_win32_path_readlink_w(target, path) >= 0) { - st->st_mode = (st->st_mode & ~S_IFMT) | S_IFLNK; - - /* st_size gets the UTF-8 length of the target name, in bytes, - * not counting the NULL terminator */ - if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) { - git_error_set(GIT_ERROR_OS, "could not convert reparse point name for '%ls'", path); - return -1; - } - } - } - - return 0; -} - #endif diff -Nru libgit2-0.28.5+dfsg.1/src/worktree.c libgit2-1.1.0+dfsg.1/src/worktree.c --- libgit2-0.28.5+dfsg.1/src/worktree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/worktree.c 2020-10-12 18:53:06.000000000 +0000 @@ -34,7 +34,7 @@ git_vector worktrees = GIT_VECTOR_INIT; git_buf path = GIT_BUF_INIT; char *worktree; - unsigned i, len; + size_t i, len; int error; assert(wts && repo); @@ -136,11 +136,11 @@ goto out; } - if ((wt->name = git__strdup(name)) == NULL - || (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL - || (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL - || (parent && (wt->parent_path = git__strdup(parent)) == NULL) - || (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) { + if ((wt->name = git__strdup(name)) == NULL || + (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL || + (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL || + (parent && (wt->parent_path = git__strdup(parent)) == NULL) || + (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) { error = -1; goto out; } @@ -149,7 +149,10 @@ goto out; wt->gitdir_path = git_buf_detach(&gitdir); - wt->locked = !!git_worktree_is_locked(NULL, wt); + if ((error = git_worktree_is_locked(NULL, wt)) < 0) + goto out; + wt->locked = !!error; + error = 0; *out = wt; @@ -238,21 +241,21 @@ if (!is_worktree_dir(wt->gitdir_path)) { git_error_set(GIT_ERROR_WORKTREE, - "Worktree gitdir ('%s') is not valid", + "worktree gitdir ('%s') is not valid", wt->gitlink_path); return GIT_ERROR; } if (wt->parent_path && !git_path_exists(wt->parent_path)) { git_error_set(GIT_ERROR_WORKTREE, - "Worktree parent directory ('%s') does not exist ", + "worktree parent directory ('%s') does not exist ", wt->parent_path); return GIT_ERROR; } if (!git_path_exists(wt->commondir_path)) { git_error_set(GIT_ERROR_WORKTREE, - "Worktree common directory ('%s') does not exist ", + "worktree common directory ('%s') does not exist ", wt->commondir_path); return GIT_ERROR; } @@ -260,7 +263,7 @@ return 0; } -int git_worktree_add_init_options(git_worktree_add_options *opts, +int git_worktree_add_options_init(git_worktree_add_options *opts, unsigned int version) { GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version, @@ -268,6 +271,14 @@ return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_worktree_add_init_options(git_worktree_add_options *opts, + unsigned int version) +{ + return git_worktree_add_options_init(opts, version); +} +#endif + int git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *worktree, const git_worktree_add_options *opts) @@ -290,6 +301,20 @@ *out = NULL; + if (wtopts.ref) { + if (!git_reference_is_branch(wtopts.ref)) { + git_error_set(GIT_ERROR_WORKTREE, "reference is not a branch"); + err = -1; + goto out; + } + + if (git_branch_is_checked_out(wtopts.ref)) { + git_error_set(GIT_ERROR_WORKTREE, "reference is already checked out"); + err = -1; + goto out; + } + } + /* Create gitdir directory ".git/worktrees/" */ if ((err = git_buf_joinpath(&gitdir, repo->commondir, "worktrees")) < 0) goto out; @@ -342,18 +367,6 @@ /* Set up worktree reference */ if (wtopts.ref) { - if (!git_reference_is_branch(wtopts.ref)) { - git_error_set(GIT_ERROR_WORKTREE, "reference is not a branch"); - err = -1; - goto out; - } - - if (git_branch_is_checked_out(wtopts.ref)) { - git_error_set(GIT_ERROR_WORKTREE, "reference is already checked out"); - err = -1; - goto out; - } - if ((err = git_reference_dup(&ref, wtopts.ref)) < 0) goto out; } else { @@ -395,20 +408,24 @@ int git_worktree_lock(git_worktree *wt, const char *reason) { git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; - int err; + int error; assert(wt); - if ((err = git_worktree_is_locked(NULL, wt)) < 0) + if ((error = git_worktree_is_locked(NULL, wt)) < 0) + goto out; + if (error) { + error = GIT_ELOCKED; goto out; + } - if ((err = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) + if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) goto out; if (reason) git_buf_attach_notowned(&buf, reason, strlen(reason)); - if ((err = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0) + if ((error = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0) goto out; wt->locked = 1; @@ -416,16 +433,19 @@ out: git_buf_dispose(&path); - return err; + return error; } int git_worktree_unlock(git_worktree *wt) { git_buf path = GIT_BUF_INIT; + int error; assert(wt); - if (!git_worktree_is_locked(NULL, wt)) + if ((error = git_worktree_is_locked(NULL, wt)) < 0) + return error; + if (!error) return 1; if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0) @@ -446,22 +466,25 @@ int git_worktree_is_locked(git_buf *reason, const git_worktree *wt) { git_buf path = GIT_BUF_INIT; - int ret; + int error, locked; assert(wt); if (reason) git_buf_clear(reason); - if ((ret = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) + if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) + goto out; + locked = git_path_exists(path.ptr); + if (locked && reason && + (error = git_futils_readbuffer(reason, path.ptr)) < 0) goto out; - if ((ret = git_path_exists(path.ptr)) && reason) - git_futils_readbuffer(reason, path.ptr); + error = locked; out: git_buf_dispose(&path); - return ret; + return error; } const char *git_worktree_name(const git_worktree *wt) @@ -476,7 +499,7 @@ return wt->worktree_path; } -int git_worktree_prune_init_options( +int git_worktree_prune_options_init( git_worktree_prune_options *opts, unsigned int version) { @@ -485,10 +508,17 @@ return 0; } +#ifndef GIT_DEPRECATE_HARD +int git_worktree_prune_init_options(git_worktree_prune_options *opts, + unsigned int version) +{ + return git_worktree_prune_options_init(opts, version); +} +#endif + int git_worktree_is_prunable(git_worktree *wt, git_worktree_prune_options *opts) { - git_buf reason = GIT_BUF_INIT; git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT; GIT_ERROR_CHECK_VERSION( @@ -498,21 +528,25 @@ if (opts) memcpy(&popts, opts, sizeof(popts)); - if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 && - git_worktree_is_locked(&reason, wt)) - { - if (!reason.size) - git_buf_attach_notowned(&reason, "no reason given", 15); - git_error_set(GIT_ERROR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr); - git_buf_dispose(&reason); - - return 0; + if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0) { + git_buf reason = GIT_BUF_INIT; + int error; + + if ((error = git_worktree_is_locked(&reason, wt)) < 0) + return error; + + if (error) { + if (!reason.size) + git_buf_attach_notowned(&reason, "no reason given", 15); + git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr); + git_buf_dispose(&reason); + return 0; + } } if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 && - git_worktree_validate(wt) == 0) - { - git_error_set(GIT_ERROR_WORKTREE, "Not pruning valid working tree"); + git_worktree_validate(wt) == 0) { + git_error_set(GIT_ERROR_WORKTREE, "not pruning valid working tree"); return 0; } @@ -544,7 +578,7 @@ goto out; if (!git_path_exists(path.ptr)) { - git_error_set(GIT_ERROR_WORKTREE, "Worktree gitdir '%s' does not exist", path.ptr); + git_error_set(GIT_ERROR_WORKTREE, "worktree gitdir '%s' does not exist", path.ptr); err = -1; goto out; } @@ -564,7 +598,7 @@ git_buf_attach(&path, wtpath, 0); if (!git_path_exists(path.ptr)) { - git_error_set(GIT_ERROR_WORKTREE, "Working tree '%s' does not exist", path.ptr); + git_error_set(GIT_ERROR_WORKTREE, "working tree '%s' does not exist", path.ptr); err = -1; goto out; } diff -Nru libgit2-0.28.5+dfsg.1/src/xdiff/xdiffi.c libgit2-1.1.0+dfsg.1/src/xdiff/xdiffi.c --- libgit2-0.28.5+dfsg.1/src/xdiff/xdiffi.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/xdiff/xdiffi.c 2020-10-12 18:53:06.000000000 +0000 @@ -36,7 +36,7 @@ #elif defined(__GNUC__) # define XDL_INLINE(type) static __inline__ type #else -#define XDG_INLINE(type) static type +# define XDL_INLINE(type) static type #endif typedef struct s_xdpsplit { diff -Nru libgit2-0.28.5+dfsg.1/src/xdiff/xmerge.c libgit2-1.1.0+dfsg.1/src/xdiff/xmerge.c --- libgit2-0.28.5+dfsg.1/src/xdiff/xmerge.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/xdiff/xmerge.c 2020-10-12 18:53:06.000000000 +0000 @@ -717,10 +717,22 @@ status = 0; if (!xscr1) { result->ptr = xdl_malloc(mf2->size); + if (!result->ptr) { + xdl_free_script(xscr2); + xdl_free_env(&xe1); + xdl_free_env(&xe2); + return -1; + } memcpy(result->ptr, mf2->ptr, mf2->size); result->size = mf2->size; } else if (!xscr2) { result->ptr = xdl_malloc(mf1->size); + if (!result->ptr) { + xdl_free_script(xscr1); + xdl_free_env(&xe1); + xdl_free_env(&xe2); + return -1; + } memcpy(result->ptr, mf1->ptr, mf1->size); result->size = mf1->size; } else { diff -Nru libgit2-0.28.5+dfsg.1/src/xdiff/xpatience.c libgit2-1.1.0+dfsg.1/src/xdiff/xpatience.c --- libgit2-0.28.5+dfsg.1/src/xdiff/xpatience.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/xdiff/xpatience.c 2020-10-12 18:53:06.000000000 +0000 @@ -217,6 +217,9 @@ */ int anchor_i = -1; + if (!sequence) + return NULL; + for (entry = map->first; entry; entry = entry->next) { if (!entry->line2 || entry->line2 == NON_UNIQUE) continue; diff -Nru libgit2-0.28.5+dfsg.1/src/zstream.c libgit2-1.1.0+dfsg.1/src/zstream.c --- libgit2-0.28.5+dfsg.1/src/zstream.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/zstream.c 2020-10-12 18:53:06.000000000 +0000 @@ -77,6 +77,11 @@ return (!zstream->in_len && zstream->zerr == Z_STREAM_END); } +bool git_zstream_eos(git_zstream *zstream) +{ + return zstream->zerr == Z_STREAM_END; +} + size_t git_zstream_suggest_output_len(git_zstream *zstream) { if (zstream->in_len > ZSTREAM_BUFFER_SIZE) diff -Nru libgit2-0.28.5+dfsg.1/src/zstream.h libgit2-1.1.0+dfsg.1/src/zstream.h --- libgit2-0.28.5+dfsg.1/src/zstream.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/src/zstream.h 2020-10-12 18:53:06.000000000 +0000 @@ -44,6 +44,7 @@ int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream); bool git_zstream_done(git_zstream *zstream); +bool git_zstream_eos(git_zstream *zstream); void git_zstream_reset(git_zstream *zstream); diff -Nru libgit2-0.28.5+dfsg.1/tests/apply/apply_helpers.h libgit2-1.1.0+dfsg.1/tests/apply/apply_helpers.h --- libgit2-0.28.5+dfsg.1/tests/apply/apply_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/apply/apply_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -21,6 +21,27 @@ "-longer. take out the slices of ham, and skim off the grease if any\n" \ "+longer; take out the slices of ham, and skim off the grease if any\n" +/* This is the binary equivalent of DIFF_MODIFY_TWO_FILES */ +#define DIFF_MODIFY_TWO_FILES_BINARY \ + "diff --git a/asparagus.txt b/asparagus.txt\n" \ + "index f51658077d85f2264fa179b4d0848268cb3475c3..ffb36e513f5fdf8a6ba850a20142676a2ac4807d 100644\n" \ + "GIT binary patch\n" \ + "delta 24\n" \ + "fcmX@ja+-zTF*v|6$k9DCSRvRyG(c}7zYP-rT_OhP\n" \ + "\n" \ + "delta 24\n" \ + "fcmX@ja+-zTF*v|6$k9DCSRvRyG(d49zYP-rT;T@W\n" \ + "\n" \ + "diff --git a/veal.txt b/veal.txt\n" \ + "index 94d2c01087f48213bd157222d54edfefd77c9bba..a7b066537e6be7109abfe4ff97b675d4e077da20 100644\n" \ + "GIT binary patch\n" \ + "delta 26\n" \ + "hcmX@kah!uI%+=9HA=p1OKyM?L03)OIW@$zpW&mXg25bNT\n" \ + "\n" \ + "delta 26\n" \ + "hcmX@kah!uI%+=9HA=p1OKyf3N03)N`W@$zpW&mU#22ub3\n" \ + "\n" + #define DIFF_DELETE_FILE \ "diff --git a/gravy.txt b/gravy.txt\n" \ "deleted file mode 100644\n" \ diff -Nru libgit2-0.28.5+dfsg.1/tests/apply/check.c libgit2-1.1.0+dfsg.1/tests/apply/check.c --- libgit2-0.28.5+dfsg.1/tests/apply/check.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/apply/check.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,121 @@ +#include "clar_libgit2.h" +#include "apply_helpers.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-recursive" + +void test_apply_check__initialize(void) +{ + git_oid oid; + git_commit *commit; + + repo = cl_git_sandbox_init(TEST_REPO_PATH); + + git_oid_fromstr(&oid, "539bd011c4822c560c1d17cab095006b7a10f707"); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + cl_git_pass(git_reset(repo, (git_object *)commit, GIT_RESET_HARD, NULL)); + git_commit_free(commit); +} + +void test_apply_check__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_apply_check__generate_diff(void) +{ + git_oid a_oid, b_oid; + git_commit *a_commit, *b_commit; + git_tree *a_tree, *b_tree; + git_diff *diff; + git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; + git_apply_options opts = GIT_APPLY_OPTIONS_INIT; + + cl_git_pass(git_oid_fromstr(&a_oid, "539bd011c4822c560c1d17cab095006b7a10f707")); + cl_git_pass(git_oid_fromstr(&b_oid, "7c7bf85e978f1d18c0566f702d2cb7766b9c8d4f")); + cl_git_pass(git_commit_lookup(&a_commit, repo, &a_oid)); + cl_git_pass(git_commit_lookup(&b_commit, repo, &b_oid)); + + cl_git_pass(git_commit_tree(&a_tree, a_commit)); + cl_git_pass(git_commit_tree(&b_tree, b_commit)); + + opts.flags |= GIT_APPLY_CHECK; + cl_git_pass(git_diff_tree_to_tree(&diff, repo, a_tree, b_tree, &diff_opts)); + cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, &opts)); + + validate_index_unchanged(repo); + validate_workdir_unchanged(repo); + + git_diff_free(diff); + git_tree_free(a_tree); + git_tree_free(b_tree); + git_commit_free(a_commit); + git_commit_free(b_commit); +} + +void test_apply_check__parsed_diff(void) +{ + git_diff *diff; + git_apply_options opts = GIT_APPLY_OPTIONS_INIT; + + opts.flags |= GIT_APPLY_CHECK; + cl_git_pass(git_diff_from_buffer(&diff, + DIFF_MODIFY_TWO_FILES, strlen(DIFF_MODIFY_TWO_FILES))); + cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_INDEX, &opts)); + + validate_index_unchanged(repo); + validate_workdir_unchanged(repo); + + git_diff_free(diff); +} + +void test_apply_check__binary(void) +{ + git_diff *diff; + git_apply_options opts = GIT_APPLY_OPTIONS_INIT; + + opts.flags |= GIT_APPLY_CHECK; + cl_git_pass(git_diff_from_buffer(&diff, + DIFF_MODIFY_TWO_FILES_BINARY, + strlen(DIFF_MODIFY_TWO_FILES_BINARY))); + cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_INDEX, &opts)); + + validate_index_unchanged(repo); + validate_workdir_unchanged(repo); + + git_diff_free(diff); +} + +void test_apply_check__does_not_apply(void) +{ + git_diff *diff; + git_index *index; + git_apply_options opts = GIT_APPLY_OPTIONS_INIT; + + const char *diff_file = DIFF_MODIFY_TWO_FILES; + + struct merge_index_entry index_expected[] = { + { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" }, + { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, + { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, + { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, + { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, + }; + size_t index_expected_cnt = sizeof(index_expected) / + sizeof(struct merge_index_entry); + + /* mutate the index */ + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_remove(index, "veal.txt", 0)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + opts.flags |= GIT_APPLY_CHECK; + cl_git_pass(git_diff_from_buffer(&diff, diff_file, strlen(diff_file))); + cl_git_fail_with(GIT_EAPPLYFAIL, git_apply(repo, diff, GIT_APPLY_LOCATION_INDEX, &opts)); + + validate_apply_index(repo, index_expected, index_expected_cnt); + + git_diff_free(diff); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/attr_expect.h libgit2-1.1.0+dfsg.1/tests/attr/attr_expect.h --- libgit2-0.28.5+dfsg.1/tests/attr/attr_expect.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/attr_expect.h 2020-10-12 18:53:06.000000000 +0000 @@ -23,15 +23,15 @@ { switch (expected) { case EXPECT_TRUE: - cl_assert_(GIT_ATTR_TRUE(value), name); + cl_assert_(GIT_ATTR_IS_TRUE(value), name); break; case EXPECT_FALSE: - cl_assert_(GIT_ATTR_FALSE(value), name); + cl_assert_(GIT_ATTR_IS_FALSE(value), name); break; case EXPECT_UNDEFINED: - cl_assert_(GIT_ATTR_UNSPECIFIED(value), name); + cl_assert_(GIT_ATTR_IS_UNSPECIFIED(value), name); break; case EXPECT_STRING: diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/file.c libgit2-1.1.0+dfsg.1/tests/attr/file.c --- libgit2-0.28.5+dfsg.1/tests/attr/file.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/file.c 2020-10-12 18:53:06.000000000 +0000 @@ -26,7 +26,7 @@ assign = get_assign(rule, 0); cl_assert(assign != NULL); cl_assert_equal_s("binary", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); git_attr_file__free(file); } @@ -53,7 +53,7 @@ assign = get_assign(rule,0); cl_assert_equal_s("attr0", assign->name); cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name)); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); rule = get_rule(1); cl_assert_equal_s("pat1", rule->match.pattern); @@ -83,7 +83,7 @@ cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); assign = get_assign(rule,0); cl_assert_equal_s("attr7", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); rule = get_rule(8); cl_assert_equal_s("pat8 with spaces", rule->match.pattern); @@ -144,11 +144,11 @@ assign = git_attr_rule__lookup_assignment(rule, "multiple"); cl_assert(assign); cl_assert_equal_s("multiple", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); assign = git_attr_rule__lookup_assignment(rule, "single"); cl_assert(assign); cl_assert_equal_s("single", assign->name); - cl_assert(GIT_ATTR_FALSE(assign->value)); + cl_assert(GIT_ATTR_IS_FALSE(assign->value)); assign = git_attr_rule__lookup_assignment(rule, "values"); cl_assert(assign); cl_assert_equal_s("values", assign->name); @@ -170,7 +170,7 @@ assign = git_attr_rule__lookup_assignment(rule, "again"); cl_assert(assign); cl_assert_equal_s("again", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); assign = git_attr_rule__lookup_assignment(rule, "another"); cl_assert(assign); cl_assert_equal_s("another", assign->name); @@ -181,16 +181,11 @@ git_attr_file__free(file); } -void test_attr_file__check_attr_examples(void) +static void assert_examples(git_attr_file *file) { - git_attr_file *file; git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr3"))); - cl_assert_equal_s(cl_fixture("attr/attr3"), file->entry->path); - cl_assert(file->rules.length == 3); - rule = get_rule(0); cl_assert_equal_s("*.java", rule->match.pattern); cl_assert(rule->assigns.length == 3); @@ -199,10 +194,10 @@ cl_assert_equal_s("java", assign->value); assign = git_attr_rule__lookup_assignment(rule, "crlf"); cl_assert_equal_s("crlf", assign->name); - cl_assert(GIT_ATTR_FALSE(assign->value)); + cl_assert(GIT_ATTR_IS_FALSE(assign->value)); assign = git_attr_rule__lookup_assignment(rule, "myAttr"); cl_assert_equal_s("myAttr", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); + cl_assert(GIT_ATTR_IS_TRUE(assign->value)); assign = git_attr_rule__lookup_assignment(rule, "missing"); cl_assert(assign == NULL); @@ -211,7 +206,7 @@ cl_assert(rule->assigns.length == 1); assign = get_assign(rule, 0); cl_assert_equal_s("myAttr", assign->name); - cl_assert(GIT_ATTR_UNSPECIFIED(assign->value)); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(assign->value)); rule = get_rule(2); cl_assert_equal_s("README", rule->match.pattern); @@ -219,6 +214,30 @@ assign = get_assign(rule, 0); cl_assert_equal_s("caveat", assign->name); cl_assert_equal_s("unspecified", assign->value); +} + +void test_attr_file__check_attr_examples(void) +{ + git_attr_file *file; + + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr3"))); + cl_assert_equal_s(cl_fixture("attr/attr3"), file->entry->path); + cl_assert(file->rules.length == 3); + + assert_examples(file); + + git_attr_file__free(file); +} + +void test_attr_file__whitespace(void) +{ + git_attr_file *file; + + cl_git_pass(git_attr_file__load_standalone(&file, cl_fixture("attr/attr4"))); + cl_assert_equal_s(cl_fixture("attr/attr4"), file->entry->path); + cl_assert(file->rules.length == 3); + + assert_examples(file); git_attr_file__free(file); } diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/flags.c libgit2-1.1.0+dfsg.1/tests/attr/flags.c --- libgit2-0.28.5+dfsg.1/tests/attr/flags.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/flags.c 2020-10-12 18:53:06.000000000 +0000 @@ -15,7 +15,7 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM, "README.md", "diff")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(value)); } void test_attr_flags__index_vs_workdir(void) @@ -29,7 +29,7 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, "README.md", "bar")); - cl_assert(GIT_ATTR_FALSE(value)); + cl_assert(GIT_ATTR_IS_FALSE(value)); cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, @@ -39,13 +39,13 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, "README.txt", "foo")); - cl_assert(GIT_ATTR_FALSE(value)); + cl_assert(GIT_ATTR_IS_FALSE(value)); /* index then wd */ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, "README.md", "bar")); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, @@ -55,7 +55,7 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, "README.txt", "foo")); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); } void test_attr_flags__subdir(void) @@ -77,7 +77,7 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, "sub/sub/README.txt", "again")); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, @@ -98,7 +98,7 @@ cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, "sub/sub/README.txt", "again")); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); cl_git_pass(git_attr_get( &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/ignore.c libgit2-1.1.0+dfsg.1/tests/attr/ignore.c --- libgit2-0.28.5+dfsg.1/tests/attr/ignore.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/ignore.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,415 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "path.h" -#include "fileops.h" - -static git_repository *g_repo = NULL; - -void test_attr_ignore__initialize(void) -{ - g_repo = cl_git_sandbox_init("attr"); -} - -void test_attr_ignore__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -static void assert_is_ignored_( - bool expected, const char *filepath, const char *file, int line) -{ - int is_ignored = 0; - - cl_git_expect( - git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), 0, file, line); - - clar__assert_equal( - file, line, "expected != is_ignored", 1, "%d", - (int)(expected != 0), (int)(is_ignored != 0)); -} -#define assert_is_ignored(expected, filepath) \ - assert_is_ignored_(expected, filepath, __FILE__, __LINE__) - -void test_attr_ignore__honor_temporary_rules(void) -{ - cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__allow_root(void) -{ - cl_git_rewritefile("attr/.gitignore", "/"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(false, "NewFolder"); - assert_is_ignored(false, "NewFolder/NewFolder"); - assert_is_ignored(false, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__ignore_space(void) -{ - cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder \n/NewFolder/NewFolder"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__ignore_dir(void) -{ - cl_git_rewritefile("attr/.gitignore", "dir/\n"); - - assert_is_ignored(true, "dir"); - assert_is_ignored(true, "dir/file"); -} - -void test_attr_ignore__ignore_dir_with_trailing_space(void) -{ - cl_git_rewritefile("attr/.gitignore", "dir/ \n"); - - assert_is_ignored(true, "dir"); - assert_is_ignored(true, "dir/file"); -} - -void test_attr_ignore__ignore_root(void) -{ - cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__full_paths(void) -{ - cl_git_rewritefile("attr/.gitignore", "Folder/*/Contained"); - - assert_is_ignored(true, "Folder/Middle/Contained"); - assert_is_ignored(false, "Folder/Middle/More/More/Contained"); - - cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained"); - - assert_is_ignored(true, "Folder/Middle/Contained"); - assert_is_ignored(true, "Folder/Middle/More/More/Contained"); - - cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained/*/Child"); - - assert_is_ignored(true, "Folder/Middle/Contained/Happy/Child"); - assert_is_ignored(false, "Folder/Middle/Contained/Not/Happy/Child"); - assert_is_ignored(true, "Folder/Middle/More/More/Contained/Happy/Child"); - assert_is_ignored(false, "Folder/Middle/More/More/Contained/Not/Happy/Child"); -} - -void test_attr_ignore__more_starstar_cases(void) -{ - cl_must_pass(p_unlink("attr/.gitignore")); - cl_git_mkfile( - "attr/dir/.gitignore", - "sub/**/*.html\n"); - - assert_is_ignored(false, "aaa.html"); - assert_is_ignored(false, "dir"); - assert_is_ignored(false, "dir/sub"); - assert_is_ignored(true, "dir/sub/sub2/aaa.html"); - assert_is_ignored(true, "dir/sub/aaa.html"); - assert_is_ignored(false, "dir/aaa.html"); - assert_is_ignored(false, "sub"); - assert_is_ignored(false, "sub/aaa.html"); - assert_is_ignored(false, "sub/sub2/aaa.html"); -} - -void test_attr_ignore__leading_stars(void) -{ - cl_git_rewritefile( - "attr/.gitignore", - "*/onestar\n" - "**/twostars\n" - "*/parent1/kid1/*\n" - "**/parent2/kid2/*\n"); - - assert_is_ignored(true, "dir1/onestar"); - assert_is_ignored(true, "dir1/onestar/child"); /* in ignored dir */ - assert_is_ignored(false, "dir1/dir2/onestar"); - - assert_is_ignored(true, "dir1/twostars"); - assert_is_ignored(true, "dir1/twostars/child"); /* in ignored dir */ - assert_is_ignored(true, "dir1/dir2/twostars"); - assert_is_ignored(true, "dir1/dir2/twostars/child"); /* in ignored dir */ - assert_is_ignored(true, "dir1/dir2/dir3/twostars"); - - assert_is_ignored(true, "dir1/parent1/kid1/file"); - assert_is_ignored(true, "dir1/parent1/kid1/file/inside/parent"); - assert_is_ignored(false, "dir1/dir2/parent1/kid1/file"); - assert_is_ignored(false, "dir1/parent1/file"); - assert_is_ignored(false, "dir1/kid1/file"); - - assert_is_ignored(true, "dir1/parent2/kid2/file"); - assert_is_ignored(true, "dir1/parent2/kid2/file/inside/parent"); - assert_is_ignored(true, "dir1/dir2/parent2/kid2/file"); - assert_is_ignored(true, "dir1/dir2/dir3/parent2/kid2/file"); - assert_is_ignored(false, "dir1/parent2/file"); - assert_is_ignored(false, "dir1/kid2/file"); -} - -void test_attr_ignore__globs_and_path_delimiters(void) -{ - cl_git_rewritefile("attr/.gitignore", "foo/bar/**"); - assert_is_ignored(true, "foo/bar/baz"); - assert_is_ignored(true, "foo/bar/baz/quux"); - - cl_git_rewritefile("attr/.gitignore", "_*/"); - assert_is_ignored(true, "sub/_test/a/file"); - assert_is_ignored(false, "test_folder/file"); - assert_is_ignored(true, "_test/file"); - assert_is_ignored(true, "_test/a/file"); - - cl_git_rewritefile("attr/.gitignore", "**/_*/"); - assert_is_ignored(true, "sub/_test/a/file"); - assert_is_ignored(false, "test_folder/file"); - assert_is_ignored(true, "_test/file"); - assert_is_ignored(true, "_test/a/file"); - - cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux"); - - assert_is_ignored(true, "sub/_test/foo/bar/qux/file"); - assert_is_ignored(true, "_test/foo/bar/qux/file"); - assert_is_ignored(true, "_test/foo/bar/crux/file"); - assert_is_ignored(false, "_test/foo/bar/code/file"); -} - -void test_attr_ignore__skip_gitignore_directory(void) -{ - cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder"); - p_unlink("attr/.gitignore"); - cl_assert(!git_path_exists("attr/.gitignore")); - p_mkdir("attr/.gitignore", 0777); - cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__subdirectory_gitignore(void) -{ - p_unlink("attr/.gitignore"); - cl_assert(!git_path_exists("attr/.gitignore")); - cl_git_mkfile( - "attr/.gitignore", - "file1\n"); - p_mkdir("attr/dir", 0777); - cl_git_mkfile( - "attr/dir/.gitignore", - "file2/\n"); - - assert_is_ignored(true, "file1"); - assert_is_ignored(true, "dir/file1"); - assert_is_ignored(true, "dir/file2/actual_file"); /* in ignored dir */ - assert_is_ignored(false, "dir/file3"); -} - -void test_attr_ignore__expand_tilde_to_homedir(void) -{ - git_config *cfg; - - assert_is_ignored(false, "example.global_with_tilde"); - - cl_fake_home(); - - /* construct fake home with fake global excludes */ - cl_git_mkfile("home/globalexclude", "# found me\n*.global_with_tilde\n"); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexclude")); - git_config_free(cfg); - - git_attr_cache_flush(g_repo); /* must reset to pick up change */ - - assert_is_ignored(true, "example.global_with_tilde"); - - cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_fake_home_cleanup(NULL); - - git_attr_cache_flush(g_repo); /* must reset to pick up change */ - - assert_is_ignored(false, "example.global_with_tilde"); -} - -/* Ensure that the .gitignore in the subdirectory only affects - * items in the subdirectory. */ -void test_attr_ignore__gitignore_in_subdir(void) -{ - cl_git_rmfile("attr/.gitignore"); - - cl_must_pass(p_mkdir("attr/dir1", 0777)); - cl_must_pass(p_mkdir("attr/dir1/dir2", 0777)); - cl_must_pass(p_mkdir("attr/dir1/dir2/dir3", 0777)); - - cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "dir1/\ndir1/subdir/"); - - assert_is_ignored(false, "dir1/file"); - assert_is_ignored(false, "dir1/dir2/file"); - assert_is_ignored(false, "dir1/dir2/dir3/file"); - assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); - assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); - - if (cl_repo_get_bool(g_repo, "core.ignorecase")) { - cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "DiR1/\nDiR1/subdir/\n"); - - assert_is_ignored(false, "dir1/file"); - assert_is_ignored(false, "dir1/dir2/file"); - assert_is_ignored(false, "dir1/dir2/dir3/file"); - assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); - assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); - } -} - -/* Ensure that files do not match folder cases */ -void test_attr_ignore__dont_ignore_files_for_folder(void) -{ - cl_git_rmfile("attr/.gitignore"); - - cl_git_mkfile("attr/dir/.gitignore", "test/\n"); - - /* Create "test" as a file; ensure it is not ignored. */ - cl_git_mkfile("attr/dir/test", "This is a file."); - - assert_is_ignored(false, "dir/test"); - if (cl_repo_get_bool(g_repo, "core.ignorecase")) - assert_is_ignored(false, "dir/TeSt"); - - /* Create "test" as a directory; ensure it is ignored. */ - cl_git_rmfile("attr/dir/test"); - cl_must_pass(p_mkdir("attr/dir/test", 0777)); - - assert_is_ignored(true, "dir/test"); - if (cl_repo_get_bool(g_repo, "core.ignorecase")) - assert_is_ignored(true, "dir/TeSt"); - - /* Remove "test" entirely; ensure it is not ignored. - * (As it doesn't exist, it is not a directory.) - */ - cl_must_pass(p_rmdir("attr/dir/test")); - - assert_is_ignored(false, "dir/test"); - if (cl_repo_get_bool(g_repo, "core.ignorecase")) - assert_is_ignored(false, "dir/TeSt"); -} - -void test_attr_ignore__symlink_to_outside(void) -{ -#ifdef GIT_WIN32 - cl_skip(); -#endif - - cl_git_rewritefile("attr/.gitignore", "symlink\n"); - cl_git_mkfile("target", "target"); - cl_git_pass(p_symlink("../target", "attr/symlink")); - assert_is_ignored(true, "symlink"); - assert_is_ignored(true, "lala/../symlink"); -} - -void test_attr_ignore__test(void) -{ - cl_git_rewritefile("attr/.gitignore", - "/*/\n" - "!/src\n"); - assert_is_ignored(false, "src/foo.c"); - assert_is_ignored(false, "src/foo/foo.c"); - assert_is_ignored(false, "README.md"); - assert_is_ignored(true, "dist/foo.o"); - assert_is_ignored(true, "bin/foo"); -} - -void test_attr_ignore__unignore_dir_succeeds(void) -{ - cl_git_rewritefile("attr/.gitignore", - "*.c\n" - "!src/*.c\n"); - assert_is_ignored(false, "src/foo.c"); - assert_is_ignored(true, "src/foo/foo.c"); -} - -void test_attr_ignore__case_insensitive_unignores_previous_rule(void) -{ - git_config *cfg; - - cl_git_rewritefile("attr/.gitignore", - "/case\n" - "!/Case/\n"); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", true)); - - cl_must_pass(p_mkdir("attr/case", 0755)); - cl_git_mkfile("attr/case/file", "content"); - - assert_is_ignored(false, "case/file"); -} - -void test_attr_ignore__case_sensitive_unignore_does_nothing(void) -{ - git_config *cfg; - - cl_git_rewritefile("attr/.gitignore", - "/case\n" - "!/Case/\n"); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", false)); - - cl_must_pass(p_mkdir("attr/case", 0755)); - cl_git_mkfile("attr/case/file", "content"); - - assert_is_ignored(true, "case/file"); -} - -void test_attr_ignore__ignored_subdirfiles_with_subdir_rule(void) -{ - cl_git_rewritefile( - "attr/.gitignore", - "dir/*\n" - "!dir/sub1/sub2/**\n"); - - assert_is_ignored(true, "dir/a.test"); - assert_is_ignored(true, "dir/sub1/a.test"); - assert_is_ignored(true, "dir/sub1/sub2"); -} - -void test_attr_ignore__ignored_subdirfiles_with_negations(void) -{ - cl_git_rewritefile( - "attr/.gitignore", - "dir/*\n" - "!dir/a.test\n"); - - assert_is_ignored(false, "dir/a.test"); - assert_is_ignored(true, "dir/b.test"); - assert_is_ignored(true, "dir/sub1/c.test"); -} - -void test_attr_ignore__negative_directory_rules_only_match_directories(void) -{ - cl_git_rewritefile( - "attr/.gitignore", - "*\n" - "!/**/\n" - "!*.keep\n" - "!.gitignore\n" - ); - - assert_is_ignored(true, "src"); - assert_is_ignored(true, "src/A"); - assert_is_ignored(false, "src/"); - assert_is_ignored(false, "src/A.keep"); - assert_is_ignored(false, ".gitignore"); -} diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/lookup.c libgit2-1.1.0+dfsg.1/tests/attr/lookup.c --- libgit2-0.28.5+dfsg.1/tests/attr/lookup.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/lookup.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,7 +19,7 @@ cl_assert(!path.is_dir); cl_git_pass(git_attr_file__lookup_one(file,&path,"binary",&value)); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); cl_git_pass(git_attr_file__lookup_one(file,&path,"missing",&value)); cl_assert(!value); @@ -252,7 +252,7 @@ cl_git_pass(git_attr_file__new(&file, NULL, 0)); - cl_git_pass(git_attr_file__parse_buffer(NULL, file, "a* foo\nabc bar\n* baz")); + cl_git_pass(git_attr_file__parse_buffer(NULL, file, "a* foo\nabc bar\n* baz", true)); cl_assert(file->rules.length == 3); diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/macro.c libgit2-1.1.0+dfsg.1/tests/attr/macro.c --- libgit2-0.28.5+dfsg.1/tests/attr/macro.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/macro.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * 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 "clar_libgit2.h" + +#include "git2/sys/repository.h" +#include "attr.h" + +static git_repository *g_repo = NULL; + +void test_attr_macro__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +void test_attr_macro__macros(void) +{ + const char *names[7] = { "rootattr", "binary", "diff", "crlf", "merge", "text", "frotz" }; + const char *names2[5] = { "mymacro", "positive", "negative", "rootattr", "another" }; + const char *names3[3] = { "macro2", "multi2", "multi3" }; + const char *values[7]; + + g_repo = cl_git_sandbox_init("attr"); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "binfile", 7, names)); + + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[1])); + cl_assert(GIT_ATTR_IS_FALSE(values[2])); + cl_assert(GIT_ATTR_IS_FALSE(values[3])); + cl_assert(GIT_ATTR_IS_FALSE(values[4])); + cl_assert(GIT_ATTR_IS_FALSE(values[5])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[6])); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 5, names2)); + + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[1])); + cl_assert(GIT_ATTR_IS_FALSE(values[2])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3])); + cl_assert_equal_s("77", values[4]); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 3, names3)); + + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_FALSE(values[1])); + cl_assert_equal_s("answer", values[2]); +} + +void test_attr_macro__bad_macros(void) +{ + const char *names[6] = { "rootattr", "positive", "negative", + "firstmacro", "secondmacro", "thirdmacro" }; + const char *values[6]; + + g_repo = cl_git_sandbox_init("attr"); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_bad", 6, names)); + + /* these three just confirm that the "mymacro" rule ran */ + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[1])); + cl_assert(GIT_ATTR_IS_FALSE(values[2])); + + /* file contains: + * # let's try some malicious macro defs + * [attr]firstmacro -thirdmacro -secondmacro + * [attr]secondmacro firstmacro -firstmacro + * [attr]thirdmacro secondmacro=hahaha -firstmacro + * macro_bad firstmacro secondmacro thirdmacro + * + * firstmacro assignment list ends up with: + * -thirdmacro -secondmacro + * secondmacro assignment list expands "firstmacro" and ends up with: + * -thirdmacro -secondmacro -firstmacro + * thirdmacro assignment don't expand so list ends up with: + * secondmacro="hahaha" + * + * macro_bad assignment list ends up with: + * -thirdmacro -secondmacro firstmacro && + * -thirdmacro -secondmacro -firstmacro secondmacro && + * secondmacro="hahaha" thirdmacro + * + * so summary results should be: + * -firstmacro secondmacro="hahaha" thirdmacro + */ + cl_assert(GIT_ATTR_IS_FALSE(values[3])); + cl_assert_equal_s("hahaha", values[4]); + cl_assert(GIT_ATTR_IS_TRUE(values[5])); +} + +void test_attr_macro__macros_in_root_wd_apply(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(p_mkdir("empty_standard_repo/dir", 0777)); + cl_git_rewritefile("empty_standard_repo/.gitattributes", "[attr]customattr key=value\n"); + cl_git_rewritefile("empty_standard_repo/dir/.gitattributes", "file customattr\n"); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "dir/file", "key")); + cl_assert_equal_s(value, "value"); +} + +void test_attr_macro__changing_macro_in_root_wd_updates_attributes(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_rewritefile("empty_standard_repo/.gitattributes", + "[attr]customattr key=first\n" + "file customattr\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "key")); + cl_assert_equal_s(value, "first"); + + cl_git_rewritefile("empty_standard_repo/.gitattributes", + "[attr]customattr key=second\n" + "file customattr\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "key")); + cl_assert_equal_s(value, "second"); +} + +void test_attr_macro__macros_in_subdir_do_not_apply(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(p_mkdir("empty_standard_repo/dir", 0777)); + cl_git_rewritefile("empty_standard_repo/dir/.gitattributes", + "[attr]customattr key=value\n" + "file customattr\n"); + + /* This should _not_ pass, as macros in subdirectories shall be ignored */ + cl_git_pass(git_attr_get(&value, g_repo, 0, "dir/file", "key")); + cl_assert_equal_p(value, NULL); +} + +void test_attr_macro__adding_macro_succeeds(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_pass(git_attr_add_macro(g_repo, "macro", "key=value")); + cl_git_rewritefile("empty_standard_repo/.gitattributes", "file.txt macro\n"); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "key")); + cl_assert_equal_s(value, "value"); +} + +void test_attr_macro__adding_boolean_macros_succeeds(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_pass(git_attr_add_macro(g_repo, "macro-pos", "positive")); + cl_git_pass(git_attr_add_macro(g_repo, "macro-neg", "-negative")); + cl_git_rewritefile("empty_standard_repo/.gitattributes", "file.txt macro-pos macro-neg\n"); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "positive")); + cl_assert(GIT_ATTR_IS_TRUE(value)); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "negative")); + cl_assert(GIT_ATTR_IS_FALSE(value)); +} + +void test_attr_macro__redefining_macro_succeeds(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_pass(git_attr_add_macro(g_repo, "macro", "key=value1")); + cl_git_pass(git_attr_add_macro(g_repo, "macro", "key=value2")); + cl_git_rewritefile("empty_standard_repo/.gitattributes", "file.txt macro"); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "key")); + cl_assert_equal_s(value, "value2"); +} + +void test_attr_macro__recursive_macro_resolves(void) +{ + const char *value; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_pass(git_attr_add_macro(g_repo, "expandme", "key=value")); + cl_git_pass(git_attr_add_macro(g_repo, "macro", "expandme")); + cl_git_rewritefile("empty_standard_repo/.gitattributes", "file.txt macro"); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "key")); + cl_assert_equal_s(value, "value"); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/attr/repo.c libgit2-1.1.0+dfsg.1/tests/attr/repo.c --- libgit2-0.28.5+dfsg.1/tests/attr/repo.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/attr/repo.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,8 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/attr.h" #include "attr.h" +#include "sysdir.h" #include "attr_expect.h" #include "git2/sys/repository.h" @@ -17,6 +18,7 @@ { cl_git_sandbox_cleanup(); g_repo = NULL; + cl_sandbox_set_search_path_defaults(); } static struct attr_expected get_one_test_cases[] = { @@ -104,23 +106,23 @@ cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test1", 4, names)); - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[1])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3])); cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test2", 4, names)); - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_FALSE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_FALSE(values[1])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3])); cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/subdir_test1", 4, names)); - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_IS_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[1])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[2])); cl_assert_equal_s("yes", values[3]); } @@ -134,9 +136,9 @@ cl_git_pass(git_attr_get_many(vals, g_repo, 0, "sub/subdir_test1", 4, vals)); - cl_assert(GIT_ATTR_TRUE(vals[0])); - cl_assert(GIT_ATTR_TRUE(vals[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(vals[2])); + cl_assert(GIT_ATTR_IS_TRUE(vals[0])); + cl_assert(GIT_ATTR_IS_TRUE(vals[1])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(vals[2])); cl_assert_equal_s("yes", vals[3]); } @@ -202,89 +204,19 @@ const char *value; cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "foo")); - cl_assert(GIT_ATTR_TRUE(value)); + cl_assert(GIT_ATTR_IS_TRUE(value)); cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "bar")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(value)); cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "baz")); - cl_assert(GIT_ATTR_FALSE(value)); + cl_assert(GIT_ATTR_IS_FALSE(value)); cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "merge")); cl_assert_equal_s("filfre", value); cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "frotz")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); -} - -void test_attr_repo__macros(void) -{ - const char *names[5] = { "rootattr", "binary", "diff", "crlf", "frotz" }; - const char *names2[5] = { "mymacro", "positive", "negative", "rootattr", "another" }; - const char *names3[3] = { "macro2", "multi2", "multi3" }; - const char *values[5]; - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "binfile", 5, names)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_FALSE(values[3])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[4])); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 5, names2)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - cl_assert_equal_s("77", values[4]); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 3, names3)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_FALSE(values[1])); - cl_assert_equal_s("answer", values[2]); -} - -void test_attr_repo__bad_macros(void) -{ - const char *names[6] = { "rootattr", "positive", "negative", - "firstmacro", "secondmacro", "thirdmacro" }; - const char *values[6]; - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_bad", 6, names)); - - /* these three just confirm that the "mymacro" rule ran */ - cl_assert(GIT_ATTR_UNSPECIFIED(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - - /* file contains: - * # let's try some malicious macro defs - * [attr]firstmacro -thirdmacro -secondmacro - * [attr]secondmacro firstmacro -firstmacro - * [attr]thirdmacro secondmacro=hahaha -firstmacro - * macro_bad firstmacro secondmacro thirdmacro - * - * firstmacro assignment list ends up with: - * -thirdmacro -secondmacro - * secondmacro assignment list expands "firstmacro" and ends up with: - * -thirdmacro -secondmacro -firstmacro - * thirdmacro assignment don't expand so list ends up with: - * secondmacro="hahaha" - * - * macro_bad assignment list ends up with: - * -thirdmacro -secondmacro firstmacro && - * -thirdmacro -secondmacro -firstmacro secondmacro && - * secondmacro="hahaha" thirdmacro - * - * so summary results should be: - * -firstmacro secondmacro="hahaha" thirdmacro - */ - cl_assert(GIT_ATTR_FALSE(values[3])); - cl_assert_equal_s("hahaha", values[4]); - cl_assert(GIT_ATTR_TRUE(values[5])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(value)); } #define CONTENT "I'm going to be dynamically processed\r\n" \ @@ -357,22 +289,117 @@ cl_git_pass(git_attr_get_many(values, g_repo, 0, "file.txt", 4, names)); - cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[0])); cl_assert_equal_s("foobar", values[1]); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + cl_assert(GIT_ATTR_IS_FALSE(values[2])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3])); cl_git_pass(git_attr_get_many(values, g_repo, 0, "trial.txt", 4, names)); - cl_assert(GIT_ATTR_FALSE(values[0])); + cl_assert(GIT_ATTR_IS_FALSE(values[0])); cl_assert_equal_s("barfoo", values[1]); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert(GIT_ATTR_TRUE(values[3])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_IS_TRUE(values[3])); cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/sub/subdir.txt", 4, names)); - cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_IS_TRUE(values[0])); cl_assert_equal_s("foobar", values[1]); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + cl_assert(GIT_ATTR_IS_FALSE(values[2])); + cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3])); +} + +void test_attr_repo__sysdir(void) +{ + git_buf sysdir = GIT_BUF_INIT; + const char *value; + + cl_git_pass(p_mkdir("system", 0777)); + cl_git_rewritefile("system/gitattributes", "file merge=foo"); + cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system")); + cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr)); + g_repo = cl_git_sandbox_reopen(); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "merge")); + cl_assert_equal_s(value, "foo"); + + cl_git_pass(p_unlink("system/gitattributes")); + cl_git_pass(p_rmdir("system")); + git_buf_dispose(&sysdir); +} + +void test_attr_repo__sysdir_with_session(void) +{ + const char *values[2], *attrs[2] = { "foo", "bar" }; + git_buf sysdir = GIT_BUF_INIT; + git_attr_session session; + + cl_git_pass(p_mkdir("system", 0777)); + cl_git_rewritefile("system/gitattributes", "file foo=1 bar=2"); + cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system")); + cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr)); + g_repo = cl_git_sandbox_reopen(); + + cl_git_pass(git_attr_session__init(&session, g_repo)); + cl_git_pass(git_attr_get_many_with_session(values, g_repo, &session, 0, "file", ARRAY_SIZE(attrs), attrs)); + + cl_assert_equal_s(values[0], "1"); + cl_assert_equal_s(values[1], "2"); + + cl_git_pass(p_unlink("system/gitattributes")); + cl_git_pass(p_rmdir("system")); + git_buf_dispose(&sysdir); + git_attr_session__free(&session); +} + +void test_attr_repo__rewrite(void) +{ + const char *value; + + cl_git_rewritefile("attr/.gitattributes", "file.txt foo=first\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "foo")); + cl_assert_equal_s(value, "first"); + + cl_git_rewritefile("attr/.gitattributes", "file.txt foo=second\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "foo")); + cl_assert_equal_s(value, "second"); + + cl_git_rewritefile("attr/.gitattributes", "file.txt other=value\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "foo")); + cl_assert_equal_p(value, NULL); +} + +void test_attr_repo__rewrite_sysdir(void) +{ + git_buf sysdir = GIT_BUF_INIT; + const char *value; + + cl_git_pass(p_mkdir("system", 0777)); + cl_git_pass(git_buf_joinpath(&sysdir, clar_sandbox_path(), "system")); + cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, sysdir.ptr)); + g_repo = cl_git_sandbox_reopen(); + + cl_git_rewritefile("system/gitattributes", "file foo=first"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "foo")); + cl_assert_equal_s(value, "first"); + + cl_git_rewritefile("system/gitattributes", "file foo=second"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file", "foo")); + cl_assert_equal_s(value, "second"); + + git_buf_dispose(&sysdir); +} + +void test_attr_repo__unlink(void) +{ + const char *value; + + cl_git_rewritefile("attr/.gitattributes", "file.txt foo=value1\n"); + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "foo")); + cl_assert_equal_s(value, "value1"); + + cl_git_pass(p_unlink("attr/.gitattributes")); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "file.txt", "foo")); + cl_assert_equal_p(value, NULL); } diff -Nru libgit2-0.28.5+dfsg.1/tests/blame/blame_helpers.c libgit2-1.1.0+dfsg.1/tests/blame/blame_helpers.c --- libgit2-0.28.5+dfsg.1/tests/blame/blame_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/blame/blame_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -31,13 +31,13 @@ } if (hunk->final_start_line_number != start_line) { - hunk_message(idx, hunk, "mismatched start line number: expected %d, got %d", + hunk_message(idx, hunk, "mismatched start line number: expected %"PRIuZ", got %"PRIuZ, start_line, hunk->final_start_line_number); } cl_assert_equal_i(hunk->final_start_line_number, start_line); if (hunk->lines_in_hunk != len) { - hunk_message(idx, hunk, "mismatched line count: expected %d, got %d", + hunk_message(idx, hunk, "mismatched line count: expected %"PRIuZ", got %"PRIuZ, len, hunk->lines_in_hunk); } cl_assert_equal_i(hunk->lines_in_hunk, len); diff -Nru libgit2-0.28.5+dfsg.1/tests/blame/blame_helpers.h libgit2-1.1.0+dfsg.1/tests/blame/blame_helpers.h --- libgit2-0.28.5+dfsg.1/tests/blame/blame_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/blame/blame_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "blame.h" -void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...); +void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) GIT_FORMAT_PRINTF(3, 4); void check_blame_hunk_index( git_repository *repo, diff -Nru libgit2-0.28.5+dfsg.1/tests/blame/simple.c libgit2-1.1.0+dfsg.1/tests/blame/simple.c --- libgit2-0.28.5+dfsg.1/tests/blame/simple.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/blame/simple.c 2020-10-12 18:53:06.000000000 +0000 @@ -203,6 +203,14 @@ check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, 0, "d12299fe", "src/git.h"); } +/* This was leading to segfaults on some systems during cache eviction. */ +void test_blame_simple__trivial_libgit2_under_cache_pressure(void) +{ + ssize_t old_max_storage = git_cache__max_storage; + git_cache__max_storage = 1024 * 1024; + test_blame_simple__trivial_libgit2(); + git_cache__max_storage = old_max_storage; +} /* * $ git blame -n b.txt -L 8 @@ -231,6 +239,24 @@ } /* + * $ git blame -n c.txt + * orig line no final line no + * commit V author timestamp V + * 702c7aa5 1 (Carl Schwan 2020-01-29 01:52:31 +0100 4 + */ +void test_blame_simple__can_ignore_whitespace_change(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + opts.flags |= GIT_BLAME_IGNORE_WHITESPACE; + cl_git_pass(git_blame_file(&g_blame, g_repo, "c.txt", &opts)); + cl_assert_equal_i(1, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "702c7aa5", "c.txt"); +} + +/* * $ git blame -n b.txt -L ,6 * orig line no final line no * commit V author timestamp V diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/binaryunicode.c libgit2-1.1.0+dfsg.1/tests/checkout/binaryunicode.c --- libgit2-0.28.5+dfsg.1/tests/checkout/binaryunicode.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/binaryunicode.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "refs.h" #include "repo/repo_helpers.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/checkout_helpers.c libgit2-1.1.0+dfsg.1/tests/checkout/checkout_helpers.c --- libgit2-0.28.5+dfsg.1/tests/checkout/checkout_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/checkout_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "checkout_helpers.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" #include "index.h" void assert_on_branch(git_repository *repo, const char *branch) diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/conflict.c libgit2-1.1.0+dfsg.1/tests/checkout/conflict.c --- libgit2-0.28.5+dfsg.1/tests/checkout/conflict.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/conflict.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "git2/repository.h" #include "git2/sys/index.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" static git_repository *g_repo; @@ -192,7 +192,7 @@ { int symlinks; - cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS)); + cl_git_pass(git_repository__configmap_lookup(&symlinks, repo, GIT_CONFIGMAP_SYMLINKS)); if (!symlinks) { ensure_workdir_contents(path, target); diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/crlf.c libgit2-1.1.0+dfsg.1/tests/checkout/crlf.c --- libgit2-0.28.5+dfsg.1/tests/checkout/crlf.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/crlf.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "checkout_helpers.h" #include "../filter/crlf.h" -#include "fileops.h" +#include "futils.h" #include "git2/checkout.h" #include "repository.h" @@ -108,7 +108,7 @@ git_buf details = GIT_BUF_INIT; git_buf_printf(&details, "filename=%s, system=%s, autocrlf=%s, attrs={%s}", git_path_basename(actual_path->ptr), systype, cd->autocrlf, cd->attrs); - clar__fail(__FILE__, __LINE__, + clar__fail(__FILE__, __func__, __LINE__, "checked out contents did not match expected", details.ptr, 0); git_buf_dispose(&details); } diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/head.c libgit2-1.1.0+dfsg.1/tests/checkout/head.c --- libgit2-0.28.5+dfsg.1/tests/checkout/head.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/head.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "refs.h" #include "repo/repo_helpers.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo; @@ -109,6 +109,32 @@ cl_assert(git_path_isfile("testrepo/tracked/subdir/untracked")); } +void test_checkout_head__do_remove_untracked_paths(void) +{ + git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; + git_index *index; + char *paths[] = {"tracked/untracked"}; + + cl_git_pass(p_mkdir("testrepo/tracked", 0755)); + cl_git_pass(p_mkdir("testrepo/tracked/subdir", 0755)); + cl_git_mkfile("testrepo/tracked/tracked", "tracked\n"); + cl_git_mkfile("testrepo/tracked/untracked", "untracked\n"); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "tracked/tracked")); + cl_git_pass(git_index_write(index)); + + git_index_free(index); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; + opts.paths.strings = paths; + opts.paths.count = 1; + cl_git_pass(git_checkout_head(g_repo, &opts)); + + cl_assert(git_path_isfile("testrepo/tracked/tracked")); + cl_assert(!git_path_isfile("testrepo/tracked/untracked")); +} + void test_checkout_head__do_remove_tracked_subdir(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/icase.c libgit2-1.1.0+dfsg.1/tests/checkout/icase.c --- libgit2-0.28.5+dfsg.1/tests/checkout/icase.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/icase.c 2020-10-12 18:53:06.000000000 +0000 @@ -33,7 +33,7 @@ cl_git_pass(git_reference_name_to_id(&id, repo, "refs/heads/dir")); cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJECT_ANY)); - git_checkout_init_options(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION); + git_checkout_options_init(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION); checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; } @@ -96,7 +96,7 @@ { int symlinks; - cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS)); + cl_git_pass(git_repository__configmap_lookup(&symlinks, repo, GIT_CONFIGMAP_SYMLINKS)); if (symlinks) return p_symlink(a, b); diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/index.c libgit2-1.1.0+dfsg.1/tests/checkout/index.c --- libgit2-0.28.5+dfsg.1/tests/checkout/index.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/index.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "checkout_helpers.h" #include "git2/checkout.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" #include "remote.h" #include "repo/repo_helpers.h" @@ -89,6 +89,61 @@ cl_assert_equal_i(false, git_path_isdir("./testrepo/dir")); } +void test_checkout_index__can_disable_pathspec_match(void) +{ + char *files_to_checkout[] = { "test10.txt", "test11.txt"}; + git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; + git_object *objects; + git_index *index; + + /* reset to beginning of history (i.e. just a README file) */ + opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; + + cl_git_pass(git_revparse_single(&objects, g_repo, "8496071c1b46c854b31185ea97743be6a8774479")); + cl_git_pass(git_checkout_tree(g_repo, objects, &opts)); + cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(objects))); + git_object_free(objects); + + cl_git_pass(git_repository_index(&index, g_repo)); + + /* We create 4 files and commit them */ + cl_git_mkfile("testrepo/test9.txt", "original\n"); + cl_git_mkfile("testrepo/test10.txt", "original\n"); + cl_git_mkfile("testrepo/test11.txt", "original\n"); + cl_git_mkfile("testrepo/test12.txt", "original\n"); + + cl_git_pass(git_index_add_bypath(index, "test9.txt")); + cl_git_pass(git_index_add_bypath(index, "test10.txt")); + cl_git_pass(git_index_add_bypath(index, "test11.txt")); + cl_git_pass(git_index_add_bypath(index, "test12.txt")); + cl_git_pass(git_index_write(index)); + + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "commit our test files"); + + /* We modify the content of all 4 of our files */ + cl_git_rewritefile("testrepo/test9.txt", "modified\n"); + cl_git_rewritefile("testrepo/test10.txt", "modified\n"); + cl_git_rewritefile("testrepo/test11.txt", "modified\n"); + cl_git_rewritefile("testrepo/test12.txt", "modified\n"); + + /* We checkout only test10.txt and test11.txt */ + opts.checkout_strategy = + GIT_CHECKOUT_FORCE | + GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH; + opts.paths.strings = files_to_checkout; + opts.paths.count = ARRAY_SIZE(files_to_checkout); + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + /* The only files that have been reverted to their original content + should be test10.txt and test11.txt */ + check_file_contents("testrepo/test9.txt", "modified\n"); + check_file_contents("testrepo/test10.txt", "original\n"); + check_file_contents("testrepo/test11.txt", "original\n"); + check_file_contents("testrepo/test12.txt", "modified\n"); + + git_index_free(index); +} + void test_checkout_index__honor_the_specified_pathspecs(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; @@ -148,13 +203,15 @@ static void populate_symlink_workdir(void) { + git_buf path = GIT_BUF_INIT; git_repository *repo; git_remote *origin; git_object *target; const char *url = git_repository_path(g_repo); - cl_git_pass(git_repository_init(&repo, "../symlink.git", true)); + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "symlink.git")); + cl_git_pass(git_repository_init(&repo, path.ptr, true)); cl_git_pass(git_repository_set_workdir(repo, "symlink", 1)); /* Delete the `origin` repo (if it exists) so we can recreate it. */ @@ -166,8 +223,10 @@ cl_git_pass(git_revparse_single(&target, repo, "remotes/origin/master")); cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL)); + git_object_free(target); git_repository_free(repo); + git_buf_dispose(&path); } void test_checkout_index__honor_coresymlinks_default_true(void) @@ -177,7 +236,7 @@ cl_must_pass(p_mkdir("symlink", 0777)); - if (!filesystem_supports_symlinks("symlink/test")) + if (!git_path_supports_symlinks("symlink/test")) cl_skip(); #ifdef GIT_WIN32 @@ -210,7 +269,7 @@ * supports symlinks. Bail entirely on POSIX platforms that * do support symlinks. */ - if (filesystem_supports_symlinks("symlink/test")) + if (git_path_supports_symlinks("symlink/test")) cl_skip(); #endif @@ -222,7 +281,7 @@ { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; - if (filesystem_supports_symlinks("testrepo/test")) { + if (git_path_supports_symlinks("testrepo/test")) { cl_skip(); } @@ -238,7 +297,7 @@ char link_data[GIT_PATH_MAX]; size_t link_size = GIT_PATH_MAX; - if (!filesystem_supports_symlinks("testrepo/test")) { + if (!git_path_supports_symlinks("testrepo/test")) { cl_skip(); } diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/nasty.c libgit2-1.1.0+dfsg.1/tests/checkout/nasty.c --- libgit2-0.28.5+dfsg.1/tests/checkout/nasty.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/nasty.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "git2/checkout.h" #include "repository.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" static const char *repo_name = "nasty"; static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/tree.c libgit2-1.1.0+dfsg.1/tests/checkout/tree.c --- libgit2-0.28.5+dfsg.1/tests/checkout/tree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/tree.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "git2/checkout.h" #include "repository.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo; static git_checkout_options g_opts; @@ -917,7 +917,7 @@ { /* A utf-8 string with 83 characters, but 249 bytes. */ const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; - char path[1024]; + char path[1024] = {0}; g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_revparse_single(&g_object, g_repo, "long-file-name")); diff -Nru libgit2-0.28.5+dfsg.1/tests/checkout/typechange.c libgit2-1.1.0+dfsg.1/tests/checkout/typechange.c --- libgit2-0.28.5+dfsg.1/tests/checkout/typechange.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/checkout/typechange.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/checkout.h" #include "path.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/cherrypick/bare.c libgit2-1.1.0+dfsg.1/tests/cherrypick/bare.c --- libgit2-0.28.5+dfsg.1/tests/cherrypick/bare.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/cherrypick/bare.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "git2/cherrypick.h" #include "../merge/merge_helpers.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/cherrypick/workdir.c libgit2-1.1.0+dfsg.1/tests/cherrypick/workdir.c --- libgit2-0.28.5+dfsg.1/tests/cherrypick/workdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/cherrypick/workdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "git2/cherrypick.h" #include "../merge/merge_helpers.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/clar/fs.h libgit2-1.1.0+dfsg.1/tests/clar/fs.h --- libgit2-0.28.5+dfsg.1/tests/clar/fs.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar/fs.h 2020-10-12 18:53:06.000000000 +0000 @@ -1,3 +1,11 @@ +/* + * By default, use a read/write loop to copy files on POSIX systems. + * On Linux, use sendfile by default as it's slightly faster. On + * macOS, we avoid fcopyfile by default because it's slightly slower. + */ +#undef USE_FCOPYFILE +#define USE_SENDFILE 1 + #ifdef _WIN32 #define RM_RETRY_COUNT 5 @@ -254,74 +262,213 @@ #include #include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +# include +#endif + +#if defined(__APPLE__) +# include +#endif + +static void basename_r(const char **out, int *out_len, const char *in) +{ + size_t in_len = strlen(in), start_pos; + + for (in_len = strlen(in); in_len; in_len--) { + if (in[in_len - 1] != '/') + break; + } -static int -shell_out(char * const argv[]) + for (start_pos = in_len; start_pos; start_pos--) { + if (in[start_pos - 1] == '/') + break; + } + + cl_assert(in_len - start_pos < INT_MAX); + + if (in_len - start_pos > 0) { + *out = &in[start_pos]; + *out_len = (in_len - start_pos); + } else { + *out = "/"; + *out_len = 1; + } +} + +static char *joinpath(const char *dir, const char *base, int base_len) { - int status, piderr; - pid_t pid; + char *out; + int len; - pid = fork(); + if (base_len == -1) { + size_t bl = strlen(base); - if (pid < 0) { - fprintf(stderr, - "System error: `fork()` call failed (%d) - %s\n", - errno, strerror(errno)); - exit(-1); + cl_assert(bl < INT_MAX); + base_len = (int)bl; } - if (pid == 0) { - execv(argv[0], argv); + len = strlen(dir) + base_len + 2; + cl_assert(len > 0); + + cl_assert(out = malloc(len)); + cl_assert(snprintf(out, len, "%s/%.*s", dir, base_len, base) < len); + + return out; +} + +static void +fs_copydir_helper(const char *source, const char *dest, int dest_mode) +{ + DIR *source_dir; + struct dirent *d; + + mkdir(dest, dest_mode); + + cl_assert_(source_dir = opendir(source), "Could not open source dir"); + while ((d = (errno = 0, readdir(source_dir))) != NULL) { + char *child; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + child = joinpath(source, d->d_name, -1); + fs_copy(child, dest); + free(child); } - do { - piderr = waitpid(pid, &status, WUNTRACED); - } while (piderr < 0 && (errno == EAGAIN || errno == EINTR)); + cl_assert_(errno == 0, "Failed to iterate source dir"); + + closedir(source_dir); +} + +static void +fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int dest_mode) +{ + int in, out; - return WEXITSTATUS(status); + cl_must_pass((in = open(source, O_RDONLY))); + cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode))); + +#if USE_FCOPYFILE && defined(__APPLE__) + ((void)(source_len)); /* unused */ + cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA)); +#elif USE_SENDFILE && defined(__linux__) + { + ssize_t ret = 0; + + while (source_len && (ret = sendfile(out, in, NULL, source_len)) > 0) { + source_len -= (size_t)ret; + } + cl_assert(ret >= 0); + } +#else + { + char buf[131072]; + ssize_t ret; + + ((void)(source_len)); /* unused */ + + while ((ret = read(in, buf, sizeof(buf))) > 0) { + size_t len = (size_t)ret; + + while (len && (ret = write(out, buf, len)) > 0) { + cl_assert(ret <= (ssize_t)len); + len -= ret; + } + cl_assert(ret >= 0); + } + cl_assert(ret == 0); + } +#endif + + close(in); + close(out); +} + +static void +fs_copy(const char *source, const char *_dest) +{ + char *dbuf = NULL; + const char *dest; + struct stat source_st, dest_st; + + cl_must_pass_(lstat(source, &source_st), "Failed to stat copy source"); + + if (lstat(_dest, &dest_st) == 0) { + const char *base; + int base_len; + + /* Target exists and is directory; append basename */ + cl_assert(S_ISDIR(dest_st.st_mode)); + + basename_r(&base, &base_len, source); + cl_assert(base_len < INT_MAX); + + dbuf = joinpath(_dest, base, base_len); + dest = dbuf; + } else if (errno != ENOENT) { + cl_fail("Cannot copy; cannot stat destination"); + } else { + dest = _dest; + } + + if (S_ISDIR(source_st.st_mode)) { + fs_copydir_helper(source, dest, source_st.st_mode); + } else { + fs_copyfile_helper(source, source_st.st_size, dest, source_st.st_mode); + } + + free(dbuf); } static void -fs_copy(const char *_source, const char *dest) +fs_rmdir_helper(const char *path) { - char *argv[5]; - char *source; - size_t source_len; - - source = strdup(_source); - source_len = strlen(source); - - if (source[source_len - 1] == '/') - source[source_len - 1] = 0; - - argv[0] = "/bin/cp"; - argv[1] = "-R"; - argv[2] = source; - argv[3] = (char *)dest; - argv[4] = NULL; - - cl_must_pass_( - shell_out(argv), - "Failed to copy test fixtures to sandbox" - ); + DIR *dir; + struct dirent *d; + + cl_assert_(dir = opendir(path), "Could not open dir"); + while ((d = (errno = 0, readdir(dir))) != NULL) { + char *child; - free(source); + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + child = joinpath(path, d->d_name, -1); + fs_rm(child); + free(child); + } + + cl_assert_(errno == 0, "Failed to iterate source dir"); + closedir(dir); + + cl_must_pass_(rmdir(path), "Could not remove directory"); } static void -fs_rm(const char *source) +fs_rm(const char *path) { - char *argv[4]; + struct stat st; + + if (lstat(path, &st)) { + if (errno == ENOENT) + return; - argv[0] = "/bin/rm"; - argv[1] = "-Rf"; - argv[2] = (char *)source; - argv[3] = NULL; - - cl_must_pass_( - shell_out(argv), - "Failed to cleanup the sandbox" - ); + cl_fail("Cannot copy; cannot stat destination"); + } + + if (S_ISDIR(st.st_mode)) { + fs_rmdir_helper(path); + } else { + cl_must_pass(unlink(path)); + } } void diff -Nru libgit2-0.28.5+dfsg.1/tests/clar/print.h libgit2-1.1.0+dfsg.1/tests/clar/print.h --- libgit2-0.28.5+dfsg.1/tests/clar/print.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar/print.h 2020-10-12 18:53:06.000000000 +0000 @@ -1,12 +1,13 @@ +/* clap: clar protocol, the traditional clar output format */ -static void clar_print_init(int test_count, int suite_count, const char *suite_names) +static void clar_print_clap_init(int test_count, int suite_count, const char *suite_names) { (void)test_count; printf("Loaded %d suites: %s\n", (int)suite_count, suite_names); printf("Started (test status codes: OK='.' FAILURE='F' SKIPPED='S')\n"); } -static void clar_print_shutdown(int test_count, int suite_count, int error_count) +static void clar_print_clap_shutdown(int test_count, int suite_count, int error_count) { (void)test_count; (void)suite_count; @@ -16,11 +17,11 @@ clar_report_all(); } -static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error) +static void clar_print_clap_error(int num, const struct clar_report *report, const struct clar_error *error) { printf(" %d) Failure:\n", num); - printf("%s::%s [%s:%d]\n", + printf("%s::%s [%s:%"PRIuZ"]\n", report->suite, report->test, error->file, @@ -35,7 +36,7 @@ fflush(stdout); } -static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status status) +static void clar_print_clap_ontest(const char *test_name, int test_number, enum cl_test_status status) { (void)test_name; (void)test_number; @@ -50,7 +51,7 @@ fflush(stdout); } -static void clar_print_onsuite(const char *suite_name, int suite_index) +static void clar_print_clap_onsuite(const char *suite_name, int suite_index) { if (_clar.report_suite_names) printf("\n%s", suite_name); @@ -58,10 +59,142 @@ (void)suite_index; } +static void clar_print_clap_onabort(const char *fmt, va_list arg) +{ + vfprintf(stderr, fmt, arg); +} + +/* tap: test anywhere protocol format */ + +static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names) +{ + (void)test_count; + (void)suite_count; + (void)suite_names; + printf("TAP version 13\n"); +} + +static void clar_print_tap_shutdown(int test_count, int suite_count, int error_count) +{ + (void)suite_count; + (void)error_count; + + printf("1..%d\n", test_count); +} + +static void clar_print_tap_error(int num, const struct clar_report *report, const struct clar_error *error) +{ + (void)num; + (void)report; + (void)error; +} + +static void print_escaped(const char *str) +{ + char *c; + + while ((c = strchr(str, '\'')) != NULL) { + printf("%.*s", (int)(c - str), str); + printf("''"); + str = c + 1; + } + + printf("%s", str); +} + +static void clar_print_tap_ontest(const char *test_name, int test_number, enum cl_test_status status) +{ + const struct clar_error *error = _clar.last_report->errors; + + (void)test_name; + (void)test_number; + + switch(status) { + case CL_TEST_OK: + printf("ok %d - %s::%s\n", test_number, _clar.active_suite, test_name); + break; + case CL_TEST_FAILURE: + printf("not ok %d - %s::%s\n", test_number, _clar.active_suite, test_name); + + printf(" ---\n"); + printf(" reason: |\n"); + printf(" %s\n", error->error_msg); + + if (error->description) + printf(" %s\n", error->description); + + printf(" at:\n"); + printf(" file: '"); print_escaped(error->file); printf("'\n"); + printf(" line: %" PRIuZ "\n", error->line_number); + printf(" function: '%s'\n", error->function); + printf(" ---\n"); + + break; + case CL_TEST_SKIP: + case CL_TEST_NOTRUN: + printf("ok %d - # SKIP %s::%s\n", test_number, _clar.active_suite, test_name); + break; + } + + fflush(stdout); +} + +static void clar_print_tap_onsuite(const char *suite_name, int suite_index) +{ + printf("# start of suite %d: %s\n", suite_index, suite_name); +} + +static void clar_print_tap_onabort(const char *fmt, va_list arg) +{ + printf("Bail out! "); + vprintf(fmt, arg); + fflush(stdout); +} + +/* indirection between protocol output selection */ + +#define PRINT(FN, ...) do { \ + switch (_clar.output_format) { \ + case CL_OUTPUT_CLAP: \ + clar_print_clap_##FN (__VA_ARGS__); \ + break; \ + case CL_OUTPUT_TAP: \ + clar_print_tap_##FN (__VA_ARGS__); \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +static void clar_print_init(int test_count, int suite_count, const char *suite_names) +{ + PRINT(init, test_count, suite_count, suite_names); +} + +static void clar_print_shutdown(int test_count, int suite_count, int error_count) +{ + PRINT(shutdown, test_count, suite_count, error_count); +} + +static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error) +{ + PRINT(error, num, report, error); +} + +static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status status) +{ + PRINT(ontest, test_name, test_number, status); +} + +static void clar_print_onsuite(const char *suite_name, int suite_index) +{ + PRINT(onsuite, suite_name, suite_index); +} + static void clar_print_onabort(const char *msg, ...) { va_list argp; va_start(argp, msg); - vfprintf(stderr, msg, argp); + PRINT(onabort, msg, argp); va_end(argp); } diff -Nru libgit2-0.28.5+dfsg.1/tests/clar.c libgit2-1.1.0+dfsg.1/tests/clar.c --- libgit2-0.28.5+dfsg.1/tests/clar.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar.c 2020-10-12 18:53:06.000000000 +0000 @@ -67,7 +67,7 @@ # define PRIxZ "Ix" # endif -# ifdef _MSC_VER +# if defined(_MSC_VER) || defined(__MINGW32__) typedef struct stat STAT_T; # else typedef struct _stat STAT_T; @@ -96,7 +96,8 @@ struct clar_error { const char *file; - int line_number; + const char *function; + size_t line_number; const char *error_msg; char *description; @@ -140,12 +141,14 @@ int tests_ran; int suites_ran; + enum cl_output_format output_format; + int report_errors_only; int exit_on_error; int report_suite_names; int write_summary; - const char *summary_filename; + char *summary_filename; struct clar_summary *summary; struct clar_explicit *explicit; @@ -293,6 +296,7 @@ const struct clar_func *test = suite->tests; size_t i, matchlen; struct clar_report *report; + int exact = 0; if (!suite->enabled) return; @@ -317,6 +321,11 @@ while (*filter == ':') ++filter; matchlen = strlen(filter); + + if (matchlen && filter[matchlen - 1] == '$') { + exact = 1; + matchlen--; + } } } @@ -324,6 +333,9 @@ if (filter && strncmp(test[i].name, filter, matchlen)) continue; + if (exact && strlen(test[i].name) != matchlen) + continue; + _clar.active_test = test[i].name; report = calloc(1, sizeof(struct clar_report)); @@ -361,6 +373,7 @@ printf(" -v Increase verbosity (show suite names)\n"); printf(" -q Only report tests that had an error\n"); printf(" -Q Quit as soon as a test fails\n"); + printf(" -t Display results in tap format\n"); printf(" -l Print suite names\n"); printf(" -r[filename] Write summary file (to the optional filename)\n"); exit(-1); @@ -376,7 +389,7 @@ char *argument = argv[i]; if (argument[0] != '-' || argument[1] == '\0' - || strchr("sixvqQlr", argument[1]) == NULL) { + || strchr("sixvqQtlr", argument[1]) == NULL) { clar_usage(argv[0]); } } @@ -459,6 +472,10 @@ _clar.exit_on_error = 1; break; + case 't': + _clar.output_format = CL_OUTPUT_TAP; + break; + case 'l': { size_t j; printf("Test suites (use -s to run just one):\n"); @@ -474,8 +491,8 @@ case 'r': _clar.write_summary = 1; - _clar.summary_filename = *(argument + 2) ? (argument + 2) : - "summary.xml"; + free(_clar.summary_filename); + _clar.summary_filename = strdup(*(argument + 2) ? (argument + 2) : "summary.xml"); break; default: @@ -487,14 +504,19 @@ void clar_test_init(int argc, char **argv) { + if (argc > 1) + clar_parse_args(argc, argv); + clar_print_init( (int)_clar_callback_count, (int)_clar_suite_count, "" ); - if (argc > 1) - clar_parse_args(argc, argv); + if ((_clar.summary_filename = getenv("CLAR_SUMMARY")) != NULL) { + _clar.write_summary = 1; + _clar.summary_filename = strdup(_clar.summary_filename); + } if (_clar.write_summary && !(_clar.summary = clar_summary_init(_clar.summary_filename))) { @@ -553,6 +575,8 @@ report_next = report->next; free(report); } + + free(_clar.summary_filename); } int @@ -589,7 +613,8 @@ void clar__fail( const char *file, - int line, + const char *function, + size_t line, const char *error_msg, const char *description, int should_abort) @@ -605,6 +630,7 @@ _clar.last_report->last_error = error; error->file = file; + error->function = function; error->line_number = line; error->error_msg = error_msg; @@ -621,7 +647,8 @@ void clar__assert( int condition, const char *file, - int line, + const char *function, + size_t line, const char *error_msg, const char *description, int should_abort) @@ -629,12 +656,13 @@ if (condition) return; - clar__fail(file, line, error_msg, description, should_abort); + clar__fail(file, function, line, error_msg, description, should_abort); } void clar__assert_equal( const char *file, - int line, + const char *function, + size_t line, const char *err, int should_abort, const char *fmt, @@ -744,7 +772,7 @@ va_end(args); if (!is_equal) - clar__fail(file, line, err, buf, should_abort); + clar__fail(file, function, line, err, buf, should_abort); } void cl_set_cleanup(void (*cleanup)(void *), void *opaque) diff -Nru libgit2-0.28.5+dfsg.1/tests/clar.h libgit2-1.1.0+dfsg.1/tests/clar.h --- libgit2-0.28.5+dfsg.1/tests/clar.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar.h 2020-10-12 18:53:06.000000000 +0000 @@ -16,6 +16,11 @@ CL_TEST_NOTRUN, }; +enum cl_output_format { + CL_OUTPUT_CLAP, + CL_OUTPUT_TAP, +}; + /** Setup clar environment */ void clar_test_init(int argc, char *argv[]); int clar_test_run(void); @@ -81,16 +86,16 @@ /** * Assertion macros with explicit error message */ -#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1) -#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1) -#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 1) +#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 1) +#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 1) +#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 1) /** * Check macros with explicit error message */ -#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 0) -#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0) -#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 0) +#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __func__, __LINE__, "Function call failed: " #expr, desc, 0) +#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __func__, __LINE__, "Expected function call to fail: " #expr, desc, 0) +#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __func__, __LINE__, "Expression is not true: " #expr, desc, 0) /** * Assertion macros with no error message @@ -109,39 +114,40 @@ /** * Forced failure/warning */ -#define cl_fail(desc) clar__fail(__FILE__, __LINE__, "Test failed.", desc, 1) -#define cl_warning(desc) clar__fail(__FILE__, __LINE__, "Warning during test execution:", desc, 0) +#define cl_fail(desc) clar__fail(__FILE__, __func__, __LINE__, "Test failed.", desc, 1) +#define cl_warning(desc) clar__fail(__FILE__, __func__, __LINE__, "Warning during test execution:", desc, 0) #define cl_skip() clar__skip() /** * Typed assertion macros */ -#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) -#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) +#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) -#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2)) -#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2)) +#define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2)) +#define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2)) -#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len)) -#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len)) +#define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len)) +#define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len)) -#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len)) -#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len)) +#define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len)) +#define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(__FILE__,__func__,__LINE__,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len)) -#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) -#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) -#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) +#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) +#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__func__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) -#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) +#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__func__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) -#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) +#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__func__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) void clar__skip(void); void clar__fail( const char *file, - int line, + const char *func, + size_t line, const char *error, const char *description, int should_abort); @@ -149,14 +155,16 @@ void clar__assert( int condition, const char *file, - int line, + const char *func, + size_t line, const char *error, const char *description, int should_abort); void clar__assert_equal( const char *file, - int line, + const char *func, + size_t line, const char *err, int should_abort, const char *fmt, diff -Nru libgit2-0.28.5+dfsg.1/tests/clar_libgit2.c libgit2-1.1.0+dfsg.1/tests/clar_libgit2.c --- libgit2-0.28.5+dfsg.1/tests/clar_libgit2.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar_libgit2.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "git2/sys/repository.h" void cl_git_report_failure( - int error, int expected, const char *file, int line, const char *fncall) + int error, int expected, const char *file, const char *func, int line, const char *fncall) { char msg[4096]; const git_error *last = git_error_last(); @@ -18,7 +18,7 @@ else p_snprintf(msg, 4096, "no error, expected non-zero return"); - clar__assert(0, file, line, fncall, msg, 1); + clar__assert(0, file, func, line, fncall, msg, 1); } void cl_git_mkfile(const char *filename, const char *content) @@ -507,6 +507,7 @@ int ignore_cr, const char *path, const char *file, + const char *func, int line) { char buf[4000]; @@ -519,7 +520,7 @@ while ((bytes = p_read(fd, buf, sizeof(buf))) != 0) { clar__assert( - bytes > 0, file, line, "error reading from file", path, 1); + bytes > 0, file, func, line, "error reading from file", path, 1); if (ignore_cr) bytes = strip_cr_from_buf(buf, bytes); @@ -532,7 +533,7 @@ buf, sizeof(buf), "file content mismatch at byte %"PRIdZ, (ssize_t)(total_bytes + pos)); p_close(fd); - clar__fail(file, line, path, buf, 1); + clar__fail(file, func, line, path, buf, 1); } expected_data += bytes; @@ -541,8 +542,8 @@ p_close(fd); - clar__assert(!bytes, file, line, "error reading from file", path, 1); - clar__assert_equal(file, line, "mismatched file length", 1, "%"PRIuZ, + clar__assert(!bytes, file, func, line, "error reading from file", path, 1); + clar__assert_equal(file, func, line, "mismatched file length", 1, "%"PRIuZ, (size_t)expected_bytes, (size_t)total_bytes); } diff -Nru libgit2-0.28.5+dfsg.1/tests/clar_libgit2.h libgit2-1.1.0+dfsg.1/tests/clar_libgit2.h --- libgit2-0.28.5+dfsg.1/tests/clar_libgit2.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar_libgit2.h 2020-10-12 18:53:06.000000000 +0000 @@ -3,8 +3,8 @@ #include "clar.h" #include -#include #include "common.h" +#include "posix.h" /** * Replace for `clar_must_pass` that passes the last library error as the @@ -12,15 +12,15 @@ * * Use this wrapper around all `git_` library calls that return error codes! */ -#define cl_git_pass(expr) cl_git_expect((expr), 0, __FILE__, __LINE__) +#define cl_git_pass(expr) cl_git_expect((expr), 0, __FILE__, __func__, __LINE__) -#define cl_git_fail_with(error, expr) cl_git_expect((expr), error, __FILE__, __LINE__) +#define cl_git_fail_with(error, expr) cl_git_expect((expr), error, __FILE__, __func__, __LINE__) -#define cl_git_expect(expr, expected, file, line) do { \ +#define cl_git_expect(expr, expected, file, func, line) do { \ int _lg2_error; \ git_error_clear(); \ if ((_lg2_error = (expr)) != expected) \ - cl_git_report_failure(_lg2_error, expected, file, line, "Function call failed: " #expr); \ + cl_git_report_failure(_lg2_error, expected, file, func, line, "Function call failed: " #expr); \ } while (0) /** @@ -31,7 +31,7 @@ #define cl_git_fail(expr) do { \ if ((expr) == 0) \ git_error_clear(), \ - cl_git_report_failure(0, 0, __FILE__, __LINE__, "Function call succeeded: " #expr); \ + cl_git_report_failure(0, 0, __FILE__, __func__, __LINE__, "Function call succeeded: " #expr); \ } while (0) /** @@ -41,7 +41,7 @@ int _win32_res; \ if ((_win32_res = (expr)) == 0) { \ git_error_set(GIT_ERROR_OS, "Returned: %d, system error code: %lu", _win32_res, GetLastError()); \ - cl_git_report_failure(_win32_res, 0, __FILE__, __LINE__, "System call failed: " #expr); \ + cl_git_report_failure(_win32_res, 0, __FILE__, __func__, __LINE__, "System call failed: " #expr); \ } \ } while(0) @@ -58,22 +58,24 @@ typedef struct { int error; const char *file; + const char *func; int line; const char *expr; char error_msg[4096]; } cl_git_thread_err; #ifdef GIT_THREADS -# define cl_git_thread_pass(threaderr, expr) cl_git_thread_pass_(threaderr, (expr), __FILE__, __LINE__) +# define cl_git_thread_pass(threaderr, expr) cl_git_thread_pass_(threaderr, (expr), __FILE__, __func__, __LINE__) #else # define cl_git_thread_pass(threaderr, expr) cl_git_pass(expr) #endif -#define cl_git_thread_pass_(__threaderr, __expr, __file, __line) do { \ +#define cl_git_thread_pass_(__threaderr, __expr, __file, __func, __line) do { \ git_error_clear(); \ if ((((cl_git_thread_err *)__threaderr)->error = (__expr)) != 0) { \ const git_error *_last = git_error_last(); \ ((cl_git_thread_err *)__threaderr)->file = __file; \ + ((cl_git_thread_err *)__threaderr)->func = __func; \ ((cl_git_thread_err *)__threaderr)->line = __line; \ ((cl_git_thread_err *)__threaderr)->expr = "Function call failed: " #__expr; \ p_snprintf(((cl_git_thread_err *)__threaderr)->error_msg, 4096, "thread 0x%" PRIxZ " - error %d - %s", \ @@ -87,38 +89,39 @@ { cl_git_thread_err *threaderr = (cl_git_thread_err *)data; if (threaderr->error != 0) - clar__assert(0, threaderr->file, threaderr->line, threaderr->expr, threaderr->error_msg, 1); + clar__assert(0, threaderr->file, threaderr->func, threaderr->line, threaderr->expr, threaderr->error_msg, 1); } -void cl_git_report_failure(int, int, const char *, int, const char *); +void cl_git_report_failure(int, int, const char *, const char *, int, const char *); -#define cl_assert_at_line(expr,file,line) \ - clar__assert((expr) != 0, file, line, "Expression is not true: " #expr, NULL, 1) +#define cl_assert_at_line(expr,file,func,line) \ + clar__assert((expr) != 0, file, func, line, "Expression is not true: " #expr, NULL, 1) GIT_INLINE(void) clar__assert_in_range( int lo, int val, int hi, - const char *file, int line, const char *err, int should_abort) + const char *file, const char *func, int line, + const char *err, int should_abort) { if (lo > val || hi < val) { char buf[128]; p_snprintf(buf, sizeof(buf), "%d not in [%d,%d]", val, lo, hi); - clar__fail(file, line, err, buf, should_abort); + clar__fail(file, func, line, err, buf, should_abort); } } #define cl_assert_equal_sz(sz1,sz2) do { \ size_t __sz1 = (size_t)(sz1), __sz2 = (size_t)(sz2); \ - clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ + clar__assert_equal(__FILE__,__func__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ } while (0) #define cl_assert_in_range(L,V,H) \ - clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) + clar__assert_in_range((L),(V),(H),__FILE__,__func__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) #define cl_assert_equal_file(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,(int)__LINE__) + clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,__func__,(int)__LINE__) #define cl_assert_equal_file_ignore_cr(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,(int)__LINE__) + clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,__func__,(int)__LINE__) void clar__assert_equal_file( const char *expected_data, @@ -126,10 +129,11 @@ int ignore_cr, const char *path, const char *file, + const char *func, int line); GIT_INLINE(void) clar__assert_equal_oid( - const char *file, int line, const char *desc, + const char *file, const char *func, int line, const char *desc, const git_oid *one, const git_oid *two) { if (git_oid_cmp(one, two)) { @@ -138,12 +142,12 @@ git_oid_fmt(&err[1], one); git_oid_fmt(&err[47], two); - clar__fail(file, line, desc, err, 1); + clar__fail(file, func, line, desc, err, 1); } } #define cl_assert_equal_oid(one, two) \ - clar__assert_equal_oid(__FILE__, __LINE__, \ + clar__assert_equal_oid(__FILE__, __func__, __LINE__, \ "OID mismatch: " #one " != " #two, (one), (two)) /* @@ -220,6 +224,12 @@ void cl_sandbox_set_search_path_defaults(void); #ifdef GIT_WIN32 +# define cl_msleep(x) Sleep(x) +#else +# define cl_msleep(x) usleep(1000 * (x)) +#endif + +#ifdef GIT_WIN32 bool cl_sandbox_supports_8dot3(void); #endif diff -Nru libgit2-0.28.5+dfsg.1/tests/clar_libgit2_trace.c libgit2-1.1.0+dfsg.1/tests/clar_libgit2_trace.c --- libgit2-0.28.5+dfsg.1/tests/clar_libgit2_trace.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clar_libgit2_trace.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,35 +1,49 @@ -#include "clar_libgit2.h" #include "clar_libgit2_trace.h" +#include "clar_libgit2.h" #include "clar_libgit2_timer.h" #include "trace.h" - struct method { const char *name; void (*git_trace_cb)(git_trace_level_t level, const char *msg); void (*close)(void); }; +static const char *message_prefix(git_trace_level_t level) +{ + switch (level) { + case GIT_TRACE_NONE: + return "[NONE]: "; + case GIT_TRACE_FATAL: + return "[FATAL]: "; + case GIT_TRACE_ERROR: + return "[ERROR]: "; + case GIT_TRACE_WARN: + return "[WARN]: "; + case GIT_TRACE_INFO: + return "[INFO]: "; + case GIT_TRACE_DEBUG: + return "[DEBUG]: "; + case GIT_TRACE_TRACE: + return "[TRACE]: "; + default: + return "[?????]: "; + } +} -#if defined(GIT_TRACE) static void _git_trace_cb__printf(git_trace_level_t level, const char *msg) { - /* TODO Use level to print a per-message prefix. */ - GIT_UNUSED(level); - - printf("%s\n", msg); + printf("%s%s\n", message_prefix(level), msg); } #if defined(GIT_WIN32) static void _git_trace_cb__debug(git_trace_level_t level, const char *msg) { - /* TODO Use level to print a per-message prefix. */ - GIT_UNUSED(level); - + OutputDebugString(message_prefix(level)); OutputDebugString(msg); OutputDebugString("\n"); - printf("%s\n", msg); + printf("%s%s\n", message_prefix(level), msg); } #else #define _git_trace_cb__debug _git_trace_cb__printf @@ -55,7 +69,7 @@ static int s_trace_loaded = 0; static int s_trace_level = GIT_TRACE_NONE; static struct method *s_trace_method = NULL; - +static int s_trace_tests = 0; static int set_method(const char *name) { @@ -101,6 +115,7 @@ { char *sz_level; char *sz_method; + char *sz_tests; s_trace_loaded = 1; @@ -117,6 +132,10 @@ sz_method = cl_getenv("CLAR_TRACE_METHOD"); if (set_method(sz_method) < 0) set_method(NULL); + + sz_tests = cl_getenv("CLAR_TRACE_TESTS"); + if (sz_tests != NULL) + s_trace_tests = 1; } #define HR "================================================================" @@ -139,6 +158,9 @@ { GIT_UNUSED(payload); + if (!s_trace_tests) + return; + switch (ev) { case CL_TRACE__SUITE_BEGIN: git_trace(GIT_TRACE_TRACE, "\n\n%s\n%s: Begin Suite", HR, suite_name); @@ -201,15 +223,11 @@ } } -#endif /*GIT_TRACE*/ - /** * Setup/Enable git_trace() based upon settings user's environment. - * */ void cl_global_trace_register(void) { -#if defined(GIT_TRACE) if (!s_trace_loaded) _load_trace_params(); @@ -222,7 +240,6 @@ git_trace_set(s_trace_level, s_trace_method->git_trace_cb); cl_trace_register(_cl_trace_cb__event_handler, NULL); -#endif } /** @@ -234,7 +251,6 @@ */ void cl_global_trace_disable(void) { -#if defined(GIT_TRACE) cl_trace_register(NULL, NULL); git_trace_set(GIT_TRACE_NONE, NULL); if (s_trace_method && s_trace_method->close) @@ -244,5 +260,4 @@ * since we only want to hit the environment variables * once. */ -#endif } diff -Nru libgit2-0.28.5+dfsg.1/tests/clone/empty.c libgit2-1.1.0+dfsg.1/tests/clone/empty.c --- libgit2-0.28.5+dfsg.1/tests/clone/empty.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clone/empty.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,6 +2,7 @@ #include "git2/clone.h" #include "repository.h" +#include "repo/repo_helpers.h" static git_clone_options g_options; static git_repository *g_repo; @@ -22,6 +23,7 @@ void test_clone_empty__cleanup(void) { + cl_fixture_cleanup("tmp_global_path"); cl_git_sandbox_cleanup(); } @@ -66,6 +68,21 @@ expected_tracked_branch_name)); } +void test_clone_empty__respects_initialbranch_config(void) +{ + git_buf buf = GIT_BUF_INIT; + + create_tmp_global_config("tmp_global_path", "init.defaultbranch", "my_default_branch"); + + cl_set_cleanup(&cleanup_repository, "./empty"); + + g_options.bare = true; + cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); + cl_git_pass(git_branch_upstream_name(&buf, g_repo_cloned, "refs/heads/my_default_branch")); + cl_assert_equal_s("refs/remotes/origin/my_default_branch", buf.ptr); + git_buf_dispose(&buf); +} + void test_clone_empty__can_clone_an_empty_local_repo(void) { cl_set_cleanup(&cleanup_repository, "./empty"); diff -Nru libgit2-0.28.5+dfsg.1/tests/clone/local.c libgit2-1.1.0+dfsg.1/tests/clone/local.c --- libgit2-0.28.5+dfsg.1/tests/clone/local.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clone/local.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,7 +5,7 @@ #include "buffer.h" #include "path.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" static int file_url(git_buf *buf, const char *host, const char *path) { diff -Nru libgit2-0.28.5+dfsg.1/tests/clone/nonetwork.c libgit2-1.1.0+dfsg.1/tests/clone/nonetwork.c --- libgit2-0.28.5+dfsg.1/tests/clone/nonetwork.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clone/nonetwork.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,10 +1,9 @@ #include "clar_libgit2.h" #include "git2/clone.h" -#include "git2/sys/commit.h" #include "../submodule/submodule_helpers.h" #include "remote.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" #define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" @@ -171,7 +170,7 @@ } static int clone_cancel_fetch_transfer_progress_cb( - const git_transfer_progress *stats, void *data) + const git_indexer_progress *stats, void *data) { GIT_UNUSED(stats); GIT_UNUSED(data); return -54321; @@ -352,56 +351,3 @@ git_repository_free(repo); cl_fixture_cleanup("./repowithunborn"); } - -static int just_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) -{ - GIT_UNUSED(url); GIT_UNUSED(payload); - - return git_remote_lookup(out, repo, name); -} - -static int just_return_repo(git_repository **out, const char *path, int bare, void *payload) -{ - git_submodule *sm = payload; - - GIT_UNUSED(path); GIT_UNUSED(bare); - - return git_submodule_open(out, sm); -} - -void test_clone_nonetwork__clone_submodule(void) -{ - git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_index *index; - git_oid tree_id, commit_id; - git_submodule *sm; - git_signature *sig; - git_repository *sm_repo; - - cl_git_pass(git_repository_init(&g_repo, "willaddsubmodule", false)); - - - /* Create the submodule structure, clone into it and finalize */ - cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo", true)); - - clone_opts.repository_cb = just_return_repo; - clone_opts.repository_cb_payload = sm; - clone_opts.remote_cb = just_return_origin; - clone_opts.remote_cb_payload = sm; - cl_git_pass(git_clone(&sm_repo, cl_fixture("testrepo.git"), "testrepo", &clone_opts)); - cl_git_pass(git_submodule_add_finalize(sm)); - git_repository_free(sm_repo); - git_submodule_free(sm); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_write_tree(&tree_id, index)); - git_index_free(index); - - cl_git_pass(git_signature_now(&sig, "Submoduler", "submoduler@local")); - cl_git_pass(git_commit_create_from_ids(&commit_id, g_repo, "HEAD", sig, sig, NULL, "A submodule\n", - &tree_id, 0, NULL)); - - git_signature_free(sig); - - assert_submodule_exists(g_repo, "testrepo"); -} diff -Nru libgit2-0.28.5+dfsg.1/tests/clone/transport.c libgit2-1.1.0+dfsg.1/tests/clone/transport.c --- libgit2-0.28.5+dfsg.1/tests/clone/transport.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/clone/transport.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/clone.h" #include "git2/transport.h" #include "git2/sys/transport.h" -#include "fileops.h" +#include "futils.h" static int custom_transport( git_transport **out, diff -Nru libgit2-0.28.5+dfsg.1/tests/CMakeLists.txt libgit2-1.1.0+dfsg.1/tests/CMakeLists.txt --- libgit2-0.28.5+dfsg.1/tests/CMakeLists.txt 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/CMakeLists.txt 2020-10-12 18:53:06.000000000 +0000 @@ -42,12 +42,7 @@ SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES C_STANDARD 90) SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR}) -IF (${CMAKE_VERSION} VERSION_LESS 2.8.12) - # Already handled by a global INCLUDE_DIRECTORY() -ELSE() - TARGET_INCLUDE_DIRECTORIES(libgit2_clar PRIVATE ../src PUBLIC ../include) -ENDIF() - +TARGET_INCLUDE_DIRECTORIES(libgit2_clar PRIVATE ../src PUBLIC ../include) TARGET_LINK_LIBRARIES(libgit2_clar ${LIBGIT2_LIBS}) IDE_SPLIT_SOURCES(libgit2_clar) @@ -57,9 +52,19 @@ SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h") ENDIF () -ADD_TEST(offline "${libgit2_BINARY_DIR}/libgit2_clar" -v -xonline) -ADD_TEST(invasive "${libgit2_BINARY_DIR}/libgit2_clar" -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root) -ADD_TEST(online "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline) -ADD_TEST(gitdaemon "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push) -ADD_TEST(ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths) -ADD_TEST(proxy "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request) +FUNCTION(ADD_CLAR_TEST name) + IF (NOT USE_LEAK_CHECKER STREQUAL "OFF") + ADD_TEST(${name} "${libgit2_SOURCE_DIR}/script/${USE_LEAK_CHECKER}.sh" "${libgit2_BINARY_DIR}/libgit2_clar" ${ARGN}) + ELSE() + ADD_TEST(${name} "${libgit2_BINARY_DIR}/libgit2_clar" ${ARGN}) + ENDIF() +ENDFUNCTION(ADD_CLAR_TEST) + +ADD_CLAR_TEST(offline -v -xonline) +ADD_CLAR_TEST(invasive -v -score::ftruncate -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root) +ADD_CLAR_TEST(online -v -sonline) +ADD_CLAR_TEST(gitdaemon -v -sonline::push) +ADD_CLAR_TEST(ssh -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths -sonline::clone::path_whitespace_ssh) +ADD_CLAR_TEST(proxy -v -sonline::clone::proxy) +ADD_CLAR_TEST(auth_clone -v -sonline::clone::cred) +ADD_CLAR_TEST(auth_clone_and_push -v -sonline::clone::push -sonline::push) diff -Nru libgit2-0.28.5+dfsg.1/tests/commit/write.c libgit2-1.1.0+dfsg.1/tests/commit/write.c --- libgit2-0.28.5+dfsg.1/tests/commit/write.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/commit/write.c 2020-10-12 18:53:06.000000000 +0000 @@ -299,19 +299,43 @@ cl_git_fail(create_commit_from_ids(&commit_id, &tree_id, &parent_id)); } -void test_commit_write__attach_singleline_signature(void) +void test_commit_write__attach_signature_checks_objects(void) { const char *sig = "magic word: pretty please"; + const char *badtree = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ +parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ +author Ben Burkert 1358451456 -0800\n\ +committer Ben Burkert 1358451456 -0800\n\ +\n\ +a simple commit which does not work\n"; - const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ + const char *badparent = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\ parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ author Ben Burkert 1358451456 -0800\n\ committer Ben Burkert 1358451456 -0800\n\ \n\ +a simple commit which does not work\n"; + + git_oid id; + + cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badtree, sig, "magicsig")); + cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badparent, sig, "magicsig")); + +} + +void test_commit_write__attach_singleline_signature(void) +{ + const char *sig = "magic word: pretty please"; + + const char *data = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\ +parent 8496071c1b46c854b31185ea97743be6a8774479\n\ +author Ben Burkert 1358451456 -0800\n\ +committer Ben Burkert 1358451456 -0800\n\ +\n\ a simple commit which works\n"; - const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ -parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ + const char *complete = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\ +parent 8496071c1b46c854b31185ea97743be6a8774479\n\ author Ben Burkert 1358451456 -0800\n\ committer Ben Burkert 1358451456 -0800\n\ magicsig magic word: pretty please\n\ @@ -352,15 +376,15 @@ =ozeK\n\ -----END PGP SIGNATURE-----"; - const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ -parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ + const char *data = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\ +parent 8496071c1b46c854b31185ea97743be6a8774479\n\ author Ben Burkert 1358451456 -0800\n\ committer Ben Burkert 1358451456 -0800\n\ \n\ a simple commit which works\n"; -const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ -parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ +const char *complete = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\ +parent 8496071c1b46c854b31185ea97743be6a8774479\n\ author Ben Burkert 1358451456 -0800\n\ committer Ben Burkert 1358451456 -0800\n\ gpgsig -----BEGIN PGP SIGNATURE-----\n\ diff -Nru libgit2-0.28.5+dfsg.1/tests/config/conditionals.c libgit2-1.1.0+dfsg.1/tests/config/conditionals.c --- libgit2-0.28.5+dfsg.1/tests/config/conditionals.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/conditionals.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" +#include "repository.h" #ifdef GIT_WIN32 # define ROOT_PREFIX "C:" @@ -22,11 +23,11 @@ static void assert_condition_includes(const char *keyword, const char *path, bool expected) { - git_config *cfg; git_buf buf = GIT_BUF_INIT; + git_config *cfg; - git_buf_printf(&buf, "[includeIf \"%s:%s\"]\n", keyword, path); - git_buf_puts(&buf, "path = other\n"); + cl_git_pass(git_buf_printf(&buf, "[includeIf \"%s:%s\"]\n", keyword, path)); + cl_git_pass(git_buf_puts(&buf, "path = other\n")); cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr); cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n"); @@ -47,53 +48,58 @@ git_config_free(cfg); } +static char *sandbox_path(git_buf *buf, const char *suffix) +{ + char *path = p_realpath(clar_sandbox_path(), NULL); + cl_assert(path); + cl_git_pass(git_buf_attach(buf, path, 0)); + cl_git_pass(git_buf_joinpath(buf, buf->ptr, suffix)); + return buf->ptr; +} + void test_config_conditionals__gitdir(void) { git_buf path = GIT_BUF_INIT; - char *sandbox_path; assert_condition_includes("gitdir", ROOT_PREFIX "/", true); - assert_condition_includes("gitdir", "empty_standard_repo", true); + assert_condition_includes("gitdir", "empty_stand", false); + assert_condition_includes("gitdir", "empty_stand/", false); + assert_condition_includes("gitdir", "empty_stand/.git", false); + assert_condition_includes("gitdir", "empty_stand/.git/", false); + assert_condition_includes("gitdir", "empty_stand*/", true); + assert_condition_includes("gitdir", "empty_stand*/.git", true); + assert_condition_includes("gitdir", "empty_stand*/.git/", false); + assert_condition_includes("gitdir", "empty_standard_repo", false); assert_condition_includes("gitdir", "empty_standard_repo/", true); - assert_condition_includes("gitdir", "./", true); + assert_condition_includes("gitdir", "empty_standard_repo/.git", true); + assert_condition_includes("gitdir", "empty_standard_repo/.git/", false); + + assert_condition_includes("gitdir", "./", false); assert_condition_includes("gitdir", ROOT_PREFIX "/nonexistent", false); assert_condition_includes("gitdir", ROOT_PREFIX "/empty_standard_repo", false); - assert_condition_includes("gitdir", "empty_stand", false); assert_condition_includes("gitdir", "~/empty_standard_repo", false); - sandbox_path = p_realpath(clar_sandbox_path(), NULL); - - git_buf_joinpath(&path, sandbox_path, "/"); - assert_condition_includes("gitdir", path.ptr, true); - - git_buf_joinpath(&path, sandbox_path, "/*"); - assert_condition_includes("gitdir", path.ptr, true); + assert_condition_includes("gitdir", sandbox_path(&path, "/"), true); + assert_condition_includes("gitdir", sandbox_path(&path, "/*"), false); + assert_condition_includes("gitdir", sandbox_path(&path, "/**"), true); + + assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo"), false); + assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true); + assert_condition_includes("gitdir", sandbox_path(&path, "empty_standard_repo/"), true); + assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo"), false); + assert_condition_includes("gitdir", sandbox_path(&path, "Empty_Standard_Repo/"), false); - git_buf_joinpath(&path, sandbox_path, "empty_standard_repo"); - assert_condition_includes("gitdir", path.ptr, true); - - git_buf_joinpath(&path, sandbox_path, "Empty_Standard_Repo"); - assert_condition_includes("gitdir", path.ptr, false); - - git__free(sandbox_path); git_buf_dispose(&path); } void test_config_conditionals__gitdir_i(void) { git_buf path = GIT_BUF_INIT; - char *sandbox_path; - - sandbox_path = p_realpath(clar_sandbox_path(), NULL); - git_buf_joinpath(&path, sandbox_path, "empty_standard_repo"); - assert_condition_includes("gitdir/i", path.ptr, true); + assert_condition_includes("gitdir/i", sandbox_path(&path, "empty_standard_repo/"), true); + assert_condition_includes("gitdir/i", sandbox_path(&path, "EMPTY_STANDARD_REPO/"), true); - git_buf_joinpath(&path, sandbox_path, "EMPTY_STANDARD_REPO"); - assert_condition_includes("gitdir/i", path.ptr, true); - - git__free(sandbox_path); git_buf_dispose(&path); } @@ -101,3 +107,42 @@ { assert_condition_includes("foobar", ".git", false); } + +static void set_head(git_repository *repo, const char *name) +{ + cl_git_pass(git_repository_create_head(git_repository_path(repo), name)); +} + +void test_config_conditionals__onbranch(void) +{ + assert_condition_includes("onbranch", "master", true); + assert_condition_includes("onbranch", "m*", true); + assert_condition_includes("onbranch", "*", true); + assert_condition_includes("onbranch", "master/", false); + assert_condition_includes("onbranch", "foo", false); + + set_head(_repo, "foo"); + assert_condition_includes("onbranch", "master", false); + assert_condition_includes("onbranch", "foo", true); + assert_condition_includes("onbranch", "f*o", true); + + set_head(_repo, "dir/ref"); + assert_condition_includes("onbranch", "dir/ref", true); + assert_condition_includes("onbranch", "dir/", true); + assert_condition_includes("onbranch", "dir/*", true); + assert_condition_includes("onbranch", "dir/**", true); + assert_condition_includes("onbranch", "**", true); + assert_condition_includes("onbranch", "dir", false); + assert_condition_includes("onbranch", "dir*", false); + + set_head(_repo, "dir/subdir/ref"); + assert_condition_includes("onbranch", "dir/subdir/", true); + assert_condition_includes("onbranch", "dir/subdir/*", true); + assert_condition_includes("onbranch", "dir/subdir/ref", true); + assert_condition_includes("onbranch", "dir/", true); + assert_condition_includes("onbranch", "dir/**", true); + assert_condition_includes("onbranch", "**", true); + assert_condition_includes("onbranch", "dir", false); + assert_condition_includes("onbranch", "dir*", false); + assert_condition_includes("onbranch", "dir/*", false); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/config/global.c libgit2-1.1.0+dfsg.1/tests/config/global.c --- libgit2-0.28.5+dfsg.1/tests/config/global.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/global.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" void test_config_global__initialize(void) { @@ -27,29 +27,61 @@ void test_config_global__cleanup(void) { cl_sandbox_set_search_path_defaults(); + cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(git_futils_rmdir_r("xdg", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(git_futils_rmdir_r("etc", NULL, GIT_RMDIR_REMOVE_FILES)); } void test_config_global__open_global(void) { git_config *cfg, *global, *selected, *dummy; + int32_t value; + + cl_git_mkfile("home/.gitconfig", "[global]\n test = 4567\n"); cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_int32(&value, cfg, "global.test")); + cl_assert_equal_i(4567, value); + cl_git_pass(git_config_open_level(&global, cfg, GIT_CONFIG_LEVEL_GLOBAL)); + cl_git_pass(git_config_get_int32(&value, global, "global.test")); + cl_assert_equal_i(4567, value); + cl_git_fail(git_config_open_level(&dummy, cfg, GIT_CONFIG_LEVEL_XDG)); + cl_git_pass(git_config_open_global(&selected, cfg)); + cl_git_pass(git_config_get_int32(&value, selected, "global.test")); + cl_assert_equal_i(4567, value); git_config_free(selected); git_config_free(global); git_config_free(cfg); } +void test_config_global__open_symlinked_global(void) +{ +#ifndef GIT_WIN32 + git_config *cfg; + int32_t value; + + cl_git_mkfile("home/.gitconfig.linked", "[global]\n test = 4567\n"); + cl_must_pass(symlink(".gitconfig.linked", "home/.gitconfig")); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_int32(&value, cfg, "global.test")); + cl_assert_equal_i(4567, value); + + git_config_free(cfg); +#endif +} + void test_config_global__lock_missing_global_config(void) { git_config *cfg; git_config_entry *entry; git_transaction *transaction; - p_unlink("home/.gitconfig"); /* No global config */ + (void)p_unlink("home/.gitconfig"); /* No global config */ cl_git_pass(git_config_open_default(&cfg)); cl_git_pass(git_config_lock(&transaction, cfg)); diff -Nru libgit2-0.28.5+dfsg.1/tests/config/include.c libgit2-1.1.0+dfsg.1/tests/config/include.c --- libgit2-0.28.5+dfsg.1/tests/config/include.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/include.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" static git_config *cfg; static git_buf buf; @@ -201,4 +201,34 @@ cl_git_pass(p_unlink("top-level")); cl_git_pass(p_unlink("included")); +} + +void test_config_include__variables_in_included_override_including(void) +{ + int i; + + cl_git_mkfile("top-level", "[foo]\nbar = 1\n[include]\npath = included"); + cl_git_mkfile("included", "[foo]\nbar = 2"); + + cl_git_pass(git_config_open_ondisk(&cfg, "top-level")); + cl_git_pass(git_config_get_int32(&i, cfg, "foo.bar")); + cl_assert_equal_i(i, 2); + + cl_git_pass(p_unlink("top-level")); + cl_git_pass(p_unlink("included")); +} + +void test_config_include__variables_in_including_override_included(void) +{ + int i; + + cl_git_mkfile("top-level", "[include]\npath = included\n[foo]\nbar = 1"); + cl_git_mkfile("included", "[foo]\nbar = 2"); + + cl_git_pass(git_config_open_ondisk(&cfg, "top-level")); + cl_git_pass(git_config_get_int32(&i, cfg, "foo.bar")); + cl_assert_equal_i(i, 1); + + cl_git_pass(p_unlink("top-level")); + cl_git_pass(p_unlink("included")); } diff -Nru libgit2-0.28.5+dfsg.1/tests/config/new.c libgit2-1.1.0+dfsg.1/tests/config/new.c --- libgit2-0.28.5+dfsg.1/tests/config/new.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/new.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "filebuf.h" -#include "fileops.h" +#include "futils.h" #include "posix.h" #define TEST_CONFIG "git-new-config" @@ -30,5 +30,5 @@ git_buf_dispose(&buf); git_config_free(config); - p_unlink(TEST_CONFIG); + cl_must_pass(p_unlink(TEST_CONFIG)); } diff -Nru libgit2-0.28.5+dfsg.1/tests/config/read.c libgit2-1.1.0+dfsg.1/tests/config/read.c --- libgit2-0.28.5+dfsg.1/tests/config/read.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/read.c 2020-10-12 18:53:06.000000000 +0000 @@ -779,6 +779,93 @@ git_buf_dispose(&buf); } +void test_config_read__arbitrary_whitespace_before_subsection(void) +{ + git_buf buf = GIT_BUF_INIT; + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[some \t \"subsection\"]\n var = value\n"); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.subsection.var")); + cl_assert_equal_s(buf.ptr, "value"); + + git_config_free(cfg); + git_buf_dispose(&buf); +} + +void test_config_read__no_whitespace_after_subsection(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[some \"subsection\" ]\n var = value\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__invalid_space_section(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some section]\n var = value\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__invalid_quoted_first_section(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[\"some\"]\n var = value\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__invalid_unquoted_subsection(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some sub section]\n var = value\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__invalid_quoted_third_section(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some sub \"section\"]\n var = value\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__unreadable_file_ignored(void) +{ + git_buf buf = GIT_BUF_INIT; + git_config *cfg; + int ret; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[some] var = value\n[some \"OtheR\"] var = value"); + cl_git_pass(p_chmod("./testconfig", 0)); + + ret = git_config_open_ondisk(&cfg, "./test/config"); + cl_assert(ret == 0 || ret == GIT_ENOTFOUND); + + git_config_free(cfg); + git_buf_dispose(&buf); +} + void test_config_read__single_line(void) { git_buf buf = GIT_BUF_INIT; @@ -841,3 +928,79 @@ git_buf_dispose(&buf); git_config_free(cfg); } + +enum { + MAP_TRUE = 0, + MAP_FALSE = 1, + MAP_ALWAYS = 2 +}; + +static git_configmap _test_map1[] = { + {GIT_CONFIGMAP_STRING, "always", MAP_ALWAYS}, + {GIT_CONFIGMAP_FALSE, NULL, MAP_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, MAP_TRUE}, +}; + +static git_configmap _test_map2[] = { + {GIT_CONFIGMAP_INT32, NULL, 0}, +}; + +void test_config_read__get_mapped(void) +{ + git_config *cfg; + int val; + int known_good; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[header]\n" + " key1 = 1\n" + " key2 = true\n" + " key3\n" + " key4 = always\n" + " key5 = false\n" + " key6 = 0\n" + " key7 = never\n" + " key8 = On\n" + " key9 = off\n"); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); + + // check parsing bool and string + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_TRUE); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key2", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_TRUE); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key3", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_TRUE); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key8", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_TRUE); + + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key4", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_ALWAYS); + + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key5", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_FALSE); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_FALSE); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key9", _test_map1, ARRAY_SIZE(_test_map1))); + cl_assert_equal_i(val, MAP_FALSE); + + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map1, ARRAY_SIZE(_test_map1))); + + // check parsing int values + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key1")); + cl_assert_equal_i(val, known_good); + cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key6")); + cl_assert_equal_i(val, known_good); + + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key2", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key3", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key4", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key5", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key8", _test_map2, ARRAY_SIZE(_test_map2))); + cl_git_fail(git_config_get_mapped(&val, cfg, "header.key9", _test_map2, ARRAY_SIZE(_test_map2))); + + git_config_free(cfg); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/config/snapshot.c libgit2-1.1.0+dfsg.1/tests/config/snapshot.c --- libgit2-0.28.5+dfsg.1/tests/config/snapshot.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/snapshot.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,45 +1,51 @@ #include "clar_libgit2.h" -void test_config_snapshot__create_snapshot(void) -{ - int32_t tmp; - git_config *cfg, *snapshot, *new_snapshot; - const char *filename = "config-ext-change"; +#include "config_backend.h" + +static git_config *cfg; +static git_config *snapshot; - cl_git_mkfile(filename, "[old]\nvalue = 5\n"); +void test_config_snapshot__cleanup(void) +{ + git_config_free(cfg); + cfg = NULL; + git_config_free(snapshot); + snapshot = NULL; +} - cl_git_pass(git_config_open_ondisk(&cfg, filename)); +void test_config_snapshot__create_snapshot(void) +{ + int32_t i; - cl_git_pass(git_config_get_int32(&tmp, cfg, "old.value")); - cl_assert_equal_i(5, tmp); + cl_git_mkfile("config", "[old]\nvalue = 5\n"); + cl_git_pass(git_config_open_ondisk(&cfg, "config")); + cl_git_pass(git_config_get_int32(&i, cfg, "old.value")); + cl_assert_equal_i(5, i); cl_git_pass(git_config_snapshot(&snapshot, cfg)); /* Change the value on the file itself (simulate external process) */ - cl_git_mkfile(filename, "[old]\nvalue = 56\n"); + cl_git_mkfile("config", "[old]\nvalue = 56\n"); - cl_git_pass(git_config_get_int32(&tmp, cfg, "old.value")); - cl_assert_equal_i(56, tmp); - - cl_git_pass(git_config_get_int32(&tmp, snapshot, "old.value")); - cl_assert_equal_i(5, tmp); + cl_git_pass(git_config_get_int32(&i, cfg, "old.value")); + cl_assert_equal_i(56, i); + cl_git_pass(git_config_get_int32(&i, snapshot, "old.value")); + cl_assert_equal_i(5, i); /* Change the value on the file itself (simulate external process) */ - cl_git_mkfile(filename, "[old]\nvalue = 999\n"); + cl_git_mkfile("config", "[old]\nvalue = 999\n"); - cl_git_pass(git_config_snapshot(&new_snapshot, cfg)); + /* Old snapshot should still have the old value */ + cl_git_pass(git_config_get_int32(&i, snapshot, "old.value")); + cl_assert_equal_i(5, i); /* New snapshot should see new value */ - cl_git_pass(git_config_get_int32(&tmp, new_snapshot, "old.value")); - cl_assert_equal_i(999, tmp); - - /* Old snapshot should still have the old value */ - cl_git_pass(git_config_get_int32(&tmp, snapshot, "old.value")); - cl_assert_equal_i(5, tmp); - - git_config_free(new_snapshot); git_config_free(snapshot); - git_config_free(cfg); + cl_git_pass(git_config_snapshot(&snapshot, cfg)); + cl_git_pass(git_config_get_int32(&i, snapshot, "old.value")); + cl_assert_equal_i(999, i); + + cl_git_pass(p_unlink("config")); } static int count_me(const git_config_entry *entry, void *payload) @@ -55,24 +61,79 @@ void test_config_snapshot__multivar(void) { - int count = 0; - git_config *cfg, *snapshot; - const char *filename = "config-file"; - - cl_git_mkfile(filename, "[old]\nvalue = 5\nvalue = 6\n"); + int count; - cl_git_pass(git_config_open_ondisk(&cfg, filename)); + count = 0; + cl_git_mkfile("config", "[old]\nvalue = 5\nvalue = 6\n"); + cl_git_pass(git_config_open_ondisk(&cfg, "config")); cl_git_pass(git_config_get_multivar_foreach(cfg, "old.value", NULL, count_me, &count)); + cl_assert_equal_i(2, count); + count = 0; + cl_git_pass(git_config_snapshot(&snapshot, cfg)); + cl_git_pass(git_config_get_multivar_foreach(snapshot, "old.value", NULL, count_me, &count)); cl_assert_equal_i(2, count); + cl_git_pass(p_unlink("config")); +} + +void test_config_snapshot__includes(void) +{ + int i; + + cl_git_mkfile("including", "[include]\npath = included"); + cl_git_mkfile("included", "[section]\nkey = 1\n"); + + cl_git_pass(git_config_open_ondisk(&cfg, "including")); cl_git_pass(git_config_snapshot(&snapshot, cfg)); - git_config_free(cfg); - count = 0; - cl_git_pass(git_config_get_multivar_foreach(snapshot, "old.value", NULL, count_me, &count)); + cl_git_pass(git_config_get_int32(&i, snapshot, "section.key")); + cl_assert_equal_i(i, 1); - cl_assert_equal_i(2, count); + /* Rewrite "included" config */ + cl_git_mkfile("included", "[section]\nkey = 11\n"); - git_config_free(snapshot); + /* Assert that the live config changed, but snapshot remained the same */ + cl_git_pass(git_config_get_int32(&i, cfg, "section.key")); + cl_assert_equal_i(i, 11); + cl_git_pass(git_config_get_int32(&i, snapshot, "section.key")); + cl_assert_equal_i(i, 1); + + cl_git_pass(p_unlink("including")); + cl_git_pass(p_unlink("included")); +} + +void test_config_snapshot__snapshot(void) +{ + git_config *snapshot_snapshot; + int i; + + cl_git_mkfile("configfile", "[section]\nkey = 1\n"); + + cl_git_pass(git_config_open_ondisk(&cfg, "configfile")); + cl_git_pass(git_config_snapshot(&snapshot, cfg)); + + cl_git_pass(git_config_snapshot(&snapshot_snapshot, snapshot)); + + cl_git_pass(git_config_get_int32(&i, snapshot_snapshot, "section.key")); + cl_assert_equal_i(i, 1); + + git_config_free(snapshot_snapshot); + + cl_git_pass(p_unlink("configfile")); +} + +void test_config_snapshot__snapshot_from_in_memony(void) +{ + const char *configuration = "[section]\nkey = 1\n"; + git_config_backend *backend; + int i; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_backend_from_string(&backend, configuration, strlen(configuration))); + cl_git_pass(git_config_add_backend(cfg, backend, 0, NULL, 0)); + + cl_git_pass(git_config_snapshot(&snapshot, cfg)); + cl_git_pass(git_config_get_int32(&i, snapshot, "section.key")); + cl_assert_equal_i(i, 1); } diff -Nru libgit2-0.28.5+dfsg.1/tests/config/stress.c libgit2-1.1.0+dfsg.1/tests/config/stress.c --- libgit2-0.28.5+dfsg.1/tests/config/stress.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/stress.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "filebuf.h" -#include "fileops.h" +#include "futils.h" #include "posix.h" #define TEST_CONFIG "git-test-config" @@ -59,6 +59,11 @@ assert_config_value(config, "some.section.multi", "hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#"); assert_config_value(config, "some.section.multi2", "good, this is a ; multiline comment # with ;\n special chars and other stuff !@#"); assert_config_value(config, "some.section.back", "this is \ba phrase"); + assert_config_value(config, "some.section.dollar", "some $sign"); + assert_config_value(config, "some.section.multiquotes", "!ls x ls # comment2 $HOME"); + assert_config_value(config, "some.section.multiquotes2", "!ls x ls \"# comment2 $HOME\""); + assert_config_value(config, "some.section.multiquotes3", "hi # ho there are # more quotes"); + assert_config_value(config, "some.section.quotecomment", "hi # ho there are # more"); git_config_free(config); } @@ -123,6 +128,7 @@ for (i = 0; i < 10; i++) { int32_t val; cl_git_pass(git_config_set_int32(config_w, key, i)); + cl_msleep(1); cl_git_pass(git_config_get_int32(&val, config_r, key)); cl_assert_equal_i(i, val); } @@ -130,3 +136,71 @@ git_config_free(config_r); git_config_free(config_w); } + +static int foreach_cb(const git_config_entry *entry, void *payload) +{ + if (!strcmp(entry->name, "key.value")) { + *(char **)payload = git__strdup(entry->value); + return 0; + } + return -1; +} + +void test_config_stress__foreach_refreshes(void) +{ + git_config *config_w, *config_r; + char *value = NULL; + + cl_git_pass(git_config_open_ondisk(&config_w, "./cfg")); + cl_git_pass(git_config_open_ondisk(&config_r, "./cfg")); + + cl_git_pass(git_config_set_string(config_w, "key.value", "1")); + cl_git_pass(git_config_foreach_match(config_r, "key.value", foreach_cb, &value)); + + cl_assert_equal_s(value, "1"); + + git_config_free(config_r); + git_config_free(config_w); + git__free(value); +} + +void test_config_stress__foreach_refreshes_snapshot(void) +{ + git_config *config, *snapshot; + char *value = NULL; + + cl_git_pass(git_config_open_ondisk(&config, "./cfg")); + + cl_git_pass(git_config_set_string(config, "key.value", "1")); + cl_git_pass(git_config_snapshot(&snapshot, config)); + cl_git_pass(git_config_foreach_match(snapshot, "key.value", foreach_cb, &value)); + + cl_assert_equal_s(value, "1"); + + git_config_free(snapshot); + git_config_free(config); + git__free(value); +} + +void test_config_stress__huge_section_with_many_values(void) +{ + git_config *config; + + if (!cl_is_env_set("GITTEST_INVASIVE_SPEED")) + cl_skip(); + + /* + * The config file is structured in such a way that is + * has a section header that is approximately 500kb of + * size followed by 40k entries. While the resulting + * configuration file itself is roughly 650kb in size and + * thus considered to be rather small, in the past we'd + * balloon to more than 20GB of memory (20000x500kb) + * while parsing the file. It thus was a trivial way to + * cause an out-of-memory situation and thus cause denial + * of service, e.g. via gitmodules. + */ + cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config-oom"))); + + git_config_free(config); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/config/write.c libgit2-1.1.0+dfsg.1/tests/config/write.c --- libgit2-0.28.5+dfsg.1/tests/config/write.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/config/write.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "git2/sys/config.h" #include "config.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/core/assert.c libgit2-1.1.0+dfsg.1/tests/core/assert.c --- libgit2-0.28.5+dfsg.1/tests/core/assert.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/assert.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,94 @@ +#ifdef GIT_ASSERT_HARD +# undef GIT_ASSERT_HARD +#endif + +#define GIT_ASSERT_HARD 0 + +#include "clar_libgit2.h" + +static const char *hello_world = "hello, world"; +static const char *fail = "FAIL"; + +static int dummy_fn(const char *myarg) +{ + GIT_ASSERT_ARG(myarg); + GIT_ASSERT_ARG(myarg != hello_world); + return 0; +} + +static const char *fn_returns_string(const char *myarg) +{ + GIT_ASSERT_ARG_WITH_RETVAL(myarg, fail); + GIT_ASSERT_ARG_WITH_RETVAL(myarg != hello_world, fail); + + return myarg; +} + +static int bad_math(void) +{ + GIT_ASSERT(1 + 1 == 3); + return 42; +} + +static const char *bad_returns_string(void) +{ + GIT_ASSERT_WITH_RETVAL(1 + 1 == 3, NULL); + return hello_world; +} + +void test_core_assert__argument(void) +{ + cl_git_fail(dummy_fn(NULL)); + cl_assert(git_error_last()); + cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass); + cl_assert_equal_s("invalid argument: 'myarg'", git_error_last()->message); + + cl_git_fail(dummy_fn(hello_world)); + cl_assert(git_error_last()); + cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass); + cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message); + + cl_git_pass(dummy_fn("foo")); +} + +void test_core_assert__argument_with_non_int_return_type(void) +{ + const char *foo = "foo"; + + cl_assert_equal_p(fail, fn_returns_string(NULL)); + cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass); + cl_assert_equal_s("invalid argument: 'myarg'", git_error_last()->message); + + cl_assert_equal_p(fail, fn_returns_string(hello_world)); + cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass); + cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message); + + cl_assert_equal_p(foo, fn_returns_string(foo)); +} + +void test_core_assert__argument_with_void_return_type(void) +{ + const char *foo = "foo"; + + git_error_clear(); + fn_returns_string(hello_world); + cl_assert_equal_i(GIT_ERROR_INVALID, git_error_last()->klass); + cl_assert_equal_s("invalid argument: 'myarg != hello_world'", git_error_last()->message); + + git_error_clear(); + cl_assert_equal_p(foo, fn_returns_string(foo)); + cl_assert_equal_p(NULL, git_error_last()); +} + +void test_core_assert__internal(void) +{ + cl_git_fail(bad_math()); + cl_assert(git_error_last()); + cl_assert_equal_i(GIT_ERROR_INTERNAL, git_error_last()->klass); + cl_assert_equal_s("unrecoverable internal error: '1 + 1 == 3'", git_error_last()->message); + + cl_assert_equal_p(NULL, bad_returns_string()); + cl_assert(git_error_last()); + cl_assert_equal_i(GIT_ERROR_INTERNAL, git_error_last()->klass); + cl_assert_equal_s("unrecoverable internal error: '1 + 1 == 3'", git_error_last()->message); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/core/buffer.c libgit2-1.1.0+dfsg.1/tests/core/buffer.c --- libgit2-0.28.5+dfsg.1/tests/core/buffer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/buffer.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "buffer.h" #include "buf_text.h" #include "git2/sys/hashsig.h" -#include "fileops.h" +#include "futils.h" #define TESTSTR "Have you seen that? Have you seeeen that??" const char *test_string = TESTSTR; diff -Nru libgit2-0.28.5+dfsg.1/tests/core/copy.c libgit2-1.1.0+dfsg.1/tests/core/copy.c --- libgit2-0.28.5+dfsg.1/tests/core/copy.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/copy.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "path.h" #include "posix.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/core/dirent.c libgit2-1.1.0+dfsg.1/tests/core/dirent.c --- libgit2-0.28.5+dfsg.1/tests/core/dirent.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/dirent.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" typedef struct name_data { int count; /* return count */ diff -Nru libgit2-0.28.5+dfsg.1/tests/core/env.c libgit2-1.1.0+dfsg.1/tests/core/env.c --- libgit2-0.28.5+dfsg.1/tests/core/env.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/env.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "sysdir.h" #include "path.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/core/filebuf.c libgit2-1.1.0+dfsg.1/tests/core/filebuf.c --- libgit2-0.28.5+dfsg.1/tests/core/filebuf.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/filebuf.c 2020-10-12 18:53:06.000000000 +0000 @@ -157,9 +157,8 @@ git_filebuf file = GIT_FILEBUF_INIT; const char *dir = "linkdir", *source = "linkdir/link"; -#ifdef GIT_WIN32 - cl_skip(); -#endif + if (!git_path_supports_symlinks(clar_sandbox_path())) + cl_skip(); cl_git_pass(p_mkdir(dir, 0777)); cl_git_pass(p_symlink("target", source)); @@ -192,9 +191,8 @@ git_filebuf file = GIT_FILEBUF_INIT; git_buf source = GIT_BUF_INIT, target = GIT_BUF_INIT; -#ifdef GIT_WIN32 - cl_skip(); -#endif + if (!git_path_supports_symlinks(clar_sandbox_path())) + cl_skip(); cl_git_pass(git_buf_joinpath(&source, clar_sandbox_path(), "linkdir/link")); cl_git_pass(git_buf_joinpath(&target, clar_sandbox_path(), "linkdir/target")); @@ -221,9 +219,8 @@ git_filebuf file = GIT_FILEBUF_INIT; const char *dir = "linkdir", *source = "linkdir/link"; -#ifdef GIT_WIN32 - cl_skip(); -#endif + if (!git_path_supports_symlinks(clar_sandbox_path())) + cl_skip(); cl_git_pass(p_mkdir(dir, 0777)); /* Endless loop */ diff -Nru libgit2-0.28.5+dfsg.1/tests/core/ftruncate.c libgit2-1.1.0+dfsg.1/tests/core/ftruncate.c --- libgit2-0.28.5+dfsg.1/tests/core/ftruncate.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/ftruncate.c 2020-10-12 18:53:06.000000000 +0000 @@ -27,7 +27,7 @@ p_unlink(filename); } -static void _extend(git_off_t i64len) +static void _extend(off64_t i64len) { struct stat st; int error; diff -Nru libgit2-0.28.5+dfsg.1/tests/core/futils.c libgit2-1.1.0+dfsg.1/tests/core/futils.c --- libgit2-0.28.5+dfsg.1/tests/core/futils.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/futils.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" /* Fixture setup and teardown */ void test_core_futils__initialize(void) @@ -66,3 +66,24 @@ #endif } +void test_core_futils__recursive_rmdir_keeps_symlink_targets(void) +{ + if (!git_path_supports_symlinks(clar_sandbox_path())) + cl_skip(); + + cl_git_pass(git_futils_mkdir_r("a/b", 0777)); + cl_git_pass(git_futils_mkdir_r("dir-target", 0777)); + cl_git_mkfile("dir-target/file", "Contents"); + cl_git_mkfile("file-target", "Contents"); + cl_must_pass(p_symlink("dir-target", "a/symlink")); + cl_must_pass(p_symlink("file-target", "a/b/symlink")); + + cl_git_pass(git_futils_rmdir_r("a", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_assert(git_path_exists("dir-target")); + cl_assert(git_path_exists("file-target")); + + cl_must_pass(p_unlink("dir-target/file")); + cl_must_pass(p_rmdir("dir-target")); + cl_must_pass(p_unlink("file-target")); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/core/link.c libgit2-1.1.0+dfsg.1/tests/core/link.c --- libgit2-0.28.5+dfsg.1/tests/core/link.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/link.c 2020-10-12 18:53:06.000000000 +0000 @@ -54,7 +54,7 @@ create_symlink_func pCreateSymbolicLink; cl_assert(module = GetModuleHandle("kernel32")); - cl_assert(pCreateSymbolicLink = (create_symlink_func)GetProcAddress(module, "CreateSymbolicLinkA")); + cl_assert(pCreateSymbolicLink = (create_symlink_func)(void *)GetProcAddress(module, "CreateSymbolicLinkA")); cl_win32_pass(pCreateSymbolicLink(new, old, is_dir)); #endif @@ -70,7 +70,7 @@ create_hardlink_func pCreateHardLink; cl_assert(module = GetModuleHandle("kernel32")); - cl_assert(pCreateHardLink = (create_hardlink_func)GetProcAddress(module, "CreateHardLinkA")); + cl_assert(pCreateHardLink = (create_hardlink_func)(void *)GetProcAddress(module, "CreateHardLinkA")); cl_win32_pass(pCreateHardLink(new, old, 0)); #endif diff -Nru libgit2-0.28.5+dfsg.1/tests/core/mkdir.c libgit2-1.1.0+dfsg.1/tests/core/mkdir.c --- libgit2-0.28.5+dfsg.1/tests/core/mkdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/mkdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "path.h" #include "posix.h" @@ -150,10 +150,11 @@ git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY); } -#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __LINE__) +#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __func__, __LINE__) static void check_mode_at_line( - mode_t expected, mode_t actual, const char *file, int line) + mode_t expected, mode_t actual, + const char *file, const char *func, int line) { /* FAT filesystems don't support exec bit, nor group/world bits */ if (!cl_is_chmod_supported()) { @@ -162,7 +163,7 @@ } clar__assert_equal( - file, line, "expected_mode != actual_mode", 1, + file, func, line, "expected_mode != actual_mode", 1, "%07o", (int)expected, (int)(actual & 0777)); } diff -Nru libgit2-0.28.5+dfsg.1/tests/core/oidmap.c libgit2-1.1.0+dfsg.1/tests/core/oidmap.c --- libgit2-0.28.5+dfsg.1/tests/core/oidmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/oidmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,108 +1,127 @@ #include "clar_libgit2.h" #include "oidmap.h" -typedef struct { +static struct { git_oid oid; size_t extra; -} oidmap_item; +} test_oids[0x0FFF]; -#define NITEMS 0x0fff +static git_oidmap *g_map; -void test_core_oidmap__basic(void) +void test_core_oidmap__initialize(void) { - git_oidmap *map; - oidmap_item items[NITEMS]; uint32_t i, j; + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) { + uint32_t segment = i / 8; + int modi = i - (segment * 8); + + test_oids[i].extra = i; - for (i = 0; i < NITEMS; ++i) { - items[i].extra = i; for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { - items[i].oid.id[j * 4 ] = (unsigned char)i; - items[i].oid.id[j * 4 + 1] = (unsigned char)(i >> 8); - items[i].oid.id[j * 4 + 2] = (unsigned char)(i >> 16); - items[i].oid.id[j * 4 + 3] = (unsigned char)(i >> 24); + test_oids[i].oid.id[j * 4 ] = (unsigned char)modi; + test_oids[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8); + test_oids[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16); + test_oids[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24); } - } - - map = git_oidmap_alloc(); - cl_assert(map != NULL); - - for (i = 0; i < NITEMS; ++i) { - size_t pos; - int ret; - - pos = git_oidmap_lookup_index(map, &items[i].oid); - cl_assert(!git_oidmap_valid_index(map, pos)); - - pos = git_oidmap_put(map, &items[i].oid, &ret); - cl_assert(ret != 0); - git_oidmap_set_value_at(map, pos, &items[i]); + test_oids[i].oid.id[ 8] = (unsigned char)i; + test_oids[i].oid.id[ 9] = (unsigned char)(i >> 8); + test_oids[i].oid.id[10] = (unsigned char)(i >> 16); + test_oids[i].oid.id[11] = (unsigned char)(i >> 24); } + cl_git_pass(git_oidmap_new(&g_map)); +} - for (i = 0; i < NITEMS; ++i) { - size_t pos; +void test_core_oidmap__cleanup(void) +{ + git_oidmap_free(g_map); +} - pos = git_oidmap_lookup_index(map, &items[i].oid); - cl_assert(git_oidmap_valid_index(map, pos)); +void test_core_oidmap__basic(void) +{ + size_t i; - cl_assert_equal_p(git_oidmap_value_at(map, pos), &items[i]); + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) { + cl_assert(!git_oidmap_exists(g_map, &test_oids[i].oid)); + cl_git_pass(git_oidmap_set(g_map, &test_oids[i].oid, &test_oids[i])); } - git_oidmap_free(map); + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) { + cl_assert(git_oidmap_exists(g_map, &test_oids[i].oid)); + cl_assert_equal_p(git_oidmap_get(g_map, &test_oids[i].oid), &test_oids[i]); + } } void test_core_oidmap__hash_collision(void) { - git_oidmap *map; - oidmap_item items[NITEMS]; - uint32_t i, j; + size_t i; - for (i = 0; i < NITEMS; ++i) { - uint32_t segment = i / 8; - int modi = i - (segment * 8); - - items[i].extra = i; - - for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { - items[i].oid.id[j * 4 ] = (unsigned char)modi; - items[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8); - items[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16); - items[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24); - } + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) { + cl_assert(!git_oidmap_exists(g_map, &test_oids[i].oid)); + cl_git_pass(git_oidmap_set(g_map, &test_oids[i].oid, &test_oids[i])); + } - items[i].oid.id[ 8] = (unsigned char)i; - items[i].oid.id[ 9] = (unsigned char)(i >> 8); - items[i].oid.id[10] = (unsigned char)(i >> 16); - items[i].oid.id[11] = (unsigned char)(i >> 24); + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) { + cl_assert(git_oidmap_exists(g_map, &test_oids[i].oid)); + cl_assert_equal_p(git_oidmap_get(g_map, &test_oids[i].oid), &test_oids[i]); } +} - map = git_oidmap_alloc(); - cl_assert(map != NULL); +void test_core_oidmap__get_succeeds_with_existing_keys(void) +{ + size_t i; - for (i = 0; i < NITEMS; ++i) { - size_t pos; - int ret; + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) + cl_git_pass(git_oidmap_set(g_map, &test_oids[i].oid, &test_oids[i])); - pos = git_oidmap_lookup_index(map, &items[i].oid); - cl_assert(!git_oidmap_valid_index(map, pos)); + for (i = 0; i < ARRAY_SIZE(test_oids); ++i) + cl_assert_equal_p(git_oidmap_get(g_map, &test_oids[i].oid), &test_oids[i]); +} - pos = git_oidmap_put(map, &items[i].oid, &ret); - cl_assert(ret != 0); +void test_core_oidmap__get_fails_with_nonexisting_key(void) +{ + size_t i; - git_oidmap_set_value_at(map, pos, &items[i]); - } + /* Do _not_ add last OID to verify that we cannot look it up */ + for (i = 0; i < ARRAY_SIZE(test_oids) - 1; ++i) + cl_git_pass(git_oidmap_set(g_map, &test_oids[i].oid, &test_oids[i])); + cl_assert_equal_p(git_oidmap_get(g_map, &test_oids[ARRAY_SIZE(test_oids) - 1].oid), NULL); +} - for (i = 0; i < NITEMS; ++i) { - size_t pos; +void test_core_oidmap__setting_oid_persists(void) +{ + git_oid oids[] = { + {{ 0x01 }}, + {{ 0x02 }}, + {{ 0x03 }} + }; + + cl_git_pass(git_oidmap_set(g_map, &oids[0], "one")); + cl_git_pass(git_oidmap_set(g_map, &oids[1], "two")); + cl_git_pass(git_oidmap_set(g_map, &oids[2], "three")); + + cl_assert_equal_s(git_oidmap_get(g_map, &oids[0]), "one"); + cl_assert_equal_s(git_oidmap_get(g_map, &oids[1]), "two"); + cl_assert_equal_s(git_oidmap_get(g_map, &oids[2]), "three"); +} - pos = git_oidmap_lookup_index(map, &items[i].oid); - cl_assert(git_oidmap_valid_index(map, pos)); +void test_core_oidmap__setting_existing_key_updates(void) +{ + git_oid oids[] = { + {{ 0x01 }}, + {{ 0x02 }}, + {{ 0x03 }} + }; + + cl_git_pass(git_oidmap_set(g_map, &oids[0], "one")); + cl_git_pass(git_oidmap_set(g_map, &oids[1], "two")); + cl_git_pass(git_oidmap_set(g_map, &oids[2], "three")); + cl_assert_equal_i(git_oidmap_size(g_map), 3); - cl_assert_equal_p(git_oidmap_value_at(map, pos), &items[i]); - } + cl_git_pass(git_oidmap_set(g_map, &oids[1], "other")); + cl_assert_equal_i(git_oidmap_size(g_map), 3); - git_oidmap_free(map); + cl_assert_equal_s(git_oidmap_get(g_map, &oids[1]), "other"); } diff -Nru libgit2-0.28.5+dfsg.1/tests/core/path.c libgit2-1.1.0+dfsg.1/tests/core/path.c --- libgit2-0.28.5+dfsg.1/tests/core/path.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/path.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" static void check_dirname(const char *A, const char *B) diff -Nru libgit2-0.28.5+dfsg.1/tests/core/posix.c libgit2-1.1.0+dfsg.1/tests/core/posix.c --- libgit2-0.28.5+dfsg.1/tests/core/posix.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/posix.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,11 +9,9 @@ # endif #endif -#include - #include "clar_libgit2.h" +#include "futils.h" #include "posix.h" -#include "userdiff.h" void test_core_posix__initialize(void) { @@ -114,7 +112,7 @@ cl_git_mkfile("foo", "Dummy file."); cl_must_pass(p_utimes("foo", times)); - p_stat("foo", &st); + cl_must_pass(p_stat("foo", &st)); cl_assert_equal_i(1234567890, st.st_atime); cl_assert_equal_i(1234567890, st.st_mtime); @@ -127,9 +125,9 @@ cl_must_pass(fd = p_open("foo", O_RDWR)); cl_must_pass(p_futimes(fd, times)); - p_close(fd); + cl_must_pass(p_close(fd)); - p_stat("foo", &st); + cl_must_pass(p_stat("foo", &st)); cl_assert_equal_i(1414141414, st.st_atime); cl_assert_equal_i(1414141414, st.st_mtime); @@ -140,53 +138,101 @@ cl_must_pass(p_utimes("foo", NULL)); curtime = time(NULL); - p_stat("foo", &st); + cl_must_pass(p_stat("foo", &st)); cl_assert((st.st_atime - curtime) < 5); cl_assert((st.st_mtime - curtime) < 5); - p_unlink("foo"); + cl_must_pass(p_unlink("foo")); } -void test_core_posix__p_regcomp_ignores_global_locale_ctype(void) +void test_core_posix__unlink_removes_symlink(void) { - regex_t preg; - int error = 0; + if (!git_path_supports_symlinks(clar_sandbox_path())) + clar__skip(); - const char* oldlocale = setlocale(LC_CTYPE, NULL); + cl_git_mkfile("file", "Dummy file."); + cl_git_pass(git_futils_mkdir("dir", 0777, 0)); - if (!setlocale(LC_CTYPE, "UTF-8") && - !setlocale(LC_CTYPE, "c.utf8") && - !setlocale(LC_CTYPE, "en_US.UTF-8")) - cl_skip(); + cl_must_pass(p_symlink("file", "file-symlink")); + cl_must_pass(p_symlink("dir", "dir-symlink")); - if (MB_CUR_MAX == 1) { - setlocale(LC_CTYPE, oldlocale); - cl_fail("Expected locale to be switched to multibyte"); - } + cl_must_pass(p_unlink("file-symlink")); + cl_must_pass(p_unlink("dir-symlink")); + + cl_assert(git_path_exists("file")); + cl_assert(git_path_exists("dir")); + + cl_must_pass(p_unlink("file")); + cl_must_pass(p_rmdir("dir")); +} + +void test_core_posix__symlink_resolves_to_correct_type(void) +{ + git_buf contents = GIT_BUF_INIT; + + if (!git_path_supports_symlinks(clar_sandbox_path())) + clar__skip(); + + cl_must_pass(git_futils_mkdir("dir", 0777, 0)); + cl_must_pass(git_futils_mkdir("file", 0777, 0)); + cl_git_mkfile("dir/file", "symlink target"); + + cl_git_pass(p_symlink("file", "dir/link")); - p_regcomp(&preg, "[\xc0-\xff][\x80-\xbf]", REG_EXTENDED); - regfree(&preg); + cl_git_pass(git_futils_readbuffer(&contents, "dir/file")); + cl_assert_equal_s(contents.ptr, "symlink target"); - setlocale(LC_CTYPE, oldlocale); + cl_must_pass(p_unlink("dir/link")); + cl_must_pass(p_unlink("dir/file")); + cl_must_pass(p_rmdir("dir")); + cl_must_pass(p_rmdir("file")); - cl_must_pass(error); + git_buf_dispose(&contents); } -void test_core_posix__p_regcomp_compile_userdiff_regexps(void) +void test_core_posix__relative_symlink(void) { - size_t idx; + git_buf contents = GIT_BUF_INIT; - for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) { - git_diff_driver_definition ddef = builtin_defs[idx]; - int error = 0; - regex_t preg; + if (!git_path_supports_symlinks(clar_sandbox_path())) + clar__skip(); - error = p_regcomp(&preg, ddef.fns, REG_EXTENDED | ddef.flags); - regfree(&preg); - cl_must_pass(error); + cl_must_pass(git_futils_mkdir("dir", 0777, 0)); + cl_git_mkfile("file", "contents"); + cl_git_pass(p_symlink("../file", "dir/link")); + cl_git_pass(git_futils_readbuffer(&contents, "dir/link")); + cl_assert_equal_s(contents.ptr, "contents"); - error = p_regcomp(&preg, ddef.words, REG_EXTENDED); - regfree(&preg); - cl_must_pass(error); - } + cl_must_pass(p_unlink("file")); + cl_must_pass(p_unlink("dir/link")); + cl_must_pass(p_rmdir("dir")); + + git_buf_dispose(&contents); +} + +void test_core_posix__symlink_to_file_across_dirs(void) +{ + git_buf contents = GIT_BUF_INIT; + + if (!git_path_supports_symlinks(clar_sandbox_path())) + clar__skip(); + + /* + * Create a relative symlink that points into another + * directory. This used to not work on Win32, where we + * forgot to convert directory separators to + * Windows-style ones. + */ + cl_must_pass(git_futils_mkdir("dir", 0777, 0)); + cl_git_mkfile("dir/target", "symlink target"); + cl_git_pass(p_symlink("dir/target", "link")); + + cl_git_pass(git_futils_readbuffer(&contents, "dir/target")); + cl_assert_equal_s(contents.ptr, "symlink target"); + + cl_must_pass(p_unlink("dir/target")); + cl_must_pass(p_unlink("link")); + cl_must_pass(p_rmdir("dir")); + + git_buf_dispose(&contents); } diff -Nru libgit2-0.28.5+dfsg.1/tests/core/qsort.c libgit2-1.1.0+dfsg.1/tests/core/qsort.c --- libgit2-0.28.5+dfsg.1/tests/core/qsort.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/qsort.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,90 @@ +#include "clar_libgit2.h" + +#define assert_sorted(a, cmp) \ + _assert_sorted(a, ARRAY_SIZE(a), sizeof(*a), cmp) + +struct big_entries { + char c[311]; +}; + +static void _assert_sorted(void *els, size_t n, size_t elsize, git__sort_r_cmp cmp) +{ + int8_t *p = els; + + git__qsort_r(p, n, elsize, cmp, NULL); + while (n-- > 1) { + cl_assert(cmp(p, p + elsize, NULL) <= 0); + p += elsize; + } +} + +static int cmp_big(const void *_a, const void *_b, void *payload) +{ + const struct big_entries *a = (const struct big_entries *)_a, *b = (const struct big_entries *)_b; + GIT_UNUSED(payload); + return (a->c[0] < b->c[0]) ? -1 : (a->c[0] > b->c[0]) ? +1 : 0; +} + +static int cmp_int(const void *_a, const void *_b, void *payload) +{ + int a = *(const int *)_a, b = *(const int *)_b; + GIT_UNUSED(payload); + return (a < b) ? -1 : (a > b) ? +1 : 0; +} + +static int cmp_str(const void *_a, const void *_b, void *payload) +{ + GIT_UNUSED(payload); + return strcmp((const char *) _a, (const char *) _b); +} + +void test_core_qsort__array_with_single_entry(void) +{ + int a[] = { 10 }; + assert_sorted(a, cmp_int); +} + +void test_core_qsort__array_with_equal_entries(void) +{ + int a[] = { 4, 4, 4, 4 }; + assert_sorted(a, cmp_int); +} + +void test_core_qsort__sorted_array(void) +{ + int a[] = { 1, 10 }; + assert_sorted(a, cmp_int); +} + +void test_core_qsort__unsorted_array(void) +{ + int a[] = { 123, 9, 412938, 10, 234, 89 }; + assert_sorted(a, cmp_int); +} + +void test_core_qsort__sorting_strings(void) +{ + char *a[] = { "foo", "bar", "baz" }; + assert_sorted(a, cmp_str); +} + +void test_core_qsort__sorting_big_entries(void) +{ + struct big_entries a[5]; + + memset(&a, 0, sizeof(a)); + + memset(a[0].c, 'w', sizeof(a[0].c) - 1); + memset(a[1].c, 'c', sizeof(a[1].c) - 1); + memset(a[2].c, 'w', sizeof(a[2].c) - 1); + memset(a[3].c, 'h', sizeof(a[3].c) - 1); + memset(a[4].c, 'a', sizeof(a[4].c) - 1); + + assert_sorted(a, cmp_big); + + cl_assert_equal_i(strspn(a[0].c, "a"), sizeof(a[0].c) - 1); + cl_assert_equal_i(strspn(a[1].c, "c"), sizeof(a[1].c) - 1); + cl_assert_equal_i(strspn(a[2].c, "h"), sizeof(a[2].c) - 1); + cl_assert_equal_i(strspn(a[3].c, "w"), sizeof(a[3].c) - 1); + cl_assert_equal_i(strspn(a[4].c, "w"), sizeof(a[4].c) - 1); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/core/regexp.c libgit2-1.1.0+dfsg.1/tests/core/regexp.c --- libgit2-0.28.5+dfsg.1/tests/core/regexp.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/regexp.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,213 @@ +#include "clar_libgit2.h" + +#include + +#include "regexp.h" +#include "userdiff.h" + +#if LC_ALL > 0 +static const char *old_locales[LC_ALL]; +#endif + +static git_regexp regex; + +void test_core_regexp__initialize(void) +{ +#if LC_ALL > 0 + memset(&old_locales, 0, sizeof(old_locales)); +#endif +} + +void test_core_regexp__cleanup(void) +{ + git_regexp_dispose(®ex); +} + +static void try_set_locale(int category) +{ +#if LC_ALL > 0 + old_locales[category] = setlocale(category, NULL); +#endif + + if (!setlocale(category, "UTF-8") && + !setlocale(category, "c.utf8") && + !setlocale(category, "en_US.UTF-8")) + cl_skip(); + + if (MB_CUR_MAX == 1) + cl_fail("Expected locale to be switched to multibyte"); +} + + +void test_core_regexp__compile_ignores_global_locale_ctype(void) +{ + try_set_locale(LC_CTYPE); + cl_git_pass(git_regexp_compile(®ex, "[\xc0-\xff][\x80-\xbf]", 0)); +} + +void test_core_regexp__compile_ignores_global_locale_collate(void) +{ +#ifdef GIT_WIN32 + cl_skip(); +#endif + + try_set_locale(LC_COLLATE); + cl_git_pass(git_regexp_compile(®ex, "[\xc0-\xff][\x80-\xbf]", 0)); +} + +void test_core_regexp__regex_matches_digits_with_locale(void) +{ + char c, str[2]; + +#ifdef GIT_WIN32 + cl_skip(); +#endif + + try_set_locale(LC_COLLATE); + try_set_locale(LC_CTYPE); + + cl_git_pass(git_regexp_compile(®ex, "[[:digit:]]", 0)); + + str[1] = '\0'; + for (c = '0'; c <= '9'; c++) { + str[0] = c; + cl_git_pass(git_regexp_match(®ex, str)); + } +} + +void test_core_regexp__regex_matches_alphabet_with_locale(void) +{ + char c, str[2]; + +#ifdef GIT_WIN32 + cl_skip(); +#endif + + try_set_locale(LC_COLLATE); + try_set_locale(LC_CTYPE); + + cl_git_pass(git_regexp_compile(®ex, "[[:alpha:]]", 0)); + + str[1] = '\0'; + for (c = 'a'; c <= 'z'; c++) { + str[0] = c; + cl_git_pass(git_regexp_match(®ex, str)); + } + for (c = 'A'; c <= 'Z'; c++) { + str[0] = c; + cl_git_pass(git_regexp_match(®ex, str)); + } +} + +void test_core_regexp__compile_userdiff_regexps(void) +{ + size_t idx; + + for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) { + git_diff_driver_definition ddef = builtin_defs[idx]; + + cl_git_pass(git_regexp_compile(®ex, ddef.fns, ddef.flags)); + git_regexp_dispose(®ex); + + cl_git_pass(git_regexp_compile(®ex, ddef.words, 0)); + git_regexp_dispose(®ex); + } +} + +void test_core_regexp__simple_search_matches(void) +{ + cl_git_pass(git_regexp_compile(®ex, "a", 0)); + cl_git_pass(git_regexp_search(®ex, "a", 0, NULL)); +} + +void test_core_regexp__case_insensitive_search_matches(void) +{ + cl_git_pass(git_regexp_compile(®ex, "a", GIT_REGEXP_ICASE)); + cl_git_pass(git_regexp_search(®ex, "A", 0, NULL)); +} + +void test_core_regexp__nonmatching_search_returns_error(void) +{ + cl_git_pass(git_regexp_compile(®ex, "a", 0)); + cl_git_fail(git_regexp_search(®ex, "b", 0, NULL)); +} + +void test_core_regexp__search_finds_complete_match(void) +{ + git_regmatch matches[1]; + + cl_git_pass(git_regexp_compile(®ex, "abc", 0)); + cl_git_pass(git_regexp_search(®ex, "abc", 1, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 3); +} + +void test_core_regexp__search_finds_correct_offsets(void) +{ + git_regmatch matches[3]; + + cl_git_pass(git_regexp_compile(®ex, "(a*)(b*)", 0)); + cl_git_pass(git_regexp_search(®ex, "ab", 3, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 2); + cl_assert_equal_i(matches[1].start, 0); + cl_assert_equal_i(matches[1].end, 1); + cl_assert_equal_i(matches[2].start, 1); + cl_assert_equal_i(matches[2].end, 2); +} + +void test_core_regexp__search_finds_empty_group(void) +{ + git_regmatch matches[3]; + + cl_git_pass(git_regexp_compile(®ex, "(a*)(b*)c", 0)); + cl_git_pass(git_regexp_search(®ex, "ac", 3, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 2); + cl_assert_equal_i(matches[1].start, 0); + cl_assert_equal_i(matches[1].end, 1); + cl_assert_equal_i(matches[2].start, 1); + cl_assert_equal_i(matches[2].end, 1); +} + +void test_core_regexp__search_fills_matches_with_first_matching_groups(void) +{ + git_regmatch matches[2]; + + cl_git_pass(git_regexp_compile(®ex, "(a)(b)(c)", 0)); + cl_git_pass(git_regexp_search(®ex, "abc", 2, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 3); + cl_assert_equal_i(matches[1].start, 0); + cl_assert_equal_i(matches[1].end, 1); +} + +void test_core_regexp__search_skips_nonmatching_group(void) +{ + git_regmatch matches[4]; + + cl_git_pass(git_regexp_compile(®ex, "(a)(b)?(c)", 0)); + cl_git_pass(git_regexp_search(®ex, "ac", 4, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 2); + cl_assert_equal_i(matches[1].start, 0); + cl_assert_equal_i(matches[1].end, 1); + cl_assert_equal_i(matches[2].start, -1); + cl_assert_equal_i(matches[2].end, -1); + cl_assert_equal_i(matches[3].start, 1); + cl_assert_equal_i(matches[3].end, 2); +} + +void test_core_regexp__search_initializes_trailing_nonmatching_groups(void) +{ + git_regmatch matches[3]; + + cl_git_pass(git_regexp_compile(®ex, "(a)bc", 0)); + cl_git_pass(git_regexp_search(®ex, "abc", 3, matches)); + cl_assert_equal_i(matches[0].start, 0); + cl_assert_equal_i(matches[0].end, 3); + cl_assert_equal_i(matches[1].start, 0); + cl_assert_equal_i(matches[1].end, 1); + cl_assert_equal_i(matches[2].start, -1); + cl_assert_equal_i(matches[2].end, -1); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/core/rmdir.c libgit2-1.1.0+dfsg.1/tests/core/rmdir.c --- libgit2-0.28.5+dfsg.1/tests/core/rmdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/rmdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test"; diff -Nru libgit2-0.28.5+dfsg.1/tests/core/stat.c libgit2-1.1.0+dfsg.1/tests/core/stat.c --- libgit2-0.28.5+dfsg.1/tests/core/stat.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/stat.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "path.h" #include "posix.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/core/strmap.c libgit2-1.1.0+dfsg.1/tests/core/strmap.c --- libgit2-0.28.5+dfsg.1/tests/core/strmap.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/strmap.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,11 +1,11 @@ #include "clar_libgit2.h" #include "strmap.h" -git_strmap *g_table; +static git_strmap *g_table; void test_core_strmap__initialize(void) { - cl_git_pass(git_strmap_alloc(&g_table)); + cl_git_pass(git_strmap_new(&g_table)); cl_assert(g_table != NULL); } @@ -16,12 +16,12 @@ void test_core_strmap__0(void) { - cl_assert(git_strmap_num_entries(g_table) == 0); + cl_assert(git_strmap_size(g_table) == 0); } -static void insert_strings(git_strmap *table, int count) +static void insert_strings(git_strmap *table, size_t count) { - int i, j, over, err; + size_t i, j, over; char *str; for (i = 0; i < count; ++i) { @@ -34,17 +34,16 @@ for (j = 0, over = i / 26; over > 0; j++, over = over / 26) str[j] = 'A' + (over % 26); - git_strmap_insert(table, str, str, &err); - cl_assert(err >= 0); + cl_git_pass(git_strmap_set(table, str, str)); } - cl_assert((int)git_strmap_num_entries(table) == count); + cl_assert_equal_i(git_strmap_size(table), count); } -void test_core_strmap__1(void) +void test_core_strmap__inserted_strings_can_be_retrieved(void) { - int i; char *str; + int i; insert_strings(g_table, 20); @@ -58,41 +57,134 @@ cl_assert(i == 20); } -void test_core_strmap__2(void) +void test_core_strmap__deleted_entry_cannot_be_retrieved(void) { - size_t pos; - int i; char *str; + int i; insert_strings(g_table, 20); - cl_assert(git_strmap_exists(g_table, "aaaaaaaaa")); - cl_assert(git_strmap_exists(g_table, "ggggggggg")); - cl_assert(!git_strmap_exists(g_table, "aaaaaaaab")); - cl_assert(!git_strmap_exists(g_table, "abcdefghi")); - cl_assert(git_strmap_exists(g_table, "bbbbbbbbb")); - pos = git_strmap_lookup_index(g_table, "bbbbbbbbb"); - cl_assert(git_strmap_valid_index(g_table, pos)); - cl_assert_equal_s(git_strmap_value_at(g_table, pos), "bbbbbbbbb"); - free(git_strmap_value_at(g_table, pos)); - git_strmap_delete_at(g_table, pos); + str = git_strmap_get(g_table, "bbbbbbbbb"); + cl_assert_equal_s(str, "bbbbbbbbb"); + cl_git_pass(git_strmap_delete(g_table, "bbbbbbbbb")); + free(str); cl_assert(!git_strmap_exists(g_table, "bbbbbbbbb")); i = 0; git_strmap_foreach_value(g_table, str, { i++; free(str); }); - cl_assert(i == 19); + cl_assert_equal_i(i, 19); } -void test_core_strmap__3(void) +void test_core_strmap__inserting_many_keys_succeeds(void) { - int i; char *str; + int i; insert_strings(g_table, 10000); i = 0; git_strmap_foreach_value(g_table, str, { i++; free(str); }); - cl_assert(i == 10000); + cl_assert_equal_i(i, 10000); +} + +void test_core_strmap__get_succeeds_with_existing_entries(void) +{ + const char *keys[] = { "foo", "bar", "gobble" }; + char *values[] = { "oof", "rab", "elbbog" }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(keys); i++) + cl_git_pass(git_strmap_set(g_table, keys[i], values[i])); + + cl_assert_equal_s(git_strmap_get(g_table, "foo"), "oof"); + cl_assert_equal_s(git_strmap_get(g_table, "bar"), "rab"); + cl_assert_equal_s(git_strmap_get(g_table, "gobble"), "elbbog"); +} + +void test_core_strmap__get_returns_null_on_nonexisting_key(void) +{ + const char *keys[] = { "foo", "bar", "gobble" }; + char *values[] = { "oof", "rab", "elbbog" }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(keys); i++) + cl_git_pass(git_strmap_set(g_table, keys[i], values[i])); + + cl_assert_equal_p(git_strmap_get(g_table, "other"), NULL); +} + +void test_core_strmap__set_persists_key(void) +{ + cl_git_pass(git_strmap_set(g_table, "foo", "oof")); + cl_assert_equal_s(git_strmap_get(g_table, "foo"), "oof"); +} + +void test_core_strmap__set_persists_multpile_keys(void) +{ + cl_git_pass(git_strmap_set(g_table, "foo", "oof")); + cl_git_pass(git_strmap_set(g_table, "bar", "rab")); + cl_assert_equal_s(git_strmap_get(g_table, "foo"), "oof"); + cl_assert_equal_s(git_strmap_get(g_table, "bar"), "rab"); +} + +void test_core_strmap__set_updates_existing_key(void) +{ + cl_git_pass(git_strmap_set(g_table, "foo", "oof")); + cl_git_pass(git_strmap_set(g_table, "bar", "rab")); + cl_git_pass(git_strmap_set(g_table, "gobble", "elbbog")); + cl_assert_equal_i(git_strmap_size(g_table), 3); + + cl_git_pass(git_strmap_set(g_table, "foo", "other")); + cl_assert_equal_i(git_strmap_size(g_table), 3); + + cl_assert_equal_s(git_strmap_get(g_table, "foo"), "other"); +} + +void test_core_strmap__iteration(void) +{ + struct { + char *key; + char *value; + int seen; + } entries[] = { + { "foo", "oof" }, + { "bar", "rab" }, + { "gobble", "elbbog" }, + }; + const char *key, *value; + size_t i, n; + + for (i = 0; i < ARRAY_SIZE(entries); i++) + cl_git_pass(git_strmap_set(g_table, entries[i].key, entries[i].value)); + + i = 0, n = 0; + while (git_strmap_iterate((void **) &value, g_table, &i, &key) == 0) { + size_t j; + + for (j = 0; j < ARRAY_SIZE(entries); j++) { + if (strcmp(entries[j].key, key)) + continue; + + cl_assert_equal_i(entries[j].seen, 0); + cl_assert_equal_s(entries[j].value, value); + entries[j].seen++; + break; + } + + n++; + } + + for (i = 0; i < ARRAY_SIZE(entries); i++) + cl_assert_equal_i(entries[i].seen, 1); + + cl_assert_equal_i(n, ARRAY_SIZE(entries)); +} + +void test_core_strmap__iterating_empty_map_stops_immediately(void) +{ + size_t i = 0; + + cl_git_fail_with(git_strmap_iterate(NULL, g_table, &i, NULL), GIT_ITEROVER); } diff -Nru libgit2-0.28.5+dfsg.1/tests/core/structinit.c libgit2-1.1.0+dfsg.1/tests/core/structinit.c --- libgit2-0.28.5+dfsg.1/tests/core/structinit.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/structinit.c 2020-10-12 18:53:06.000000000 +0000 @@ -48,7 +48,7 @@ p_snprintf(desc, 1024, "Difference in %s at byte %" PRIuZ ": macro=%u / func=%u", name, i, ((char *)one)[i], ((char *)two)[i]); - clar__fail(__FILE__, __LINE__, + clar__fail(__FILE__, __func__, __LINE__, "Difference between macro and function options initializer", desc, 0); return; @@ -72,30 +72,35 @@ clar__skip(); #endif + /* apply */ + CHECK_MACRO_FUNC_INIT_EQUAL( \ + git_apply_options, GIT_APPLY_OPTIONS_VERSION, \ + GIT_APPLY_OPTIONS_INIT, git_apply_options_init); + /* blame */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_blame_options, GIT_BLAME_OPTIONS_VERSION, \ - GIT_BLAME_OPTIONS_INIT, git_blame_init_options); + GIT_BLAME_OPTIONS_INIT, git_blame_options_init); /* checkout */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_checkout_options, GIT_CHECKOUT_OPTIONS_VERSION, \ - GIT_CHECKOUT_OPTIONS_INIT, git_checkout_init_options); + GIT_CHECKOUT_OPTIONS_INIT, git_checkout_options_init); /* clone */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_clone_options, GIT_CLONE_OPTIONS_VERSION, \ - GIT_CLONE_OPTIONS_INIT, git_clone_init_options); + GIT_CLONE_OPTIONS_INIT, git_clone_options_init); /* diff */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_diff_options, GIT_DIFF_OPTIONS_VERSION, \ - GIT_DIFF_OPTIONS_INIT, git_diff_init_options); + GIT_DIFF_OPTIONS_INIT, git_diff_options_init); /* diff_find */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_diff_find_options, GIT_DIFF_FIND_OPTIONS_VERSION, \ - GIT_DIFF_FIND_OPTIONS_INIT, git_diff_find_init_options); + GIT_DIFF_FIND_OPTIONS_INIT, git_diff_find_options_init); /* filter */ CHECK_MACRO_FUNC_INIT_EQUAL( \ @@ -105,22 +110,22 @@ /* merge_file_input */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_merge_file_input, GIT_MERGE_FILE_INPUT_VERSION, \ - GIT_MERGE_FILE_INPUT_INIT, git_merge_file_init_input); + GIT_MERGE_FILE_INPUT_INIT, git_merge_file_input_init); /* merge_file */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_merge_file_options, GIT_MERGE_FILE_OPTIONS_VERSION, \ - GIT_MERGE_FILE_OPTIONS_INIT, git_merge_file_init_options); + GIT_MERGE_FILE_OPTIONS_INIT, git_merge_file_options_init); /* merge_tree */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_merge_options, GIT_MERGE_OPTIONS_VERSION, \ - GIT_MERGE_OPTIONS_INIT, git_merge_init_options); + GIT_MERGE_OPTIONS_INIT, git_merge_options_init); /* push */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_push_options, GIT_PUSH_OPTIONS_VERSION, \ - GIT_PUSH_OPTIONS_INIT, git_push_init_options); + GIT_PUSH_OPTIONS_INIT, git_push_options_init); /* remote */ CHECK_MACRO_FUNC_INIT_EQUAL( \ @@ -130,22 +135,22 @@ /* repository_init */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_repository_init_options, GIT_REPOSITORY_INIT_OPTIONS_VERSION, \ - GIT_REPOSITORY_INIT_OPTIONS_INIT, git_repository_init_init_options); + GIT_REPOSITORY_INIT_OPTIONS_INIT, git_repository_init_options_init); /* revert */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_revert_options, GIT_REVERT_OPTIONS_VERSION, \ - GIT_REVERT_OPTIONS_INIT, git_revert_init_options); + GIT_REVERT_OPTIONS_INIT, git_revert_options_init); /* stash apply */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_stash_apply_options, GIT_STASH_APPLY_OPTIONS_VERSION, \ - GIT_STASH_APPLY_OPTIONS_INIT, git_stash_apply_init_options); + GIT_STASH_APPLY_OPTIONS_INIT, git_stash_apply_options_init); /* status */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_status_options, GIT_STATUS_OPTIONS_VERSION, \ - GIT_STATUS_OPTIONS_INIT, git_status_init_options); + GIT_STATUS_OPTIONS_INIT, git_status_options_init); /* transport */ CHECK_MACRO_FUNC_INIT_EQUAL( \ @@ -170,14 +175,14 @@ /* submodule update */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_submodule_update_options, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \ - GIT_SUBMODULE_UPDATE_OPTIONS_INIT, git_submodule_update_init_options); + GIT_SUBMODULE_UPDATE_OPTIONS_INIT, git_submodule_update_options_init); /* submodule update */ CHECK_MACRO_FUNC_INIT_EQUAL( \ git_proxy_options, GIT_PROXY_OPTIONS_VERSION, \ - GIT_PROXY_OPTIONS_INIT, git_proxy_init_options); + GIT_PROXY_OPTIONS_INIT, git_proxy_options_init); CHECK_MACRO_FUNC_INIT_EQUAL( \ git_diff_patchid_options, GIT_DIFF_PATCHID_OPTIONS_VERSION, \ - GIT_DIFF_PATCHID_OPTIONS_INIT, git_diff_patchid_init_options); + GIT_DIFF_PATCHID_OPTIONS_INIT, git_diff_patchid_options_init); } diff -Nru libgit2-0.28.5+dfsg.1/tests/core/wildmatch.c libgit2-1.1.0+dfsg.1/tests/core/wildmatch.c --- libgit2-0.28.5+dfsg.1/tests/core/wildmatch.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/wildmatch.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,248 @@ +#include "clar_libgit2.h" + +#include "wildmatch.h" + +#define assert_matches(string, pattern, wildmatch, iwildmatch, pathmatch, ipathmatch) \ + assert_matches_(string, pattern, wildmatch, iwildmatch, pathmatch, ipathmatch, __FILE__, __func__, __LINE__) + +static void assert_matches_(const char *string, const char *pattern, + char expected_wildmatch, char expected_iwildmatch, + char expected_pathmatch, char expected_ipathmatch, + const char *file, const char *func, size_t line) +{ + if (wildmatch(pattern, string, WM_PATHNAME) == expected_wildmatch) + clar__fail(file, func, line, "Test failed (wildmatch).", string, 1); + if (wildmatch(pattern, string, WM_PATHNAME|WM_CASEFOLD) == expected_iwildmatch) + clar__fail(file, func, line, "Test failed (iwildmatch).", string, 1); + if (wildmatch(pattern, string, 0) == expected_pathmatch) + clar__fail(file, func, line, "Test failed (pathmatch).", string, 1); + if (wildmatch(pattern, string, WM_CASEFOLD) == expected_ipathmatch) + clar__fail(file, func, line, "Test failed (ipathmatch).", string, 1); +} + +/* + * Below testcases are imported from git.git, t3070-wildmatch,sh at tag v2.22.0. + * Note that we've only imported the direct wildcard tests, but not the matching + * tests for git-ls-files. + */ + +void test_core_wildmatch__basic_wildmatch(void) +{ + assert_matches("foo", "foo", 1, 1, 1, 1); + assert_matches("foo", "bar", 0, 0, 0, 0); + assert_matches("", "", 1, 1, 1, 1); + assert_matches("foo", "???", 1, 1, 1, 1); + assert_matches("foo", "??", 0, 0, 0, 0); + assert_matches("foo", "*", 1, 1, 1, 1); + assert_matches("foo", "f*", 1, 1, 1, 1); + assert_matches("foo", "*f", 0, 0, 0, 0); + assert_matches("foo", "*foo*", 1, 1, 1, 1); + assert_matches("foobar", "*ob*a*r*", 1, 1, 1, 1); + assert_matches("aaaaaaabababab", "*ab", 1, 1, 1, 1); + assert_matches("foo*", "foo\\*", 1, 1, 1, 1); + assert_matches("foobar", "foo\\*bar", 0, 0, 0, 0); + assert_matches("f\\oo", "f\\\\oo", 1, 1, 1, 1); + assert_matches("ball", "*[al]?", 1, 1, 1, 1); + assert_matches("ten", "[ten]", 0, 0, 0, 0); + assert_matches("ten", "**[!te]", 1, 1, 1, 1); + assert_matches("ten", "**[!ten]", 0, 0, 0, 0); + assert_matches("ten", "t[a-g]n", 1, 1, 1, 1); + assert_matches("ten", "t[!a-g]n", 0, 0, 0, 0); + assert_matches("ton", "t[!a-g]n", 1, 1, 1, 1); + assert_matches("ton", "t[^a-g]n", 1, 1, 1, 1); + assert_matches("a]b", "a[]]b", 1, 1, 1, 1); + assert_matches("a-b", "a[]-]b", 1, 1, 1, 1); + assert_matches("a]b", "a[]-]b", 1, 1, 1, 1); + assert_matches("aab", "a[]-]b", 0, 0, 0, 0); + assert_matches("aab", "a[]a-]b", 1, 1, 1, 1); + assert_matches("]", "]", 1, 1, 1, 1); +} + +void test_core_wildmatch__slash_matching_features(void) +{ + assert_matches("foo/baz/bar", "foo*bar", 0, 0, 1, 1); + assert_matches("foo/baz/bar", "foo**bar", 0, 0, 1, 1); + assert_matches("foobazbar", "foo**bar", 1, 1, 1, 1); + assert_matches("foo/baz/bar", "foo/**/bar", 1, 1, 1, 1); + assert_matches("foo/baz/bar", "foo/**/**/bar", 1, 1, 0, 0); + assert_matches("foo/b/a/z/bar", "foo/**/bar", 1, 1, 1, 1); + assert_matches("foo/b/a/z/bar", "foo/**/**/bar", 1, 1, 1, 1); + assert_matches("foo/bar", "foo/**/bar", 1, 1, 0, 0); + assert_matches("foo/bar", "foo/**/**/bar", 1, 1, 0, 0); + assert_matches("foo/bar", "foo?bar", 0, 0, 1, 1); + assert_matches("foo/bar", "foo[/]bar", 0, 0, 1, 1); + assert_matches("foo/bar", "foo[^a-z]bar", 0, 0, 1, 1); + assert_matches("foo/bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", 0, 0, 1, 1); + assert_matches("foo-bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", 1, 1, 1, 1); + assert_matches("foo", "**/foo", 1, 1, 0, 0); + assert_matches("XXX/foo", "**/foo", 1, 1, 1, 1); + assert_matches("bar/baz/foo", "**/foo", 1, 1, 1, 1); + assert_matches("bar/baz/foo", "*/foo", 0, 0, 1, 1); + assert_matches("foo/bar/baz", "**/bar*", 0, 0, 1, 1); + assert_matches("deep/foo/bar/baz", "**/bar/*", 1, 1, 1, 1); + assert_matches("deep/foo/bar/baz/", "**/bar/*", 0, 0, 1, 1); + assert_matches("deep/foo/bar/baz/", "**/bar/**", 1, 1, 1, 1); + assert_matches("deep/foo/bar", "**/bar/*", 0, 0, 0, 0); + assert_matches("deep/foo/bar/", "**/bar/**", 1, 1, 1, 1); + assert_matches("foo/bar/baz", "**/bar**", 0, 0, 1, 1); + assert_matches("foo/bar/baz/x", "*/bar/**", 1, 1, 1, 1); + assert_matches("deep/foo/bar/baz/x", "*/bar/**", 0, 0, 1, 1); + assert_matches("deep/foo/bar/baz/x", "**/bar/*/*", 1, 1, 1, 1); +} + +void test_core_wildmatch__various_additional(void) +{ + assert_matches("acrt", "a[c-c]st", 0, 0, 0, 0); + assert_matches("acrt", "a[c-c]rt", 1, 1, 1, 1); + assert_matches("]", "[!]-]", 0, 0, 0, 0); + assert_matches("a", "[!]-]", 1, 1, 1, 1); + assert_matches("", "\\", 0, 0, 0, 0); + assert_matches("\\", "\\", 0, 0, 0, 0); + assert_matches("XXX/\\", "*/\\", 0, 0, 0, 0); + assert_matches("XXX/\\", "*/\\\\", 1, 1, 1, 1); + assert_matches("foo", "foo", 1, 1, 1, 1); + assert_matches("@foo", "@foo", 1, 1, 1, 1); + assert_matches("foo", "@foo", 0, 0, 0, 0); + assert_matches("[ab]", "\\[ab]", 1, 1, 1, 1); + assert_matches("[ab]", "[[]ab]", 1, 1, 1, 1); + assert_matches("[ab]", "[[:]ab]", 1, 1, 1, 1); + assert_matches("[ab]", "[[::]ab]", 0, 0, 0, 0); + assert_matches("[ab]", "[[:digit]ab]", 1, 1, 1, 1); + assert_matches("[ab]", "[\\[:]ab]", 1, 1, 1, 1); + assert_matches("?a?b", "\\??\\?b", 1, 1, 1, 1); + assert_matches("abc", "\\a\\b\\c", 1, 1, 1, 1); + assert_matches("foo", "", 0, 0, 0, 0); + assert_matches("foo/bar/baz/to", "**/t[o]", 1, 1, 1, 1); +} + +void test_core_wildmatch__character_classes(void) +{ + assert_matches("a1B", "[[:alpha:]][[:digit:]][[:upper:]]", 1, 1, 1, 1); + assert_matches("a", "[[:digit:][:upper:][:space:]]", 0, 1, 0, 1); + assert_matches("A", "[[:digit:][:upper:][:space:]]", 1, 1, 1, 1); + assert_matches("1", "[[:digit:][:upper:][:space:]]", 1, 1, 1, 1); + assert_matches("1", "[[:digit:][:upper:][:spaci:]]", 0, 0, 0, 0); + assert_matches(" ", "[[:digit:][:upper:][:space:]]", 1, 1, 1, 1); + assert_matches(".", "[[:digit:][:upper:][:space:]]", 0, 0, 0, 0); + assert_matches(".", "[[:digit:][:punct:][:space:]]", 1, 1, 1, 1); + assert_matches("5", "[[:xdigit:]]", 1, 1, 1, 1); + assert_matches("f", "[[:xdigit:]]", 1, 1, 1, 1); + assert_matches("D", "[[:xdigit:]]", 1, 1, 1, 1); + assert_matches("_", "[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]", 1, 1, 1, 1); + assert_matches(".", "[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]", 1, 1, 1, 1); + assert_matches("5", "[a-c[:digit:]x-z]", 1, 1, 1, 1); + assert_matches("b", "[a-c[:digit:]x-z]", 1, 1, 1, 1); + assert_matches("y", "[a-c[:digit:]x-z]", 1, 1, 1, 1); + assert_matches("q", "[a-c[:digit:]x-z]", 0, 0, 0, 0); +} + +void test_core_wildmatch__additional_with_malformed(void) +{ + assert_matches("]", "[\\\\-^]", 1, 1, 1, 1); + assert_matches("[", "[\\\\-^]", 0, 0, 0, 0); + assert_matches("-", "[\\-_]", 1, 1, 1, 1); + assert_matches("]", "[\\]]", 1, 1, 1, 1); + assert_matches("\\]", "[\\]]", 0, 0, 0, 0); + assert_matches("\\", "[\\]]", 0, 0, 0, 0); + assert_matches("ab", "a[]b", 0, 0, 0, 0); + assert_matches("a[]b", "a[]b", 0, 0, 0, 0); + assert_matches("ab[", "ab[", 0, 0, 0, 0); + assert_matches("ab", "[!", 0, 0, 0, 0); + assert_matches("ab", "[-", 0, 0, 0, 0); + assert_matches("-", "[-]", 1, 1, 1, 1); + assert_matches("-", "[a-", 0, 0, 0, 0); + assert_matches("-", "[!a-", 0, 0, 0, 0); + assert_matches("-", "[--A]", 1, 1, 1, 1); + assert_matches("5", "[--A]", 1, 1, 1, 1); + assert_matches(" ", "[ --]", 1, 1, 1, 1); + assert_matches("$", "[ --]", 1, 1, 1, 1); + assert_matches("-", "[ --]", 1, 1, 1, 1); + assert_matches("0", "[ --]", 0, 0, 0, 0); + assert_matches("-", "[---]", 1, 1, 1, 1); + assert_matches("-", "[------]", 1, 1, 1, 1); + assert_matches("j", "[a-e-n]", 0, 0, 0, 0); + assert_matches("-", "[a-e-n]", 1, 1, 1, 1); + assert_matches("a", "[!------]", 1, 1, 1, 1); + assert_matches("[", "[]-a]", 0, 0, 0, 0); + assert_matches("^", "[]-a]", 1, 1, 1, 1); + assert_matches("^", "[!]-a]", 0, 0, 0, 0); + assert_matches("[", "[!]-a]", 1, 1, 1, 1); + assert_matches("^", "[a^bc]", 1, 1, 1, 1); + assert_matches("-b]", "[a-]b]", 1, 1, 1, 1); + assert_matches("\\", "[\\]", 0, 0, 0, 0); + assert_matches("\\", "[\\\\]", 1, 1, 1, 1); + assert_matches("\\", "[!\\\\]", 0, 0, 0, 0); + assert_matches("G", "[A-\\\\]", 1, 1, 1, 1); + assert_matches("aaabbb", "b*a", 0, 0, 0, 0); + assert_matches("aabcaa", "*ba*", 0, 0, 0, 0); + assert_matches(",", "[,]", 1, 1, 1, 1); + assert_matches(",", "[\\\\,]", 1, 1, 1, 1); + assert_matches("\\", "[\\\\,]", 1, 1, 1, 1); + assert_matches("-", "[,-.]", 1, 1, 1, 1); + assert_matches("+", "[,-.]", 0, 0, 0, 0); + assert_matches("-.]", "[,-.]", 0, 0, 0, 0); + assert_matches("2", "[\\1-\\3]", 1, 1, 1, 1); + assert_matches("3", "[\\1-\\3]", 1, 1, 1, 1); + assert_matches("4", "[\\1-\\3]", 0, 0, 0, 0); + assert_matches("\\", "[[-\\]]", 1, 1, 1, 1); + assert_matches("[", "[[-\\]]", 1, 1, 1, 1); + assert_matches("]", "[[-\\]]", 1, 1, 1, 1); + assert_matches("-", "[[-\\]]", 0, 0, 0, 0); +} + +void test_core_wildmatch__recursion(void) +{ + assert_matches("-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", 1, 1, 1, 1); + assert_matches("-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", 0, 0, 0, 0); + assert_matches("-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", 0, 0, 0, 0); + assert_matches("XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*", 1, 1, 1, 1); + assert_matches("XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*", 0, 0, 0, 0); + assert_matches("abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt", "**/*a*b*g*n*t", 1, 1, 1, 1); + assert_matches("abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz", "**/*a*b*g*n*t", 0, 0, 0, 0); + assert_matches("foo", "*/*/*", 0, 0, 0, 0); + assert_matches("foo/bar", "*/*/*", 0, 0, 0, 0); + assert_matches("foo/bba/arr", "*/*/*", 1, 1, 1, 1); + assert_matches("foo/bb/aa/rr", "*/*/*", 0, 0, 1, 1); + assert_matches("foo/bb/aa/rr", "**/**/**", 1, 1, 1, 1); + assert_matches("abcXdefXghi", "*X*i", 1, 1, 1, 1); + assert_matches("ab/cXd/efXg/hi", "*X*i", 0, 0, 1, 1); + assert_matches("ab/cXd/efXg/hi", "*/*X*/*/*i", 1, 1, 1, 1); + assert_matches("ab/cXd/efXg/hi", "**/*X*/**/*i", 1, 1, 1, 1); +} + +void test_core_wildmatch__pathmatch(void) +{ + assert_matches("foo", "fo", 0, 0, 0, 0); + assert_matches("foo/bar", "foo/bar", 1, 1, 1, 1); + assert_matches("foo/bar", "foo/*", 1, 1, 1, 1); + assert_matches("foo/bba/arr", "foo/*", 0, 0, 1, 1); + assert_matches("foo/bba/arr", "foo/**", 1, 1, 1, 1); + assert_matches("foo/bba/arr", "foo*", 0, 0, 1, 1); + assert_matches("foo/bba/arr", "foo**", 0, 0, 1, 1); + assert_matches("foo/bba/arr", "foo/*arr", 0, 0, 1, 1); + assert_matches("foo/bba/arr", "foo/**arr", 0, 0, 1, 1); + assert_matches("foo/bba/arr", "foo/*z", 0, 0, 0, 0); + assert_matches("foo/bba/arr", "foo/**z", 0, 0, 0, 0); + assert_matches("foo/bar", "foo?bar", 0, 0, 1, 1); + assert_matches("foo/bar", "foo[/]bar", 0, 0, 1, 1); + assert_matches("foo/bar", "foo[^a-z]bar", 0, 0, 1, 1); + assert_matches("ab/cXd/efXg/hi", "*Xg*i", 0, 0, 1, 1); +} + +void test_core_wildmatch__case_sensitivity(void) +{ + assert_matches("a", "[A-Z]", 0, 1, 0, 1); + assert_matches("A", "[A-Z]", 1, 1, 1, 1); + assert_matches("A", "[a-z]", 0, 1, 0, 1); + assert_matches("a", "[a-z]", 1, 1, 1, 1); + assert_matches("a", "[[:upper:]]", 0, 1, 0, 1); + assert_matches("A", "[[:upper:]]", 1, 1, 1, 1); + assert_matches("A", "[[:lower:]]", 0, 1, 0, 1); + assert_matches("a", "[[:lower:]]", 1, 1, 1, 1); + assert_matches("A", "[B-Za]", 0, 1, 0, 1); + assert_matches("a", "[B-Za]", 1, 1, 1, 1); + assert_matches("A", "[B-a]", 0, 1, 0, 1); + assert_matches("a", "[B-a]", 1, 1, 1, 1); + assert_matches("z", "[Z-y]", 0, 1, 0, 1); + assert_matches("Z", "[Z-y]", 1, 1, 1, 1); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/core/zstream.c libgit2-1.1.0+dfsg.1/tests/core/zstream.c --- libgit2-0.28.5+dfsg.1/tests/core/zstream.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/core/zstream.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ static void assert_zlib_equal_( const void *expected, size_t e_len, const void *compressed, size_t c_len, - const char *msg, const char *file, int line) + const char *msg, const char *file, const char *func, int line) { z_stream stream; char *expanded = git__calloc(1, e_len + INFLATE_EXTRA); @@ -26,21 +26,21 @@ inflateEnd(&stream); clar__assert_equal( - file, line, msg, 1, + file, func, line, msg, 1, "%d", (int)stream.total_out, (int)e_len); clar__assert_equal( - file, line, "Buffer len was not exact match", 1, + file, func, line, "Buffer len was not exact match", 1, "%d", (int)stream.avail_out, (int)INFLATE_EXTRA); clar__assert( memcmp(expanded, expected, e_len) == 0, - file, line, "uncompressed data did not match", NULL, 1); + file, func, line, "uncompressed data did not match", NULL, 1); git__free(expanded); } #define assert_zlib_equal(E,EL,C,CL) \ - assert_zlib_equal_(E, EL, C, CL, #EL " != " #CL, __FILE__, (int)__LINE__) + assert_zlib_equal_(E, EL, C, CL, #EL " != " #CL, __FILE__, __func__, (int)__LINE__) void test_core_zstream__basic(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/describe/describe_helpers.c libgit2-1.1.0+dfsg.1/tests/describe/describe_helpers.c --- libgit2-0.28.5+dfsg.1/tests/describe/describe_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/describe/describe_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,7 @@ #include "describe_helpers.h" +#include "wildmatch.h" + void assert_describe( const char *expected_output, const char *revparse_spec, @@ -16,7 +18,7 @@ cl_git_pass(git_describe_commit(&result, object, opts)); cl_git_pass(git_describe_format(&label, result, fmt_opts)); - cl_must_pass(p_fnmatch(expected_output, git_buf_cstr(&label), 0)); + cl_must_pass(wildmatch(expected_output, git_buf_cstr(&label), 0)); git_describe_result_free(result); git_object_free(object); @@ -35,7 +37,7 @@ cl_git_pass(git_describe_workdir(&result, repo, opts)); cl_git_pass(git_describe_format(&label, result, fmt_opts)); - cl_must_pass(p_fnmatch(expected_output, git_buf_cstr(&label), 0)); + cl_must_pass(wildmatch(expected_output, git_buf_cstr(&label), 0)); git_describe_result_free(result); git_buf_dispose(&label); diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/blob.c libgit2-1.1.0+dfsg.1/tests/diff/blob.c --- libgit2-0.28.5+dfsg.1/tests/diff/blob.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/blob.c 2020-10-12 18:53:06.000000000 +0000 @@ -39,7 +39,7 @@ g_repo = cl_git_sandbox_init("attr"); - cl_git_pass(git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION)); + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); opts.context_lines = 1; memset(&expected, 0, sizeof(expected)); @@ -315,7 +315,7 @@ cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert_equal_oid(git_blob_id(d), &delta->old_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size); - cl_assert(git_oid_iszero(&delta->new_file.id)); + cl_assert(git_oid_is_zero(&delta->new_file.id)); cl_assert_equal_sz(0, delta->new_file.size); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); @@ -338,7 +338,7 @@ delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); - cl_assert(git_oid_iszero(&delta->old_file.id)); + cl_assert(git_oid_is_zero(&delta->old_file.id)); cl_assert_equal_sz(0, delta->old_file.size); cl_assert_equal_oid(git_blob_id(d), &delta->new_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); @@ -445,9 +445,9 @@ cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(0, delta->old_file.size); - cl_assert(git_oid_iszero(&delta->old_file.id)); + cl_assert(git_oid_is_zero(&delta->old_file.id)); cl_assert_equal_sz(0, delta->new_file.size); - cl_assert(git_oid_iszero(&delta->new_file.id)); + cl_assert(git_oid_is_zero(&delta->new_file.id)); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); @@ -520,19 +520,19 @@ * +++ b/a0f7217 * @@ -1,6 +1,6 @@ * Here is some stuff at the start - * + * * -This should go in one hunk * +This should go in one hunk (first) - * + * * Some additional lines - * + * * @@ -8,7 +8,7 @@ Down here below the other lines - * + * * With even more at the end - * + * * -Followed by a second hunk of stuff * +Followed by a second hunk of stuff (second) - * + * * That happens down here */ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/diff_helpers.h libgit2-1.1.0+dfsg.1/tests/diff/diff_helpers.h --- libgit2-0.28.5+dfsg.1/tests/diff/diff_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/diff_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -1,4 +1,4 @@ -#include "fileops.h" +#include "futils.h" #include "git2/diff.h" extern git_tree *resolve_commit_oid_to_tree( diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/format_email.c libgit2-1.1.0+dfsg.1/tests/diff/format_email.c --- libgit2-0.28.5+dfsg.1/tests/diff/format_email.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/format_email.c 2020-10-12 18:53:06.000000000 +0000 @@ -487,7 +487,7 @@ "Subject: [PATCH] Modified binary file\n" \ "\n" \ "---\n" \ - " binary.bin | Bin 3 -> 0 bytes\n" \ + " binary.bin | Bin 3 -> 5 bytes\n" \ " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \ "\n" \ "diff --git a/binary.bin b/binary.bin\n" \ @@ -496,7 +496,6 @@ "--\n" \ "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ opts.summary = "Modified binary file"; diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/parse.c libgit2-1.1.0+dfsg.1/tests/diff/parse.c --- libgit2-0.28.5+dfsg.1/tests/diff/parse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/parse.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,6 @@ #include "patch.h" #include "patch_parse.h" #include "diff_helpers.h" -#include "../src/diff.h" #include "../patch/patch_common.h" @@ -108,6 +107,29 @@ git_diff_free(diff); } +void test_diff_parse__add_delete_no_index(void) +{ + const char *content = + "diff --git a/file.txt b/file.txt\n" + "new file mode 100644\n" + "--- /dev/null\n" + "+++ b/file.txt\n" + "@@ -0,0 +1,2 @@\n" + "+one\n" + "+two\n" + "diff --git a/otherfile.txt b/otherfile.txt\n" + "deleted file mode 100644\n" + "--- a/otherfile.txt\n" + "+++ /dev/null\n" + "@@ -1,1 +0,0 @@\n" + "-three\n"; + git_diff *diff; + + cl_git_pass(git_diff_from_buffer( + &diff, content, strlen(content))); + git_diff_free(diff); +} + void test_diff_parse__invalid_patches_fails(void) { test_parse_invalid_diff(PATCH_CORRUPT_MISSING_NEW_FILE); @@ -319,20 +341,20 @@ git_buf_dispose(&diffbuf); } -#define cl_assert_equal_i_src(i1,i2,file,line) clar__assert_equal(file,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_src(i1,i2,file,func,line) clar__assert_equal(file,func,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) -static void cl_git_assert_lineinfo_(int old_lineno, int new_lineno, int num_lines, git_patch *patch, size_t hunk_idx, size_t line_idx, const char *file, int lineno) +static void cl_git_assert_lineinfo_(int old_lineno, int new_lineno, int num_lines, git_patch *patch, size_t hunk_idx, size_t line_idx, const char *file, const char *func, int lineno) { const git_diff_line *line; - cl_git_expect(git_patch_get_line_in_hunk(&line, patch, hunk_idx, line_idx), 0, file, lineno); - cl_assert_equal_i_src(old_lineno, line->old_lineno, file, lineno); - cl_assert_equal_i_src(new_lineno, line->new_lineno, file, lineno); - cl_assert_equal_i_src(num_lines, line->num_lines, file, lineno); + cl_git_expect(git_patch_get_line_in_hunk(&line, patch, hunk_idx, line_idx), 0, file, func, lineno); + cl_assert_equal_i_src(old_lineno, line->old_lineno, file, func, lineno); + cl_assert_equal_i_src(new_lineno, line->new_lineno, file, func, lineno); + cl_assert_equal_i_src(num_lines, line->num_lines, file, func, lineno); } #define cl_git_assert_lineinfo(old, new, num, p, h, l) \ - cl_git_assert_lineinfo_(old,new,num,p,h,l,__FILE__,__LINE__) + cl_git_assert_lineinfo_(old,new,num,p,h,l,__FILE__,__func__,__LINE__) void test_diff_parse__issue4672(void) diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/patch.c libgit2-1.1.0+dfsg.1/tests/diff/patch.c --- libgit2-0.28.5+dfsg.1/tests/diff/patch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/patch.c 2020-10-12 18:53:06.000000000 +0000 @@ -692,7 +692,7 @@ git_patch *patch; git_buf buf = GIT_BUF_INIT; - cl_git_pass(git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION)); + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); cl_git_pass(git_patch_from_buffers(&patch, a, strlen(a), NULL, b, strlen(b), NULL, &opts)); cl_git_pass(git_patch_to_buf(&buf, patch)); diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/patchid.c libgit2-1.1.0+dfsg.1/tests/diff/patchid.c --- libgit2-0.28.5+dfsg.1/tests/diff/patchid.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/patchid.c 2020-10-12 18:53:06.000000000 +0000 @@ -20,6 +20,39 @@ verify_patch_id(PATCH_SIMPLE_COMMIT, "06094b1948b878b7d9ff7560b4eae672a014b0ec"); } +void test_diff_patchid__deleted_file(void) +{ + verify_patch_id(PATCH_DELETE_ORIGINAL, "d18507fe189f49c028b32c8c34e1ad98dd6a1aad"); + verify_patch_id(PATCH_DELETED_FILE_2_HUNKS, "f31412498a17e6c3fbc635f2c5f9aa3ef4c1a9b7"); +} + +void test_diff_patchid__created_file(void) +{ + verify_patch_id(PATCH_ADD_ORIGINAL, "a7d39379308021465ae2ce65e338c048a3110db6"); +} + +void test_diff_patchid__binary_file(void) +{ + verify_patch_id(PATCH_ADD_BINARY_NOT_PRINTED, "2b31236b485faa30cf4dd33e4d6539829996739f"); +} + +void test_diff_patchid__renamed_file(void) +{ + verify_patch_id(PATCH_RENAME_EXACT, "4666d50cea4976f6f727448046d43461912058fd"); + verify_patch_id(PATCH_RENAME_SIMILAR, "a795087575fcb940227be524488bedd6b3d3f438"); +} + +void test_diff_patchid__modechange(void) +{ + verify_patch_id(PATCH_MODECHANGE_UNCHANGED, "dbf3423ee98375ef1c72a79fbd29a049a2bae771"); + verify_patch_id(PATCH_MODECHANGE_MODIFIED, "93aba696e1bbd2bbb73e3e3e62ed71f232137657"); +} + +void test_diff_patchid__shuffle_hunks(void) +{ + verify_patch_id(PATCH_DELETED_FILE_2_HUNKS_SHUFFLED, "f31412498a17e6c3fbc635f2c5f9aa3ef4c1a9b7"); +} + void test_diff_patchid__filename_with_spaces(void) { verify_patch_id(PATCH_APPEND_NO_NL, "f0ba05413beaef743b630e796153839462ee477a"); diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/stats.c libgit2-1.1.0+dfsg.1/tests/diff/stats.c --- libgit2-0.28.5+dfsg.1/tests/diff/stats.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/stats.c 2020-10-12 18:53:06.000000000 +0000 @@ -298,9 +298,8 @@ { git_buf buf = GIT_BUF_INIT; const char *stat = - " binary.bin | Bin 3 -> 0 bytes\n" + " binary.bin | Bin 3 -> 5 bytes\n" " 1 file changed, 0 insertions(+), 0 deletions(-)\n"; - /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ diff_stats_from_commit_oid( &_stats, "8d7523f6fcb2404257889abe0d96f093d9f524f9", false); @@ -343,3 +342,38 @@ cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_dispose(&buf); } + +void test_diff_stats__new_file(void) +{ + git_diff *diff; + git_buf buf = GIT_BUF_INIT; + + const char *input = + "---\n" + " Gurjeet Singh | 1 +\n" + " 1 file changed, 1 insertion(+)\n" + " create mode 100644 Gurjeet Singh\n" + "\n" + "diff --git a/Gurjeet Singh b/Gurjeet Singh\n" + "new file mode 100644\n" + "index 0000000..6d0ecfd\n" + "--- /dev/null\n" + "+++ b/Gurjeet Singh \n" + "@@ -0,0 +1 @@\n" + "+I'm about to try git send-email\n" + "-- \n" + "2.21.0\n"; + + const char *stat = + " Gurjeet Singh | 1 +\n" + " 1 file changed, 1 insertion(+)\n" + " create mode 100644 Gurjeet Singh\n"; + + cl_git_pass(git_diff_from_buffer(&diff, input, strlen(input))); + cl_git_pass(git_diff_get_stats(&_stats, diff)); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); + + git_buf_dispose(&buf); + git_diff_free(diff); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/submodules.c libgit2-1.1.0+dfsg.1/tests/diff/submodules.c --- libgit2-0.28.5+dfsg.1/tests/diff/submodules.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/submodules.c 2020-10-12 18:53:06.000000000 +0000 @@ -18,7 +18,8 @@ #define get_buf_ptr(buf) ((buf)->asize ? (buf)->ptr : NULL) static void check_diff_patches_at_line( - git_diff *diff, const char **expected, const char *file, int line) + git_diff *diff, const char **expected, + const char *file, const char *func, int line) { const git_diff_delta *delta; git_patch *patch = NULL; @@ -30,34 +31,34 @@ cl_assert((delta = git_patch_get_delta(patch)) != NULL); if (delta->status == GIT_DELTA_UNMODIFIED) { - cl_assert_at_line(expected[d] == NULL, file, line); + cl_assert_at_line(expected[d] == NULL, file, func, line); continue; } if (expected[d] && !strcmp(expected[d], "")) continue; if (expected[d] && !strcmp(expected[d], "")) { - cl_assert_at_line(delta->status == GIT_DELTA_UNTRACKED, file, line); + cl_assert_at_line(delta->status == GIT_DELTA_UNTRACKED, file, func, line); continue; } if (expected[d] && !strcmp(expected[d], "")) { cl_git_pass(git_patch_to_buf(&buf, patch)); - cl_assert_at_line(!strcmp(expected[d], ""), file, line); + cl_assert_at_line(!strcmp(expected[d], ""), file, func, line); } cl_git_pass(git_patch_to_buf(&buf, patch)); clar__assert_equal( - file, line, "expected diff did not match actual diff", 1, + file, func, line, "expected diff did not match actual diff", 1, "%s", expected[d], get_buf_ptr(&buf)); git_buf_dispose(&buf); } - cl_assert_at_line(expected[d] && !strcmp(expected[d], ""), file, line); + cl_assert_at_line(expected[d] && !strcmp(expected[d], ""), file, func, line); } #define check_diff_patches(diff, exp) \ - check_diff_patches_at_line(diff, exp, __FILE__, __LINE__) + check_diff_patches_at_line(diff, exp, __FILE__, __func__, __LINE__) void test_diff_submodules__unmodified_submodule(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/tree.c libgit2-1.1.0+dfsg.1/tests/diff/tree.c --- libgit2-0.28.5+dfsg.1/tests/diff/tree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/tree.c 2020-10-12 18:53:06.000000000 +0000 @@ -9,7 +9,7 @@ void test_diff_tree__initialize(void) { - cl_git_pass(git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION)); + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); memset(&expect, 0, sizeof(expect)); @@ -472,7 +472,7 @@ cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - cl_git_pass(git_diff_foreach(diff, + cl_git_pass(git_diff_foreach(diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); @@ -524,3 +524,52 @@ cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); } + +void test_diff_tree__diff_tree_with_empty_dir_entry_succeeds(void) +{ + const char *content = "This is a blob\n"; + const git_diff_delta *delta; + git_oid empty_tree, invalid_tree, blob; + git_buf patch = GIT_BUF_INIT; + git_treebuilder *builder; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_blob_create_from_buffer(&blob, g_repo, content, strlen(content))); + cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); + cl_git_pass(git_treebuilder_write(&empty_tree, builder)); + cl_git_pass(git_treebuilder_insert(NULL, builder, "empty_tree", &empty_tree, GIT_FILEMODE_TREE)); + cl_git_pass(git_treebuilder_insert(NULL, builder, "blob", &blob, GIT_FILEMODE_BLOB)); + cl_git_pass(git_treebuilder_write(&invalid_tree, builder)); + + cl_git_pass(git_tree_lookup(&a, g_repo, &empty_tree)); + cl_git_pass(git_tree_lookup(&b, g_repo, &invalid_tree)); + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); + + cl_git_pass(git_diff_foreach(diff, + diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); + cl_assert_equal_i(1, expect.files); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, expect.hunks); + cl_assert_equal_i(1, expect.lines); + cl_assert_equal_i(0, expect.line_ctxt); + cl_assert_equal_i(1, expect.line_adds); + cl_assert_equal_i(0, expect.line_dels); + + cl_git_pass(git_diff_to_buf(&patch, diff, GIT_DIFF_FORMAT_PATCH)); + cl_assert_equal_s(patch.ptr, + "diff --git a/blob b/blob\n" + "new file mode 100644\n" + "index 0000000..bbf2e80\n" + "--- /dev/null\n" + "+++ b/blob\n" + "@@ -0,0 +1 @@\n" + "+This is a blob\n"); + + cl_assert_equal_i(git_diff_num_deltas(diff), 1); + delta = git_diff_get_delta(diff, 0); + cl_assert_equal_s(delta->new_file.path, "blob"); + + git_treebuilder_free(builder); + git_buf_dispose(&patch); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/diff/workdir.c libgit2-1.1.0+dfsg.1/tests/diff/workdir.c --- libgit2-0.28.5+dfsg.1/tests/diff/workdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/diff/workdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -1876,9 +1876,9 @@ git_buf b = GIT_BUF_INIT; int i; git_buf data[10] = { - { "1234567890", 0, 0 }, /* 0 - all ascii text control */ - { "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 0 }, /* 1 - UTF-8 multibyte text */ - { "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 0 }, /* 2 - UTF-8 with BOM */ + { "1234567890", 0, 10 }, /* 0 - all ascii text control */ + { "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 14 }, /* 1 - UTF-8 multibyte text */ + { "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 16 }, /* 2 - UTF-8 with BOM */ { STR999Z, 0, 1000 }, /* 3 - ASCII with NUL at 1000 */ { STR3999Z, 0, 4000 }, /* 4 - ASCII with NUL at 4000 */ { STR4000 STR3999Z "x", 0, 8001 }, /* 5 - ASCII with NUL at 8000 */ @@ -2112,7 +2112,7 @@ g_repo = cl_git_sandbox_init("unsymlinked.git"); - cl_git_pass(git_repository__cvar(&symlinks, g_repo, GIT_CVAR_SYMLINKS)); + cl_git_pass(git_repository__configmap_lookup(&symlinks, g_repo, GIT_CONFIGMAP_SYMLINKS)); if (symlinks) cl_skip(); @@ -2160,3 +2160,46 @@ git_tree_free(tree); git_vector_free(&pathlist); } + +void test_diff_workdir__order(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_buf patch = GIT_BUF_INIT; + git_oid tree_oid, blob_oid; + git_treebuilder *builder; + git_tree *tree; + git_diff *diff; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + /* Build tree with a single file "abc.txt" */ + cl_git_pass(git_blob_create_from_buffer(&blob_oid, g_repo, "foo\n", 4)); + cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); + cl_git_pass(git_treebuilder_insert(NULL, builder, "abc.txt", &blob_oid, GIT_FILEMODE_BLOB)); + cl_git_pass(git_treebuilder_write(&tree_oid, builder)); + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); + + /* Create a directory that sorts before and one that sorts after "abc.txt" */ + cl_git_mkfile("empty_standard_repo/abc.txt", "bar\n"); + cl_must_pass(p_mkdir("empty_standard_repo/abb", 0777)); + cl_must_pass(p_mkdir("empty_standard_repo/abd", 0777)); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); + + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_diff_to_buf(&patch, diff, GIT_DIFF_FORMAT_PATCH)); + cl_assert_equal_s(patch.ptr, + "diff --git a/abc.txt b/abc.txt\n" + "index 257cc56..5716ca5 100644\n" + "--- a/abc.txt\n" + "+++ b/abc.txt\n" + "@@ -1 +1 @@\n" + "-foo\n" + "+bar\n"); + + git_treebuilder_free(builder); + git_buf_dispose(&patch); + git_diff_free(diff); + git_tree_free(tree); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/fetchhead/nonetwork.c libgit2-1.1.0+dfsg.1/tests/fetchhead/nonetwork.c --- libgit2-0.28.5+dfsg.1/tests/fetchhead/nonetwork.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/fetchhead/nonetwork.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "fetchhead.h" #include "fetchhead_data.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/filter/bare.c libgit2-1.1.0+dfsg.1/tests/filter/bare.c --- libgit2-0.28.5+dfsg.1/tests/filter/bare.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/filter/bare.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,134 @@ +#include "clar_libgit2.h" +#include "crlf.h" + +static git_repository *g_repo = NULL; +static git_blob_filter_options filter_opts = GIT_BLOB_FILTER_OPTIONS_INIT; + +void test_filter_bare__initialize(void) +{ + cl_fixture_sandbox("crlf.git"); + cl_git_pass(git_repository_open(&g_repo, "crlf.git")); + + filter_opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES; + filter_opts.flags |= GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD; +} + +void test_filter_bare__cleanup(void) +{ + git_repository_free(g_repo); + cl_fixture_cleanup("crlf.git"); +} + +void test_filter_bare__all_crlf(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "a9a2e89")); /* all-crlf */ + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &filter_opts)); + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts)); + + /* we never convert CRLF -> LF on platforms that have LF */ + cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.txt", &filter_opts)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} + +void test_filter_bare__from_lf(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "799770d")); /* all-lf */ + + cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &filter_opts)); + + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts)); + + /* we never convert CRLF -> LF on platforms that have LF */ + cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} + +void test_filter_bare__nested_attributes(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "799770d")); /* all-lf */ + + cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "raw/file.bin", &filter_opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "raw/file.crlf", &filter_opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "raw/file.lf", &filter_opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} + +void test_filter_bare__sanitizes(void) +{ + git_blob *blob; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "e69de29")); /* zero-byte */ + + cl_assert_equal_i(0, git_blob_rawsize(blob)); + cl_assert_equal_s("", git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &filter_opts)); + cl_assert_equal_sz(0, buf.size); + cl_assert_equal_s("", buf.ptr); + git_buf_dispose(&buf); + + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts)); + cl_assert_equal_sz(0, buf.size); + cl_assert_equal_s("", buf.ptr); + git_buf_dispose(&buf); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts)); + cl_assert_equal_sz(0, buf.size); + cl_assert_equal_s("", buf.ptr); + git_buf_dispose(&buf); + + git_blob_free(blob); +} + diff -Nru libgit2-0.28.5+dfsg.1/tests/filter/blob.c libgit2-1.1.0+dfsg.1/tests/filter/blob.c --- libgit2-0.28.5+dfsg.1/tests/filter/blob.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/filter/blob.c 2020-10-12 18:53:06.000000000 +0000 @@ -30,16 +30,16 @@ cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL)); cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL)); /* in this case, raw content has crlf in it already */ cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL)); /* we never convert CRLF -> LF on platforms that have LF */ cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); @@ -48,6 +48,34 @@ git_blob_free(blob); } +void test_filter_blob__from_lf(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "799770d")); /* all-lf */ + + cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL)); + + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL)); + + /* we never convert CRLF -> LF on platforms that have LF */ + cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} + void test_filter_blob__sanitizes(void) { git_blob *blob; @@ -60,19 +88,19 @@ cl_assert_equal_s("", git_blob_rawcontent(blob)); memset(&buf, 0, sizeof(git_buf)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL)); cl_assert_equal_sz(0, buf.size); cl_assert_equal_s("", buf.ptr); git_buf_dispose(&buf); memset(&buf, 0, sizeof(git_buf)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL)); cl_assert_equal_sz(0, buf.size); cl_assert_equal_s("", buf.ptr); git_buf_dispose(&buf); memset(&buf, 0, sizeof(git_buf)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL)); cl_assert_equal_sz(0, buf.size); cl_assert_equal_s("", buf.ptr); git_buf_dispose(&buf); @@ -87,27 +115,27 @@ git_buf buf = { 0 }; cl_git_mkfile("crlf/test.ident", "Some text\n$Id$\nGoes there\n"); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_create_from_workdir(&id, g_repo, "test.ident")); cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); cl_assert_equal_s( "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); git_blob_free(blob); cl_git_mkfile("crlf/test.ident", "Some text\n$Id: Any old just you want$\nGoes there\n"); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_create_from_workdir(&id, g_repo, "test.ident")); cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); cl_assert_equal_s( "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.bin", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "filter.bin", NULL)); cl_assert_equal_s( "Some text\n$Id$\nGoes there\n", buf.ptr); - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identcrlf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "filter.identcrlf", NULL)); cl_assert_equal_s( "Some text\r\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845 $\r\nGoes there\r\n", buf.ptr); - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identlf", 1)); + cl_git_pass(git_blob_filter(&buf, blob, "filter.identlf", NULL)); cl_assert_equal_s( "Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845 $\nGoes there\n", buf.ptr); diff -Nru libgit2-0.28.5+dfsg.1/tests/filter/custom.c libgit2-1.1.0+dfsg.1/tests/filter/custom.c --- libgit2-0.28.5+dfsg.1/tests/filter/custom.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/filter/custom.c 2020-10-12 18:53:06.000000000 +0000 @@ -208,7 +208,7 @@ & git_index_get_bypath(index, "hero.1.rev-ident", 0)->id)); cl_assert_equal_s( "\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0)); + cl_git_pass(git_blob_filter(&buf, blob, "hero.1.rev-ident", NULL)); /* no expansion because id was reversed at checkin and now at ident * time, reverse is not applied yet */ cl_assert_equal_s( @@ -219,7 +219,7 @@ & git_index_get_bypath(index, "hero.2.rev-ident", 0)->id)); cl_assert_equal_s( "\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0)); + cl_git_pass(git_blob_filter(&buf, blob, "hero.2.rev-ident", NULL)); /* expansion because reverse was applied at checkin and at ident time, * reverse is not applied yet */ cl_assert_equal_s( diff -Nru libgit2-0.28.5+dfsg.1/tests/filter/ident.c libgit2-1.1.0+dfsg.1/tests/filter/ident.c --- libgit2-0.28.5+dfsg.1/tests/filter/ident.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/filter/ident.c 2020-10-12 18:53:06.000000000 +0000 @@ -23,7 +23,7 @@ git_buf out = { 0 }; cl_git_mkfile("crlf/identtest", data); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "identtest")); + cl_git_pass(git_blob_create_from_workdir(&id, g_repo, "identtest")); cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); diff -Nru libgit2-0.28.5+dfsg.1/tests/filter/systemattrs.c libgit2-1.1.0+dfsg.1/tests/filter/systemattrs.c --- libgit2-0.28.5+dfsg.1/tests/filter/systemattrs.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/filter/systemattrs.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,81 @@ +#include "clar_libgit2.h" +#include "crlf.h" +#include "path.h" + +static git_repository *g_repo = NULL; +static git_buf system_attr_path = GIT_BUF_INIT; + +void test_filter_systemattrs__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + cl_must_pass(p_unlink("crlf/.gitattributes")); + + cl_git_pass(git_libgit2_opts( + GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &system_attr_path)); + cl_git_pass(git_buf_joinpath(&system_attr_path, + system_attr_path.ptr, "gitattributes")); + + cl_git_mkfile(system_attr_path.ptr, + "*.txt text\n" + "*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n"); +} + +void test_filter_systemattrs__cleanup(void) +{ + cl_must_pass(p_unlink(system_attr_path.ptr)); + git_buf_dispose(&system_attr_path); + + cl_git_sandbox_cleanup(); +} + +void test_filter_systemattrs__reads_system_attributes(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "799770d")); /* all-lf */ + + cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL)); + cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL)); + cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} + +void test_filter_systemattrs__disables_system_attributes(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT; + + opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "799770d")); /* all-lf */ + + cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + /* No attributes mean these are all treated literally */ + cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &opts)); + cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr); + + git_buf_dispose(&buf); + git_blob_free(blob); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/generate.py libgit2-1.1.0+dfsg.1/tests/generate.py --- libgit2-0.28.5+dfsg.1/tests/generate.py 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/generate.py 2020-10-12 18:53:06.000000000 +0000 @@ -24,8 +24,8 @@ def render(self): out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + "\n" - if self.module.initialize: - out += "extern %s;\n" % self.module.initialize['declaration'] + for initializer in self.module.initializers: + out += "extern %s;\n" % initializer['declaration'] if self.module.cleanup: out += "extern %s;\n" % self.module.cleanup['declaration'] @@ -41,7 +41,19 @@ class InfoTemplate(Template): def render(self): - return Template( + templates = [] + + initializers = self.module.initializers + if len(initializers) == 0: + initializers = [ None ] + + for initializer in initializers: + name = self.module.clean_name() + if initializer and initializer['short_name'].startswith('initialize_'): + variant = initializer['short_name'][len('initialize_'):] + name += " (%s)" % variant.replace('_', ' ') + + template = Template( r""" { "${clean_name}", @@ -49,14 +61,17 @@ ${cleanup}, ${cb_ptr}, ${cb_count}, ${enabled} }""" - ).substitute( - clean_name = self.module.clean_name(), - initialize = self._render_callback(self.module.initialize), - cleanup = self._render_callback(self.module.cleanup), - cb_ptr = "_clar_cb_%s" % self.module.name, - cb_count = len(self.module.callbacks), - enabled = int(self.module.enabled) - ) + ).substitute( + clean_name = name, + initialize = self._render_callback(initializer), + cleanup = self._render_callback(self.module.cleanup), + cb_ptr = "_clar_cb_%s" % self.module.name, + cb_count = len(self.module.callbacks), + enabled = int(self.module.enabled) + ) + templates.append(template) + + return ','.join(templates) def __init__(self, name): self.name = name @@ -86,7 +101,7 @@ regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE) self.callbacks = [] - self.initialize = None + self.initializers = [] self.cleanup = None for (declaration, symbol, short_name) in regex.findall(contents): @@ -96,8 +111,8 @@ "symbol" : symbol } - if short_name == 'initialize': - self.initialize = data + if short_name.startswith('initialize'): + self.initializers.append(data) elif short_name == 'cleanup': self.cleanup = data else: @@ -195,7 +210,7 @@ module.modified = True def suite_count(self): - return len(self.modules) + return sum(max(1, len(m.initializers)) for m in self.modules.values()) def callback_count(self): return sum(len(module.callbacks) for module in self.modules.values()) diff -Nru libgit2-0.28.5+dfsg.1/tests/graph/ahead_behind.c libgit2-1.1.0+dfsg.1/tests/graph/ahead_behind.c --- libgit2-0.28.5+dfsg.1/tests/graph/ahead_behind.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/graph/ahead_behind.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,58 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; +static git_commit *commit; +static size_t ahead; +static size_t behind; + +void test_graph_ahead_behind__initialize(void) +{ + git_oid oid; + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + + cl_git_pass(git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); +} + +void test_graph_ahead_behind__cleanup(void) +{ + git_commit_free(commit); + commit = NULL; + + git_repository_free(_repo); + _repo = NULL; +} + +void test_graph_ahead_behind__returns_correct_result(void) +{ + git_oid oid; + git_oid oid2; + git_commit *other; + + cl_git_pass(git_oid_fromstr(&oid, "e90810b8df3e80c413d903f631643c716887138d")); + cl_git_pass(git_oid_fromstr(&oid2, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &oid, &oid2)); + cl_assert_equal_sz(2, ahead); + cl_assert_equal_sz(6, behind); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, git_commit_id(commit), git_commit_id(commit))); + cl_assert_equal_sz(ahead, behind); + cl_git_pass(git_commit_nth_gen_ancestor(&other, commit, 1)); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, git_commit_id(commit), git_commit_id(other))); + cl_assert_equal_sz(ahead, behind + 2); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, git_commit_id(other), git_commit_id(commit))); + cl_assert_equal_sz(ahead + 2, behind); + + git_commit_free(other); + + cl_git_pass(git_commit_nth_gen_ancestor(&other, commit, 3)); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, git_commit_id(commit), git_commit_id(other))); + cl_assert_equal_sz(ahead, behind + 4); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, git_commit_id(other), git_commit_id(commit))); + cl_assert_equal_sz(ahead + 4, behind); + + git_commit_free(other); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/ignore/path.c libgit2-1.1.0+dfsg.1/tests/ignore/path.c --- libgit2-0.28.5+dfsg.1/tests/ignore/path.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/ignore/path.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,577 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "futils.h" + +static git_repository *g_repo = NULL; + +void test_ignore_path__initialize(void) +{ + g_repo = cl_git_sandbox_init("attr"); +} + +void test_ignore_path__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static void assert_is_ignored_( + bool expected, const char *filepath, + const char *file, const char *func, int line) +{ + int is_ignored = 0; + + cl_git_expect( + git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), 0, file, func, line); + + clar__assert_equal( + file, func, line, "expected != is_ignored", 1, "%d", + (int)(expected != 0), (int)(is_ignored != 0)); +} +#define assert_is_ignored(expected, filepath) \ + assert_is_ignored_(expected, filepath, __FILE__, __func__, __LINE__) + +void test_ignore_path__honor_temporary_rules(void) +{ + cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_ignore_path__allow_root(void) +{ + cl_git_rewritefile("attr/.gitignore", "/"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(false, "NewFolder"); + assert_is_ignored(false, "NewFolder/NewFolder"); + assert_is_ignored(false, "NewFolder/NewFolder/File.txt"); +} + +void test_ignore_path__ignore_space(void) +{ + cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder \n/NewFolder/NewFolder"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_ignore_path__intermittent_space(void) +{ + cl_git_rewritefile("attr/.gitignore", "foo bar\n"); + + assert_is_ignored(false, "foo"); + assert_is_ignored(false, "bar"); + assert_is_ignored(true, "foo bar"); +} + +void test_ignore_path__trailing_space(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "foo \n" + "bar \n" + ); + + assert_is_ignored(true, "foo"); + assert_is_ignored(false, "foo "); + assert_is_ignored(true, "bar"); + assert_is_ignored(false, "bar "); + assert_is_ignored(false, "bar "); +} + +void test_ignore_path__escaped_trailing_spaces(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "foo\\ \n" + "bar\\ \\ \n" + "baz \\ \n" + "qux\\ \n" + ); + + assert_is_ignored(false, "foo"); + assert_is_ignored(true, "foo "); + assert_is_ignored(false, "bar"); + assert_is_ignored(false, "bar "); + assert_is_ignored(true, "bar "); + assert_is_ignored(true, "baz "); + assert_is_ignored(false, "baz "); + assert_is_ignored(true, "qux "); + assert_is_ignored(false, "qux"); + assert_is_ignored(false, "qux "); +} + +void test_ignore_path__ignore_dir(void) +{ + cl_git_rewritefile("attr/.gitignore", "dir/\n"); + + assert_is_ignored(true, "dir"); + assert_is_ignored(true, "dir/file"); +} + +void test_ignore_path__ignore_dir_with_trailing_space(void) +{ + cl_git_rewritefile("attr/.gitignore", "dir/ \n"); + + assert_is_ignored(true, "dir"); + assert_is_ignored(true, "dir/file"); +} + +void test_ignore_path__ignore_root(void) +{ + cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_ignore_path__full_paths(void) +{ + cl_git_rewritefile("attr/.gitignore", "Folder/*/Contained"); + + assert_is_ignored(true, "Folder/Middle/Contained"); + assert_is_ignored(false, "Folder/Middle/More/More/Contained"); + + cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained"); + + assert_is_ignored(true, "Folder/Middle/Contained"); + assert_is_ignored(true, "Folder/Middle/More/More/Contained"); + + cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained/*/Child"); + + assert_is_ignored(true, "Folder/Middle/Contained/Happy/Child"); + assert_is_ignored(false, "Folder/Middle/Contained/Not/Happy/Child"); + assert_is_ignored(true, "Folder/Middle/More/More/Contained/Happy/Child"); + assert_is_ignored(false, "Folder/Middle/More/More/Contained/Not/Happy/Child"); +} + +void test_ignore_path__more_starstar_cases(void) +{ + cl_must_pass(p_unlink("attr/.gitignore")); + cl_git_mkfile( + "attr/dir/.gitignore", + "sub/**/*.html\n"); + + assert_is_ignored(false, "aaa.html"); + assert_is_ignored(false, "dir"); + assert_is_ignored(false, "dir/sub"); + assert_is_ignored(true, "dir/sub/sub2/aaa.html"); + assert_is_ignored(true, "dir/sub/aaa.html"); + assert_is_ignored(false, "dir/aaa.html"); + assert_is_ignored(false, "sub"); + assert_is_ignored(false, "sub/aaa.html"); + assert_is_ignored(false, "sub/sub2/aaa.html"); +} + +void test_ignore_path__leading_stars(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "*/onestar\n" + "**/twostars\n" + "*/parent1/kid1/*\n" + "**/parent2/kid2/*\n"); + + assert_is_ignored(true, "dir1/onestar"); + assert_is_ignored(true, "dir1/onestar/child"); /* in ignored dir */ + assert_is_ignored(false, "dir1/dir2/onestar"); + + assert_is_ignored(true, "dir1/twostars"); + assert_is_ignored(true, "dir1/twostars/child"); /* in ignored dir */ + assert_is_ignored(true, "dir1/dir2/twostars"); + assert_is_ignored(true, "dir1/dir2/twostars/child"); /* in ignored dir */ + assert_is_ignored(true, "dir1/dir2/dir3/twostars"); + + assert_is_ignored(true, "dir1/parent1/kid1/file"); + assert_is_ignored(true, "dir1/parent1/kid1/file/inside/parent"); + assert_is_ignored(false, "dir1/dir2/parent1/kid1/file"); + assert_is_ignored(false, "dir1/parent1/file"); + assert_is_ignored(false, "dir1/kid1/file"); + + assert_is_ignored(true, "dir1/parent2/kid2/file"); + assert_is_ignored(true, "dir1/parent2/kid2/file/inside/parent"); + assert_is_ignored(true, "dir1/dir2/parent2/kid2/file"); + assert_is_ignored(true, "dir1/dir2/dir3/parent2/kid2/file"); + assert_is_ignored(false, "dir1/parent2/file"); + assert_is_ignored(false, "dir1/kid2/file"); +} + +void test_ignore_path__globs_and_path_delimiters(void) +{ + cl_git_rewritefile("attr/.gitignore", "foo/bar/**"); + assert_is_ignored(true, "foo/bar/baz"); + assert_is_ignored(true, "foo/bar/baz/quux"); + + cl_git_rewritefile("attr/.gitignore", "_*/"); + assert_is_ignored(true, "sub/_test/a/file"); + assert_is_ignored(false, "test_folder/file"); + assert_is_ignored(true, "_test/file"); + assert_is_ignored(true, "_test/a/file"); + + cl_git_rewritefile("attr/.gitignore", "**/_*/"); + assert_is_ignored(true, "sub/_test/a/file"); + assert_is_ignored(false, "test_folder/file"); + assert_is_ignored(true, "_test/file"); + assert_is_ignored(true, "_test/a/file"); + + cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux"); + + assert_is_ignored(true, "sub/_test/foo/bar/qux/file"); + assert_is_ignored(true, "_test/foo/bar/qux/file"); + assert_is_ignored(true, "_test/foo/bar/crux/file"); + assert_is_ignored(false, "_test/foo/bar/code/file"); +} + +void test_ignore_path__globs_without_star(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "*.foo\n" + "**.bar\n" + ); + + assert_is_ignored(true, ".foo"); + assert_is_ignored(true, "xyz.foo"); + assert_is_ignored(true, ".bar"); + assert_is_ignored(true, "x.bar"); + assert_is_ignored(true, "xyz.bar"); + + assert_is_ignored(true, "test/.foo"); + assert_is_ignored(true, "test/x.foo"); + assert_is_ignored(true, "test/xyz.foo"); + assert_is_ignored(true, "test/.bar"); + assert_is_ignored(true, "test/x.bar"); + assert_is_ignored(true, "test/xyz.bar"); +} + +void test_ignore_path__skip_gitignore_directory(void) +{ + cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder"); + cl_must_pass(p_unlink("attr/.gitignore")); + cl_assert(!git_path_exists("attr/.gitignore")); + p_mkdir("attr/.gitignore", 0777); + cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_ignore_path__subdirectory_gitignore(void) +{ + cl_must_pass(p_unlink("attr/.gitignore")); + cl_assert(!git_path_exists("attr/.gitignore")); + cl_git_mkfile( + "attr/.gitignore", + "file1\n"); + cl_git_mkfile( + "attr/dir/.gitignore", + "file2/\n"); + + assert_is_ignored(true, "file1"); + assert_is_ignored(true, "dir/file1"); + assert_is_ignored(true, "dir/file2/actual_file"); /* in ignored dir */ + assert_is_ignored(false, "dir/file3"); +} + +void test_ignore_path__expand_tilde_to_homedir(void) +{ + git_config *cfg; + + assert_is_ignored(false, "example.global_with_tilde"); + + cl_fake_home(); + + /* construct fake home with fake global excludes */ + cl_git_mkfile("home/globalexclude", "# found me\n*.global_with_tilde\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexclude")); + git_config_free(cfg); + + git_attr_cache_flush(g_repo); /* must reset to pick up change */ + + assert_is_ignored(true, "example.global_with_tilde"); + + cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_fake_home_cleanup(NULL); + + git_attr_cache_flush(g_repo); /* must reset to pick up change */ + + assert_is_ignored(false, "example.global_with_tilde"); +} + +/* Ensure that the .gitignore in the subdirectory only affects + * items in the subdirectory. */ +void test_ignore_path__gitignore_in_subdir(void) +{ + cl_git_rmfile("attr/.gitignore"); + + cl_must_pass(p_mkdir("attr/dir1", 0777)); + cl_must_pass(p_mkdir("attr/dir1/dir2", 0777)); + cl_must_pass(p_mkdir("attr/dir1/dir2/dir3", 0777)); + + cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "dir1/\ndir1/subdir/"); + + assert_is_ignored(false, "dir1/file"); + assert_is_ignored(false, "dir1/dir2/file"); + assert_is_ignored(false, "dir1/dir2/dir3/file"); + assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); + assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); + + if (cl_repo_get_bool(g_repo, "core.ignorecase")) { + cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "DiR1/\nDiR1/subdir/\n"); + + assert_is_ignored(false, "dir1/file"); + assert_is_ignored(false, "dir1/dir2/file"); + assert_is_ignored(false, "dir1/dir2/dir3/file"); + assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); + assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); + } +} + +/* Ensure that files do not match folder cases */ +void test_ignore_path__dont_ignore_files_for_folder(void) +{ + cl_git_rmfile("attr/.gitignore"); + + cl_git_mkfile("attr/dir/.gitignore", "test/\n"); + + /* Create "test" as a file; ensure it is not ignored. */ + cl_git_mkfile("attr/dir/test", "This is a file."); + + assert_is_ignored(false, "dir/test"); + if (cl_repo_get_bool(g_repo, "core.ignorecase")) + assert_is_ignored(false, "dir/TeSt"); + + /* Create "test" as a directory; ensure it is ignored. */ + cl_git_rmfile("attr/dir/test"); + cl_must_pass(p_mkdir("attr/dir/test", 0777)); + + assert_is_ignored(true, "dir/test"); + if (cl_repo_get_bool(g_repo, "core.ignorecase")) + assert_is_ignored(true, "dir/TeSt"); + + /* Remove "test" entirely; ensure it is not ignored. + * (As it doesn't exist, it is not a directory.) + */ + cl_must_pass(p_rmdir("attr/dir/test")); + + assert_is_ignored(false, "dir/test"); + if (cl_repo_get_bool(g_repo, "core.ignorecase")) + assert_is_ignored(false, "dir/TeSt"); +} + +void test_ignore_path__symlink_to_outside(void) +{ +#ifdef GIT_WIN32 + cl_skip(); +#endif + + cl_git_rewritefile("attr/.gitignore", "symlink\n"); + cl_git_mkfile("target", "target"); + cl_git_pass(p_symlink("../target", "attr/symlink")); + assert_is_ignored(true, "symlink"); + assert_is_ignored(true, "lala/../symlink"); +} + +void test_ignore_path__test(void) +{ + cl_git_rewritefile("attr/.gitignore", + "/*/\n" + "!/src\n"); + assert_is_ignored(false, "src/foo.c"); + assert_is_ignored(false, "src/foo/foo.c"); + assert_is_ignored(false, "README.md"); + assert_is_ignored(true, "dist/foo.o"); + assert_is_ignored(true, "bin/foo"); +} + +void test_ignore_path__unignore_dir_succeeds(void) +{ + cl_git_rewritefile("attr/.gitignore", + "*.c\n" + "!src/*.c\n"); + assert_is_ignored(false, "src/foo.c"); + assert_is_ignored(true, "src/foo/foo.c"); +} + +void test_ignore_path__case_insensitive_unignores_previous_rule(void) +{ + git_config *cfg; + + cl_git_rewritefile("attr/.gitignore", + "/case\n" + "!/Case/\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", true)); + + cl_must_pass(p_mkdir("attr/case", 0755)); + cl_git_mkfile("attr/case/file", "content"); + + assert_is_ignored(false, "case/file"); +} + +void test_ignore_path__case_sensitive_unignore_does_nothing(void) +{ + git_config *cfg; + + cl_git_rewritefile("attr/.gitignore", + "/case\n" + "!/Case/\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", false)); + + cl_must_pass(p_mkdir("attr/case", 0755)); + cl_git_mkfile("attr/case/file", "content"); + + assert_is_ignored(true, "case/file"); +} + +void test_ignore_path__ignored_subdirfiles_with_subdir_rule(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "dir/*\n" + "!dir/sub1/sub2/**\n"); + + assert_is_ignored(true, "dir/a.test"); + assert_is_ignored(true, "dir/sub1/a.test"); + assert_is_ignored(true, "dir/sub1/sub2"); +} + +void test_ignore_path__ignored_subdirfiles_with_negations(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "dir/*\n" + "!dir/a.test\n"); + + assert_is_ignored(false, "dir/a.test"); + assert_is_ignored(true, "dir/b.test"); + assert_is_ignored(true, "dir/sub1/c.test"); +} + +void test_ignore_path__negative_directory_rules_only_match_directories(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "*\n" + "!/**/\n" + "!*.keep\n" + "!.gitignore\n" + ); + + assert_is_ignored(true, "src"); + assert_is_ignored(true, "src/A"); + assert_is_ignored(false, "src/"); + assert_is_ignored(false, "src/A.keep"); + assert_is_ignored(false, ".gitignore"); +} + +void test_ignore_path__escaped_character(void) +{ + cl_git_rewritefile("attr/.gitignore", "\\c\n"); + assert_is_ignored(true, "c"); + assert_is_ignored(false, "\\c"); +} + +void test_ignore_path__escaped_newline(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "\\\nnewline\n" + ); + + assert_is_ignored(true, "\nnewline"); +} + +void test_ignore_path__escaped_glob(void) +{ + cl_git_rewritefile("attr/.gitignore", "\\*\n"); + assert_is_ignored(true, "*"); + assert_is_ignored(false, "foo"); +} + +void test_ignore_path__escaped_comments(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "#foo\n" + "\\#bar\n" + "\\##baz\n" + "\\#\\\\#qux\n" + ); + + assert_is_ignored(false, "#foo"); + assert_is_ignored(true, "#bar"); + assert_is_ignored(false, "\\#bar"); + assert_is_ignored(true, "##baz"); + assert_is_ignored(false, "\\##baz"); + assert_is_ignored(true, "#\\#qux"); + assert_is_ignored(false, "##qux"); + assert_is_ignored(false, "\\##qux"); +} + +void test_ignore_path__escaped_slash(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "\\\\\n" + "\\\\preceding\n" + "inter\\\\mittent\n" + "trailing\\\\\n" + ); + +#ifndef GIT_WIN32 + assert_is_ignored(true, "\\"); + assert_is_ignored(true, "\\preceding"); +#endif + assert_is_ignored(true, "inter\\mittent"); + assert_is_ignored(true, "trailing\\"); +} + +void test_ignore_path__escaped_space(void) +{ + cl_git_rewritefile( + "attr/.gitignore", + "foo\\\\ \n" + "bar\\\\\\ \n"); + assert_is_ignored(true, "foo\\"); + assert_is_ignored(false, "foo\\ "); + assert_is_ignored(false, "foo\\\\ "); + assert_is_ignored(false, "foo\\\\"); + assert_is_ignored(true, "bar\\ "); + assert_is_ignored(false, "bar\\\\"); + assert_is_ignored(false, "bar\\\\ "); + assert_is_ignored(false, "bar\\\\\\"); + assert_is_ignored(false, "bar\\\\\\ "); +} + +void test_ignore_path__invalid_pattern(void) +{ + cl_git_rewritefile("attr/.gitignore", "["); + assert_is_ignored(false, "[f"); + assert_is_ignored(false, "f"); +} + +void test_ignore_path__negative_prefix_rule(void) +{ + cl_git_rewritefile("attr/.gitignore", "ff*\n!f\n"); + assert_is_ignored(true, "fff"); + assert_is_ignored(true, "ff"); + assert_is_ignored(false, "f"); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/ignore/status.c libgit2-1.1.0+dfsg.1/tests/ignore/status.c --- libgit2-0.28.5+dfsg.1/tests/ignore/status.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/ignore/status.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,1337 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "git2/attr.h" +#include "ignore.h" +#include "attr.h" +#include "status/status_helpers.h" + +static git_repository *g_repo = NULL; + +void test_ignore_status__initialize(void) +{ +} + +void test_ignore_status__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void assert_ignored_( + bool expected, const char *filepath, + const char *file, const char *func, int line) +{ + int is_ignored = 0; + cl_git_expect( + git_status_should_ignore(&is_ignored, g_repo, filepath), 0, file, func, line); + clar__assert( + (expected != 0) == (is_ignored != 0), + file, func, line, "expected != is_ignored", filepath, 1); +} +#define assert_ignored(expected, filepath) \ + assert_ignored_(expected, filepath, __FILE__, __func__, __LINE__) +#define assert_is_ignored(filepath) \ + assert_ignored_(true, filepath, __FILE__, __func__, __LINE__) +#define refute_is_ignored(filepath) \ + assert_ignored_(false, filepath, __FILE__, __func__, __LINE__) + +void test_ignore_status__0(void) +{ + struct { + const char *path; + int expected; + } test_cases[] = { + /* pattern "ign" from .gitignore */ + { "file", 0 }, + { "ign", 1 }, + { "sub", 0 }, + { "sub/file", 0 }, + { "sub/ign", 1 }, + { "sub/ign/file", 1 }, + { "sub/ign/sub", 1 }, + { "sub/ign/sub/file", 1 }, + { "sub/sub", 0 }, + { "sub/sub/file", 0 }, + { "sub/sub/ign", 1 }, + { "sub/sub/sub", 0 }, + /* pattern "dir/" from .gitignore */ + { "dir", 1 }, + { "dir/", 1 }, + { "sub/dir", 1 }, + { "sub/dir/", 1 }, + { "sub/dir/file", 1 }, /* contained in ignored parent */ + { "sub/sub/dir", 0 }, /* dir is not actually a dir, but a file */ + { NULL, 0 } + }, *one_test; + + g_repo = cl_git_sandbox_init("attr"); + + for (one_test = test_cases; one_test->path != NULL; one_test++) + assert_ignored(one_test->expected, one_test->path); + + /* confirm that ignore files were cached */ + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/exclude")); + cl_assert(git_attr_cache__is_cached( + g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitignore")); +} + + +void test_ignore_status__1(void) +{ + g_repo = cl_git_sandbox_init("attr"); + + cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n"); + git_attr_cache_flush(g_repo); + + assert_is_ignored("root_test4.txt"); + refute_is_ignored("sub/subdir_test2.txt"); + assert_is_ignored("dir"); + assert_is_ignored("dir/"); + refute_is_ignored("sub/dir"); + refute_is_ignored("sub/dir/"); +} + +void test_ignore_status__empty_repo_with_gitignore_rewrite(void) +{ + status_entry_single st; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/look-ma.txt", "I'm going to be ignored!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 1); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + refute_is_ignored("look-ma.txt"); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 2); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + refute_is_ignored("look-ma.txt"); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 2); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + assert_is_ignored("look-ma.txt"); +} + +void test_ignore_status__ignore_pattern_contains_space(void) +{ + unsigned int flags; + const mode_t mode = 0777; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n"); + + cl_git_mkfile( + "empty_standard_repo/foo bar.txt", "I'm going to be ignored!"); + + cl_git_pass(git_status_file(&flags, g_repo, "foo bar.txt")); + cl_assert(flags == GIT_STATUS_IGNORED); + + cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", mode)); + cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!"); + + cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt")); + cl_assert(flags == GIT_STATUS_WT_NEW); +} + +void test_ignore_status__ignore_pattern_ignorecase(void) +{ + unsigned int flags; + bool ignore_case; + git_index *index; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_rewritefile("empty_standard_repo/.gitignore", "a.txt\n"); + + cl_git_mkfile("empty_standard_repo/A.txt", "Differs in case"); + + cl_git_pass(git_repository_index(&index, g_repo)); + ignore_case = (git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0; + git_index_free(index); + + cl_git_pass(git_status_file(&flags, g_repo, "A.txt")); + cl_assert(flags == ignore_case ? GIT_STATUS_IGNORED : GIT_STATUS_WT_NEW); +} + +void test_ignore_status__subdirectories(void) +{ + status_entry_single st; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/ignore_me", "I'm going to be ignored!"); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert_equal_i(2, st.count); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + assert_is_ignored("ignore_me"); + + /* I've changed libgit2 so that the behavior here now differs from + * core git but seems to make more sense. In core git, the following + * items are skipped completed, even if --ignored is passed to status. + * It you mirror these steps and run "git status -uall --ignored" then + * you will not see "test/ignore_me/" in the results. + * + * However, we had a couple reports of this as a bug, plus there is a + * similar circumstance where we were differing for core git when you + * used a rooted path for an ignore, so I changed this behavior. + */ + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/test/ignore_me", 0775)); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file2", "Me, too!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert_equal_i(3, st.count); + + cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + assert_is_ignored("test/ignore_me/file"); +} + +static void make_test_data(const char *reponame, const char **files) +{ + const char **scan; + size_t repolen = strlen(reponame) + 1; + + g_repo = cl_git_sandbox_init(reponame); + + for (scan = files; *scan != NULL; ++scan) { + cl_git_pass(git_futils_mkdir_relative( + *scan + repolen, reponame, + 0777, GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST, NULL)); + cl_git_mkfile(*scan, "contents"); + } +} + +static const char *test_repo_1 = "empty_standard_repo"; +static const char *test_files_1[] = { + "empty_standard_repo/dir/a/ignore_me", + "empty_standard_repo/dir/b/ignore_me", + "empty_standard_repo/dir/ignore_me", + "empty_standard_repo/ignore_also/file", + "empty_standard_repo/ignore_me", + "empty_standard_repo/test/ignore_me/file", + "empty_standard_repo/test/ignore_me/file2", + "empty_standard_repo/test/ignore_me/and_me/file", + NULL +}; + +void test_ignore_status__subdirectories_recursion(void) +{ + /* Let's try again with recursing into ignored dirs turned on */ + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths_r[] = { + ".gitignore", + "dir/a/ignore_me", + "dir/b/ignore_me", + "dir/ignore_me", + "ignore_also/file", + "ignore_me", + "test/ignore_me/and_me/file", + "test/ignore_me/file", + "test/ignore_me/file2", + }; + static const unsigned int statuses_r[] = { + GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + }; + static const char *paths_nr[] = { + ".gitignore", + "dir/a/ignore_me", + "dir/b/ignore_me", + "dir/ignore_me", + "ignore_also/", + "ignore_me", + "test/ignore_me/", + }; + static const unsigned int statuses_nr[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + }; + + make_test_data(test_repo_1, test_files_1); + cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n/ignore_also\n"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 9; + counts.expected_paths = paths_r; + counts.expected_statuses = statuses_r; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 7; + counts.expected_paths = paths_nr; + counts.expected_statuses = statuses_nr; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_ignore_status__subdirectories_not_at_root(void) +{ + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths_1[] = { + "dir/.gitignore", + "dir/a/ignore_me", + "dir/b/ignore_me", + "dir/ignore_me", + "ignore_also/file", + "ignore_me", + "test/.gitignore", + "test/ignore_me/and_me/file", + "test/ignore_me/file", + "test/ignore_me/file2", + }; + static const unsigned int statuses_1[] = { + GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, + }; + + make_test_data(test_repo_1, test_files_1); + cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "ignore_me\n/ignore_also\n"); + cl_git_rewritefile("empty_standard_repo/test/.gitignore", "and_me\n"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 10; + counts.expected_paths = paths_1; + counts.expected_statuses = statuses_1; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_ignore_status__leading_slash_ignores(void) +{ + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths_2[] = { + "dir/.gitignore", + "dir/a/ignore_me", + "dir/b/ignore_me", + "dir/ignore_me", + "ignore_also/file", + "ignore_me", + "test/.gitignore", + "test/ignore_me/and_me/file", + "test/ignore_me/file", + "test/ignore_me/file2", + }; + static const unsigned int statuses_2[] = { + GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, + GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, + }; + + make_test_data(test_repo_1, test_files_1); + + cl_fake_home(); + cl_git_mkfile("home/.gitignore", "/ignore_me\n"); + { + git_config *cfg; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string( + cfg, "core.excludesfile", "~/.gitignore")); + git_config_free(cfg); + } + + cl_git_rewritefile("empty_standard_repo/.git/info/exclude", "/ignore_also\n"); + cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "/ignore_me\n"); + cl_git_rewritefile("empty_standard_repo/test/.gitignore", "/and_me\n"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 10; + counts.expected_paths = paths_2; + counts.expected_statuses = statuses_2; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_ignore_status__multiple_leading_slash(void) +{ + static const char *test_files[] = { + "empty_standard_repo/a.test", + "empty_standard_repo/b.test", + "empty_standard_repo/c.test", + "empty_standard_repo/d.test", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "a.test\n" + "/b.test\n" + "//c.test\n" + "///d.test\n"); + + assert_is_ignored("a.test"); + assert_is_ignored("b.test"); + refute_is_ignored("c.test"); + refute_is_ignored("d.test"); +} + +void test_ignore_status__contained_dir_with_matching_name(void) +{ + static const char *test_files[] = { + "empty_standard_repo/subdir_match/aaa/subdir_match/file", + "empty_standard_repo/subdir_match/zzz_ignoreme", + NULL + }; + static const char *expected_paths[] = { + "subdir_match/.gitignore", + "subdir_match/aaa/subdir_match/file", + "subdir_match/zzz_ignoreme", + }; + static const unsigned int expected_statuses[] = { + GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED + }; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/subdir_match/.gitignore", "*_ignoreme\n"); + + refute_is_ignored("subdir_match/aaa/subdir_match/file"); + assert_is_ignored("subdir_match/zzz_ignoreme"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 3; + counts.expected_paths = expected_paths; + counts.expected_statuses = expected_statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_ignore_status__trailing_slash_star(void) +{ + static const char *test_files[] = { + "empty_standard_repo/file", + "empty_standard_repo/subdir/file", + "empty_standard_repo/subdir/sub2/sub3/file", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/subdir/.gitignore", "/**/*\n"); + + refute_is_ignored("file"); + assert_is_ignored("subdir/sub2/sub3/file"); + assert_is_ignored("subdir/file"); +} + +void test_ignore_status__adding_internal_ignores(void) +{ + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + refute_is_ignored("one.txt"); + refute_is_ignored("two.bar"); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.nomatch\n")); + + refute_is_ignored("one.txt"); + refute_is_ignored("two.bar"); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.txt\n")); + + assert_is_ignored("one.txt"); + refute_is_ignored("two.bar"); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.bar\n")); + + assert_is_ignored("one.txt"); + assert_is_ignored("two.bar"); + + cl_git_pass(git_ignore_clear_internal_rules(g_repo)); + + refute_is_ignored("one.txt"); + refute_is_ignored("two.bar"); + + cl_git_pass(git_ignore_add_rule( + g_repo, "multiple\n*.rules\n# comment line\n*.bar\n")); + + refute_is_ignored("one.txt"); + assert_is_ignored("two.bar"); +} + +void test_ignore_status__add_internal_as_first_thing(void) +{ + const char *add_me = "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_ignore_add_rule(g_repo, add_me)); + + assert_is_ignored("one.tmp"); + refute_is_ignored("two.bar"); +} + +void test_ignore_status__internal_ignores_inside_deep_paths(void) +{ + const char *add_me = "Debug\nthis/is/deep\npatterned*/dir\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_ignore_add_rule(g_repo, add_me)); + + assert_is_ignored("Debug"); + assert_is_ignored("and/Debug"); + assert_is_ignored("really/Debug/this/file"); + assert_is_ignored("Debug/what/I/say"); + + refute_is_ignored("and/NoDebug"); + refute_is_ignored("NoDebug/this"); + refute_is_ignored("please/NoDebug/this"); + + assert_is_ignored("this/is/deep"); + /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ + refute_is_ignored("and/this/is/deep"); + assert_is_ignored("this/is/deep/too"); + /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ + refute_is_ignored("but/this/is/deep/and/ignored"); + + refute_is_ignored("this/is/not/deep"); + refute_is_ignored("is/this/not/as/deep"); + refute_is_ignored("this/is/deepish"); + refute_is_ignored("xthis/is/deep"); +} + +void test_ignore_status__automatically_ignore_bad_files(void) +{ + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + assert_is_ignored(".git"); + assert_is_ignored("this/file/."); + assert_is_ignored("path/../funky"); + refute_is_ignored("path/whatever.c"); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.c\n")); + + assert_is_ignored(".git"); + assert_is_ignored("this/file/."); + assert_is_ignored("path/../funky"); + assert_is_ignored("path/whatever.c"); + + cl_git_pass(git_ignore_clear_internal_rules(g_repo)); + + assert_is_ignored(".git"); + assert_is_ignored("this/file/."); + assert_is_ignored("path/../funky"); + refute_is_ignored("path/whatever.c"); +} + +void test_ignore_status__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void) +{ + status_entry_single st; + char *test_cases[] = { + "!file", + "#blah", + "[blah]", + "[attr]", + "[attr]blah", + NULL + }; + int i; + + for (i = 0; *(test_cases + i) != NULL; i++) { + git_buf file = GIT_BUF_INIT; + char *file_name = *(test_cases + i); + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name)); + cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert(st.count == 1); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, repo, file_name)); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_sandbox_cleanup(); + git_buf_dispose(&file); + } +} + +void test_ignore_status__issue_1766_negated_ignores(void) +{ + unsigned int status; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/a", 0775)); + cl_git_mkfile( + "empty_standard_repo/a/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/a/ignoreme", "I should be ignored\n"); + + refute_is_ignored("a/.gitignore"); + assert_is_ignored("a/ignoreme"); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/b", 0775)); + cl_git_mkfile( + "empty_standard_repo/b/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/b/ignoreme", "I should be ignored\n"); + + refute_is_ignored("b/.gitignore"); + assert_is_ignored("b/ignoreme"); + + /* shouldn't have changed results from first couple either */ + refute_is_ignored("a/.gitignore"); + assert_is_ignored("a/ignoreme"); + + /* status should find the two ignore files and nothing else */ + + cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + { + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths[] = { + "a/.gitignore", + "a/ignoreme", + "b/.gitignore", + "b/ignoreme", + }; + static const unsigned int statuses[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + }; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 4; + counts.expected_paths = paths; + counts.expected_statuses = statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + } +} + +static void add_one_to_index(const char *file) +{ + git_index *index; + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, file)); + git_index_free(index); +} + +/* Some further broken scenarios that have been reported */ +void test_ignore_status__more_breakage(void) +{ + static const char *test_files[] = { + "empty_standard_repo/d1/pfx-d2/d3/d4/d5/tracked", + "empty_standard_repo/d1/pfx-d2/d3/d4/d5/untracked", + "empty_standard_repo/d1/pfx-d2/d3/d4/untracked", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "/d1/pfx-*\n" + "!/d1/pfx-d2/\n" + "/d1/pfx-d2/*\n" + "!/d1/pfx-d2/d3/\n" + "/d1/pfx-d2/d3/*\n" + "!/d1/pfx-d2/d3/d4/\n"); + add_one_to_index("d1/pfx-d2/d3/d4/d5/tracked"); + + { + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *files[] = { + ".gitignore", + "d1/pfx-d2/d3/d4/d5/tracked", + "d1/pfx-d2/d3/d4/d5/untracked", + "d1/pfx-d2/d3/d4/untracked", + }; + static const unsigned int statuses[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + }; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 4; + counts.expected_paths = files; + counts.expected_statuses = statuses; + opts.flags = GIT_STATUS_OPT_DEFAULTS | + GIT_STATUS_OPT_INCLUDE_IGNORED | + GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + } + + refute_is_ignored("d1/pfx-d2/d3/d4/d5/tracked"); + refute_is_ignored("d1/pfx-d2/d3/d4/d5/untracked"); + refute_is_ignored("d1/pfx-d2/d3/d4/untracked"); +} + +void test_ignore_status__negative_ignores_inside_ignores(void) +{ + static const char *test_files[] = { + "empty_standard_repo/top/mid/btm/tracked", + "empty_standard_repo/top/mid/btm/untracked", + "empty_standard_repo/zoo/bar", + "empty_standard_repo/zoo/foo/bar", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "top\n" + "!top/mid/btm\n" + "zoo/*\n" + "!zoo/bar\n" + "!zoo/foo/bar\n"); + add_one_to_index("top/mid/btm/tracked"); + + { + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *files[] = { + ".gitignore", "top/mid/btm/tracked", "top/mid/btm/untracked", + "zoo/bar", "zoo/foo/bar", + }; + static const unsigned int statuses[] = { + GIT_STATUS_WT_NEW, GIT_STATUS_INDEX_NEW, GIT_STATUS_IGNORED, + GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, + }; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 5; + counts.expected_paths = files; + counts.expected_statuses = statuses; + opts.flags = GIT_STATUS_OPT_DEFAULTS | + GIT_STATUS_OPT_INCLUDE_IGNORED | + GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + } + + assert_is_ignored("top/mid/btm/tracked"); + assert_is_ignored("top/mid/btm/untracked"); + refute_is_ignored("foo/bar"); +} + +void test_ignore_status__negative_ignores_in_slash_star(void) +{ + git_status_options status_opts = GIT_STATUS_OPTIONS_INIT; + git_status_list *list; + int found_look_ma = 0, found_what_about = 0; + size_t i; + static const char *test_files[] = { + "empty_standard_repo/bin/look-ma.txt", + "empty_standard_repo/bin/what-about-me.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "bin/*\n" + "!bin/w*\n"); + + assert_is_ignored("bin/look-ma.txt"); + refute_is_ignored("bin/what-about-me.txt"); + + status_opts.flags = GIT_STATUS_OPT_DEFAULTS; + cl_git_pass(git_status_list_new(&list, g_repo, &status_opts)); + for (i = 0; i < git_status_list_entrycount(list); i++) { + const git_status_entry *entry = git_status_byindex(list, i); + + if (!strcmp("bin/look-ma.txt", entry->index_to_workdir->new_file.path)) + found_look_ma = 1; + + if (!strcmp("bin/what-about-me.txt", entry->index_to_workdir->new_file.path)) + found_what_about = 1; + } + git_status_list_free(list); + + cl_assert(found_look_ma); + cl_assert(found_what_about); +} + +void test_ignore_status__negative_ignores_without_trailing_slash_inside_ignores(void) +{ + git_status_options status_opts = GIT_STATUS_OPTIONS_INIT; + git_status_list *list; + int found_parent_file = 0, found_parent_child1_file = 0, found_parent_child2_file = 0; + size_t i; + static const char *test_files[] = { + "empty_standard_repo/parent/file.txt", + "empty_standard_repo/parent/force.txt", + "empty_standard_repo/parent/child1/file.txt", + "empty_standard_repo/parent/child2/file.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "parent/*\n" + "!parent/force.txt\n" + "!parent/child1\n" + "!parent/child2/\n"); + + add_one_to_index("parent/force.txt"); + + assert_is_ignored("parent/file.txt"); + refute_is_ignored("parent/force.txt"); + refute_is_ignored("parent/child1/file.txt"); + refute_is_ignored("parent/child2/file.txt"); + + status_opts.flags = GIT_STATUS_OPT_DEFAULTS; + cl_git_pass(git_status_list_new(&list, g_repo, &status_opts)); + for (i = 0; i < git_status_list_entrycount(list); i++) { + const git_status_entry *entry = git_status_byindex(list, i); + + if (!entry->index_to_workdir) + continue; + + if (!strcmp("parent/file.txt", entry->index_to_workdir->new_file.path)) + found_parent_file = 1; + + if (!strcmp("parent/force.txt", entry->index_to_workdir->new_file.path)) + found_parent_file = 1; + + if (!strcmp("parent/child1/file.txt", entry->index_to_workdir->new_file.path)) + found_parent_child1_file = 1; + + if (!strcmp("parent/child2/file.txt", entry->index_to_workdir->new_file.path)) + found_parent_child2_file = 1; + } + git_status_list_free(list); + + cl_assert(found_parent_file); + cl_assert(found_parent_child1_file); + cl_assert(found_parent_child2_file); +} + +void test_ignore_status__negative_directory_ignores(void) +{ + static const char *test_files[] = { + "empty_standard_repo/parent/child1/bar.txt", + "empty_standard_repo/parent/child2/bar.txt", + "empty_standard_repo/parent/child3/foo.txt", + "empty_standard_repo/parent/child4/bar.txt", + "empty_standard_repo/parent/nested/child5/bar.txt", + "empty_standard_repo/parent/nested/child6/bar.txt", + "empty_standard_repo/parent/nested/child7/bar.txt", + "empty_standard_repo/padded_parent/child8/bar.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "foo.txt\n" + "parent/child1\n" + "parent/child2\n" + "parent/child4\n" + "parent/nested/child5\n" + "nested/child6\n" + "nested/child7\n" + "padded_parent/child8\n" + /* test simple exact match */ + "!parent/child1\n" + /* test negating file without negating dir */ + "!parent/child2/bar.txt\n" + /* test negative pattern on dir with its content + * being ignored */ + "!parent/child3\n" + /* test with partial match at end */ + "!child4\n" + /* test with partial match with '/' at end */ + "!nested/child5\n" + /* test with complete match */ + "!nested/child6\n" + /* test with trailing '/' */ + "!child7/\n" + /* test with partial dir match */ + "!_parent/child8\n"); + + refute_is_ignored("parent/child1/bar.txt"); + assert_is_ignored("parent/child2/bar.txt"); + assert_is_ignored("parent/child3/foo.txt"); + refute_is_ignored("parent/child4/bar.txt"); + assert_is_ignored("parent/nested/child5/bar.txt"); + refute_is_ignored("parent/nested/child6/bar.txt"); + refute_is_ignored("parent/nested/child7/bar.txt"); + assert_is_ignored("padded_parent/child8/bar.txt"); +} + +void test_ignore_status__unignore_entry_in_ignored_dir(void) +{ + static const char *test_files[] = { + "empty_standard_repo/bar.txt", + "empty_standard_repo/parent/bar.txt", + "empty_standard_repo/parent/child/bar.txt", + "empty_standard_repo/nested/parent/child/bar.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "bar.txt\n" + "!parent/child/bar.txt\n"); + + assert_is_ignored("bar.txt"); + assert_is_ignored("parent/bar.txt"); + refute_is_ignored("parent/child/bar.txt"); + assert_is_ignored("nested/parent/child/bar.txt"); +} + +void test_ignore_status__do_not_unignore_basename_prefix(void) +{ + static const char *test_files[] = { + "empty_standard_repo/foo_bar.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "foo_bar.txt\n" + "!bar.txt\n"); + + assert_is_ignored("foo_bar.txt"); +} + +void test_ignore_status__filename_with_cr(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\r\n"); + + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); + cl_assert_equal_i(1, ignored); + + cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\n"); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn")); + cl_assert_equal_i(1, ignored); + + cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\n"); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn")); + cl_assert_equal_i(1, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r")); + cl_assert_equal_i(0, ignored); + + cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\r\n"); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r")); + cl_assert_equal_i(1, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); + cl_assert_equal_i(0, ignored); + + cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\n"); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); + cl_assert_equal_i(0, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon")); + cl_assert_equal_i(1, ignored); +} + +void test_ignore_status__subdir_doesnt_match_above(void) +{ + int ignored, icase = 0, error; + git_config *cfg; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); + error = git_config_get_bool(&icase, cfg, "core.ignorecase"); + git_config_free(cfg); + if (error == GIT_ENOTFOUND) + error = 0; + + cl_git_pass(error); + + cl_git_pass(p_mkdir("empty_standard_repo/src", 0777)); + cl_git_pass(p_mkdir("empty_standard_repo/src/src", 0777)); + cl_git_mkfile("empty_standard_repo/src/.gitignore", "src\n"); + cl_git_mkfile("empty_standard_repo/.gitignore", ""); + + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/test.txt")); + cl_assert_equal_i(0, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/src/test.txt")); + cl_assert_equal_i(1, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/foo/test.txt")); + cl_assert_equal_i(0, ignored); + + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "SRC/src/test.txt")); + cl_assert_equal_i(icase, ignored); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/SRC/test.txt")); + cl_assert_equal_i(icase, ignored); +} + +void test_ignore_status__negate_exact_previous(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile("empty_standard_repo/.gitignore", "*.com\ntags\n!tags/\n.buildpath"); + cl_git_mkfile("empty_standard_repo/.buildpath", ""); + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, ".buildpath")); + cl_assert_equal_i(1, ignored); +} + +void test_ignore_status__negate_starstar(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile("empty_standard_repo/.gitignore", + "code/projects/**/packages/*\n" + "!code/projects/**/packages/repositories.config"); + + cl_git_pass(git_futils_mkdir_r("empty_standard_repo/code/projects/foo/bar/packages", 0777)); + cl_git_mkfile("empty_standard_repo/code/projects/foo/bar/packages/repositories.config", ""); + + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "code/projects/foo/bar/packages/repositories.config")); + cl_assert_equal_i(0, ignored); +} + +void test_ignore_status__ignore_all_toplevel_dirs_include_files(void) +{ + static const char *test_files[] = { + "empty_standard_repo/README.md", + "empty_standard_repo/src/main.c", + "empty_standard_repo/src/foo/foo.c", + "empty_standard_repo/dist/foo.o", + "empty_standard_repo/dist/main.o", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "/*/\n" + "!/src\n"); + + assert_is_ignored("dist/foo.o"); + assert_is_ignored("dist/main.o"); + + refute_is_ignored("README.md"); + refute_is_ignored("src/foo.c"); + refute_is_ignored("src/foo/foo.c"); +} + +void test_ignore_status__subdir_ignore_all_toplevel_dirs_include_files(void) +{ + static const char *test_files[] = { + "empty_standard_repo/project/README.md", + "empty_standard_repo/project/src/main.c", + "empty_standard_repo/project/src/foo/foo.c", + "empty_standard_repo/project/dist/foo.o", + "empty_standard_repo/project/dist/main.o", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/project/.gitignore", + "/*/\n" + "!/src\n"); + + assert_is_ignored("project/dist/foo.o"); + assert_is_ignored("project/dist/main.o"); + + refute_is_ignored("project/src/foo.c"); + refute_is_ignored("project/src/foo/foo.c"); + refute_is_ignored("project/README.md"); +} + +void test_ignore_status__subdir_ignore_everything_except_certain_files(void) +{ + static const char *test_files[] = { + "empty_standard_repo/project/README.md", + "empty_standard_repo/project/some_file", + "empty_standard_repo/project/src/main.c", + "empty_standard_repo/project/src/foo/foo.c", + "empty_standard_repo/project/dist/foo.o", + "empty_standard_repo/project/dist/main.o", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/project/.gitignore", + "/*\n" + "!/src\n" + "!README.md\n"); + + assert_is_ignored("project/some_file"); + assert_is_ignored("project/dist/foo.o"); + assert_is_ignored("project/dist/main.o"); + + refute_is_ignored("project/README.md"); + refute_is_ignored("project/src/foo.c"); + refute_is_ignored("project/src/foo/foo.c"); +} + +void test_ignore_status__deeper(void) +{ + const char *test_files[] = { + "empty_standard_repo/foo.data", + "empty_standard_repo/bar.data", + "empty_standard_repo/dont_ignore/foo.data", + "empty_standard_repo/dont_ignore/bar.data", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile("empty_standard_repo/.gitignore", + "*.data\n" + "!dont_ignore/*.data\n"); + + assert_is_ignored("foo.data"); + assert_is_ignored("bar.data"); + + refute_is_ignored("dont_ignore/foo.data"); + refute_is_ignored("dont_ignore/bar.data"); +} + +void test_ignore_status__unignored_dir_with_ignored_contents(void) +{ + static const char *test_files[] = { + "empty_standard_repo/dir/a.test", + "empty_standard_repo/dir/subdir/a.test", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "*.test\n" + "!dir/*\n"); + + refute_is_ignored("dir/a.test"); + assert_is_ignored("dir/subdir/a.test"); +} + +void test_ignore_status__unignored_subdirs(void) +{ + static const char *test_files[] = { + "empty_standard_repo/dir/a.test", + "empty_standard_repo/dir/subdir/a.test", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "dir/*\n" + "!dir/*/\n"); + + assert_is_ignored("dir/a.test"); + refute_is_ignored("dir/subdir/a.test"); +} + +void test_ignore_status__skips_bom(void) +{ + static const char *test_files[] = { + "empty_standard_repo/a.test", + "empty_standard_repo/b.test", + "empty_standard_repo/c.test", + "empty_standard_repo/foo.txt", + "empty_standard_repo/bar.txt", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + "\xEF\xBB\xBF*.test\n"); + + assert_is_ignored("a.test"); + assert_is_ignored("b.test"); + assert_is_ignored("c.test"); + refute_is_ignored("foo.txt"); + refute_is_ignored("bar.txt"); +} + +void test_ignore_status__leading_spaces_are_significant(void) +{ + static const char *test_files[] = { + "empty_standard_repo/a.test", + "empty_standard_repo/b.test", + "empty_standard_repo/c.test", + "empty_standard_repo/d.test", + NULL + }; + + make_test_data("empty_standard_repo", test_files); + cl_git_mkfile( + "empty_standard_repo/.gitignore", + " a.test\n" + "# this is a comment\n" + "b.test\n" + "\tc.test\n" + " # not a comment\n" + "d.test\n"); + + refute_is_ignored("a.test"); + assert_is_ignored(" a.test"); + refute_is_ignored("# this is a comment"); + assert_is_ignored("b.test"); + refute_is_ignored("c.test"); + assert_is_ignored("\tc.test"); + assert_is_ignored(" # not a comment"); + assert_is_ignored("d.test"); +} + +void test_ignore_status__override_nested_wildcard_unignore(void) +{ + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + const git_status_entry *status; + + cl_git_pass(git_futils_mkdir_r("empty_standard_repo/dir", 0777)); + cl_git_pass(git_futils_mkdir_r("empty_standard_repo/dir/subdir", 0777)); + cl_git_mkfile("empty_standard_repo/.gitignore", "a.test\n"); + cl_git_mkfile("empty_standard_repo/dir/.gitignore", "!*.test\n"); + cl_git_mkfile("empty_standard_repo/dir/subdir/.gitignore", "a.test\n"); + cl_git_mkfile("empty_standard_repo/dir/a.test", "pong"); + cl_git_mkfile("empty_standard_repo/dir/subdir/a.test", "pong"); + + opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + + cl_git_pass(git_status_list_new(&statuslist, repo, &opts)); + cl_assert_equal_sz(4, git_status_list_entrycount(statuslist)); + + status = git_status_byindex(statuslist, 0); + cl_assert(status != NULL); + cl_assert_equal_s(".gitignore", status->index_to_workdir->old_file.path); + cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); + + status = git_status_byindex(statuslist, 1); + cl_assert(status != NULL); + cl_assert_equal_s("dir/.gitignore", status->index_to_workdir->old_file.path); + cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); + + status = git_status_byindex(statuslist, 2); + cl_assert(status != NULL); + cl_assert_equal_s("dir/a.test", status->index_to_workdir->old_file.path); + cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); + + status = git_status_byindex(statuslist, 3); + cl_assert(status != NULL); + cl_assert_equal_s("dir/subdir/.gitignore", status->index_to_workdir->old_file.path); + cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); + + git_status_list_free(statuslist); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/index/addall.c libgit2-1.1.0+dfsg.1/tests/index/addall.c --- libgit2-0.28.5+dfsg.1/tests/index/addall.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/addall.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "../status/status_helpers.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; #define TEST_DIR "addall" @@ -75,7 +75,7 @@ git_repository *repo, size_t index_adds, size_t index_dels, size_t index_mods, size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores, - size_t conflicts, const char *file, int line) + size_t conflicts, const char *file, const char *func, int line) { index_status_counts vals; @@ -84,25 +84,25 @@ cl_git_pass(git_status_foreach(repo, index_status_cb, &vals)); clar__assert_equal( - file,line,"wrong index adds", 1, "%"PRIuZ, index_adds, vals.index_adds); + file,func,line,"wrong index adds", 1, "%"PRIuZ, index_adds, vals.index_adds); clar__assert_equal( - file,line,"wrong index dels", 1, "%"PRIuZ, index_dels, vals.index_dels); + file,func,line,"wrong index dels", 1, "%"PRIuZ, index_dels, vals.index_dels); clar__assert_equal( - file,line,"wrong index mods", 1, "%"PRIuZ, index_mods, vals.index_mods); + file,func,line,"wrong index mods", 1, "%"PRIuZ, index_mods, vals.index_mods); clar__assert_equal( - file,line,"wrong workdir adds", 1, "%"PRIuZ, wt_adds, vals.wt_adds); + file,func,line,"wrong workdir adds", 1, "%"PRIuZ, wt_adds, vals.wt_adds); clar__assert_equal( - file,line,"wrong workdir dels", 1, "%"PRIuZ, wt_dels, vals.wt_dels); + file,func,line,"wrong workdir dels", 1, "%"PRIuZ, wt_dels, vals.wt_dels); clar__assert_equal( - file,line,"wrong workdir mods", 1, "%"PRIuZ, wt_mods, vals.wt_mods); + file,func,line,"wrong workdir mods", 1, "%"PRIuZ, wt_mods, vals.wt_mods); clar__assert_equal( - file,line,"wrong ignores", 1, "%"PRIuZ, ignores, vals.ignores); + file,func,line,"wrong ignores", 1, "%"PRIuZ, ignores, vals.ignores); clar__assert_equal( - file,line,"wrong conflicts", 1, "%"PRIuZ, conflicts, vals.conflicts); + file,func,line,"wrong conflicts", 1, "%"PRIuZ, conflicts, vals.conflicts); } #define check_status(R,IA,ID,IM,WA,WD,WM,IG,C) \ - check_status_at_line(R,IA,ID,IM,WA,WD,WM,IG,C,__FILE__,__LINE__) + check_status_at_line(R,IA,ID,IM,WA,WD,WM,IG,C,__FILE__,__func__,__LINE__) static void check_stat_data(git_index *index, const char *path, bool match) { diff -Nru libgit2-0.28.5+dfsg.1/tests/index/bypath.c libgit2-1.1.0+dfsg.1/tests/index/bypath.c --- libgit2-0.28.5+dfsg.1/tests/index/bypath.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/bypath.c 2020-10-12 18:53:06.000000000 +0000 @@ -338,7 +338,7 @@ git_index_entry new_entry; int symlinks; - cl_git_pass(git_repository__cvar(&symlinks, g_repo, GIT_CVAR_SYMLINKS)); + cl_git_pass(git_repository__configmap_lookup(&symlinks, g_repo, GIT_CONFIGMAP_SYMLINKS)); if (symlinks) cl_skip(); diff -Nru libgit2-0.28.5+dfsg.1/tests/index/crlf.c libgit2-1.1.0+dfsg.1/tests/index/crlf.c --- libgit2-0.28.5+dfsg.1/tests/index/crlf.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/crlf.c 2020-10-12 18:53:06.000000000 +0000 @@ -96,7 +96,7 @@ git_buf details = GIT_BUF_INIT; git_buf_printf(&details, "filename=%s, system=%s, autocrlf=%s, safecrlf=%s, attrs={%s}", basename, cd->systype, cd->autocrlf, cd->safecrlf, cd->attrs); - clar__fail(__FILE__, __LINE__, + clar__fail(__FILE__, __func__, __LINE__, "index contents did not match expected", details.ptr, 0); git_buf_dispose(&details); } diff -Nru libgit2-0.28.5+dfsg.1/tests/index/filemodes.c libgit2-1.1.0+dfsg.1/tests/index/filemodes.c --- libgit2-0.28.5+dfsg.1/tests/index/filemodes.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/filemodes.c 2020-10-12 18:53:06.000000000 +0000 @@ -51,11 +51,11 @@ git_buf_dispose(&content); } -#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__) +#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__func__,__LINE__) static void add_and_check_mode_( git_index *index, const char *filename, unsigned int expect_mode, - const char *file, int line) + const char *file, const char *func, int line) { size_t pos; const git_index_entry *entry; @@ -63,11 +63,11 @@ cl_git_pass(git_index_add_bypath(index, filename)); clar__assert(!git_index_find(&pos, index, filename), - file, line, "Cannot find index entry", NULL, 1); + file, func, line, "Cannot find index entry", NULL, 1); entry = git_index_get_byindex(index, pos); - clar__assert_equal(file, line, "Expected mode does not match index", + clar__assert_equal(file, func, line, "Expected mode does not match index", 1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode); } @@ -153,23 +153,23 @@ git_index_free(index); } -#define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__LINE__) +#define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__func__,__LINE__) static void add_entry_and_check_mode_( git_index *index, bool from_file, git_filemode_t mode, - const char *file, int line) + const char *file, const char *func, int line) { size_t pos; const git_index_entry* entry; git_index_entry new_entry; /* If old_filename exists, we copy that to the new file, and test - * git_index_add(), otherwise create a new entry testing git_index_add_frombuffer + * git_index_add(), otherwise create a new entry testing git_index_add_from_buffer */ if (from_file) { clar__assert(!git_index_find(&pos, index, "exec_off"), - file, line, "Cannot find original index entry", NULL, 1); + file, func, line, "Cannot find original index entry", NULL, 1); entry = git_index_get_byindex(index, pos); @@ -184,21 +184,21 @@ if (from_file) { clar__assert(!git_index_add(index, &new_entry), - file, line, "Cannot add index entry", NULL, 1); + file, func, line, "Cannot add index entry", NULL, 1); } else { const char *content = "hey there\n"; - clar__assert(!git_index_add_frombuffer(index, &new_entry, content, strlen(content)), - file, line, "Cannot add index entry from buffer", NULL, 1); + clar__assert(!git_index_add_from_buffer(index, &new_entry, content, strlen(content)), + file, func, line, "Cannot add index entry from buffer", NULL, 1); } clar__assert(!git_index_find(&pos, index, "filemodes/explicit_test"), - file, line, "Cannot find new index entry", NULL, 1); + file, func, line, "Cannot find new index entry", NULL, 1); entry = git_index_get_byindex(index, pos); - clar__assert_equal(file, line, "Expected mode does not match index", + clar__assert_equal(file, func, line, "Expected mode does not match index", 1, "%07o", (unsigned int)entry->mode, (unsigned int)mode); } @@ -207,7 +207,7 @@ git_index *index; /* These tests should run and work everywhere, as the filemode is - * given explicitly to git_index_add or git_index_add_frombuffer + * given explicitly to git_index_add or git_index_add_from_buffer */ cl_repo_set_bool(g_repo, "core.filemode", false); @@ -271,7 +271,7 @@ new_entry.path = "dummy-file.txt"; new_entry.mode = GIT_FILEMODE_BLOB; - cl_git_pass(git_index_add_frombuffer(index, + cl_git_pass(git_index_add_from_buffer(index, &new_entry, content, strlen(content))); cl_assert((ret_entry = git_index_get_bypath(index, "dummy-file.txt", 0))); @@ -282,7 +282,7 @@ new_entry.path = "dummy-file.txt"; new_entry.mode = GIT_FILEMODE_BLOB_EXECUTABLE; - cl_git_pass(git_index_add_frombuffer(index, + cl_git_pass(git_index_add_from_buffer(index, &new_entry, content, strlen(content))); cl_assert((ret_entry = git_index_get_bypath(index, "dummy-file.txt", 0))); @@ -293,7 +293,7 @@ new_entry.path = "dummy-link.txt"; new_entry.mode = GIT_FILEMODE_LINK; - cl_git_pass(git_index_add_frombuffer(index, + cl_git_pass(git_index_add_from_buffer(index, &new_entry, content, strlen(content))); cl_assert((ret_entry = git_index_get_bypath(index, "dummy-link.txt", 0))); @@ -304,7 +304,7 @@ new_entry.path = "invalid_mode.txt"; new_entry.mode = GIT_FILEMODE_TREE; - cl_git_fail(git_index_add_frombuffer(index, + cl_git_fail(git_index_add_from_buffer(index, &new_entry, content, strlen(content))); cl_assert_equal_p(NULL, git_index_get_bypath(index, "invalid_mode.txt", 0)); @@ -312,7 +312,7 @@ new_entry.path = "invalid_mode.txt"; new_entry.mode = GIT_FILEMODE_COMMIT; - cl_git_fail(git_index_add_frombuffer(index, + cl_git_fail(git_index_add_from_buffer(index, &new_entry, content, strlen(content))); cl_assert_equal_p(NULL, git_index_get_bypath(index, "invalid_mode.txt", 0)); diff -Nru libgit2-0.28.5+dfsg.1/tests/index/nsec.c libgit2-1.1.0+dfsg.1/tests/index/nsec.c --- libgit2-0.28.5+dfsg.1/tests/index/nsec.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/nsec.c 2020-10-12 18:53:06.000000000 +0000 @@ -54,7 +54,7 @@ expect = try_create_file_with_nsec_timestamp(nsec_path.ptr); - p_unlink(nsec_path.ptr); + cl_must_pass(p_unlink(nsec_path.ptr)); git_buf_dispose(&nsec_path); diff -Nru libgit2-0.28.5+dfsg.1/tests/index/racy.c libgit2-1.1.0+dfsg.1/tests/index/racy.c --- libgit2-0.28.5+dfsg.1/tests/index/racy.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/racy.c 2020-10-12 18:53:06.000000000 +0000 @@ -193,7 +193,7 @@ /* Put 'C' into the index */ new_entry.path = "C"; new_entry.mode = GIT_FILEMODE_BLOB; - cl_git_pass(git_index_add_frombuffer(index, &new_entry, "hello!\n", 7)); + cl_git_pass(git_index_add_from_buffer(index, &new_entry, "hello!\n", 7)); git_index_free(index); git_buf_dispose(&path); diff -Nru libgit2-0.28.5+dfsg.1/tests/index/tests.c libgit2-1.1.0+dfsg.1/tests/index/tests.c --- libgit2-0.28.5+dfsg.1/tests/index/tests.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/tests.c 2020-10-12 18:53:06.000000000 +0000 @@ -13,7 +13,7 @@ struct test_entry { size_t index; char path[128]; - git_off_t file_size; + off64_t file_size; git_time_t mtime; }; @@ -310,7 +310,7 @@ memset(&entry, 0x0, sizeof(git_index_entry)); entry.mode = GIT_FILEMODE_BLOB; entry.path = "test.txt"; - cl_git_pass(git_index_add_frombuffer(index, &entry, + cl_git_pass(git_index_add_from_buffer(index, &entry, content, strlen(content))); /* Wow... it worked! */ @@ -352,7 +352,7 @@ /* Index is dirty after adding an entry */ entry.mode = GIT_FILEMODE_BLOB; entry.path = "test.txt"; - cl_git_pass(git_index_add_frombuffer(index, &entry, "Hi.\n", 4)); + cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); cl_assert(git_index_entrycount(index) == 1); cl_assert(git_index_is_dirty(index)); @@ -374,7 +374,7 @@ cl_assert(!git_index_is_dirty(index)); /* Index is dirty when we do an unforced read with dirty content */ - cl_git_pass(git_index_add_frombuffer(index, &entry, "Hi.\n", 4)); + cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); cl_assert(git_index_entrycount(index) == 1); cl_assert(git_index_is_dirty(index)); @@ -402,7 +402,7 @@ /* Index is dirty after adding an entry */ entry.mode = GIT_FILEMODE_BLOB; entry.path = "test.txt"; - cl_git_pass(git_index_add_frombuffer(index, &entry, "Hi.\n", 4)); + cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); cl_assert(git_index_is_dirty(index)); cl_git_pass(git_checkout_head(repo, NULL)); @@ -410,7 +410,7 @@ /* Index is dirty (again) after adding an entry */ entry.mode = GIT_FILEMODE_BLOB; entry.path = "test.txt"; - cl_git_pass(git_index_add_frombuffer(index, &entry, "Hi.\n", 4)); + cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); cl_assert(git_index_is_dirty(index)); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, 1)); @@ -455,7 +455,7 @@ memset(&entry, 0x0, sizeof(git_index_entry)); entry.mode = GIT_FILEMODE_BLOB; entry.path = "test.txt"; - cl_git_pass(git_index_add_frombuffer(index, &entry, + cl_git_pass(git_index_add_from_buffer(index, &entry, content, strlen(content))); /* Wow... it worked! */ @@ -566,8 +566,7 @@ { git_repository *repo; - p_mkdir("invalid", 0700); - + cl_must_pass(p_mkdir("invalid", 0700)); cl_git_pass(git_repository_init(&repo, "./invalid", 0)); cl_must_pass(p_mkdir("./invalid/subdir", 0777)); diff -Nru libgit2-0.28.5+dfsg.1/tests/index/version.c libgit2-1.1.0+dfsg.1/tests/index/version.c --- libgit2-0.28.5+dfsg.1/tests/index/version.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/index/version.c 2020-10-12 18:53:06.000000000 +0000 @@ -43,6 +43,7 @@ "xz", "xyzzyx" }; + git_repository *repo; git_index_entry entry; git_index *index; size_t i; @@ -55,7 +56,7 @@ memset(&entry, 0, sizeof(entry)); entry.path = paths[i]; entry.mode = GIT_FILEMODE_BLOB; - cl_git_pass(git_index_add_frombuffer(index, &entry, paths[i], + cl_git_pass(git_index_add_from_buffer(index, &entry, paths[i], strlen(paths[i]) + 1)); } cl_assert_equal_sz(git_index_entrycount(index), ARRAY_SIZE(paths)); @@ -63,7 +64,8 @@ cl_git_pass(git_index_write(index)); git_index_free(index); - cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_repository_open(&repo, git_repository_path(g_repo))); + cl_git_pass(git_repository_index(&index, repo)); cl_assert(git_index_version(index) == 4); for (i = 0; i < ARRAY_SIZE(paths); i++) { @@ -74,6 +76,7 @@ } git_index_free(index); + git_repository_free(repo); } void test_index_version__v4_uses_path_compression(void) @@ -100,7 +103,7 @@ path[ARRAY_SIZE(path) - 3] = i; path[ARRAY_SIZE(path) - 2] = j; path[ARRAY_SIZE(path) - 1] = '\0'; - cl_git_pass(git_index_add_frombuffer(index, &entry, buf, sizeof(buf))); + cl_git_pass(git_index_add_from_buffer(index, &entry, buf, sizeof(buf))); } } diff -Nru libgit2-0.28.5+dfsg.1/tests/iterator/index.c libgit2-1.1.0+dfsg.1/tests/iterator/index.c --- libgit2-0.28.5+dfsg.1/tests/iterator/index.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/iterator/index.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "iterator.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "iterator_helpers.h" #include "../submodule/submodule_helpers.h" #include diff -Nru libgit2-0.28.5+dfsg.1/tests/iterator/iterator_helpers.c libgit2-1.1.0+dfsg.1/tests/iterator/iterator_helpers.c --- libgit2-0.28.5+dfsg.1/tests/iterator/iterator_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/iterator/iterator_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "iterator.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "iterator_helpers.h" #include diff -Nru libgit2-0.28.5+dfsg.1/tests/iterator/tree.c libgit2-1.1.0+dfsg.1/tests/iterator/tree.c --- libgit2-0.28.5+dfsg.1/tests/iterator/tree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/iterator/tree.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "iterator.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "tree.h" #include "../submodule/submodule_helpers.h" #include "../diff/diff_helpers.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/iterator/workdir.c libgit2-1.1.0+dfsg.1/tests/iterator/workdir.c --- libgit2-0.28.5+dfsg.1/tests/iterator/workdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/iterator/workdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "iterator.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" #include "../submodule/submodule_helpers.h" #include "../merge/merge_helpers.h" #include "iterator_helpers.h" @@ -100,7 +100,7 @@ void test_iterator_workdir__0(void) { - workdir_iterator_test("attr", NULL, NULL, 23, 5, NULL, "ign"); + workdir_iterator_test("attr", NULL, NULL, 24, 5, NULL, "ign"); } static const char *status_paths[] = { @@ -637,13 +637,14 @@ git_iterator_free(i); } -/* Lots of empty dirs, or nearly empty ones, make the old workdir - * iterator cry. Also, segfault. +/* + * Lots of empty dirs, or nearly empty ones, make the old workdir + * iterator cry. Also, segfault. */ void test_iterator_workdir__filesystem_gunk(void) { - git_iterator *i; git_buf parent = GIT_BUF_INIT; + git_iterator *i; int n; if (!cl_is_env_set("GITTEST_INVASIVE_SPEED")) @@ -653,19 +654,18 @@ for (n = 0; n < 100000; n++) { git_buf_clear(&parent); - git_buf_printf(&parent, "%s/refs/heads/foo/%d/subdir", - git_repository_path(g_repo), n); - cl_assert(!git_buf_oom(&parent)); - + cl_git_pass(git_buf_printf(&parent, "%s/refs/heads/foo/%d/subdir", git_repository_path(g_repo), n)); cl_git_pass(git_futils_mkdir(parent.ptr, 0775, GIT_MKDIR_PATH)); } cl_git_pass(git_iterator_for_filesystem(&i, "testrepo/.git/refs", NULL)); - /* should only have 16 items, since we're not asking for trees to be + /* + * Should only have 17 items, since we're not asking for trees to be * returned. the goal of this test is simply to not crash. */ - expect_iterator_items(i, 16, NULL, 15, NULL); + expect_iterator_items(i, 17, NULL, 16, NULL); + git_iterator_free(i); git_buf_dispose(&parent); } diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/analysis.c libgit2-1.1.0+dfsg.1/tests/merge/analysis.c --- libgit2-0.28.5+dfsg.1/tests/merge/analysis.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/analysis.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,184 @@ +/* +NOTE: this is the implementation for both merge/trees/analysis.c and merge/workdir/analysis.c +You probably want to make changes to both files. +*/ + +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/annotated_commit.h" +#include "git2/sys/index.h" +#include "merge.h" +#include "merge_helpers.h" +#include "refs.h" +#include "posix.h" + +#define TEST_REPO_PATH "merge-resolve" + +#define UPTODATE_BRANCH "master" +#define PREVIOUS_BRANCH "previous" + +#define FASTFORWARD_BRANCH "ff_branch" +#define FASTFORWARD_ID "fd89f8cffb663ac89095a0f9764902e93ceaca6a" + +#define NOFASTFORWARD_BRANCH "branch" +#define NOFASTFORWARD_ID "7cb63eed597130ba4abb87b3e544b85021905520" + +static git_repository *sandbox; +static git_repository *repo; + +void test_merge_analysis__initialize_with_bare_repository(void) +{ + sandbox = cl_git_sandbox_init(TEST_REPO_PATH); + cl_git_pass(git_repository_open_ext(&repo, git_repository_path(sandbox), + GIT_REPOSITORY_OPEN_BARE, NULL)); +} + +void test_merge_analysis__initialize_with_nonbare_repository(void) +{ + sandbox = cl_git_sandbox_init(TEST_REPO_PATH); + cl_git_pass(git_repository_open_ext(&repo, git_repository_workdir(sandbox), + 0, NULL)); +} + +void test_merge_analysis__cleanup(void) +{ + git_repository_free(repo); + cl_git_sandbox_cleanup(); +} + +static void analysis_from_branch( + git_merge_analysis_t *merge_analysis, + git_merge_preference_t *merge_pref, + const char *our_branchname, + const char *their_branchname) +{ + git_buf our_refname = GIT_BUF_INIT; + git_buf their_refname = GIT_BUF_INIT; + git_reference *our_ref; + git_reference *their_ref; + git_annotated_commit *their_head; + + if (our_branchname != NULL) { + cl_git_pass(git_buf_printf(&our_refname, "%s%s", GIT_REFS_HEADS_DIR, our_branchname)); + cl_git_pass(git_reference_lookup(&our_ref, repo, git_buf_cstr(&our_refname))); + } else { + cl_git_pass(git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)); + } + + cl_git_pass(git_buf_printf(&their_refname, "%s%s", GIT_REFS_HEADS_DIR, their_branchname)); + + cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&their_refname))); + cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); + + cl_git_pass(git_merge_analysis_for_ref(merge_analysis, merge_pref, repo, our_ref, (const git_annotated_commit **)&their_head, 1)); + + git_buf_dispose(&our_refname); + git_buf_dispose(&their_refname); + git_annotated_commit_free(their_head); + git_reference_free(our_ref); + git_reference_free(their_ref); +} + +void test_merge_analysis__fastforward(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, FASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL|GIT_MERGE_ANALYSIS_FASTFORWARD, merge_analysis); +} + +void test_merge_analysis__no_fastforward(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); +} + +void test_merge_analysis__uptodate(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, UPTODATE_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); +} + +void test_merge_analysis__uptodate_merging_prev_commit(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, PREVIOUS_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); +} + +void test_merge_analysis__unborn(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + git_buf master = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&master, git_repository_path(repo), "refs/heads/master")); + cl_must_pass(p_unlink(git_buf_cstr(&master))); + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_FASTFORWARD|GIT_MERGE_ANALYSIS_UNBORN, merge_analysis); + + git_buf_dispose(&master); +} + +void test_merge_analysis__fastforward_with_config_noff(void) +{ + git_config *config; + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_string(config, "merge.ff", "false")); + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, FASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL|GIT_MERGE_ANALYSIS_FASTFORWARD, merge_analysis); + + cl_assert_equal_i(GIT_MERGE_PREFERENCE_NO_FASTFORWARD, (merge_pref & GIT_MERGE_PREFERENCE_NO_FASTFORWARD)); + + git_config_free(config); +} + +void test_merge_analysis__no_fastforward_with_config_ffonly(void) +{ + git_config *config; + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_string(config, "merge.ff", "only")); + + analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); + + cl_assert_equal_i(GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY, (merge_pref & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY)); + + git_config_free(config); +} + +void test_merge_analysis__between_uptodate_refs(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, NOFASTFORWARD_BRANCH, PREVIOUS_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); +} + +void test_merge_analysis__between_noff_refs(void) +{ + git_merge_analysis_t merge_analysis; + git_merge_preference_t merge_pref; + + analysis_from_branch(&merge_analysis, &merge_pref, "branch", FASTFORWARD_BRANCH); + cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/files.c libgit2-1.1.0+dfsg.1/tests/merge/files.c --- libgit2-0.28.5+dfsg.1/tests/merge/files.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/files.c 2020-10-12 18:53:06.000000000 +0000 @@ -6,7 +6,7 @@ #include "merge_helpers.h" #include "conflict_data.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" #include "diff_xdiff.h" #define TEST_REPO_PATH "merge-resolve" diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/merge_helpers.c libgit2-1.1.0+dfsg.1/tests/merge/merge_helpers.c --- libgit2-0.28.5+dfsg.1/tests/merge/merge_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/merge_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "refs.h" #include "tree.h" #include "merge_helpers.h" @@ -352,7 +352,7 @@ return 0; for (i = 0; i < expected_len; i++) { - git_blob_create_fromworkdir(&actual_oid, repo, expected[i].path); + git_blob_create_from_workdir(&actual_oid, repo, expected[i].path); git_oid_fromstr(&expected_oid, expected[i].oid_str); if (git_oid_cmp(&actual_oid, &expected_oid) != 0) diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/merge_helpers.h libgit2-1.1.0+dfsg.1/tests/merge/merge_helpers.h --- libgit2-0.28.5+dfsg.1/tests/merge/merge_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/merge_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -36,7 +36,7 @@ struct merge_index_with_status ancestor; struct merge_index_with_status ours; struct merge_index_with_status theirs; - git_merge_diff_type_t change_type; + git_merge_diff_t change_type; }; int merge_trees_from_branches( diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/trees/automerge.c libgit2-1.1.0+dfsg.1/tests/merge/trees/automerge.c --- libgit2-0.28.5+dfsg.1/tests/merge/trees/automerge.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/trees/automerge.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/merge.h" #include "buffer.h" #include "merge.h" -#include "fileops.h" +#include "futils.h" #include "../merge_helpers.h" #include "../conflict_data.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/trees/modeconflict.c libgit2-1.1.0+dfsg.1/tests/merge/trees/modeconflict.c --- libgit2-0.28.5+dfsg.1/tests/merge/trees/modeconflict.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/trees/modeconflict.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "buffer.h" #include "merge.h" #include "../merge_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/trees/renames.c libgit2-1.1.0+dfsg.1/tests/merge/trees/renames.c --- libgit2-0.28.5+dfsg.1/tests/merge/trees/renames.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/trees/renames.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "buffer.h" #include "merge.h" #include "../merge_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; @@ -274,3 +274,80 @@ cl_assert(merge_test_index(index, merge_index_entries, 7)); git_index_free(index); } + +void test_merge_trees_renames__cache_recomputation(void) +{ + git_oid blob, binary, ancestor_oid, theirs_oid, ours_oid; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + git_buf path = GIT_BUF_INIT; + git_treebuilder *builder; + git_tree *ancestor_tree, *their_tree, *our_tree; + git_index *index; + size_t blob_size; + void *data; + size_t i; + + cl_git_pass(git_oid_fromstr(&blob, "a2d8d1824c68541cca94ffb90f79291eba495921")); + + /* + * Create a 50MB blob that consists of NUL bytes only. It is important + * that this blob is of a special format, most importantly it cannot + * contain more than four non-consecutive newlines or NUL bytes. This + * is because of git_hashsig's inner workings where all files with less + * than four "lines" are deemed to small. + */ + blob_size = 50 * 1024 * 1024; + cl_assert(data = git__calloc(blob_size, 1)); + cl_git_pass(git_blob_create_from_buffer(&binary, repo, data, blob_size)); + + /* + * Create the common ancestor, which has 1000 dummy blobs and the binary + * blob. The dummy blobs serve as potential rename targets for the + * dummy blob. + */ + cl_git_pass(git_treebuilder_new(&builder, repo, NULL)); + for (i = 0; i < 1000; i++) { + cl_git_pass(git_buf_printf(&path, "%"PRIuZ".txt", i)); + cl_git_pass(git_treebuilder_insert(NULL, builder, path.ptr, &blob, GIT_FILEMODE_BLOB)); + git_buf_clear(&path); + } + cl_git_pass(git_treebuilder_insert(NULL, builder, "original.bin", &binary, GIT_FILEMODE_BLOB)); + cl_git_pass(git_treebuilder_write(&ancestor_oid, builder)); + + /* We now the binary blob in our tree. */ + cl_git_pass(git_treebuilder_remove(builder, "original.bin")); + cl_git_pass(git_treebuilder_insert(NULL, builder, "renamed.bin", &binary, GIT_FILEMODE_BLOB)); + cl_git_pass(git_treebuilder_write(&ours_oid, builder)); + + git_treebuilder_free(builder); + + /* And move everything into a subdirectory in their tree. */ + cl_git_pass(git_treebuilder_new(&builder, repo, NULL)); + cl_git_pass(git_treebuilder_insert(NULL, builder, "subdir", &ancestor_oid, GIT_FILEMODE_TREE)); + cl_git_pass(git_treebuilder_write(&theirs_oid, builder)); + + /* + * Now merge ancestor, ours and theirs. As `git_hashsig` refuses to + * create a hash signature for the 50MB binary file, we historically + * didn't cache the hashsig computation for it. As a result, we now + * started looking up the 50MB blob and scanning it at least 1000 + * times, which takes a long time. + * + * The number of 1000 blobs is chosen in such a way that it's + * noticeable when the bug creeps in again, as it takes around 12 + * minutes on my machine to compute the following merge. + */ + opts.target_limit = 5000; + cl_git_pass(git_tree_lookup(&ancestor_tree, repo, &ancestor_oid)); + cl_git_pass(git_tree_lookup(&their_tree, repo, &theirs_oid)); + cl_git_pass(git_tree_lookup(&our_tree, repo, &ours_oid)); + cl_git_pass(git_merge_trees(&index, repo, ancestor_tree, our_tree, their_tree, &opts)); + + git_treebuilder_free(builder); + git_buf_dispose(&path); + git_index_free(index); + git_tree_free(ancestor_tree); + git_tree_free(their_tree); + git_tree_free(our_tree); + git__free(data); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/trees/trivial.c libgit2-1.1.0+dfsg.1/tests/merge/trees/trivial.c --- libgit2-0.28.5+dfsg.1/tests/merge/trees/trivial.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/trees/trivial.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "merge.h" #include "../merge_helpers.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" #include "git2/sys/index.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/trees/whitespace.c libgit2-1.1.0+dfsg.1/tests/merge/trees/whitespace.c --- libgit2-0.28.5+dfsg.1/tests/merge/trees/whitespace.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/trees/whitespace.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "buffer.h" #include "merge.h" #include "../merge_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/workdir/analysis.c libgit2-1.1.0+dfsg.1/tests/merge/workdir/analysis.c --- libgit2-0.28.5+dfsg.1/tests/merge/workdir/analysis.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/workdir/analysis.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "git2/annotated_commit.h" -#include "git2/sys/index.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "refs.h" -#include "posix.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define UPTODATE_BRANCH "master" -#define PREVIOUS_BRANCH "previous" - -#define FASTFORWARD_BRANCH "ff_branch" -#define FASTFORWARD_ID "fd89f8cffb663ac89095a0f9764902e93ceaca6a" - -#define NOFASTFORWARD_BRANCH "branch" -#define NOFASTFORWARD_ID "7cb63eed597130ba4abb87b3e544b85021905520" - - -/* Fixture setup and teardown */ -void test_merge_workdir_analysis__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_analysis__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - -static void analysis_from_branch( - git_merge_analysis_t *merge_analysis, - git_merge_preference_t *merge_pref, - const char *our_branchname, - const char *their_branchname) -{ - git_buf our_refname = GIT_BUF_INIT; - git_buf their_refname = GIT_BUF_INIT; - git_reference *our_ref; - git_reference *their_ref; - git_annotated_commit *their_head; - - if (our_branchname != NULL) { - cl_git_pass(git_buf_printf(&our_refname, "%s%s", GIT_REFS_HEADS_DIR, our_branchname)); - cl_git_pass(git_reference_lookup(&our_ref, repo, git_buf_cstr(&our_refname))); - } else { - cl_git_pass(git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)); - } - - cl_git_pass(git_buf_printf(&their_refname, "%s%s", GIT_REFS_HEADS_DIR, their_branchname)); - - cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&their_refname))); - cl_git_pass(git_annotated_commit_from_ref(&their_head, repo, their_ref)); - - cl_git_pass(git_merge_analysis_for_ref(merge_analysis, merge_pref, repo, our_ref, (const git_annotated_commit **)&their_head, 1)); - - git_buf_dispose(&our_refname); - git_buf_dispose(&their_refname); - git_annotated_commit_free(their_head); - git_reference_free(our_ref); - git_reference_free(their_ref); -} - -void test_merge_workdir_analysis__fastforward(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, FASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL|GIT_MERGE_ANALYSIS_FASTFORWARD, merge_analysis); -} - -void test_merge_workdir_analysis__no_fastforward(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); -} - -void test_merge_workdir_analysis__uptodate(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, UPTODATE_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); -} - -void test_merge_workdir_analysis__uptodate_merging_prev_commit(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, PREVIOUS_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); -} - -void test_merge_workdir_analysis__unborn(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - git_buf master = GIT_BUF_INIT; - - git_buf_joinpath(&master, git_repository_path(repo), "refs/heads/master"); - p_unlink(git_buf_cstr(&master)); - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_FASTFORWARD|GIT_MERGE_ANALYSIS_UNBORN, merge_analysis); - - git_buf_dispose(&master); -} - -void test_merge_workdir_analysis__fastforward_with_config_noff(void) -{ - git_config *config; - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - git_repository_config(&config, repo); - git_config_set_string(config, "merge.ff", "false"); - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, FASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL|GIT_MERGE_ANALYSIS_FASTFORWARD, merge_analysis); - - cl_assert_equal_i(GIT_MERGE_PREFERENCE_NO_FASTFORWARD, (merge_pref & GIT_MERGE_PREFERENCE_NO_FASTFORWARD)); -} - -void test_merge_workdir_analysis__no_fastforward_with_config_ffonly(void) -{ - git_config *config; - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - git_repository_config(&config, repo); - git_config_set_string(config, "merge.ff", "only"); - - analysis_from_branch(&merge_analysis, &merge_pref, NULL, NOFASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); - - cl_assert_equal_i(GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY, (merge_pref & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY)); -} - -void test_merge_workdir_analysis__between_uptodate_refs(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, NOFASTFORWARD_BRANCH, PREVIOUS_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, merge_analysis); -} - -void test_merge_workdir_analysis__between_noff_refs(void) -{ - git_merge_analysis_t merge_analysis; - git_merge_preference_t merge_pref; - - analysis_from_branch(&merge_analysis, &merge_pref, "branch", FASTFORWARD_BRANCH); - cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, merge_analysis); -} diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/workdir/renames.c libgit2-1.1.0+dfsg.1/tests/merge/workdir/renames.c --- libgit2-0.28.5+dfsg.1/tests/merge/workdir/renames.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/workdir/renames.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,7 +4,7 @@ #include "buffer.h" #include "merge.h" #include "../merge_helpers.h" -#include "fileops.h" +#include "futils.h" #include "refs.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/workdir/setup.c libgit2-1.1.0+dfsg.1/tests/merge/workdir/setup.c --- libgit2-0.28.5+dfsg.1/tests/merge/workdir/setup.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/workdir/setup.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/merge.h" #include "merge.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; static git_index *repo_index; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/workdir/simple.c libgit2-1.1.0+dfsg.1/tests/merge/workdir/simple.c --- libgit2-0.28.5+dfsg.1/tests/merge/workdir/simple.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/workdir/simple.c 2020-10-12 18:53:06.000000000 +0000 @@ -6,7 +6,7 @@ #include "../merge_helpers.h" #include "../conflict_data.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; static git_index *repo_index; diff -Nru libgit2-0.28.5+dfsg.1/tests/merge/workdir/trivial.c libgit2-1.1.0+dfsg.1/tests/merge/workdir/trivial.c --- libgit2-0.28.5+dfsg.1/tests/merge/workdir/trivial.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/merge/workdir/trivial.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,7 +5,7 @@ #include "merge.h" #include "../merge_helpers.h" #include "refs.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; static git_index *repo_index; diff -Nru libgit2-0.28.5+dfsg.1/tests/network/cred.c libgit2-1.1.0+dfsg.1/tests/network/cred.c --- libgit2-0.28.5+dfsg.1/tests/network/cred.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/cred.c 2020-10-12 18:53:06.000000000 +0000 @@ -4,47 +4,43 @@ void test_network_cred__stock_userpass_validates_args(void) { - git_cred_userpass_payload payload = {0}; + git_credential_userpass_payload payload = {0}; - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, NULL)); + cl_git_fail(git_credential_userpass(NULL, NULL, NULL, 0, NULL)); payload.username = "user"; - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); + cl_git_fail(git_credential_userpass(NULL, NULL, NULL, 0, &payload)); payload.username = NULL; payload.username = "pass"; - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); + cl_git_fail(git_credential_userpass(NULL, NULL, NULL, 0, &payload)); } void test_network_cred__stock_userpass_validates_that_method_is_allowed(void) { - git_cred *cred; - git_cred_userpass_payload payload = {"user", "pass"}; + git_credential *cred; + git_credential_userpass_payload payload = {"user", "pass"}; - cl_git_fail(git_cred_userpass(&cred, NULL, NULL, 0, &payload)); - cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - cred->free(cred); + cl_git_fail(git_credential_userpass(&cred, NULL, NULL, 0, &payload)); + cl_git_pass(git_credential_userpass(&cred, NULL, NULL, GIT_CREDENTIAL_USERPASS_PLAINTEXT, &payload)); + git_credential_free(cred); } void test_network_cred__stock_userpass_properly_handles_username_in_url(void) { - git_cred *cred; - git_cred_userpass_plaintext *plain; - git_cred_userpass_payload payload = {"alice", "password"}; - - cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "alice"); - cred->free(cred); - - cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "alice"); - cred->free(cred); + git_credential *cred; + git_credential_userpass_payload payload = {"alice", "password"}; + + cl_git_pass(git_credential_userpass(&cred, NULL, NULL, GIT_CREDENTIAL_USERPASS_PLAINTEXT, &payload)); + cl_assert_equal_s("alice", git_credential_get_username(cred)); + git_credential_free(cred); + + cl_git_pass(git_credential_userpass(&cred, NULL, "bob", GIT_CREDENTIAL_USERPASS_PLAINTEXT, &payload)); + cl_assert_equal_s("alice", git_credential_get_username(cred)); + git_credential_free(cred); payload.username = NULL; - cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "bob"); - cred->free(cred); + cl_git_pass(git_credential_userpass(&cred, NULL, "bob", GIT_CREDENTIAL_USERPASS_PLAINTEXT, &payload)); + cl_assert_equal_s("bob", git_credential_get_username(cred)); + git_credential_free(cred); } diff -Nru libgit2-0.28.5+dfsg.1/tests/network/fetchlocal.c libgit2-1.1.0+dfsg.1/tests/network/fetchlocal.c --- libgit2-0.28.5+dfsg.1/tests/network/fetchlocal.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/fetchlocal.c 2020-10-12 18:53:06.000000000 +0000 @@ -8,7 +8,7 @@ static const char* tagger_email = "vicent@github.com"; static const char* tagger_message = "This is my tag.\n\nThere are many tags, but this one is mine\n"; -static int transfer_cb(const git_transfer_progress *stats, void *payload) +static int transfer_cb(const git_indexer_progress *stats, void *payload) { int *callcount = (int*)payload; GIT_UNUSED(stats); @@ -49,7 +49,7 @@ cl_assert_equal_i(19, (int)refnames.count); cl_assert(callcount > 0); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); git_repository_free(repo); } @@ -77,7 +77,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); cl_assert(callcount > 0); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2")); @@ -90,7 +90,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(18, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed")); @@ -103,7 +103,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(17, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); git_repository_free(repo); @@ -168,7 +168,7 @@ assert_ref_exists(repo, "refs/remotes/origin/pr/42"); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(20, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs")); cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/pull/*/head:refs/remotes/origin/pr/*")); @@ -183,7 +183,7 @@ assert_ref_exists(repo, "refs/remotes/origin/pr/42"); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(20, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); cl_git_pass(git_config_delete_multivar(config, "remote.origin.fetch", "refs")); cl_git_pass(git_config_set_multivar(config, "remote.origin.fetch", "^$", "refs/heads/*:refs/remotes/origin/*")); @@ -195,7 +195,7 @@ cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); git_config_free(config); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); git_repository_free(repo); } @@ -224,7 +224,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); cl_assert(callcount > 0); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2")); @@ -237,7 +237,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(18, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed")); @@ -253,7 +253,7 @@ cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(17, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); git_repository_free(repo); @@ -333,13 +333,13 @@ cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */ cl_assert(callcount > 0); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(origin); } @@ -419,17 +419,17 @@ cl_git_pass(git_remote_fetch(test, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); - cl_assert_equal_i(32, (int)refnames.count); - git_strarray_free(&refnames); + cl_assert_equal_i(33, (int)refnames.count); + git_strarray_dispose(&refnames); cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git"))); cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl")); cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); - cl_assert_equal_i(44, (int)refnames.count); + cl_assert_equal_i(45, (int)refnames.count); - git_strarray_free(&refnames); + git_strarray_dispose(&refnames); git_remote_free(test); git_remote_free(test2); } diff -Nru libgit2-0.28.5+dfsg.1/tests/network/joinpath.c libgit2-1.1.0+dfsg.1/tests/network/joinpath.c --- libgit2-0.28.5+dfsg.1/tests/network/joinpath.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/joinpath.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,194 @@ +#include "clar_libgit2.h" +#include "net.h" +#include "netops.h" + +static git_net_url source, target; + +void test_network_joinpath__initialize(void) +{ + memset(&source, 0, sizeof(source)); + memset(&target, 0, sizeof(target)); +} + +void test_network_joinpath__cleanup(void) +{ + git_net_url_dispose(&source); + git_net_url_dispose(&target); +} + +void test_network_joinpath__target_paths_and_queries(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d")); + cl_assert_equal_s(target.path, "/a/b/c/d"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d?foo")); + cl_assert_equal_s(target.path, "/a/b/c/d"); + cl_assert_equal_s(target.query, "foo"); + git_net_url_dispose(&target); +} + +void test_network_joinpath__source_query_removed(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b?query&one&two")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d")); + cl_assert_equal_s(target.path, "/a/b/c/d"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d?foo")); + cl_assert_equal_s(target.path, "/a/b/c/d"); + cl_assert_equal_s(target.query, "foo"); + git_net_url_dispose(&target); +} + +void test_network_joinpath__source_lacks_path(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); +} + +void test_network_joinpath__source_is_slash(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com/")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); +} + + +void test_network_joinpath__source_has_query(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com?query")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "")); + cl_assert_equal_s(target.path, "/"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello")); + cl_assert_equal_s(target.path, "/asdf"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello")); + cl_assert_equal_s(target.path, "/foo/bar"); + cl_assert_equal_s(target.query, "hello"); + git_net_url_dispose(&target); +} + + +void test_network_joinpath__empty_query_ignored(void) +{ + cl_git_pass(git_net_url_parse(&source, "http://example.com/foo")); + + cl_git_pass(git_net_url_joinpath(&target, &source, "/bar/baz?")); + cl_assert_equal_s(target.path, "/foo/bar/baz"); + cl_assert_equal_p(target.query, NULL); + git_net_url_dispose(&target); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/network/redirect.c libgit2-1.1.0+dfsg.1/tests/network/redirect.c --- libgit2-0.28.5+dfsg.1/tests/network/redirect.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/redirect.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,129 @@ +#include "clar_libgit2.h" +#include "net.h" +#include "netops.h" + +static git_net_url conndata; + +void test_network_redirect__initialize(void) +{ + memset(&conndata, 0, sizeof(conndata)); +} + +void test_network_redirect__cleanup(void) +{ + git_net_url_dispose(&conndata); +} + +void test_network_redirect__redirect_http(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "http://example.com/foo/bar/baz")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "http://example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); +} + +void test_network_redirect__redirect_ssl(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://example.com/foo/bar/baz")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "https://example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); +} + +void test_network_redirect__redirect_leaves_root_path(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://example.com/foo/bar/baz")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "https://example.com/foo/bar/baz", "/foo/bar/baz")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); +} + +void test_network_redirect__redirect_encoded_username_password(void) +{ + cl_git_pass(git_net_url_parse(&conndata, + "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_s(conndata.username, "user/name"); + cl_assert_equal_s(conndata.password, "pass@word%zyx%v"); +} + +void test_network_redirect__redirect_cross_host_denied(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "https://bar.com/bar/baz")); + cl_git_fail_with(git_net_url_apply_redirect(&conndata, + "https://foo.com/bar/baz", NULL), + -1); +} + +void test_network_redirect__redirect_http_downgrade_denied(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz")); + cl_git_fail_with(git_net_url_apply_redirect(&conndata, + "http://foo.com/bar/baz", NULL), + -1); +} + +void test_network_redirect__redirect_relative(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "http://foo.com/bar/baz/biff")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); +} + +void test_network_redirect__redirect_relative_ssl(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz/biff")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); +} + +void test_network_redirect__service_query_no_query_params_in_location(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "/baz/info/refs", "/info/refs?service=git-upload-pack")); + cl_assert_equal_s(conndata.path, "/baz"); +} + +void test_network_redirect__service_query_with_query_params_in_location(void) +{ + cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack")); + cl_git_pass(git_net_url_apply_redirect(&conndata, + "/baz/info/refs?service=git-upload-pack", "/info/refs?service=git-upload-pack")); + cl_assert_equal_s(conndata.path, "/baz"); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/network/refspecs.c libgit2-1.1.0+dfsg.1/tests/network/refspecs.c --- libgit2-0.28.5+dfsg.1/tests/network/refspecs.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/refspecs.c 2020-10-12 18:53:06.000000000 +0000 @@ -70,15 +70,18 @@ assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/delete me", false); assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD to me", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", true); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", true); assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*g*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*g*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); @@ -93,7 +96,7 @@ git_refspec spec; git_buf buf = GIT_BUF_INIT; - git_refspec__parse(&spec, refspec, true); + cl_git_pass(git_refspec__parse(&spec, refspec, true)); cl_git_pass(git_refspec_transform(&buf, &spec, name)); cl_assert_equal_s(result, buf.ptr); @@ -111,6 +114,17 @@ assert_valid_transform("refs/*:refs/*", "refs/heads/master", "refs/heads/master"); } +void test_network_refspecs__transform_loosened_star(void) +{ + assert_valid_transform("refs/heads/branch-*:refs/remotes/origin/branch-*", "refs/heads/branch-a", "refs/remotes/origin/branch-a"); + assert_valid_transform("refs/heads/branch-*/head:refs/remotes/origin/branch-*/head", "refs/heads/branch-a/head", "refs/remotes/origin/branch-a/head"); +} + +void test_network_refspecs__transform_nested_star(void) +{ + assert_valid_transform("refs/heads/x*x/for-linus:refs/remotes/mine/*", "refs/heads/xbranchx/for-linus", "refs/remotes/mine/branch"); +} + void test_network_refspecs__no_dst(void) { assert_valid_transform("refs/heads/master:", "refs/heads/master", ""); @@ -139,7 +153,7 @@ git_refspec spec; git_buf buf = GIT_BUF_INIT; - git_refspec__parse(&spec, refspec, true); + cl_git_pass(git_refspec__parse(&spec, refspec, true)); cl_git_fail(git_refspec_rtransform(&buf, &spec, name)); git_buf_dispose(&buf); diff -Nru libgit2-0.28.5+dfsg.1/tests/network/remote/local.c libgit2-1.1.0+dfsg.1/tests/network/remote/local.c --- libgit2-0.28.5+dfsg.1/tests/network/remote/local.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/remote/local.c 2020-10-12 18:53:06.000000000 +0000 @@ -62,7 +62,7 @@ cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(refs_len, 28); + cl_assert_equal_i(refs_len, 29); } void test_network_remote_local__retrieve_advertised_before_connect(void) @@ -86,7 +86,7 @@ cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(refs_len, 28); + cl_assert_equal_i(refs_len, 29); } void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) @@ -101,7 +101,7 @@ cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(refs_len, 28); + cl_assert_equal_i(refs_len, 29); git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */ remote = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/network/remote/remotes.c libgit2-1.1.0+dfsg.1/tests/network/remote/remotes.c --- libgit2-0.28.5+dfsg.1/tests/network/remote/remotes.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/remote/remotes.c 2020-10-12 18:53:06.000000000 +0000 @@ -28,28 +28,97 @@ void test_network_remote_remotes__parsing(void) { + git_buf url = GIT_BUF_INIT; git_remote *_remote2 = NULL; cl_assert_equal_s(git_remote_name(_remote), "test"); cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert(git_remote_pushurl(_remote) == NULL); - cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_FETCH), - "git://github.com/libgit2/libgit2"); - cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_PUSH), - "git://github.com/libgit2/libgit2"); + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, NULL)); + cl_assert_equal_s(url.ptr, "git://github.com/libgit2/libgit2"); + + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, NULL)); + cl_assert_equal_s(url.ptr, "git://github.com/libgit2/libgit2"); cl_git_pass(git_remote_lookup(&_remote2, _repo, "test_with_pushurl")); cl_assert_equal_s(git_remote_name(_remote2), "test_with_pushurl"); cl_assert_equal_s(git_remote_url(_remote2), "git://github.com/libgit2/fetchlibgit2"); cl_assert_equal_s(git_remote_pushurl(_remote2), "git://github.com/libgit2/pushlibgit2"); - cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_FETCH), - "git://github.com/libgit2/fetchlibgit2"); - cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_PUSH), - "git://github.com/libgit2/pushlibgit2"); + cl_git_pass(git_remote__urlfordirection(&url, _remote2, GIT_DIRECTION_FETCH, NULL)); + cl_assert_equal_s(url.ptr, "git://github.com/libgit2/fetchlibgit2"); + + cl_git_pass(git_remote__urlfordirection(&url, _remote2, GIT_DIRECTION_PUSH, NULL)); + cl_assert_equal_s(url.ptr, "git://github.com/libgit2/pushlibgit2"); git_remote_free(_remote2); + git_buf_dispose(&url); +} + +static int urlresolve_callback(git_buf *url_resolved, const char *url, int direction, void *payload) +{ + cl_assert(strcmp(url, "git://github.com/libgit2/libgit2") == 0); + cl_assert(strcmp(payload, "payload") == 0); + cl_assert(url_resolved->size == 0); + + if (direction == GIT_DIRECTION_PUSH) + git_buf_sets(url_resolved, "pushresolve"); + if (direction == GIT_DIRECTION_FETCH) + git_buf_sets(url_resolved, "fetchresolve"); + + return GIT_OK; +} + +void test_network_remote_remotes__urlresolve(void) +{ + git_buf url = GIT_BUF_INIT; + + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + callbacks.resolve_url = urlresolve_callback; + callbacks.payload = "payload"; + + cl_assert_equal_s(git_remote_name(_remote), "test"); + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); + cl_assert(git_remote_pushurl(_remote) == NULL); + + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, &callbacks)); + cl_assert_equal_s(url.ptr, "fetchresolve"); + + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks)); + cl_assert_equal_s(url.ptr, "pushresolve"); + + git_buf_dispose(&url); +} + +static int urlresolve_passthrough_callback(git_buf *url_resolved, const char *url, int direction, void *payload) +{ + GIT_UNUSED(url_resolved); + GIT_UNUSED(url); + GIT_UNUSED(direction); + GIT_UNUSED(payload); + return GIT_PASSTHROUGH; +} + +void test_network_remote_remotes__urlresolve_passthrough(void) +{ + git_buf url = GIT_BUF_INIT; + const char *orig_url = "git://github.com/libgit2/libgit2"; + + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + callbacks.resolve_url = urlresolve_passthrough_callback; + + cl_assert_equal_s(git_remote_name(_remote), "test"); + cl_assert_equal_s(git_remote_url(_remote), orig_url); + cl_assert(git_remote_pushurl(_remote) == NULL); + + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_FETCH, &callbacks)); + cl_assert_equal_s(url.ptr, orig_url); + + cl_git_pass(git_remote__urlfordirection(&url, _remote, GIT_DIRECTION_PUSH, &callbacks)); + cl_assert_equal_s(url.ptr, orig_url); + + git_buf_dispose(&url); } void test_network_remote_remotes__pushurl(void) @@ -146,11 +215,11 @@ cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); cl_assert_equal_i(1, (int)array.count); cl_assert_equal_s("+refs/heads/*:refs/remotes/test/*", array.strings[0]); - git_strarray_free(&array); + git_strarray_dispose(&array); cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); cl_assert_equal_i(0, (int)array.count); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(dup); } @@ -249,7 +318,7 @@ cl_git_pass(git_remote_list(&list, _repo)); cl_assert(list.count == 5); - git_strarray_free(&list); + git_strarray_dispose(&list); cl_git_pass(git_repository_config(&cfg, _repo)); @@ -261,7 +330,7 @@ cl_git_pass(git_remote_list(&list, _repo)); cl_assert(list.count == 7); - git_strarray_free(&list); + git_strarray_dispose(&list); git_config_free(cfg); } @@ -397,13 +466,13 @@ for (i = 0; i < 3; i++) { cl_assert_equal_s(fetch_refspecs[i], array.strings[i]); } - git_strarray_free(&array); + git_strarray_dispose(&array); cl_git_pass(git_remote_get_push_refspecs(&array, remote)); for (i = 0; i < 3; i++) { cl_assert_equal_s(push_refspecs[i], array.strings[i]); } - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); git_remote_delete(_repo, "test"); diff -Nru libgit2-0.28.5+dfsg.1/tests/network/remote/rename.c libgit2-1.1.0+dfsg.1/tests/network/remote/rename.c --- libgit2-0.28.5+dfsg.1/tests/network/remote/rename.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/remote/rename.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,7 +25,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_existence(_repo, "remote.test.fetch", false); assert_config_entry_existence(_repo, "remote.just/renamed.fetch", true); @@ -39,7 +39,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_value(_repo, "branch.master.remote", "just/renamed"); } @@ -50,7 +50,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/heads/*:refs/remotes/just/renamed/*"); } @@ -71,7 +71,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false); } @@ -90,11 +90,11 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(1, problems.count); cl_assert_equal_s("+refs/*:refs/*", problems.strings[0]); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/*:refs/*"); - git_strarray_free(&problems); + git_strarray_dispose(&problems); } void test_network_remote_rename__new_name_can_contain_dots(void) @@ -103,7 +103,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just.renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); assert_config_entry_existence(_repo, "remote.just.renamed.fetch", true); } @@ -126,7 +126,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); cl_git_pass(git_repository_open(&another_repo, "testrepo.git")); cl_git_pass(git_remote_lookup(&renamed, _repo, "just/renamed")); @@ -154,7 +154,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "just/renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&underlying, _repo, "refs/remotes/test/master")); cl_git_pass(git_reference_lookup(&underlying, _repo, "refs/remotes/just/renamed/master")); @@ -176,7 +176,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); /* make sure there's only one remote-tracking branch */ cl_git_pass(git_branch_iterator_new(&iter, _repo, GIT_BRANCH_REMOTE)); @@ -214,7 +214,7 @@ cl_git_pass(git_remote_rename(&problems, _repo, _remote_name, "renamed")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); cl_git_pass(git_vector_init(&refs, 2, (git_vector_cmp) git_reference_cmp)); cl_git_pass(git_branch_iterator_new(&iter, _repo, GIT_BRANCH_REMOTE)); diff -Nru libgit2-0.28.5+dfsg.1/tests/network/urlparse.c libgit2-1.1.0+dfsg.1/tests/network/urlparse.c --- libgit2-0.28.5+dfsg.1/tests/network/urlparse.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/network/urlparse.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,220 +1,168 @@ #include "clar_libgit2.h" -#include "netops.h" +#include "net.h" -static char *host, *port, *path, *user, *pass; -static gitno_connection_data conndata; +static git_net_url conndata; void test_network_urlparse__initialize(void) { - host = port = path = user = pass = NULL; memset(&conndata, 0, sizeof(conndata)); } void test_network_urlparse__cleanup(void) { -#define FREE_AND_NULL(x) if (x) { git__free(x); x = NULL; } - FREE_AND_NULL(host); - FREE_AND_NULL(port); - FREE_AND_NULL(path); - FREE_AND_NULL(user); - FREE_AND_NULL(pass); - - gitno_connection_data_free_ptrs(&conndata); + git_net_url_dispose(&conndata); } void test_network_urlparse__trivial(void) { - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "http://example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_p(user, NULL); - cl_assert_equal_p(pass, NULL); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } void test_network_urlparse__root(void) { - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "http://example.com/", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/"); - cl_assert_equal_p(user, NULL); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__just_hostname(void) -{ - cl_git_fail_with(GIT_EINVALIDSPEC, - gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "http://example.com", "8080")); -} - -void test_network_urlparse__encoded_password(void) -{ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass%2fis%40bad@hostname.com:1234/", "1")); - cl_assert_equal_s(host, "hostname.com"); - cl_assert_equal_s(port, "1234"); - cl_assert_equal_s(path, "/"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass/is@bad"); -} - -void test_network_urlparse__user(void) -{ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user@example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__user_pass(void) -{ - /* user:pass@hostname.tld/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass@example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass"); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com/")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__port(void) +void test_network_urlparse__implied_root(void) { - /* hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_p(user, NULL); - cl_assert_equal_p(pass, NULL); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__user_port(void) +void test_network_urlparse__implied_root_custom_port(void) { - /* user@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user@example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_p(pass, NULL); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "42"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__user_pass_port(void) +void test_network_urlparse__implied_root_empty_port(void) { - /* user:pass@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass@example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass"); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com:")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__optional_path(void) +void test_network_urlparse__encoded_password(void) { - cl_git_fail(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass@example.com:9191", "8080")); - - cl_git_pass(gitno_extract_url_parts(&host, &port, NULL, &user, &pass, - "https://user:pass@example.com:9191", "8080")); + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass%2fis%40bad@hostname.com:1234/")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "hostname.com"); + cl_assert_equal_s(conndata.port, "1234"); + cl_assert_equal_s(conndata.path, "/"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass/is@bad"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__connection_data_http(void) +void test_network_urlparse__user(void) { - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://example.com/foo/bar/baz", "bar/baz")); + cl_git_pass(git_net_url_parse(&conndata, + "https://user@example.com/resource")); + cl_assert_equal_s(conndata.scheme, "https"); cl_assert_equal_s(conndata.host, "example.com"); - cl_assert_equal_s(conndata.port, "80"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, false); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__connection_data_ssl(void) +void test_network_urlparse__user_pass(void) { - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://example.com/foo/bar/baz", "bar/baz")); + /* user:pass@hostname.tld/resource */ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@example.com/resource")); + cl_assert_equal_s(conndata.scheme, "https"); cl_assert_equal_s(conndata.host, "example.com"); cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, true); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__encoded_username_password(void) +void test_network_urlparse__port(void) { - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); + /* hostname.tld:port/resource */ + cl_git_pass(git_net_url_parse(&conndata, + "https://example.com:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); cl_assert_equal_s(conndata.host, "example.com"); - cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_s(conndata.user, "user/name"); - cl_assert_equal_s(conndata.pass, "pass@word%zyx%v"); - cl_assert_equal_i(conndata.use_ssl, true); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__connection_data_cross_host_redirect(void) +void test_network_urlparse__empty_port(void) { - conndata.host = git__strdup("bar.com"); - cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz", NULL), - -1); + cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource")); + cl_assert_equal_s(conndata.scheme, "http"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_p(conndata.username, NULL); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1); } -void test_network_urlparse__connection_data_http_downgrade(void) +void test_network_urlparse__user_port(void) { - conndata.use_ssl = true; - cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz", NULL), - -1); + /* user@hostname.tld:port/resource */ + cl_git_pass(git_net_url_parse(&conndata, + "https://user@example.com:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_p(conndata.password, NULL); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } -void test_network_urlparse__connection_data_relative_redirect(void) +void test_network_urlparse__user_pass_port(void) { - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz/biff", NULL)); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "/zap/baz/biff?bam", NULL)); - cl_assert_equal_s(conndata.host, "foo.com"); - cl_assert_equal_s(conndata.port, "80"); - cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, false); -} - -void test_network_urlparse__connection_data_relative_redirect_ssl(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz/biff", NULL)); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "/zap/baz/biff?bam", NULL)); - cl_assert_equal_s(conndata.host, "foo.com"); - cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, true); -} - -/* Run this under valgrind */ -void test_network_urlparse__connection_data_cleanup(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz/biff", "baz/biff")); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz/biff", "baz/biff")); + /* user:pass@hostname.tld:port/resource */ + cl_git_pass(git_net_url_parse(&conndata, + "https://user:pass@example.com:9191/resource")); + cl_assert_equal_s(conndata.scheme, "https"); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "9191"); + cl_assert_equal_s(conndata.path, "/resource"); + cl_assert_equal_s(conndata.username, "user"); + cl_assert_equal_s(conndata.password, "pass"); + cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0); } diff -Nru libgit2-0.28.5+dfsg.1/tests/notes/notes.c libgit2-1.1.0+dfsg.1/tests/notes/notes.c --- libgit2-0.28.5+dfsg.1/tests/notes/notes.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/notes/notes.c 2020-10-12 18:53:06.000000000 +0000 @@ -400,15 +400,11 @@ git_note *note; cl_git_pass(git_oid_fromstr(&oid, "4a202b346bb0fb0db7eff3cffeb3c70babbd2045")); - cl_git_pass(git_note_commit_create(¬es_commit_oid, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 1)); - - git_commit_lookup(¬es_commit, _repo, ¬es_commit_oid); - + cl_git_pass(git_commit_lookup(¬es_commit, _repo, ¬es_commit_oid)); cl_assert(notes_commit); cl_git_pass(git_note_commit_read(¬e, _repo, notes_commit, &oid)); - cl_assert_equal_s(git_note_message(note), "I decorate 4a20\n"); git_commit_free(notes_commit); @@ -457,7 +453,7 @@ git_note *_note; cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - + for (i = 0; i < MESSAGES_COUNT; i++) { cl_git_pass(git_note_create(¬e_oid, _repo, "refs/notes/fanout", _sig, _sig, &target_oid, messages[i], 0)); cl_git_pass(git_note_read(&_note, _repo, "refs/notes/fanout", &target_oid)); @@ -511,7 +507,7 @@ cl_git_pass(git_note_commit_create(¬es_commit_oid, NULL, _repo, NULL, _sig, _sig, &oid, "I decorate 4a20\n", 0)); - git_commit_lookup(&existing_notes_commit, _repo, ¬es_commit_oid); + cl_git_pass(git_commit_lookup(&existing_notes_commit, _repo, ¬es_commit_oid)); cl_assert(existing_notes_commit); @@ -547,7 +543,7 @@ cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid)); - + error = git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid); cl_git_fail(error); cl_assert_equal_i(GIT_ENOTFOUND, error); diff -Nru libgit2-0.28.5+dfsg.1/tests/object/blob/filter.c libgit2-1.1.0+dfsg.1/tests/object/blob/filter.c --- libgit2-0.28.5+dfsg.1/tests/object/blob/filter.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/blob/filter.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,7 +19,7 @@ "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; -static git_off_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = { +static off64_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; @@ -59,7 +59,7 @@ if (g_crlf_raw_len[i] < 0) g_crlf_raw_len[i] = strlen(g_crlf_raw[i]); - cl_git_pass(git_blob_create_frombuffer( + cl_git_pass(git_blob_create_from_buffer( &g_crlf_oids[i], g_repo, g_crlf_raw[i], (size_t)g_crlf_raw_len[i])); } } diff -Nru libgit2-0.28.5+dfsg.1/tests/object/blob/fromstream.c libgit2-1.1.0+dfsg.1/tests/object/blob/fromstream.c --- libgit2-0.28.5+dfsg.1/tests/object/blob/fromstream.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/blob/fromstream.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "buffer.h" #include "posix.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; static char textual_content[] = "libgit2\n\r\n\0"; @@ -29,12 +29,12 @@ cl_git_fail_with(GIT_ENOTFOUND, git_object_lookup(&blob, repo, &expected_id, GIT_OBJECT_ANY)); - cl_git_pass(git_blob_create_fromstream(&stream, repo, NULL)); + cl_git_pass(git_blob_create_from_stream(&stream, repo, NULL)); for (i = 0; i < howmany; i++) cl_git_pass(stream->write(stream, textual_content, strlen(textual_content))); - cl_git_pass(git_blob_create_fromstream_commit(&id, stream)); + cl_git_pass(git_blob_create_from_stream_commit(&id, stream)); cl_assert_equal_oid(&expected_id, &id); cl_git_pass(git_object_lookup(&blob, repo, &expected_id, GIT_OBJECT_BLOB)); @@ -67,12 +67,12 @@ cl_git_pass(git_oid_fromstr(&expected_id, expected_sha)); - cl_git_pass(git_blob_create_fromstream(&stream, repo, fake_name)); + cl_git_pass(git_blob_create_from_stream(&stream, repo, fake_name)); for (i = 0; i < howmany; i++) cl_git_pass(stream->write(stream, textual_content, strlen(textual_content))); - cl_git_pass(git_blob_create_fromstream_commit(&id, stream)); + cl_git_pass(git_blob_create_from_stream_commit(&id, stream)); cl_assert_equal_oid(&expected_id, &id); } diff -Nru libgit2-0.28.5+dfsg.1/tests/object/blob/write.c libgit2-1.1.0+dfsg.1/tests/object/blob/write.c --- libgit2-0.28.5+dfsg.1/tests/object/blob/write.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/blob/write.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "buffer.h" #include "posix.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; @@ -33,7 +33,7 @@ { repo = cl_git_sandbox_init(WORKDIR); - assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_fromworkdir); + assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_from_workdir); } void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void) @@ -46,7 +46,7 @@ cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); cl_must_pass(git_buf_puts(&full_path, "test.txt")); - assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_from_disk); git_buf_dispose(&full_path); cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); @@ -62,7 +62,7 @@ cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); cl_must_pass(git_buf_puts(&full_path, "test.txt")); - assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_from_disk); git_buf_dispose(&full_path); cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); diff -Nru libgit2-0.28.5+dfsg.1/tests/object/cache.c libgit2-1.1.0+dfsg.1/tests/object/cache.c --- libgit2-0.28.5+dfsg.1/tests/object/cache.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/cache.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,10 +2,35 @@ #include "repository.h" static git_repository *g_repo; +static size_t cache_limit; +static int object_type; -void test_object_cache__initialize(void) +void test_object_cache__initialize_cache_no_blobs(void) { g_repo = NULL; + object_type = GIT_OBJECT_BLOB; + cache_limit = 0; +} + +void test_object_cache__initialize_cache_tiny_blobs(void) +{ + g_repo = NULL; + object_type = GIT_OBJECT_BLOB; + cache_limit = 10; +} + +void test_object_cache__initialize_cache_all_blobs(void) +{ + g_repo = NULL; + object_type = GIT_OBJECT_BLOB; + cache_limit = 32767; +} + +void test_object_cache__initialize_cache_no_trees(void) +{ + g_repo = NULL; + object_type = GIT_OBJECT_TREE; + cache_limit = 0; } void test_object_cache__cleanup(void) @@ -14,47 +39,49 @@ g_repo = NULL; git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJECT_BLOB, (size_t)0); + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJECT_TREE, (size_t)4096); + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJECT_COMMIT, (size_t)4096); } static struct { git_object_t type; const char *sha; + size_t size; } g_data[] = { /* HEAD */ - { GIT_OBJECT_BLOB, "a8233120f6ad708f843d861ce2b7228ec4e3dec6" }, /* README */ - { GIT_OBJECT_BLOB, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc" }, /* branch_file.txt */ - { GIT_OBJECT_BLOB, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd" }, /* new.txt */ + { GIT_OBJECT_BLOB, "a8233120f6ad708f843d861ce2b7228ec4e3dec6", 10 }, /* README */ + { GIT_OBJECT_BLOB, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc", 8 }, /* branch_file.txt */ + { GIT_OBJECT_BLOB, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd", 12 }, /* new.txt */ /* refs/heads/subtrees */ - { GIT_OBJECT_BLOB, "1385f264afb75a56a5bec74243be9b367ba4ca08" }, /* README */ - { GIT_OBJECT_TREE, "f1425cef211cc08caa31e7b545ffb232acb098c3" }, /* ab */ - { GIT_OBJECT_BLOB, "d6c93164c249c8000205dd4ec5cbca1b516d487f" }, /* ab/4.txt */ - { GIT_OBJECT_TREE, "9a03079b8a8ee85a0bee58bf9be3da8b62414ed4" }, /* ab/c */ - { GIT_OBJECT_BLOB, "270b8ea76056d5cad83af921837702d3e3c2924d" }, /* ab/c/3.txt */ - { GIT_OBJECT_TREE, "b6361fc6a97178d8fc8639fdeed71c775ab52593" }, /* ab/de */ - { GIT_OBJECT_BLOB, "e7b4ad382349ff96dd8199000580b9b1e2042eb0" }, /* ab/de/2.txt */ - { GIT_OBJECT_TREE, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54" }, /* ab/de/fgh */ - { GIT_OBJECT_BLOB, "1f67fc4386b2d171e0d21be1c447e12660561f9b" }, /* ab/de/fgh/1.txt */ - { GIT_OBJECT_BLOB, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057" }, /* branch_file.txt */ - { GIT_OBJECT_BLOB, "fa49b077972391ad58037050f2a75f74e3671e92" }, /* new.txt */ + { GIT_OBJECT_BLOB, "1385f264afb75a56a5bec74243be9b367ba4ca08", 4 }, /* README */ + { GIT_OBJECT_TREE, "f1425cef211cc08caa31e7b545ffb232acb098c3", 90 }, /* ab */ + { GIT_OBJECT_BLOB, "d6c93164c249c8000205dd4ec5cbca1b516d487f", 6 }, /* ab/4.txt */ + { GIT_OBJECT_TREE, "9a03079b8a8ee85a0bee58bf9be3da8b62414ed4", 33 }, /* ab/c */ + { GIT_OBJECT_BLOB, "270b8ea76056d5cad83af921837702d3e3c2924d", 6 }, /* ab/c/3.txt */ + { GIT_OBJECT_TREE, "b6361fc6a97178d8fc8639fdeed71c775ab52593", 63 }, /* ab/de */ + { GIT_OBJECT_BLOB, "e7b4ad382349ff96dd8199000580b9b1e2042eb0", 6 }, /* ab/de/2.txt */ + { GIT_OBJECT_TREE, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54", 33 }, /* ab/de/fgh */ + { GIT_OBJECT_BLOB, "1f67fc4386b2d171e0d21be1c447e12660561f9b", 6 }, /* ab/de/fgh/1.txt */ + { GIT_OBJECT_BLOB, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", 3 }, /* branch_file.txt */ + { GIT_OBJECT_BLOB, "fa49b077972391ad58037050f2a75f74e3671e92", 9 }, /* new.txt */ /* refs/heads/chomped */ - { GIT_OBJECT_BLOB, "0266163a49e280c4f5ed1e08facd36a2bd716bcf" }, /* readme.txt */ + { GIT_OBJECT_BLOB, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", 51 }, /* readme.txt */ - { 0, NULL }, - { 0, NULL } + { 0, NULL, 0 }, + { 0, NULL, 0 } }; -void test_object_cache__cache_everything(void) +void test_object_cache__cache_counts(void) { - int i, start; + int i, start, nonmatching = 0; git_oid oid; git_odb_object *odb_obj; git_object *obj; git_odb *odb; - git_libgit2_opts( - GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJECT_BLOB, (size_t)32767); + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, object_type, cache_limit); cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); cl_git_pass(git_repository_odb(&odb, g_repo)); @@ -77,12 +104,16 @@ git_object_free(obj); } - cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); + if ((g_data[i].type == object_type && g_data[i].size >= cache_limit) || + (g_data[i].type != object_type && g_data[i].type == GIT_OBJECT_BLOB)) + cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); + else { + cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); + nonmatching++; + } } - cl_assert_equal_i(i, (int)git_cache_size(&g_repo->objects) - start); - - git_odb_free(odb); + cl_assert_equal_i(nonmatching, (int)git_cache_size(&g_repo->objects) - start); for (i = 0; g_data[i].sha != NULL; ++i) { int count = (int)git_cache_size(&g_repo->objects); @@ -94,48 +125,6 @@ cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); } -} - -void test_object_cache__cache_no_blobs(void) -{ - int i, start, nonblobs = 0; - git_oid oid; - git_odb_object *odb_obj; - git_object *obj; - git_odb *odb; - - git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJECT_BLOB, (size_t)0); - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_odb(&odb, g_repo)); - - start = (int)git_cache_size(&g_repo->objects); - - for (i = 0; g_data[i].sha != NULL; ++i) { - int count = (int)git_cache_size(&g_repo->objects); - - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - - /* alternate between loading raw and parsed objects */ - if ((i & 1) == 0) { - cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); - cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); - git_odb_object_free(odb_obj); - } else { - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJECT_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - } - - if (g_data[i].type == GIT_OBJECT_BLOB) - cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); - else { - cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); - nonblobs++; - } - } - - cl_assert_equal_i(nonblobs, (int)git_cache_size(&g_repo->objects) - start); git_odb_free(odb); } @@ -255,15 +244,15 @@ void test_object_cache__fast_thread_rush(void) { - int try, th, data[THREADCOUNT*2]; + int try, th, data[THREADCOUNT]; #ifdef GIT_THREADS - git_thread t[THREADCOUNT*2]; + git_thread t[THREADCOUNT]; #endif for (try = 0; try < REPEAT; ++try) { cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - for (th = 0; th < THREADCOUNT*2; ++th) { + for (th = 0; th < THREADCOUNT; ++th) { data[th] = th; #ifdef GIT_THREADS cl_git_pass( @@ -274,7 +263,7 @@ } #ifdef GIT_THREADS - for (th = 0; th < THREADCOUNT*2; ++th) { + for (th = 0; th < THREADCOUNT; ++th) { void *rval; cl_git_pass(git_thread_join(&t[th], &rval)); cl_assert_equal_i(th, *((int *)rval)); diff -Nru libgit2-0.28.5+dfsg.1/tests/object/commit/commitstagedfile.c libgit2-1.1.0+dfsg.1/tests/object/commit/commitstagedfile.c --- libgit2-0.28.5+dfsg.1/tests/object/commit/commitstagedfile.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/commit/commitstagedfile.c 2020-10-12 18:53:06.000000000 +0000 @@ -49,9 +49,9 @@ * tree 2b297e643c551e76cfa1f93810c50811382f9117 * author nulltoken 1323847743 +0100 * committer nulltoken 1323847743 +0100 - * + * * Initial commit - * + * * diff --git a/test.txt b/test.txt * new file mode 100644 * index 0000000..9daeafb @@ -141,14 +141,14 @@ git_tree_free(tree); } -static void assert_commit_is_head_(git_commit *c, const char *file, int line) +static void assert_commit_is_head_(git_commit *c, const char *file, const char *func, int line) { git_commit *head; cl_git_pass(git_revparse_single((git_object **)&head, repo, "HEAD")); - clar__assert(git_oid_equal(git_commit_id(c), git_commit_id(head)), file, line, "Commit is not the HEAD", NULL, 1); + clar__assert(git_oid_equal(git_commit_id(c), git_commit_id(head)), file, func, line, "Commit is not the HEAD", NULL, 1); git_commit_free(head); } -#define assert_commit_is_head(C) assert_commit_is_head_((C),__FILE__,__LINE__) +#define assert_commit_is_head(C) assert_commit_is_head_((C),__FILE__,__func__,__LINE__) void test_object_commit_commitstagedfile__amend_commit(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/object/raw/write.c libgit2-1.1.0+dfsg.1/tests/object/raw/write.c --- libgit2-0.28.5+dfsg.1/tests/object/raw/write.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/raw/write.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "git2/odb_backend.h" -#include "fileops.h" +#include "futils.h" #include "odb.h" typedef struct object_data { diff -Nru libgit2-0.28.5+dfsg.1/tests/object/tag/list.c libgit2-1.1.0+dfsg.1/tests/object/tag/list.c --- libgit2-0.28.5+dfsg.1/tests/object/tag/list.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/tag/list.c 2020-10-12 18:53:06.000000000 +0000 @@ -50,7 +50,7 @@ cl_assert_equal_i((int)sucessfully_found, (int)data->expected_matches); exit: - git_strarray_free(&tag_list); + git_strarray_dispose(&tag_list); cl_git_pass(error); } @@ -74,7 +74,7 @@ cl_assert_equal_i((int)tag_list.count, 6); - git_strarray_free(&tag_list); + git_strarray_dispose(&tag_list); } static const struct pattern_match_t matches[] = { diff -Nru libgit2-0.28.5+dfsg.1/tests/object/tree/read.c libgit2-1.1.0+dfsg.1/tests/object/tree/read.c --- libgit2-0.28.5+dfsg.1/tests/object/tree/read.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/tree/read.c 2020-10-12 18:53:06.000000000 +0000 @@ -73,3 +73,47 @@ git_object_free(obj); git_tree_free(tree); } + +#define BIGFILE "bigfile" + +#ifdef GIT_ARCH_64 +#define BIGFILE_SIZE (off_t)4294967296 +#else +# define BIGFILE_SIZE SIZE_MAX +#endif + +void test_object_tree_read__largefile(void) +{ + const git_tree_entry *entry; + git_index_entry ie; + git_commit *commit; + git_object *object; + git_index *index; + git_tree *tree; + git_oid oid; + char *buf; + + if (!cl_is_env_set("GITTEST_INVASIVE_FS_SIZE")) + cl_skip(); + + cl_assert(buf = git__calloc(1, BIGFILE_SIZE)); + + memset(&ie, 0, sizeof(ie)); + ie.mode = GIT_FILEMODE_BLOB; + ie.path = BIGFILE; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_from_buffer(index, &ie, buf, BIGFILE_SIZE)); + cl_repo_commit_from_index(&oid, g_repo, NULL, 0, BIGFILE); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_git_pass(git_commit_tree(&tree, commit)); + cl_assert(entry = git_tree_entry_byname(tree, BIGFILE)); + cl_git_pass(git_tree_entry_to_object(&object, g_repo, entry)); + + git_object_free(object); + git_tree_free(tree); + git_index_free(index); + git_commit_free(commit); + git__free(buf); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/object/tree/write.c libgit2-1.1.0+dfsg.1/tests/object/tree/write.c --- libgit2-0.28.5+dfsg.1/tests/object/tree/write.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/object/tree/write.c 2020-10-12 18:53:06.000000000 +0000 @@ -453,7 +453,8 @@ git_oid valid_blob_id, invalid_blob_id, valid_tree_id, invalid_tree_id; #define assert_allowed(expr) \ - clar__assert(!(expr) == should_allow_invalid, __FILE__, __LINE__, \ + clar__assert(!(expr) == should_allow_invalid, \ + __FILE__, __func__, __LINE__, \ (should_allow_invalid ? \ "Expected function call to succeed: " #expr : \ "Expected function call to fail: " #expr), \ diff -Nru libgit2-0.28.5+dfsg.1/tests/odb/backend/mempack.c libgit2-1.1.0+dfsg.1/tests/odb/backend/mempack.c --- libgit2-0.28.5+dfsg.1/tests/odb/backend/mempack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/odb/backend/mempack.c 2020-10-12 18:53:06.000000000 +0000 @@ -51,10 +51,10 @@ cl_assert(git_odb_exists(_odb, &_oid) == 1); } -void test_odb_backend_mempack__blob_create_frombuffer_succeeds(void) +void test_odb_backend_mempack__blob_create_from_buffer_succeeds(void) { const char *data = "data"; - cl_git_pass(git_blob_create_frombuffer(&_oid, _repo, data, strlen(data) + 1)); + cl_git_pass(git_blob_create_from_buffer(&_oid, _repo, data, strlen(data) + 1)); cl_assert(git_odb_exists(_odb, &_oid) == 1); } diff -Nru libgit2-0.28.5+dfsg.1/tests/odb/freshen.c libgit2-1.1.0+dfsg.1/tests/odb/freshen.c --- libgit2-0.28.5+dfsg.1/tests/odb/freshen.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/odb/freshen.c 2020-10-12 18:53:06.000000000 +0000 @@ -47,7 +47,7 @@ set_time_wayback(&before, LOOSE_BLOB_FN); /* make sure we freshen a blob */ - cl_git_pass(git_blob_create_frombuffer(&id, repo, LOOSE_STR, CONST_STRLEN(LOOSE_STR))); + cl_git_pass(git_blob_create_from_buffer(&id, repo, LOOSE_STR, CONST_STRLEN(LOOSE_STR))); cl_assert_equal_oid(&expected_id, &id); cl_must_pass(p_lstat("testrepo.git/objects/" LOOSE_BLOB_FN, &after)); @@ -66,13 +66,13 @@ cl_git_pass(git_oid_fromstr(&expected_id, UNIQUE_BLOB_ID)); - cl_git_pass(git_blob_create_frombuffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR))); + cl_git_pass(git_blob_create_from_buffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR))); cl_assert_equal_oid(&expected_id, &id); set_time_wayback(&before, UNIQUE_BLOB_FN); cl_assert((before.st_mode & S_IWUSR) == 0); - cl_git_pass(git_blob_create_frombuffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR))); + cl_git_pass(git_blob_create_from_buffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR))); cl_assert_equal_oid(&expected_id, &id); cl_must_pass(p_lstat("testrepo.git/objects/" UNIQUE_BLOB_FN, &after)); diff -Nru libgit2-0.28.5+dfsg.1/tests/online/clone.c libgit2-1.1.0+dfsg.1/tests/online/clone.c --- libgit2-0.28.5+dfsg.1/tests/online/clone.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/clone.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/clone.h" #include "git2/cred_helpers.h" #include "remote.h" -#include "fileops.h" +#include "futils.h" #include "refs.h" #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" @@ -11,6 +11,7 @@ #define BB_REPO_URL "https://libgit3@bitbucket.org/libgit2/testgitrepository.git" #define BB_REPO_URL_WITH_PASS "https://libgit3:libgit3@bitbucket.org/libgit2/testgitrepository.git" #define BB_REPO_URL_WITH_WRONG_PASS "https://libgit3:wrong@bitbucket.org/libgit2/testgitrepository.git" +#define GOOGLESOURCE_REPO_URL "https://chromium.googlesource.com/external/github.com/sergi/go-diff" #define SSH_REPO_URL "ssh://github.com/libgit2/TestGitRepository" @@ -30,6 +31,7 @@ static char *_remote_proxy_user = NULL; static char *_remote_proxy_pass = NULL; static char *_remote_proxy_selfsigned = NULL; +static char *_remote_expectcontinue = NULL; static int _orig_proxies_need_reset = 0; static char *_orig_http_proxy = NULL; @@ -74,6 +76,10 @@ _remote_proxy_user = cl_getenv("GITTEST_REMOTE_PROXY_USER"); _remote_proxy_pass = cl_getenv("GITTEST_REMOTE_PROXY_PASS"); _remote_proxy_selfsigned = cl_getenv("GITTEST_REMOTE_PROXY_SELFSIGNED"); + _remote_expectcontinue = cl_getenv("GITTEST_REMOTE_EXPECTCONTINUE"); + + if (_remote_expectcontinue) + git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 1); _orig_proxies_need_reset = 0; } @@ -99,6 +105,7 @@ git__free(_remote_proxy_user); git__free(_remote_proxy_pass); git__free(_remote_proxy_selfsigned); + git__free(_remote_expectcontinue); if (_orig_proxies_need_reset) { cl_setenv("HTTP_PROXY", _orig_http_proxy); @@ -158,7 +165,7 @@ (*was_called) = true; } -static int fetch_progress(const git_transfer_progress *stats, void *payload) +static int fetch_progress(const git_indexer_progress *stats, void *payload) { bool *was_called = (bool*)payload; GIT_UNUSED(stats); @@ -169,7 +176,7 @@ void test_online_clone__can_checkout_a_cloned_repo(void) { git_buf path = GIT_BUF_INIT; - git_reference *head; + git_reference *head, *remote_head; bool checkout_progress_cb_was_called = false, fetch_progress_cb_was_called = false; @@ -188,9 +195,14 @@ cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + cl_git_pass(git_reference_lookup(&remote_head, g_repo, "refs/remotes/origin/HEAD")); + cl_assert_equal_i(GIT_REFERENCE_SYMBOLIC, git_reference_type(remote_head)); + cl_assert_equal_s("refs/remotes/origin/master", git_reference_symbolic_target(remote_head)); + cl_assert_equal_i(true, checkout_progress_cb_was_called); cl_assert_equal_i(true, fetch_progress_cb_was_called); + git_reference_free(remote_head); git_reference_free(head); git_buf_dispose(&path); } @@ -285,7 +297,7 @@ } static int cred_failure_cb( - git_cred **cred, + git_credential **cred, const char *url, const char *username_from_url, unsigned int allowed_types, @@ -309,22 +321,22 @@ cl_git_fail_with(-172, git_clone(&g_repo, _remote_url, "./foo", &g_options)); } -static int cred_count_calls_cb(git_cred **cred, const char *url, const char *user, +static int cred_count_calls_cb(git_credential **cred, const char *url, const char *user, unsigned int allowed_types, void *data) { size_t *counter = (size_t *) data; GIT_UNUSED(url); GIT_UNUSED(user); GIT_UNUSED(allowed_types); - if (allowed_types == GIT_CREDTYPE_USERNAME) - return git_cred_username_new(cred, "foo"); + if (allowed_types == GIT_CREDENTIAL_USERNAME) + return git_credential_username_new(cred, "foo"); (*counter)++; if (*counter == 3) return GIT_EUSER; - return git_cred_userpass_plaintext_new(cred, "foo", "bar"); + return git_credential_userpass_plaintext_new(cred, "foo", "bar"); } void test_online_clone__cred_callback_called_again_on_auth_failure(void) @@ -334,7 +346,7 @@ git__free(_remote_url); git__free(_remote_user); - _remote_url = git__strdup("https://github.com/libgit2/non-existent"); + _remote_url = git__strdup("https://gitlab.com/libgit2/non-existent"); _remote_user = git__strdup("libgit2test"); g_options.fetch_opts.callbacks.credentials = cred_count_calls_cb; @@ -345,7 +357,7 @@ } int cred_default( - git_cred **cred, + git_credential **cred, const char *url, const char *user_from_url, unsigned int allowed_types, @@ -355,10 +367,10 @@ GIT_UNUSED(user_from_url); GIT_UNUSED(payload); - if (!(allowed_types & GIT_CREDTYPE_DEFAULT)) + if (!(allowed_types & GIT_CREDENTIAL_DEFAULT)) return 0; - return git_cred_default_new(cred); + return git_credential_default_new(cred); } void test_online_clone__credentials(void) @@ -366,7 +378,7 @@ /* Remote URL environment variable must be set. * User and password are optional. */ - git_cred_userpass_payload user_pass = { + git_credential_userpass_payload user_pass = { _remote_user, _remote_pass }; @@ -377,7 +389,7 @@ if (cl_is_env_set("GITTEST_REMOTE_DEFAULT")) { g_options.fetch_opts.callbacks.credentials = cred_default; } else { - g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.credentials = git_credential_userpass; g_options.fetch_opts.callbacks.payload = &user_pass; } @@ -386,13 +398,28 @@ cl_fixture_cleanup("./foo"); } +void test_online_clone__credentials_via_custom_headers(void) +{ + const char *creds = "libgit3:libgit3"; + git_buf auth = GIT_BUF_INIT; + + cl_git_pass(git_buf_puts(&auth, "Authorization: Basic ")); + cl_git_pass(git_buf_encode_base64(&auth, creds, strlen(creds))); + g_options.fetch_opts.custom_headers.count = 1; + g_options.fetch_opts.custom_headers.strings = &auth.ptr; + + cl_git_pass(git_clone(&g_repo, "https://bitbucket.org/libgit2/testgitrepository.git", "./foo", &g_options)); + + git_buf_dispose(&auth); +} + void test_online_clone__bitbucket_style(void) { - git_cred_userpass_payload user_pass = { + git_credential_userpass_payload user_pass = { "libgit3", "libgit3" }; - g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.credentials = git_credential_userpass; g_options.fetch_opts.callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); @@ -402,16 +429,16 @@ void test_online_clone__bitbucket_uses_creds_in_url(void) { - git_cred_userpass_payload user_pass = { + git_credential_userpass_payload user_pass = { "libgit2", "wrong" }; - g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.credentials = git_credential_userpass; g_options.fetch_opts.callbacks.payload = &user_pass; /* * Correct user and pass are in the URL; the (incorrect) creds in - * the `git_cred_userpass_payload` should be ignored. + * the `git_credential_userpass_payload` should be ignored. */ cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -420,11 +447,11 @@ void test_online_clone__bitbucket_falls_back_to_specified_creds(void) { - git_cred_userpass_payload user_pass = { + git_credential_userpass_payload user_pass = { "libgit2", "libgit2" }; - g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.credentials = git_credential_userpass; g_options.fetch_opts.callbacks.payload = &user_pass; /* @@ -435,14 +462,21 @@ /* * Incorrect user and pass are in the URL; the (correct) creds in - * the `git_cred_userpass_payload` should be used as a fallback. + * the `git_credential_userpass_payload` should be used as a fallback. */ cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; cl_fixture_cleanup("./foo"); } -static int cancel_at_half(const git_transfer_progress *stats, void *payload) +void test_online_clone__googlesource(void) +{ + cl_git_pass(git_clone(&g_repo, GOOGLESOURCE_REPO_URL, "./foo", &g_options)); + git_repository_free(g_repo); g_repo = NULL; + cl_fixture_cleanup("./foo"); +} + +static int cancel_at_half(const git_indexer_progress *stats, void *payload) { GIT_UNUSED(payload); @@ -455,20 +489,20 @@ { g_options.fetch_opts.callbacks.transfer_progress = cancel_at_half; - cl_git_fail_with( - git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321); + cl_git_fail_with(4321, + git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); } -static int cred_cb(git_cred **cred, const char *url, const char *user_from_url, +static int cred_cb(git_credential **cred, const char *url, const char *user_from_url, unsigned int allowed_types, void *payload) { GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload); - if (allowed_types & GIT_CREDTYPE_USERNAME) - return git_cred_username_new(cred, _remote_user); + if (allowed_types & GIT_CREDENTIAL_USERNAME) + return git_credential_username_new(cred, _remote_user); - if (allowed_types & GIT_CREDTYPE_SSH_KEY) - return git_cred_ssh_key_new(cred, + if (allowed_types & GIT_CREDENTIAL_SSH_KEY) + return git_credential_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_privkey, _remote_ssh_passphrase); @@ -476,16 +510,16 @@ return -1; } -static int check_ssh_auth_methods(git_cred **cred, const char *url, const char *username_from_url, +static int check_ssh_auth_methods(git_credential **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data) { int *with_user = (int *) data; GIT_UNUSED(cred); GIT_UNUSED(url); GIT_UNUSED(username_from_url); GIT_UNUSED(data); if (!*with_user) - cl_assert_equal_i(GIT_CREDTYPE_USERNAME, allowed_types); + cl_assert_equal_i(GIT_CREDENTIAL_USERNAME, allowed_types); else - cl_assert(!(allowed_types & GIT_CREDTYPE_USERNAME)); + cl_assert(!(allowed_types & GIT_CREDENTIAL_USERNAME)); return GIT_EUSER; } @@ -560,13 +594,13 @@ cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options)); } -static int cred_foo_bar(git_cred **cred, const char *url, const char *username_from_url, +static int cred_foo_bar(git_credential **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data) { GIT_UNUSED(url); GIT_UNUSED(username_from_url); GIT_UNUSED(allowed_types); GIT_UNUSED(data); - return git_cred_userpass_plaintext_new(cred, "foo", "bar"); + return git_credential_userpass_plaintext_new(cred, "foo", "bar"); } void test_online_clone__ssh_cannot_change_username(void) @@ -643,20 +677,20 @@ return buf; } -static int ssh_memory_cred_cb(git_cred **cred, const char *url, const char *user_from_url, +static int ssh_memory_cred_cb(git_credential **cred, const char *url, const char *user_from_url, unsigned int allowed_types, void *payload) { GIT_UNUSED(url); GIT_UNUSED(user_from_url); GIT_UNUSED(payload); - if (allowed_types & GIT_CREDTYPE_USERNAME) - return git_cred_username_new(cred, _remote_user); + if (allowed_types & GIT_CREDENTIAL_USERNAME) + return git_credential_username_new(cred, _remote_user); - if (allowed_types & GIT_CREDTYPE_SSH_KEY) + if (allowed_types & GIT_CREDENTIAL_SSH_KEY) { char *pubkey = read_key_file(_remote_ssh_pubkey); char *privkey = read_key_file(_remote_ssh_privkey); - int ret = git_cred_ssh_key_memory_new(cred, _remote_user, pubkey, privkey, _remote_ssh_passphrase); + int ret = git_credential_ssh_key_memory_new(cred, _remote_user, pubkey, privkey, _remote_ssh_passphrase); if (privkey) free(privkey); @@ -682,12 +716,6 @@ cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options)); } -void test_online_clone__url_with_no_path_returns_EINVALIDSPEC(void) -{ - cl_git_fail_with(git_clone(&g_repo, "http://github.com", "./foo", &g_options), - GIT_EINVALIDSPEC); -} - static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload) { GIT_UNUSED(cert); @@ -737,7 +765,7 @@ } static int called_proxy_creds; -static int proxy_cred_cb(git_cred **out, const char *url, const char *username, unsigned int allowed, void *payload) +static int proxy_cred_cb(git_credential **out, const char *url, const char *username, unsigned int allowed, void *payload) { GIT_UNUSED(url); GIT_UNUSED(username); @@ -745,7 +773,7 @@ GIT_UNUSED(payload); called_proxy_creds = 1; - return git_cred_userpass_plaintext_new(out, _remote_proxy_user, _remote_proxy_pass); + return git_credential_userpass_plaintext_new(out, _remote_proxy_user, _remote_proxy_pass); } static int proxy_cert_cb(git_cert *cert, int valid, const char *host, void *payload) @@ -847,3 +875,37 @@ cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options)); } + +void test_online_clone__proxy_cred_callback_after_failed_url_creds(void) +{ + git_buf url = GIT_BUF_INIT; + + if (!_remote_proxy_host || !_remote_proxy_user || !_remote_proxy_pass) + cl_skip(); + + cl_git_pass(git_buf_printf(&url, "%s://invalid_user_name:INVALID_pass_WORD@%s/", + _remote_proxy_scheme ? _remote_proxy_scheme : "http", + _remote_proxy_host)); + + g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED; + g_options.fetch_opts.proxy_opts.url = url.ptr; + g_options.fetch_opts.proxy_opts.credentials = proxy_cred_cb; + g_options.fetch_opts.proxy_opts.certificate_check = proxy_cert_cb; + called_proxy_creds = 0; + cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options)); + cl_assert(called_proxy_creds); + + git_buf_dispose(&url); +} + +void test_online_clone__azurerepos(void) +{ + cl_git_pass(git_clone(&g_repo, "https://libgit2@dev.azure.com/libgit2/test/_git/test", "./foo", &g_options)); + cl_assert(git_path_exists("./foo/master.txt")); +} + +void test_online_clone__path_whitespace(void) +{ + cl_git_pass(git_clone(&g_repo, "https://libgit2@dev.azure.com/libgit2/test/_git/spaces%20in%20the%20name", "./foo", &g_options)); + cl_assert(git_path_exists("./foo/master.txt")); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/online/fetch.c libgit2-1.1.0+dfsg.1/tests/online/fetch.c --- libgit2-0.28.5+dfsg.1/tests/online/fetch.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/fetch.c 2020-10-12 18:53:06.000000000 +0000 @@ -25,7 +25,7 @@ return 0; } -static int progress(const git_transfer_progress *stats, void *payload) +static int progress(const git_indexer_progress *stats, void *payload) { size_t *bytes_received = (size_t *)payload; *bytes_received = stats->received_bytes; @@ -84,15 +84,15 @@ cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL)); cl_git_pass(git_remote_download(remote, NULL, NULL)); git_remote_disconnect(remote); - + git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL); cl_git_pass(git_remote_download(remote, NULL, NULL)); git_remote_disconnect(remote); - + git_remote_free(remote); } -static int transferProgressCallback(const git_transfer_progress *stats, void *payload) +static int transferProgressCallback(const git_indexer_progress *stats, void *payload) { bool *invoked = (bool *)payload; @@ -134,7 +134,7 @@ git_repository_free(_repository); } -static int cancel_at_half(const git_transfer_progress *stats, void *payload) +static int cancel_at_half(const git_indexer_progress *stats, void *payload) { GIT_UNUSED(payload); diff -Nru libgit2-0.28.5+dfsg.1/tests/online/fetchhead.c libgit2-1.1.0+dfsg.1/tests/online/fetchhead.c --- libgit2-0.28.5+dfsg.1/tests/online/fetchhead.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/fetchhead.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "fetchhead.h" #include "../fetchhead/fetchhead_data.h" #include "git2/clone.h" @@ -35,15 +35,15 @@ cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); } -static int count_references(void) +static size_t count_references(void) { git_strarray array; - int refs; + size_t refs; cl_git_pass(git_reference_list(&array, g_repo)); refs = array.count; - git_strarray_free(&array); + git_strarray_dispose(&array); return refs; } @@ -118,7 +118,7 @@ void test_online_fetchhead__explicit_dst_refspec_creates_branch(void) { git_reference *ref; - int refs; + size_t refs; fetchhead_test_clone(); refs = count_references(); @@ -133,7 +133,7 @@ void test_online_fetchhead__empty_dst_refspec_creates_no_branch(void) { git_reference *ref; - int refs; + size_t refs; fetchhead_test_clone(); refs = count_references(); @@ -146,7 +146,7 @@ void test_online_fetchhead__colon_only_dst_refspec_creates_no_branch(void) { - int refs; + size_t refs; fetchhead_test_clone(); refs = count_references(); @@ -161,12 +161,12 @@ git_remote *remote; cl_git_pass(git_repository_init(&g_repo, "./foo", 0)); - cl_git_pass(git_remote_create_anonymous(&remote, g_repo, "https://libgit3:libgit3@bitbucket.org/libgit2/testgitrepository.git")); + cl_git_pass(git_remote_create_anonymous(&remote, g_repo, "https://foo:bar@github.com/libgit2/TestGitRepository")); cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); cl_git_pass(git_futils_readbuffer(&buf, "./foo/.git/FETCH_HEAD")); cl_assert_equal_s(buf.ptr, - "49322bb17d3acc9146f98c97d078513228bbf3c0\t\thttps://bitbucket.org/libgit2/testgitrepository.git\n"); + "49322bb17d3acc9146f98c97d078513228bbf3c0\t\thttps://github.com/libgit2/TestGitRepository\n"); git_remote_free(remote); git_buf_dispose(&buf); diff -Nru libgit2-0.28.5+dfsg.1/tests/online/push.c libgit2-1.1.0+dfsg.1/tests/online/push.c --- libgit2-0.28.5+dfsg.1/tests/online/push.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/push.c 2020-10-12 18:53:06.000000000 +0000 @@ -19,8 +19,9 @@ static char *_remote_ssh_passphrase = NULL; static char *_remote_default = NULL; +static char *_remote_expectcontinue = NULL; -static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); +static int cred_acquire_cb(git_credential **, const char *, const char *, unsigned int, void *); static git_remote *_remote; static record_callbacks_data _record_cbs_data = {{ 0 }}; @@ -40,7 +41,7 @@ static git_oid _tag_tag; static int cred_acquire_cb( - git_cred **cred, + git_credential **cred, const char *url, const char *user_from_url, unsigned int allowed_types, @@ -50,40 +51,40 @@ GIT_UNUSED(user_from_url); GIT_UNUSED(payload); - if (GIT_CREDTYPE_USERNAME & allowed_types) { + if (GIT_CREDENTIAL_USERNAME & allowed_types) { if (!_remote_user) { printf("GITTEST_REMOTE_USER must be set\n"); return -1; } - return git_cred_username_new(cred, _remote_user); + return git_credential_username_new(cred, _remote_user); } - if (GIT_CREDTYPE_DEFAULT & allowed_types) { + if (GIT_CREDENTIAL_DEFAULT & allowed_types) { if (!_remote_default) { printf("GITTEST_REMOTE_DEFAULT must be set to use NTLM/Negotiate credentials\n"); return -1; } - return git_cred_default_new(cred); + return git_credential_default_new(cred); } - if (GIT_CREDTYPE_SSH_KEY & allowed_types) { + if (GIT_CREDENTIAL_SSH_KEY & allowed_types) { if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); return -1; } - return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); + return git_credential_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); } - if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { + if (GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) { if (!_remote_user || !_remote_pass) { printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_PASS must be set\n"); return -1; } - return git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass); + return git_credential_userpass_plaintext_new(cred, _remote_user, _remote_pass); } return -1; @@ -366,12 +367,16 @@ _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); _remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT"); + _remote_expectcontinue = cl_getenv("GITTEST_REMOTE_EXPECTCONTINUE"); _remote = NULL; /* Skip the test if we're missing the remote URL */ if (!_remote_url) cl_skip(); + if (_remote_expectcontinue) + git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 1); + cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); record_callbacks_data_clear(&_record_cbs_data); @@ -417,10 +422,13 @@ git__free(_remote_ssh_pubkey); git__free(_remote_ssh_passphrase); git__free(_remote_default); + git__free(_remote_expectcontinue); /* Freed by cl_git_sandbox_cleanup */ _repo = NULL; + git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 0); + record_callbacks_data_clear(&_record_cbs_data); cl_fixture_cleanup("testrepo.git"); diff -Nru libgit2-0.28.5+dfsg.1/tests/online/push_util.h libgit2-1.1.0+dfsg.1/tests/online/push_util.h --- libgit2-0.28.5+dfsg.1/tests/online/push_util.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/push_util.h 2020-10-12 18:53:06.000000000 +0000 @@ -12,7 +12,7 @@ * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, data, NULL } typedef struct { char *name; diff -Nru libgit2-0.28.5+dfsg.1/tests/online/remotes.c libgit2-1.1.0+dfsg.1/tests/online/remotes.c --- libgit2-0.28.5+dfsg.1/tests/online/remotes.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/online/remotes.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,7 +32,7 @@ } cl_assert_equal_i(1, count); - git_strarray_free(&refs); + git_strarray_dispose(&refs); cl_git_pass(git_remote_lookup(&remote, repo, "origin")); cl_git_pass(git_remote_get_fetch_refspecs(&refs, remote)); @@ -40,7 +40,7 @@ cl_assert_equal_i(1, refs.count); cl_assert_equal_s(REFSPEC, refs.strings[0]); - git_strarray_free(&refs); + git_strarray_dispose(&refs); git_remote_free(remote); git_repository_free(repo); } diff -Nru libgit2-0.28.5+dfsg.1/tests/pack/filelimit.c libgit2-1.1.0+dfsg.1/tests/pack/filelimit.c --- libgit2-0.28.5+dfsg.1/tests/pack/filelimit.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/pack/filelimit.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,136 @@ +#include "clar_libgit2.h" +#include "mwindow.h" +#include "global.h" + +#include +#include "git2/sys/commit.h" +#include "git2/sys/mempack.h" + +static size_t expected_open_mwindow_files = 0; +static size_t original_mwindow_file_limit = 0; + +extern git_mwindow_ctl git_mwindow__mem_ctl; + +void test_pack_filelimit__initialize_tiny(void) +{ + expected_open_mwindow_files = 1; + cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files)); +} + +void test_pack_filelimit__initialize_medium(void) +{ + expected_open_mwindow_files = 10; + cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, expected_open_mwindow_files)); +} + +void test_pack_filelimit__initialize_unlimited(void) +{ + expected_open_mwindow_files = 15; + cl_git_pass(git_libgit2_opts(GIT_OPT_GET_MWINDOW_FILE_LIMIT, &original_mwindow_file_limit)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, 0)); +} + +void test_pack_filelimit__cleanup(void) +{ + git_buf path = GIT_BUF_INIT; + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_MWINDOW_FILE_LIMIT, original_mwindow_file_limit)); + + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git")); + cl_fixture_cleanup(path.ptr); + git_buf_dispose(&path); +} + +/* + * Create a packfile with one commit, one tree, and two blobs. The first blob + * (README.md) has the same content in all commits, but the second one + * (file.txt) has a different content in each commit. + */ +void create_packfile_commit( + git_repository *repo, + git_oid *out_commit_id, + git_oid *parent_id, + size_t commit_index, + size_t commit_count) +{ + git_buf file_contents = GIT_BUF_INIT; + git_treebuilder *treebuilder; + git_packbuilder *packbuilder; + git_signature *s; + git_oid oid, tree_id, commit_id; + const git_oid *parents[] = { parent_id }; + size_t parent_count = parent_id ? 1 : 0; + + cl_git_pass(git_treebuilder_new(&treebuilder, repo, NULL)); + + cl_git_pass(git_blob_create_from_buffer(&oid, repo, "", 0)); + cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "README.md", &oid, 0100644)); + + cl_git_pass(git_buf_printf(&file_contents, "Commit %zd/%zd", commit_index, commit_count)); + cl_git_pass(git_blob_create_from_buffer(&oid, repo, file_contents.ptr, file_contents.size)); + cl_git_pass(git_treebuilder_insert(NULL, treebuilder, "file.txt", &oid, 0100644)); + + cl_git_pass(git_treebuilder_write(&tree_id, treebuilder)); + cl_git_pass(git_signature_now(&s, "alice", "alice@example.com")); + cl_git_pass(git_commit_create_from_ids(&commit_id, repo, "refs/heads/master", s, s, + NULL, file_contents.ptr, &tree_id, parent_count, parents)); + + cl_git_pass(git_packbuilder_new(&packbuilder, repo)); + cl_git_pass(git_packbuilder_insert_commit(packbuilder, &commit_id)); + cl_git_pass(git_packbuilder_write(packbuilder, NULL, 0, NULL, NULL)); + + cl_git_pass(git_oid_cpy(out_commit_id, &commit_id)); + + git_buf_dispose(&file_contents); + git_treebuilder_free(treebuilder); + git_packbuilder_free(packbuilder); + git_signature_free(s); +} + +void test_pack_filelimit__open_repo_with_multiple_packfiles(void) +{ + git_buf path = GIT_BUF_INIT; + git_mwindow_ctl *ctl = &git_mwindow__mem_ctl; + git_repository *repo; + git_revwalk *walk; + git_oid id, *parent_id = NULL; + size_t i; + const size_t commit_count = 16; + unsigned int open_windows; + + /* + * Create a repository and populate it with 16 commits, each in its own + * packfile. + */ + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "repo.git")); + cl_git_pass(git_repository_init(&repo, path.ptr, true)); + for (i = 0; i < commit_count; ++i) { + create_packfile_commit(repo, &id, parent_id, i + 1, commit_count); + parent_id = &id; + } + + cl_git_pass(git_revwalk_new(&walk, repo)); + cl_git_pass(git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL)); + cl_git_pass(git_revwalk_push_ref(walk, "refs/heads/master")); + + /* Walking the repository requires eventually opening each of the packfiles. */ + i = 0; + while (git_revwalk_next(&id, walk) == 0) + ++i; + cl_assert_equal_i(commit_count, i); + + cl_git_pass(git_mutex_lock(&git__mwindow_mutex)); + /* + * Adding an assert while holding a lock will cause the whole process to + * deadlock. Copy the value and do the assert after releasing the lock. + */ + open_windows = ctl->open_windows; + cl_git_pass(git_mutex_unlock(&git__mwindow_mutex)); + + cl_assert_equal_i(expected_open_mwindow_files, open_windows); + + git_buf_dispose(&path); + git_revwalk_free(walk); + git_repository_free(repo); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/pack/indexer.c libgit2-1.1.0+dfsg.1/tests/pack/indexer.c --- libgit2-0.28.5+dfsg.1/tests/pack/indexer.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/pack/indexer.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" #include -#include "fileops.h" +#include "futils.h" #include "hash.h" #include "iterator.h" #include "vector.h" @@ -98,7 +98,7 @@ void test_pack_indexer__out_of_order(void) { git_indexer *idx = 0; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL)); cl_git_pass(git_indexer_append( @@ -115,7 +115,7 @@ void test_pack_indexer__missing_trailer(void) { git_indexer *idx = 0; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL)); cl_git_pass(git_indexer_append( @@ -131,7 +131,7 @@ void test_pack_indexer__leaky(void) { git_indexer *idx = 0; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL)); cl_git_pass(git_indexer_append( @@ -147,7 +147,7 @@ void test_pack_indexer__fix_thin(void) { git_indexer *idx = NULL; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; git_repository *repo; git_odb *odb; git_oid id, should_id; @@ -213,7 +213,7 @@ void test_pack_indexer__corrupt_length(void) { git_indexer *idx = NULL; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; git_repository *repo; git_odb *odb; git_oid id, should_id; @@ -243,7 +243,7 @@ { git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT; git_indexer *idx = 0; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; opts.verify = 1; @@ -263,7 +263,7 @@ { git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT; git_indexer *idx = 0; - git_transfer_progress stats = { 0 }; + git_indexer_progress stats = { 0 }; opts.verify = 1; diff -Nru libgit2-0.28.5+dfsg.1/tests/pack/midx.c libgit2-1.1.0+dfsg.1/tests/pack/midx.c --- libgit2-0.28.5+dfsg.1/tests/pack/midx.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/pack/midx.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,29 @@ +#include "clar_libgit2.h" + +#include + +#include "midx.h" + +void test_pack_midx__parse(void) +{ + git_repository *repo; + struct git_midx_file *idx; + struct git_midx_entry e; + git_oid id; + git_buf midx_path = GIT_BUF_INIT; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_buf_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index")); + cl_git_pass(git_midx_open(&idx, git_buf_cstr(&midx_path))); + + cl_git_pass(git_oid_fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5")); + cl_git_pass(git_midx_entry_find(&e, idx, &id, GIT_OID_HEXSZ)); + cl_assert_equal_oid(&e.sha1, &id); + cl_assert_equal_s( + (const char *)git_vector_get(&idx->packfile_names, e.pack_index), + "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx"); + + git_midx_free(idx); + git_repository_free(repo); + git_buf_dispose(&midx_path); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/pack/packbuilder.c libgit2-1.1.0+dfsg.1/tests/pack/packbuilder.c --- libgit2-0.28.5+dfsg.1/tests/pack/packbuilder.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/pack/packbuilder.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "pack.h" #include "hash.h" #include "iterator.h" @@ -12,7 +12,9 @@ static git_indexer *_indexer; static git_vector _commits; static int _commits_is_initialized; -static git_transfer_progress _stats; +static git_indexer_progress _stats; + +extern bool git_disable_pack_keep_file_checks; void test_pack_packbuilder__initialize(void) { @@ -32,6 +34,7 @@ unsigned int i; cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 0)); + cl_git_pass(git_libgit2_opts(GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, false)); if (_commits_is_initialized) { _commits_is_initialized = 0; @@ -85,14 +88,14 @@ static int feed_indexer(void *ptr, size_t len, void *payload) { - git_transfer_progress *stats = (git_transfer_progress *)payload; + git_indexer_progress *stats = (git_indexer_progress *)payload; return git_indexer_append(_indexer, ptr, len, stats); } void test_pack_packbuilder__create_pack(void) { - git_transfer_progress stats; + git_indexer_progress stats; git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; git_hash_ctx ctx; git_oid hash; @@ -142,12 +145,21 @@ seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL); + cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL)); git_oid_fmt(hex, git_packbuilder_hash(_packbuilder)); cl_assert_equal_s(hex, "7f5fa362c664d68ba7221259be1cbd187434b2f0"); } +void test_pack_packbuilder__write_default_path(void) +{ + seed_packbuilder(); + + cl_git_pass(git_packbuilder_write(_packbuilder, NULL, 0, NULL, NULL)); + cl_assert(git_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx")); + cl_assert(git_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack")); +} + static void test_write_pack_permission(mode_t given, mode_t expected) { struct stat statbuf; @@ -155,7 +167,7 @@ seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", given, NULL, NULL); + cl_git_pass(git_packbuilder_write(_packbuilder, ".", given, NULL, NULL)); /* Windows does not return group/user bits from stat, * files are never executable. @@ -194,7 +206,7 @@ void test_pack_packbuilder__does_not_fsync_by_default(void) { seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL)); cl_assert_equal_sz(0, p_fsync__cnt); } @@ -212,7 +224,7 @@ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 1)); p_fsync__cnt = 0; seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL)); cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt); } @@ -221,7 +233,7 @@ cl_repo_set_bool(_repo, "core.fsyncObjectFiles", true); p_fsync__cnt = 0; seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL)); cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt); } @@ -260,3 +272,10 @@ git_packbuilder_foreach(_packbuilder, foreach_cancel_cb, idx), -1111); git_indexer_free(idx); } + +void test_pack_packbuilder__keep_file_check(void) +{ + assert(!git_disable_pack_keep_file_checks); + cl_git_pass(git_libgit2_opts(GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS, true)); + assert(git_disable_pack_keep_file_checks); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/pack/sharing.c libgit2-1.1.0+dfsg.1/tests/pack/sharing.c --- libgit2-0.28.5+dfsg.1/tests/pack/sharing.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/pack/sharing.c 2020-10-12 18:53:06.000000000 +0000 @@ -24,13 +24,13 @@ cl_git_pass(git_object_lookup(&obj2, repo2, &id, GIT_OBJECT_ANY)); pos = 0; - while ((error = git_strmap_next(&data, &pos, git__pack_cache)) == 0) { + while ((error = git_strmap_iterate(&data, git__pack_cache, &pos, NULL)) == 0) { struct git_pack_file *pack = (struct git_pack_file *) data; cl_assert_equal_i(2, pack->refcount.val); } - cl_assert_equal_i(3, git_strmap_num_entries(git__pack_cache)); + cl_assert_equal_i(3, git_strmap_size(git__pack_cache)); git_object_free(obj1); git_object_free(obj2); @@ -38,5 +38,5 @@ git_repository_free(repo2); /* we don't want to keep the packs open after the repos go away */ - cl_assert_equal_i(0, git_strmap_num_entries(git__pack_cache)); + cl_assert_equal_i(0, git_strmap_size(git__pack_cache)); } diff -Nru libgit2-0.28.5+dfsg.1/tests/patch/patch_common.h libgit2-1.1.0+dfsg.1/tests/patch/patch_common.h --- libgit2-0.28.5+dfsg.1/tests/patch/patch_common.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/patch/patch_common.h 2020-10-12 18:53:06.000000000 +0000 @@ -385,6 +385,38 @@ "@@ -9,0 +10 @@ below it!\n" \ "+insert at end\n" +#define PATCH_DELETED_FILE_2_HUNKS \ + "diff --git a/a b/a\n" \ + "index 7f129fd..af431f2 100644\n" \ + "--- a/a\n" \ + "+++ b/a\n" \ + "@@ -1 +1 @@\n" \ + "-a contents 2\n" \ + "+a contents\n" \ + "diff --git a/c/d b/c/d\n" \ + "deleted file mode 100644\n" \ + "index 297efb8..0000000\n" \ + "--- a/c/d\n" \ + "+++ /dev/null\n" \ + "@@ -1 +0,0 @@\n" \ + "-c/d contents\n" + +#define PATCH_DELETED_FILE_2_HUNKS_SHUFFLED \ + "diff --git a/c/d b/c/d\n" \ + "deleted file mode 100644\n" \ + "index 297efb8..0000000\n" \ + "--- a/c/d\n" \ + "+++ /dev/null\n" \ + "@@ -1 +0,0 @@\n" \ + "-c/d contents\n" \ + "diff --git a/a b/a\n" \ + "index 7f129fd..af431f2 100644\n" \ + "--- a/a\n" \ + "+++ b/a\n" \ + "@@ -1 +1 @@\n" \ + "-a contents 2\n" \ + "+a contents\n" + #define PATCH_SIMPLE_COMMIT \ "commit 15e119375018fba121cf58e02a9f17fe22df0df8\n" \ "Author: Edward Thomson \n" \ @@ -547,6 +579,14 @@ "rename from file.txt\n" \ "rename to newfile.txt\n" +#define PATCH_RENAME_EXACT_WITH_MODE \ + "diff --git a/RENAMED.md b/README.md\n" \ + "old mode 100644\n" \ + "new mode 100755\n" \ + "similarity index 100%\n" \ + "rename from RENAMED.md\n" \ + "rename to README.md\n" + #define PATCH_RENAME_SIMILAR \ "diff --git a/file.txt b/newfile.txt\n" \ "similarity index 77%\n" \ @@ -878,6 +918,12 @@ "index 27184d9..7c94f9e 100644\n" \ "Binary files a/binary.bin and b/binary.bin differ\n" +#define PATCH_ADD_BINARY_NOT_PRINTED \ + "diff --git a/test.bin b/test.bin\n" \ + "new file mode 100644\n" \ + "index 0000000..9e0f96a\n" \ + "Binary files /dev/null and b/test.bin differ\n" + #define PATCH_ORIGINAL_NEW_FILE_WITH_SPACE \ "diff --git a/sp ace.txt b/sp ace.txt\n" \ "new file mode 100644\n" \ diff -Nru libgit2-0.28.5+dfsg.1/tests/patch/print.c libgit2-1.1.0+dfsg.1/tests/patch/print.c --- libgit2-0.28.5+dfsg.1/tests/patch/print.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/patch/print.c 2020-10-12 18:53:06.000000000 +0000 @@ -107,6 +107,12 @@ strlen(PATCH_RENAME_EXACT)); } +void test_patch_print__rename_exact_with_mode(void) +{ + patch_print_from_patchfile(PATCH_RENAME_EXACT_WITH_MODE, + strlen(PATCH_RENAME_EXACT_WITH_MODE)); +} + void test_patch_print__rename_similar(void) { patch_print_from_patchfile(PATCH_RENAME_SIMILAR, @@ -172,3 +178,9 @@ patch_print_from_patchfile(PATCH_BINARY_NOT_PRINTED, strlen(PATCH_BINARY_NOT_PRINTED)); } + +void test_patch_print__binary_add_not_shown(void) +{ + patch_print_from_patchfile(PATCH_ADD_BINARY_NOT_PRINTED, + strlen(PATCH_ADD_BINARY_NOT_PRINTED)); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/path/core.c libgit2-1.1.0+dfsg.1/tests/path/core.c --- libgit2-0.28.5+dfsg.1/tests/path/core.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/path/core.c 2020-10-12 18:53:06.000000000 +0000 @@ -343,6 +343,16 @@ test_join_unrooted("c:/foo", 2, "c:/foo", "c:/asdf"); test_join_unrooted("c:/foo/bar", 2, "c:/foo/bar", "c:/asdf"); +#ifdef GIT_WIN32 + /* Paths starting with '\\' are absolute */ + test_join_unrooted("\\bar", 0, "\\bar", "c:/foo/"); + test_join_unrooted("\\\\network\\bar", 9, "\\\\network\\bar", "c:/foo/"); +#else + /* Paths starting with '\\' are not absolute on non-Windows systems */ + test_join_unrooted("/foo/\\bar", 4, "\\bar", "/foo"); + test_join_unrooted("c:/foo/\\bar", 7, "\\bar", "c:/foo/"); +#endif + /* Base is returned when it's provided and is the prefix */ test_join_unrooted("c:/foo/bar/foobar", 6, "c:/foo/bar/foobar", "c:/foo"); test_join_unrooted("c:/foo/bar/foobar", 10, "c:/foo/bar/foobar", "c:/foo/bar"); diff -Nru libgit2-0.28.5+dfsg.1/tests/path/win32.c libgit2-1.1.0+dfsg.1/tests/path/win32.c --- libgit2-0.28.5+dfsg.1/tests/path/win32.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/path/win32.c 2020-10-12 18:53:06.000000000 +0000 @@ -21,6 +21,21 @@ #endif } +void test_utf8_to_utf16_relative(const char* utf8_in, const wchar_t* utf16_expected) +{ +#ifdef GIT_WIN32 + git_win32_path path_utf16; + int path_utf16len; + + cl_assert((path_utf16len = git_win32_path_relative_from_utf8(path_utf16, utf8_in)) >= 0); + cl_assert_equal_wcs(utf16_expected, path_utf16); + cl_assert_equal_i(wcslen(utf16_expected), path_utf16len); +#else + GIT_UNUSED(utf8_in); + GIT_UNUSED(utf16_expected); +#endif +} + void test_path_win32__utf8_to_utf16(void) { #ifdef GIT_WIN32 @@ -129,6 +144,31 @@ #endif } +void test_path_win32__keeps_relative(void) +{ +#ifdef GIT_WIN32 + /* Relative paths stay relative */ + test_utf8_to_utf16_relative("Foo", L"Foo"); + test_utf8_to_utf16_relative("..\\..\\Foo", L"..\\..\\Foo"); + test_utf8_to_utf16_relative("Foo\\..", L"Foo\\.."); + test_utf8_to_utf16_relative("Foo\\..\\..", L"Foo\\..\\.."); + test_utf8_to_utf16_relative("Foo\\Bar", L"Foo\\Bar"); + test_utf8_to_utf16_relative("Foo\\..\\Bar", L"Foo\\..\\Bar"); + test_utf8_to_utf16_relative("../../Foo", L"..\\..\\Foo"); + test_utf8_to_utf16_relative("Foo/..", L"Foo\\.."); + test_utf8_to_utf16_relative("Foo/../..", L"Foo\\..\\.."); + test_utf8_to_utf16_relative("Foo/Bar", L"Foo\\Bar"); + test_utf8_to_utf16_relative("Foo/../Bar", L"Foo\\..\\Bar"); + test_utf8_to_utf16_relative("Foo/../Bar/", L"Foo\\..\\Bar\\"); + test_utf8_to_utf16_relative("", L""); + + /* Absolute paths are canonicalized */ + test_utf8_to_utf16_relative("\\Foo", L"\\\\?\\C:\\Foo"); + test_utf8_to_utf16_relative("/Foo/Bar/", L"\\\\?\\C:\\Foo\\Bar"); + test_utf8_to_utf16_relative("\\\\server\\c$\\unc\\path", L"\\\\?\\UNC\\server\\c$\\unc\\path"); +#endif +} + #ifdef GIT_WIN32 static void test_canonicalize(const wchar_t *in, const wchar_t *expected) { @@ -203,16 +243,6 @@ test_canonicalize(L"C:/Foo/Bar", L"C:\\Foo\\Bar"); test_canonicalize(L"C:/", L"C:\\"); - test_canonicalize(L"Foo\\\\Bar\\\\Asdf\\\\", L"Foo\\Bar\\Asdf"); - test_canonicalize(L"Foo\\\\Bar\\\\..\\\\Asdf\\", L"Foo\\Asdf"); - test_canonicalize(L"Foo\\\\Bar\\\\.\\\\Asdf\\", L"Foo\\Bar\\Asdf"); - test_canonicalize(L"Foo\\\\..\\Bar\\\\.\\\\Asdf\\", L"Bar\\Asdf"); - test_canonicalize(L"\\", L""); - test_canonicalize(L"", L""); - test_canonicalize(L"Foo\\..\\..\\..\\..", L""); - test_canonicalize(L"..\\..\\..\\..", L""); - test_canonicalize(L"\\..\\..\\..\\..", L""); - test_canonicalize(L"\\\\?\\C:\\Foo\\Bar", L"\\\\?\\C:\\Foo\\Bar"); test_canonicalize(L"\\\\?\\C:\\Foo\\Bar\\", L"\\\\?\\C:\\Foo\\Bar"); test_canonicalize(L"\\\\?\\C:\\\\Foo\\.\\Bar\\\\..\\", L"\\\\?\\C:\\Foo"); diff -Nru libgit2-0.28.5+dfsg.1/tests/README.md libgit2-1.1.0+dfsg.1/tests/README.md --- libgit2-0.28.5+dfsg.1/tests/README.md 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/README.md 2020-10-12 18:53:06.000000000 +0000 @@ -20,3 +20,29 @@ * Make sure everything is fine. * Send your pull request. That's it. + + +Memory leak checks +------------------ + +These are automatically run as part of CI, but if you want to check locally: + +#### Linux + +Uses [`valgrind`](http://www.valgrind.org/): + +```console +$ cmake -DBUILD_CLAR=ON -DVALGRIND=ON .. +$ cmake --build . +$ valgrind --leak-check=full --show-reachable=yes --num-callers=50 --suppressions=../libgit2_clar.supp \ + ./libgit2_clar +``` + +#### macOS + +Uses [`leaks`](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/FindingLeaks.html), which requires XCode installed: + +```console +$ MallocStackLogging=1 MallocScribble=1 MallocLogFile=/dev/null CLAR_AT_EXIT="leaks -quiet \$PPID" \ + ./libgit2_clar +``` diff -Nru libgit2-0.28.5+dfsg.1/tests/rebase/merge.c libgit2-1.1.0+dfsg.1/tests/rebase/merge.c --- libgit2-0.28.5+dfsg.1/tests/rebase/merge.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/rebase/merge.c 2020-10-12 18:53:06.000000000 +0000 @@ -44,6 +44,10 @@ git_status_list *status_list; const git_status_entry *status_entry; git_oid pick_id, file1_id; + git_oid master_id, beef_id; + + git_oid_fromstr(&master_id, "efad0b11c47cb2f0220cbd6f5b0f93bb99064b00"); + git_oid_fromstr(&beef_id, "b146bd7608eac53d9bf9e1a6963543588b555c64"); cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/beef")); cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/master")); @@ -53,6 +57,12 @@ cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, NULL)); + cl_assert_equal_s("refs/heads/beef", git_rebase_orig_head_name(rebase)); + cl_assert_equal_oid(&beef_id, git_rebase_orig_head_id(rebase)); + + cl_assert_equal_s("master", git_rebase_onto_name(rebase)); + cl_assert_equal_oid(&master_id, git_rebase_onto_id(rebase)); + cl_git_pass(git_rebase_next(&rebase_operation, rebase)); git_oid_fromstr(&pick_id, "da9c51a23d02d931a486f45ad18cda05cf5d2b94"); diff -Nru libgit2-0.28.5+dfsg.1/tests/rebase/sign.c libgit2-1.1.0+dfsg.1/tests/rebase/sign.c --- libgit2-0.28.5+dfsg.1/tests/rebase/sign.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/rebase/sign.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,243 @@ +#include "clar_libgit2.h" +#include "git2/rebase.h" + +static git_repository *repo; +static git_signature *signature; + +/* Fixture setup and teardown */ +void test_rebase_sign__initialize(void) +{ + repo = cl_git_sandbox_init("rebase"); + cl_git_pass(git_signature_new(&signature, "Rebaser", + "rebaser@rebaser.rb", 1405694510, 0)); +} + +void test_rebase_sign__cleanup(void) +{ + git_signature_free(signature); + cl_git_sandbox_cleanup(); +} + +static const char *expected_commit_content = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\ +parent f87d14a4a236582a0278a916340a793714256864\n\ +author Edward Thomson 1405625055 -0400\n\ +committer Rebaser 1405694510 +0000\n\ +\n\ +Modification 3 to gravy\n"; + +int signing_cb_passthrough( + git_buf *signature, + git_buf *signature_field, + const char *commit_content, + void *payload) +{ + cl_assert_equal_b(false, git_buf_is_allocated(signature)); + cl_assert_equal_b(false, git_buf_is_allocated(signature_field)); + cl_assert_equal_s(expected_commit_content, commit_content); + cl_assert_equal_p(NULL, payload); + return GIT_PASSTHROUGH; +} + +/* git checkout gravy ; git rebase --merge veal */ +void test_rebase_sign__passthrough_signing_cb(void) +{ + git_rebase *rebase; + git_reference *branch_ref, *upstream_ref; + git_annotated_commit *branch_head, *upstream_head; + git_rebase_operation *rebase_operation; + git_oid commit_id, expected_id; + git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT; + git_commit *commit; + const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\ +parent f87d14a4a236582a0278a916340a793714256864\n\ +author Edward Thomson 1405625055 -0400\n\ +committer Rebaser 1405694510 +0000\n"; + + rebase_opts.signing_cb = signing_cb_passthrough; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); + + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts)); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); + + git_oid_fromstr(&expected_id, "129183968a65abd6c52da35bff43325001bfc630"); + cl_assert_equal_oid(&expected_id, &commit_id); + + cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); + cl_assert_equal_s(expected_commit_raw_header, git_commit_raw_header(commit)); + + cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase)); + + git_reference_free(branch_ref); + git_reference_free(upstream_ref); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); + git_commit_free(commit); + git_rebase_free(rebase); +} + +int signing_cb_gpg( + git_buf *signature, + git_buf *signature_field, + const char *commit_content, + void *payload) +{ + const char *gpg_signature = "-----BEGIN PGP SIGNATURE-----\n\ +\n\ +iQIzBAEBCgAdFiEEgVlDEfSlmKn0fvGgK++h5T2/ctIFAlwZcrAACgkQK++h5T2/\n\ +ctIPVhAA42RyZhMdKl5Bm0KtQco2scsukIg2y7tjSwhti91zDu3HQgpusjjo0fQx\n\ +ZzB+OrmlvQ9CDcGpZ0THIzXD8GRJoDMPqdrvZVrBWkGcHvw7/YPA8skzsjkauJ8W\n\ +7lzF5LCuHSS6OUmPT/+5hEHPin5PB3zhfszyC+Q7aujnIuPJMrKiMnUa+w1HWifM\n\ +km49OOygQ9S6NQoVuEQede22+c76DlDL7yFghGoo1f0sKCE/9LW6SEnwI/bWv9eo\n\ +nom5vOPrvQeJiYCQk+2DyWo8RdSxINtY+G9bPE4RXm+6ZgcXECPm9TYDIWpL36fC\n\ +jvtGLs98woWFElOziBMp5Tb630GMcSI+q5ivHfJ3WS5NKLYLHBNK4iSFN0/dgAnB\n\ +dj6GcKXKWnIBWn6ZM4o40pcM5KSRUUCLtA0ZmjJH4c4zx3X5fUxd+enwkf3e9VZO\n\ +fNKC/+xfq6NfoPUPK9+UnchHpJaJw7RG5tZS+sWCz2xpQ1y3/o49xImNyM3wnpvB\n\ +cRAZabqIHpZa9/DIUkELOtCzln6niqkjRgg3M/YCCNznwV+0RNgz87VtyTPerdef\n\ +xrqn0+ROMF6ebVqIs6PPtuPkxnAJu7TMKXVB5rFnAewS24e6cIGFzeIA7810py3l\n\ +cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\ +=KbsY\n\ +-----END PGP SIGNATURE-----"; + + cl_assert_equal_b(false, git_buf_is_allocated(signature)); + cl_assert_equal_b(false, git_buf_is_allocated(signature_field)); + cl_assert_equal_s(expected_commit_content, commit_content); + cl_assert_equal_p(NULL, payload); + + cl_git_pass(git_buf_set(signature, gpg_signature, strlen(gpg_signature) + 1)); + return GIT_OK; +} + +/* git checkout gravy ; git rebase --merge veal */ +void test_rebase_sign__gpg_with_no_field(void) +{ + git_rebase *rebase; + git_reference *branch_ref, *upstream_ref; + git_annotated_commit *branch_head, *upstream_head; + git_rebase_operation *rebase_operation; + git_oid commit_id, expected_id; + git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT; + git_commit *commit; + const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\ +parent f87d14a4a236582a0278a916340a793714256864\n\ +author Edward Thomson 1405625055 -0400\n\ +committer Rebaser 1405694510 +0000\n\ +gpgsig -----BEGIN PGP SIGNATURE-----\n\ + \n\ + iQIzBAEBCgAdFiEEgVlDEfSlmKn0fvGgK++h5T2/ctIFAlwZcrAACgkQK++h5T2/\n\ + ctIPVhAA42RyZhMdKl5Bm0KtQco2scsukIg2y7tjSwhti91zDu3HQgpusjjo0fQx\n\ + ZzB+OrmlvQ9CDcGpZ0THIzXD8GRJoDMPqdrvZVrBWkGcHvw7/YPA8skzsjkauJ8W\n\ + 7lzF5LCuHSS6OUmPT/+5hEHPin5PB3zhfszyC+Q7aujnIuPJMrKiMnUa+w1HWifM\n\ + km49OOygQ9S6NQoVuEQede22+c76DlDL7yFghGoo1f0sKCE/9LW6SEnwI/bWv9eo\n\ + nom5vOPrvQeJiYCQk+2DyWo8RdSxINtY+G9bPE4RXm+6ZgcXECPm9TYDIWpL36fC\n\ + jvtGLs98woWFElOziBMp5Tb630GMcSI+q5ivHfJ3WS5NKLYLHBNK4iSFN0/dgAnB\n\ + dj6GcKXKWnIBWn6ZM4o40pcM5KSRUUCLtA0ZmjJH4c4zx3X5fUxd+enwkf3e9VZO\n\ + fNKC/+xfq6NfoPUPK9+UnchHpJaJw7RG5tZS+sWCz2xpQ1y3/o49xImNyM3wnpvB\n\ + cRAZabqIHpZa9/DIUkELOtCzln6niqkjRgg3M/YCCNznwV+0RNgz87VtyTPerdef\n\ + xrqn0+ROMF6ebVqIs6PPtuPkxnAJu7TMKXVB5rFnAewS24e6cIGFzeIA7810py3l\n\ + cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\ + =KbsY\n\ + -----END PGP SIGNATURE-----\n"; + + rebase_opts.signing_cb = signing_cb_gpg; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); + + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts)); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); + + git_oid_fromstr(&expected_id, "bf78348e45c8286f52b760f1db15cb6da030f2ef"); + cl_assert_equal_oid(&expected_id, &commit_id); + + cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); + cl_assert_equal_s(expected_commit_raw_header, git_commit_raw_header(commit)); + + cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase)); + + git_reference_free(branch_ref); + git_reference_free(upstream_ref); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); + git_commit_free(commit); + git_rebase_free(rebase); +} + + +int signing_cb_magic_field( + git_buf *signature, + git_buf *signature_field, + const char *commit_content, + void *payload) +{ + const char *signature_content = "magic word: pretty please"; + const char *signature_field_content = "magicsig"; + + cl_assert_equal_b(false, git_buf_is_allocated(signature)); + cl_assert_equal_b(false, git_buf_is_allocated(signature_field)); + cl_assert_equal_s(expected_commit_content, commit_content); + cl_assert_equal_p(NULL, payload); + + cl_git_pass(git_buf_set(signature, signature_content, + strlen(signature_content) + 1)); + cl_git_pass(git_buf_set(signature_field, signature_field_content, + strlen(signature_field_content) + 1)); + + return GIT_OK; +} + +/* git checkout gravy ; git rebase --merge veal */ +void test_rebase_sign__custom_signature_field(void) +{ + git_rebase *rebase; + git_reference *branch_ref, *upstream_ref; + git_annotated_commit *branch_head, *upstream_head; + git_rebase_operation *rebase_operation; + git_oid commit_id, expected_id; + git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT; + git_commit *commit; + const char *expected_commit_raw_header = "tree cd99b26250099fc38d30bfaed7797a7275ed3366\n\ +parent f87d14a4a236582a0278a916340a793714256864\n\ +author Edward Thomson 1405625055 -0400\n\ +committer Rebaser 1405694510 +0000\n\ +magicsig magic word: pretty please\n"; + + rebase_opts.signing_cb = signing_cb_magic_field; + + cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy")); + cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal")); + + cl_git_pass(git_annotated_commit_from_ref(&branch_head, repo, branch_ref)); + cl_git_pass(git_annotated_commit_from_ref(&upstream_head, repo, upstream_ref)); + + cl_git_pass(git_rebase_init(&rebase, repo, branch_head, upstream_head, NULL, &rebase_opts)); + + cl_git_pass(git_rebase_next(&rebase_operation, rebase)); + cl_git_pass(git_rebase_commit(&commit_id, rebase, NULL, signature, NULL, NULL)); + + git_oid_fromstr(&expected_id, "f46a4a8d26ae411b02aa61b7d69576627f4a1e1c"); + cl_assert_equal_oid(&expected_id, &commit_id); + + cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); + cl_assert_equal_s(expected_commit_raw_header, git_commit_raw_header(commit)); + + cl_git_fail_with(GIT_ITEROVER, git_rebase_next(&rebase_operation, rebase)); + + git_reference_free(branch_ref); + git_reference_free(upstream_ref); + git_annotated_commit_free(branch_head); + git_annotated_commit_free(upstream_head); + git_commit_free(commit); + git_rebase_free(rebase); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/basic.c libgit2-1.1.0+dfsg.1/tests/refs/basic.c --- libgit2-0.28.5+dfsg.1/tests/refs/basic.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/basic.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,44 @@ +#include "clar_libgit2.h" + +#include "futils.h" +#include "refs.h" +#include "ref_helpers.h" + +static git_repository *g_repo; + +static const char *loose_tag_ref_name = "refs/tags/e90810b"; + +void test_refs_basic__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); + cl_git_pass(git_repository_set_ident(g_repo, "me", "foo@example.com")); +} + +void test_refs_basic__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_basic__reference_realloc(void) +{ + git_reference *ref; + git_reference *new_ref; + const char *new_name = "refs/tags/awful/name-which-is/clearly/really-that-much/longer-than/the-old-one"; + + /* Retrieval of the reference to rename */ + cl_git_pass(git_reference_lookup(&ref, g_repo, loose_tag_ref_name)); + + new_ref = git_reference__realloc(&ref, new_name); + cl_assert(new_ref != NULL); + git_reference_free(new_ref); + git_reference_free(ref); + + /* Reload, so we restore the value */ + cl_git_pass(git_reference_lookup(&ref, g_repo, loose_tag_ref_name)); + + cl_git_pass(git_reference_rename(&new_ref, ref, new_name, 1, "log message")); + cl_assert(ref != NULL); + cl_assert(new_ref != NULL); + git_reference_free(new_ref); + git_reference_free(ref); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/branches/checkedout.c libgit2-1.1.0+dfsg.1/tests/refs/branches/checkedout.c --- libgit2-0.28.5+dfsg.1/tests/refs/branches/checkedout.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/branches/checkedout.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,53 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "worktree/worktree_helpers.h" + +static git_repository *repo; + +static void assert_checked_out(git_repository *repo, const char *branch, int checked_out) +{ + git_reference *ref; + + cl_git_pass(git_reference_lookup(&ref, repo, branch)); + cl_assert(git_branch_is_checked_out(ref) == checked_out); + + git_reference_free(ref); +} + +void test_refs_branches_checkedout__simple_repo(void) +{ + repo = cl_git_sandbox_init("testrepo"); + assert_checked_out(repo, "refs/heads/master", 1); + assert_checked_out(repo, "refs/heads/executable", 0); + cl_git_sandbox_cleanup(); +} + +void test_refs_branches_checkedout__worktree(void) +{ + static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT("testrepo", "testrepo-worktree"); + + setup_fixture_worktree(&fixture); + + assert_checked_out(fixture.repo, "refs/heads/master", 1); + assert_checked_out(fixture.repo, "refs/heads/testrepo-worktree", 1); + + assert_checked_out(fixture.worktree, "refs/heads/master", 1); + assert_checked_out(fixture.worktree, "refs/heads/testrepo-worktree", 1); + + cleanup_fixture_worktree(&fixture); +} + +void test_refs_branches_checkedout__head_is_not_checked_out(void) +{ + repo = cl_git_sandbox_init("testrepo"); + assert_checked_out(repo, "HEAD", 0); + cl_git_sandbox_cleanup(); +} + +void test_refs_branches_checkedout__master_in_bare_repo_is_not_checked_out(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); + assert_checked_out(repo, "refs/heads/master", 0); + cl_git_sandbox_cleanup(); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/branches/delete.c libgit2-1.1.0+dfsg.1/tests/refs/branches/delete.c --- libgit2-0.28.5+dfsg.1/tests/refs/branches/delete.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/branches/delete.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "refs.h" #include "repo/repo_helpers.h" #include "config/config_helpers.h" -#include "fileops.h" +#include "futils.h" #include "reflog.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/branches/lookup.c libgit2-1.1.0+dfsg.1/tests/refs/branches/lookup.c --- libgit2-0.28.5+dfsg.1/tests/refs/branches/lookup.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/branches/lookup.c 2020-10-12 18:53:06.000000000 +0000 @@ -20,20 +20,41 @@ repo = NULL; } -void test_refs_branches_lookup__can_retrieve_a_local_branch(void) +void test_refs_branches_lookup__can_retrieve_a_local_branch_local(void) { cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); } -void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch(void) +void test_refs_branches_lookup__can_retrieve_a_local_branch_all(void) +{ + cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_ALL)); +} + +void test_refs_branches_lookup__trying_to_retrieve_a_local_branch_remote(void) +{ + cl_git_fail(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_REMOTE)); +} + +void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch_remote(void) { cl_git_pass(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_REMOTE)); } +void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch_all(void) +{ + cl_git_pass(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_ALL)); +} + +void test_refs_branches_lookup__trying_to_retrieve_a_remote_tracking_branch_local(void) +{ + cl_git_fail(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_LOCAL)); +} + void test_refs_branches_lookup__trying_to_retrieve_an_unknown_branch_returns_ENOTFOUND(void) { cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "where/are/you", GIT_BRANCH_LOCAL)); cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "over/here", GIT_BRANCH_REMOTE)); + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "maybe/here", GIT_BRANCH_ALL)); } void test_refs_branches_lookup__trying_to_retrieve_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) @@ -42,4 +63,6 @@ git_branch_lookup(&branch, repo, "are/you/inv@{id", GIT_BRANCH_LOCAL)); cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_lookup(&branch, repo, "yes/i am", GIT_BRANCH_REMOTE)); + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_branch_lookup(&branch, repo, "inv al/id", GIT_BRANCH_ALL)); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/create.c libgit2-1.1.0+dfsg.1/tests/refs/create.c --- libgit2-0.28.5+dfsg.1/tests/refs/create.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/create.c 2020-10-12 18:53:06.000000000 +0000 @@ -212,17 +212,12 @@ void test_refs_create__propagate_eexists(void) { - int error; git_oid oid; - git_reference *ref; /* Make sure it works for oid and for symbolic both */ - git_oid_fromstr(&oid, current_master_tip); - error = git_reference_create(&ref, g_repo, current_head_target, &oid, false, NULL); - cl_assert(error == GIT_EEXISTS); - - error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false, NULL); - cl_assert(error == GIT_EEXISTS); + cl_git_pass(git_oid_fromstr(&oid, current_master_tip)); + cl_git_fail_with(GIT_EEXISTS, git_reference_create(NULL, g_repo, current_head_target, &oid, false, NULL)); + cl_git_fail_with(GIT_EEXISTS, git_reference_symbolic_create(NULL, g_repo, "HEAD", current_head_target, false, NULL)); } void test_refs_create__existing_dir_propagates_edirectory(void) diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/delete.c libgit2-1.1.0+dfsg.1/tests/refs/delete.c --- libgit2-0.28.5+dfsg.1/tests/refs/delete.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/delete.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/reflog.h" #include "git2/refdb.h" #include "reflog.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/foreachglob.c libgit2-1.1.0+dfsg.1/tests/refs/foreachglob.c --- libgit2-0.28.5+dfsg.1/tests/refs/foreachglob.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/foreachglob.c 2020-10-12 18:53:06.000000000 +0000 @@ -48,8 +48,8 @@ void test_refs_foreachglob__retrieve_all_refs(void) { - /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags */ - assert_retrieval("*", 22); + /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */ + assert_retrieval("*", 23); } void test_refs_foreachglob__retrieve_remote_branches(void) diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/iterator.c libgit2-1.1.0+dfsg.1/tests/refs/iterator.c --- libgit2-0.28.5+dfsg.1/tests/refs/iterator.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/iterator.c 2020-10-12 18:53:06.000000000 +0000 @@ -15,6 +15,7 @@ } static const char *refnames[] = { + "refs/blobs/annotated_tag_to_blob", "refs/heads/br2", "refs/heads/cannot-fetch", "refs/heads/chomped", @@ -40,6 +41,7 @@ }; static const char *refnames_with_symlink[] = { + "refs/blobs/annotated_tag_to_blob", "refs/heads/br2", "refs/heads/cannot-fetch", "refs/heads/chomped", @@ -99,7 +101,7 @@ git_vector output; git_reference *ref; - cl_git_pass(git_vector_init(&output, 32, &refcmp_cb)); + cl_git_pass(git_vector_init(&output, 33, &refcmp_cb)); cl_git_pass(git_reference_iterator_new(&iter, repo)); while (1) { @@ -143,7 +145,7 @@ void test_refs_iterator__foreach(void) { git_vector output; - cl_git_pass(git_vector_init(&output, 32, &refcmp_cb)); + cl_git_pass(git_vector_init(&output, 33, &refcmp_cb)); cl_git_pass(git_reference_foreach(repo, refs_foreach_cb, &output)); assert_all_refnames_match(refnames, &output); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/listall.c libgit2-1.1.0+dfsg.1/tests/refs/listall.c --- libgit2-0.28.5+dfsg.1/tests/refs/listall.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/listall.c 2020-10-12 18:53:06.000000000 +0000 @@ -16,7 +16,7 @@ for (i = 0; i < ref_list.count; i++) cl_assert(git__prefixcmp(ref_list.strings[i], "/") != 0); - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); git_repository_free(repo); } @@ -42,6 +42,6 @@ cl_assert(ref_list.count > 0); - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); git_repository_free(repo); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/list.c libgit2-1.1.0+dfsg.1/tests/refs/list.c --- libgit2-0.28.5+dfsg.1/tests/refs/list.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/list.c 2020-10-12 18:53:06.000000000 +0000 @@ -38,7 +38,7 @@ * loose, but we only list it once */ cl_assert_equal_i((int)ref_list.count, 19); - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); } void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_extension(void) @@ -53,5 +53,5 @@ cl_git_pass(git_reference_list(&ref_list, g_repo)); cl_assert_equal_i((int)ref_list.count, 19); - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/namespaces.c libgit2-1.1.0+dfsg.1/tests/refs/namespaces.c --- libgit2-0.28.5+dfsg.1/tests/refs/namespaces.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/namespaces.c 2020-10-12 18:53:06.000000000 +0000 @@ -32,5 +32,5 @@ cl_git_pass(git_repository_set_namespace(g_repo, "namespace")); cl_git_pass(git_reference_list(&ref_list, g_repo)); cl_assert_equal_i(0, ref_list.count); - git_strarray_free(&ref_list); + git_strarray_dispose(&ref_list); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/normalize.c libgit2-1.1.0+dfsg.1/tests/refs/normalize.c --- libgit2-0.28.5+dfsg.1/tests/refs/normalize.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/normalize.c 2020-10-12 18:53:06.000000000 +0000 @@ -352,12 +352,12 @@ void test_refs_normalize__refspec_pattern(void) { - ensure_refname_invalid( - GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar"); - ensure_refname_invalid( - GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar"); - ensure_refname_invalid( - GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar"); + ensure_refname_normalized( + GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar", "heads/*foo/bar"); + ensure_refname_normalized( + GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar", "heads/foo*/bar"); + ensure_refname_normalized( + GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar", "heads/f*o/bar"); ensure_refname_invalid( GIT_REFERENCE_FORMAT_REFSPEC_PATTERN, "foo"); diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/pack.c libgit2-1.1.0+dfsg.1/tests/refs/pack.c --- libgit2-0.28.5+dfsg.1/tests/refs/pack.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/pack.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/reflog.h" #include "git2/refdb.h" #include "reflog.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/reflog/messages.c libgit2-1.1.0+dfsg.1/tests/refs/reflog/messages.c --- libgit2-0.28.5+dfsg.1/tests/refs/reflog/messages.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/reflog/messages.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/reflog.h" #include "reflog.h" #include "refs.h" @@ -24,11 +24,8 @@ void test_refs_reflog_messages__setting_head_updates_reflog(void) { git_object *tag; - git_signature *sig; git_annotated_commit *annotated; - cl_git_pass(git_signature_now(&sig, "me", "foo@example.com")); - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); /* 4 */ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/unborn")); cl_git_pass(git_revparse_single(&tag, g_repo, "tags/test")); @@ -68,7 +65,6 @@ git_annotated_commit_free(annotated); git_object_free(tag); - git_signature_free(sig); } void test_refs_reflog_messages__setting_head_to_same_target_ignores_reflog(void) @@ -87,12 +83,9 @@ void test_refs_reflog_messages__detaching_writes_reflog(void) { - git_signature *sig; git_oid id; const char *msg; - cl_git_pass(git_signature_now(&sig, "me", "foo@example.com")); - msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d"; git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d"); cl_git_pass(git_repository_set_head_detached(g_repo, &id)); @@ -107,8 +100,6 @@ "e90810b8df3e80c413d903f631643c716887138d", "258f0e2a959a364e40ed6603d5d44fbb24765b10", NULL, msg); - - git_signature_free(sig); } void test_refs_reflog_messages__orphan_branch_does_not_count(void) @@ -281,6 +272,27 @@ git_reference_free(reference); } +void test_refs_reflog_messages__newline_gets_replaced(void) +{ + const git_reflog_entry *entry; + git_signature *signature; + git_reflog *reflog; + git_oid oid; + + cl_git_pass(git_signature_now(&signature, "me", "foo@example.com")); + cl_git_pass(git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); + + cl_git_pass(git_reflog_read(&reflog, g_repo, "HEAD")); + cl_assert_equal_sz(7, git_reflog_entrycount(reflog)); + cl_git_pass(git_reflog_append(reflog, &oid, signature, "inner\nnewline")); + cl_assert_equal_sz(8, git_reflog_entrycount(reflog)); + + cl_assert(entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_s(git_reflog_entry_message(entry), "inner newline"); + + git_signature_free(signature); + git_reflog_free(reflog); +} void test_refs_reflog_messages__renaming_ref(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/reflog/reflog.c libgit2-1.1.0+dfsg.1/tests/refs/reflog/reflog.c --- libgit2-0.28.5+dfsg.1/tests/refs/reflog/reflog.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/reflog/reflog.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/reflog.h" #include "reflog.h" @@ -87,15 +87,13 @@ cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); - - cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); cl_git_pass(git_reflog_append(reflog, &oid, committer, commit_msg "\n")); cl_git_pass(git_reflog_write(reflog)); - git_reflog_free(reflog); assert_appends(committer, &oid); + git_reflog_free(reflog); git_signature_free(committer); } @@ -224,45 +222,45 @@ git_buf_dispose(&subtrees_log_path); } -void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_returns_error(void) +void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_succeeds(void) { git_reflog *reflog; - const git_error *error; const char *refname = "refs/heads/newline"; const char *refmessage = "Reflog*message with a newline and enough content after it to pass the GIT_REFLOG_SIZE_MIN check inside reflog_parse."; + const git_reflog_entry *entry; git_reference *ref; git_oid id; git_buf logpath = GIT_BUF_INIT, logcontents = GIT_BUF_INIT; char *star; - git_oid_fromstr(&id, current_master_tip); - - /* create a new branch */ + /* Create a new branch. */ + cl_git_pass(git_oid_fromstr(&id, current_master_tip)); cl_git_pass(git_reference_create(&ref, g_repo, refname, &id, 1, refmessage)); - /* corrupt the branch reflog by introducing a newline inside the reflog message (we replace '*' with '\n') */ - git_buf_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname); + /* + * Corrupt the branch reflog by introducing a newline inside the reflog message. + * We do this by replacing '*' with '\n' + */ + cl_git_pass(git_buf_join_n(&logpath, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname)); cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath))); cl_assert((star = strchr(git_buf_cstr(&logcontents), '*')) != NULL); *star = '\n'; cl_git_rewritefile(git_buf_cstr(&logpath), git_buf_cstr(&logcontents)); - /* confirm that the file was rewritten successfully and now contains a '\n' in the expected location */ + /* + * Confirm that the file was rewritten successfully + * and now contains a '\n' in the expected location + */ cl_git_pass(git_futils_readbuffer(&logcontents, git_buf_cstr(&logpath))); cl_assert(strstr(git_buf_cstr(&logcontents), "Reflog\nmessage") != NULL); - /* clear the error state so we can capture the error generated by git_reflog_read */ - git_error_clear(); - - cl_git_fail(git_reflog_read(&reflog, g_repo, refname)); - - error = git_error_last(); - - cl_assert(error != NULL); - cl_assert_equal_s("unable to parse OID - contains invalid characters", error->message); + cl_git_pass(git_reflog_read(&reflog, g_repo, refname)); + cl_assert(entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_s(git_reflog_entry_message(entry), "Reflog"); git_reference_free(ref); + git_reflog_free(reflog); git_buf_dispose(&logpath); git_buf_dispose(&logcontents); } diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/reflog/reflog_helpers.c libgit2-1.1.0+dfsg.1/tests/refs/reflog/reflog_helpers.c --- libgit2-0.28.5+dfsg.1/tests/refs/reflog/reflog_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/reflog/reflog_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -29,7 +29,8 @@ void cl_reflog_check_entry_(git_repository *repo, const char *reflog, size_t idx, const char *old_spec, const char *new_spec, - const char *email, const char *message, const char *file, int line) + const char *email, const char *message, + const char *file, const char *func, int line) { git_reflog *log; const git_reflog_entry *entry; @@ -38,7 +39,7 @@ cl_git_pass(git_reflog_read(&log, repo, reflog)); entry = git_reflog_entry_byindex(log, idx); if (entry == NULL) - clar__fail(file, line, "Reflog has no such entry", NULL, 1); + clar__fail(file, func, line, "Reflog has no such entry", NULL, 1); if (old_spec) { git_object *obj = NULL; @@ -92,7 +93,7 @@ git_buf_printf(&result, "\tMessage: \"%s\" != \"%s\"\n", message, entry_msg); } if (git_buf_len(&result) != 0) - clar__fail(file, line, "Reflog entry mismatch", git_buf_cstr(&result), 1); + clar__fail(file, func, line, "Reflog entry mismatch", git_buf_cstr(&result), 1); git_buf_dispose(&result); git_reflog_free(log); diff -Nru libgit2-0.28.5+dfsg.1/tests/refs/rename.c libgit2-1.1.0+dfsg.1/tests/refs/rename.c --- libgit2-0.28.5+dfsg.1/tests/refs/rename.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/refs/rename.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "git2/reflog.h" #include "reflog.h" #include "refs.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/remote/create.c libgit2-1.1.0+dfsg.1/tests/remote/create.c --- libgit2-0.28.5+dfsg.1/tests/remote/create.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/remote/create.c 2020-10-12 18:53:06.000000000 +0000 @@ -117,7 +117,7 @@ cl_assert_equal_i(1, array.count); cl_assert_equal_i(section_count + 2, count_config_entries_match(_repo, "remote\\.")); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -132,7 +132,7 @@ cl_assert_equal_i(0, array.count); cl_assert_equal_i(section_count + 1, count_config_entries_match(_repo, "remote\\.")); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -167,7 +167,7 @@ cl_assert_equal_i(0, array.count); cl_assert_equal_i(section_count, count_config_entries_match(_repo, "remote\\.")); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -195,7 +195,7 @@ cl_assert_equal_i(0, array.count); cl_assert_equal_i(section_count, count_config_entries_match(_repo, "remote\\.")); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -225,7 +225,7 @@ cl_assert_equal_i(1, array.count); cl_assert_equal_s("+refs/heads/*:refs/remotes/test-new/*", array.strings[0]); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -248,7 +248,7 @@ cl_assert_equal_i(1, array.count); cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -270,7 +270,7 @@ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); cl_assert_equal_i(0, array.count); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -290,7 +290,7 @@ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); cl_assert_equal_i(0, array.count); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } @@ -308,7 +308,7 @@ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); cl_assert_equal_i(0, array.count); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); @@ -320,7 +320,7 @@ cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); cl_assert_equal_i(0, array.count); - git_strarray_free(&array); + git_strarray_dispose(&array); git_remote_free(remote); } diff -Nru libgit2-0.28.5+dfsg.1/tests/remote/list.c libgit2-1.1.0+dfsg.1/tests/remote/list.c --- libgit2-0.28.5+dfsg.1/tests/remote/list.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/remote/list.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,43 @@ +#include "clar_libgit2.h" +#include "config/config_helpers.h" + +static git_repository *_repo; + +#define TEST_URL "http://github.com/libgit2/libgit2.git" + +void test_remote_list__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo"); +} + +void test_remote_list__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_remote_list__always_checks_disk_config(void) +{ + git_repository *repo; + git_strarray remotes; + git_remote *remote; + + cl_git_pass(git_repository_open(&repo, git_repository_path(_repo))); + + cl_git_pass(git_remote_list(&remotes, _repo)); + cl_assert_equal_sz(remotes.count, 1); + git_strarray_dispose(&remotes); + + cl_git_pass(git_remote_create(&remote, _repo, "valid-name", TEST_URL)); + + cl_git_pass(git_remote_list(&remotes, _repo)); + cl_assert_equal_sz(remotes.count, 2); + git_strarray_dispose(&remotes); + + cl_git_pass(git_remote_list(&remotes, repo)); + cl_assert_equal_sz(remotes.count, 2); + git_strarray_dispose(&remotes); + + git_repository_free(repo); + git_remote_free(remote); +} + diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/config.c libgit2-1.1.0+dfsg.1/tests/repo/config.c --- libgit2-0.28.5+dfsg.1/tests/repo/config.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/config.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,6 +1,6 @@ #include "clar_libgit2.h" #include "sysdir.h" -#include "fileops.h" +#include "futils.h" #include static git_buf path = GIT_BUF_INIT; @@ -104,9 +104,9 @@ cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(GIT_ABBREV_DEFAULT, val); git_repository_free(repo); @@ -121,9 +121,9 @@ GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(10, val); git_repository_free(repo); @@ -136,9 +136,9 @@ GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(20, val); git_repository_free(repo); @@ -151,9 +151,9 @@ GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(30, val); git_repository_free(repo); @@ -162,18 +162,18 @@ cl_git_rewritefile("empty_standard_repo/.git/config", "[core]\n\tabbrev = 40\n"); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(40, val); git_repository_free(repo); /* with all configs but delete the files ? */ cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(40, val); cl_must_pass(p_unlink("empty_standard_repo/.git/config")); @@ -188,9 +188,9 @@ cl_must_pass(p_unlink("alternate/3/.gitconfig")); cl_assert(!git_path_isfile("alternate/3/.gitconfig")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(40, val); git_repository_free(repo); @@ -200,9 +200,9 @@ cl_assert(!git_path_isfile("alternate/3/.gitconfig")); cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); + git_repository__configmap_lookup_cache_clear(repo); val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_git_pass(git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_ABBREV)); cl_assert_equal_i(7, val); git_repository_free(repo); diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/discover.c libgit2-1.1.0+dfsg.1/tests/repo/discover.c --- libgit2-0.28.5+dfsg.1/tests/repo/discover.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/discover.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "odb.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" #define TEMP_REPO_FOLDER "temprepo/" diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/env.c libgit2-1.1.0+dfsg.1/tests/repo/env.c --- libgit2-0.28.5+dfsg.1/tests/repo/env.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/env.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "sysdir.h" #include @@ -53,44 +53,44 @@ * from the caller rather than those of the helper. The expression strings * distinguish between the possible failures within the helper. */ -static void env_pass_(const char *path, const char *file, int line) +static void env_pass_(const char *path, const char *file, const char *func, int line) { git_repository *repo; - cl_git_expect(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); - cl_git_expect(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); - cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line); - cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line); - cl_assert_at_line(!git_repository_is_bare(repo), file, line); + cl_git_expect(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, func, line); + cl_git_expect(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, func, line); + cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, func, line); + cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, func, line); + cl_assert_at_line(!git_repository_is_bare(repo), file, func, line); git_repository_free(repo); } -#define env_pass(path) env_pass_((path), __FILE__, __LINE__) +#define env_pass(path) env_pass_((path), __FILE__, __func__, __LINE__) -#define cl_git_fail_at_line(expr, file, line) clar__assert((expr) < 0, file, line, "Expected function call to fail: " #expr, NULL, 1) +#define cl_git_fail_at_line(expr, file, func, line) clar__assert((expr) < 0, file, func, line, "Expected function call to fail: " #expr, NULL, 1) -static void env_fail_(const char *path, const char *file, int line) +static void env_fail_(const char *path, const char *file, const char *func, int line) { git_repository *repo; - cl_git_fail_at_line(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - cl_git_fail_at_line(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_git_fail_at_line(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, func, line); + cl_git_fail_at_line(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, func, line); } -#define env_fail(path) env_fail_((path), __FILE__, __LINE__) +#define env_fail(path) env_fail_((path), __FILE__, __func__, __LINE__) static void env_cd_( const char *path, - void (*passfail_)(const char *, const char *, int), - const char *file, int line) + void (*passfail_)(const char *, const char *, const char *, int), + const char *file, const char *func, int line) { git_buf cwd_buf = GIT_BUF_INIT; cl_git_pass(git_path_prettify_dir(&cwd_buf, ".", NULL)); cl_must_pass(p_chdir(path)); - passfail_(NULL, file, line); + passfail_(NULL, file, func, line); cl_must_pass(p_chdir(git_buf_cstr(&cwd_buf))); git_buf_dispose(&cwd_buf); } -#define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __LINE__) -#define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __LINE__) +#define env_cd_pass(path) env_cd_((path), env_pass_, __FILE__, __func__, __LINE__) +#define env_cd_fail(path) env_cd_((path), env_fail_, __FILE__, __func__, __LINE__) -static void env_check_objects_(bool a, bool t, bool p, const char *file, int line) +static void env_check_objects_(bool a, bool t, bool p, const char *file, const char *func, int line) { git_repository *repo; git_oid oid_a, oid_t, oid_p; @@ -98,32 +98,32 @@ cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d")); cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08")); cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07")); - cl_git_expect(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); + cl_git_expect(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, func, line); if (a) { - cl_git_expect(git_object_lookup(&object, repo, &oid_a, GIT_OBJECT_BLOB), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_a, GIT_OBJECT_BLOB), 0, file, func, line); git_object_free(object); } else { - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJECT_BLOB), file, line); + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJECT_BLOB), file, func, line); } if (t) { - cl_git_expect(git_object_lookup(&object, repo, &oid_t, GIT_OBJECT_BLOB), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_t, GIT_OBJECT_BLOB), 0, file, func, line); git_object_free(object); } else { - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJECT_BLOB), file, line); + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJECT_BLOB), file, func, line); } if (p) { - cl_git_expect(git_object_lookup(&object, repo, &oid_p, GIT_OBJECT_COMMIT), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_p, GIT_OBJECT_COMMIT), 0, file, func, line); git_object_free(object); } else { - cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJECT_COMMIT), file, line); + cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJECT_COMMIT), file, func, line); } git_repository_free(repo); } -#define env_check_objects(a, t, t2) env_check_objects_((a), (t), (t2), __FILE__, __LINE__) +#define env_check_objects(a, t, t2) env_check_objects_((a), (t), (t2), __FILE__, __func__, __LINE__) void test_repo_env__open(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/init.c libgit2-1.1.0+dfsg.1/tests/repo/init.c --- libgit2-0.28.5+dfsg.1/tests/repo/init.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/init.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" #include "config.h" #include "path.h" @@ -13,20 +13,13 @@ static git_repository *_repo = NULL; static git_buf _global_path = GIT_BUF_INIT; -static mode_t g_umask = 0; void test_repo_init__initialize(void) { _repo = NULL; - /* load umask if not already loaded */ - if (!g_umask) { - g_umask = p_umask(022); - (void)p_umask(g_umask); - } - - git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, - &_global_path); + git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, + &_global_path); } void test_repo_init__cleanup(void) @@ -260,7 +253,7 @@ git_config *config, *repo_config; int val; - if (!filesystem_supports_symlinks("link")) + if (!git_path_supports_symlinks("link")) cl_skip(); create_tmp_global_config("tmp_global_config", "core.symlinks", "true"); @@ -303,7 +296,7 @@ cl_skip(); #else assert_config_entry_on_init( - "core.symlinks", filesystem_supports_symlinks("link") ? GIT_ENOTFOUND : false); + "core.symlinks", git_path_supports_symlinks("link") ? GIT_ENOTFOUND : false); #endif } @@ -380,17 +373,6 @@ assert_config_entry_on_init_bytype("core.logallrefupdates", true, false); } -void test_repo_init__empty_template_path(void) -{ - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - opts.template_path = ""; - - cl_git_pass(git_futils_mkdir("foo", 0755, 0)); - cl_git_pass(git_repository_init_ext(&_repo, "foo", &opts)); - - cleanup_repository("foo"); -} - void test_repo_init__extended_0(void) { git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; @@ -524,253 +506,6 @@ cleanup_repository("root"); } -#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) - -static void assert_hooks_match( - const char *template_dir, - const char *repo_dir, - const char *hook_path, - bool core_filemode) -{ - git_buf expected = GIT_BUF_INIT; - git_buf actual = GIT_BUF_INIT; - struct stat expected_st, st; - - cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path)); - cl_git_pass(git_path_lstat(expected.ptr, &expected_st)); - - cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); - cl_git_pass(git_path_lstat(actual.ptr, &st)); - - cl_assert(expected_st.st_size == st.st_size); - - if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { - mode_t expected_mode = - GIT_MODE_TYPE(expected_st.st_mode) | - (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask); - - if (!core_filemode) { - CLEAR_FOR_CORE_FILEMODE(expected_mode); - CLEAR_FOR_CORE_FILEMODE(st.st_mode); - } - - cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o"); - } - - git_buf_dispose(&expected); - git_buf_dispose(&actual); -} - -static void assert_mode_seems_okay( - const char *base, const char *path, - git_filemode_t expect_mode, bool expect_setgid, bool core_filemode) -{ - git_buf full = GIT_BUF_INIT; - struct stat st; - - cl_git_pass(git_buf_joinpath(&full, base, path)); - cl_git_pass(git_path_lstat(full.ptr, &st)); - git_buf_dispose(&full); - - if (!core_filemode) { - CLEAR_FOR_CORE_FILEMODE(expect_mode); - CLEAR_FOR_CORE_FILEMODE(st.st_mode); - expect_setgid = false; - } - - if (S_ISGID != 0) - cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); - - cl_assert_equal_b( - GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); - - cl_assert_equal_i_fmt( - GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); -} - -static const char *template_sandbox(const char *name) -{ - git_buf hooks_path = GIT_BUF_INIT, link_path = GIT_BUF_INIT, - dotfile_path = GIT_BUF_INIT; - const char *path = cl_fixture(name); - - cl_fixture_sandbox(name); - - /* create a symlink from link.sample to update.sample if the filesystem - * supports it. - */ - - cl_git_pass(git_buf_joinpath(&hooks_path, name, "hooks")); - cl_git_pass(git_buf_joinpath(&link_path, hooks_path.ptr, "link.sample")); - -#ifdef GIT_WIN32 - cl_git_mkfile(link_path.ptr, "#!/bin/sh\necho hello, world\n"); -#else - cl_must_pass(symlink("update.sample", link_path.ptr)); -#endif - - /* create a file starting with a dot */ - cl_git_pass(git_buf_joinpath(&dotfile_path, hooks_path.ptr, ".dotfile")); - cl_git_mkfile(dotfile_path.ptr, "something\n"); - git_buf_dispose(&dotfile_path); - - git_buf_dispose(&dotfile_path); - git_buf_dispose(&link_path); - git_buf_dispose(&hooks_path); - - return path; -} - -static void configure_templatedir(const char *template_path) -{ - create_tmp_global_config("tmp_global_path", "init.templatedir", template_path); -} - -static void validate_templates(git_repository *repo, const char *template_path) -{ - git_buf template_description = GIT_BUF_INIT; - git_buf repo_description = GIT_BUF_INIT; - git_buf expected = GIT_BUF_INIT; - git_buf actual = GIT_BUF_INIT; - int filemode; - - cl_git_pass(git_buf_joinpath(&template_description, template_path, - "description")); - cl_git_pass(git_buf_joinpath(&repo_description, git_repository_path(repo), - "description")); - - cl_git_pass(git_futils_readbuffer(&expected, template_description.ptr)); - cl_git_pass(git_futils_readbuffer(&actual, repo_description.ptr)); - - cl_assert_equal_s(expected.ptr, actual.ptr); - - filemode = cl_repo_get_bool(repo, "core.filemode"); - - assert_hooks_match( - template_path, git_repository_path(repo), - "hooks/update.sample", filemode); - - assert_hooks_match( - template_path, git_repository_path(repo), - "hooks/link.sample", filemode); - - assert_hooks_match( - template_path, git_repository_path(repo), - "hooks/.dotfile", filemode); - - git_buf_dispose(&expected); - git_buf_dispose(&actual); - git_buf_dispose(&repo_description); - git_buf_dispose(&template_description); -} - -void test_repo_init__external_templates_specified_in_options(void) -{ - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - - cl_set_cleanup(&cleanup_repository, "templated.git"); - template_sandbox("template"); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - opts.template_path = "template"; - - cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); - - cl_assert(git_repository_is_bare(_repo)); - - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/")); - - validate_templates(_repo, "template"); - cl_fixture_cleanup("template"); -} - -void test_repo_init__external_templates_specified_in_config(void) -{ - git_buf template_path = GIT_BUF_INIT; - - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - - cl_set_cleanup(&cleanup_repository, "templated.git"); - template_sandbox("template"); - - cl_git_pass(git_buf_joinpath(&template_path, clar_sandbox_path(), - "template")); - - configure_templatedir(template_path.ptr); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - - cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); - - validate_templates(_repo, "template"); - cl_fixture_cleanup("template"); - - git_buf_dispose(&template_path); -} - -void test_repo_init__external_templates_with_leading_dot(void) -{ - git_buf template_path = GIT_BUF_INIT; - - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - - cl_set_cleanup(&cleanup_repository, "templated.git"); - template_sandbox("template"); - - cl_must_pass(p_rename("template", ".template_with_leading_dot")); - - cl_git_pass(git_buf_joinpath(&template_path, clar_sandbox_path(), - ".template_with_leading_dot")); - - configure_templatedir(template_path.ptr); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - - cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); - - validate_templates(_repo, ".template_with_leading_dot"); - cl_fixture_cleanup(".template_with_leading_dot"); - - git_buf_dispose(&template_path); -} - -void test_repo_init__extended_with_template_and_shared_mode(void) -{ - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - int filemode = true; - const char *repo_path = NULL; - - cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl"); - template_sandbox("template"); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - opts.template_path = "template"; - opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; - - cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts)); - - cl_assert(!git_repository_is_bare(_repo)); - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); - - filemode = cl_repo_get_bool(_repo, "core.filemode"); - - repo_path = git_repository_path(_repo); - assert_mode_seems_okay(repo_path, "hooks", - GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); - assert_mode_seems_okay(repo_path, "info", - GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); - assert_mode_seems_okay(repo_path, "description", - GIT_FILEMODE_BLOB, false, filemode); - - validate_templates(_repo, "template"); - - cl_fixture_cleanup("template"); -} - void test_repo_init__can_reinit_an_initialized_repository(void) { git_repository *reinit; @@ -878,14 +613,71 @@ git_repository_free(repo); } -void test_repo_init__nonexistent_paths(void) +void test_repo_init__nonexisting_directory(void) { + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; git_repository *repo; + /* + * If creating a repo with non-existing parent directories, then libgit2 + * will by default create the complete directory hierarchy if using + * `git_repository_init`. Thus, let's use the extended version and not + * set the `GIT_REPOSITORY_INIT_MKPATH` flag. + */ + cl_git_fail(git_repository_init_ext(&repo, "nonexisting/path", &opts)); +} + +void test_repo_init__nonexisting_root(void) +{ #ifdef GIT_WIN32 + git_repository *repo; + + /* + * This really only depends on the nonexistence of the Q: drive. We + * cannot implement the equivalent test on Unix systems, as there is + * fundamentally no path that is disconnected from the root directory. + */ cl_git_fail(git_repository_init(&repo, "Q:/non/existent/path", 0)); cl_git_fail(git_repository_init(&repo, "Q:\\non\\existent\\path", 0)); #else - cl_git_fail(git_repository_init(&repo, "/non/existent/path", 0)); + clar__skip(); +#endif +} + +void test_repo_init__unwriteable_directory(void) +{ +#ifndef GIT_WIN32 + git_repository *repo; + + if (geteuid() == 0) + clar__skip(); + + /* + * Create a non-writeable directory so that we cannot create directories + * inside of it. The root user has CAP_DAC_OVERRIDE, so he doesn't care + * for the directory permissions and thus we need to skip the test if + * run as root user. + */ + cl_must_pass(p_mkdir("unwriteable", 0444)); + cl_git_fail(git_repository_init(&repo, "unwriteable/repo", 0)); + cl_must_pass(p_rmdir("unwriteable")); +#else + clar__skip(); #endif } + +void test_repo_init__defaultbranch_config(void) +{ + git_reference *head; + + cl_set_cleanup(&cleanup_repository, "repo"); + + create_tmp_global_config("tmp_global_path", "init.defaultbranch", "my_default_branch"); + + cl_git_pass(git_repository_init(&_repo, "repo", 0)); + cl_git_pass(git_reference_lookup(&head, _repo, "HEAD")); + + cl_assert_equal_s("refs/heads/my_default_branch", git_reference_symbolic_target(head)); + + git_reference_free(head); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/open.c libgit2-1.1.0+dfsg.1/tests/repo/open.c --- libgit2-0.28.5+dfsg.1/tests/repo/open.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/open.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "sysdir.h" #include @@ -35,7 +35,53 @@ git_config_free(config); git_repository_free(repo); + + cl_git_pass(git_repository_open(&repo, "empty_bare.git")); + cl_assert(git_repository_path(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); + git_repository_free(repo); +} + +void test_repo_open__format_version_1_with_valid_extension(void) +{ + git_repository *repo; + git_config *config; + + repo = cl_git_sandbox_init("empty_bare.git"); + + cl_git_pass(git_repository_open(&repo, "empty_bare.git")); + cl_git_pass(git_repository_config(&config, repo)); + + cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1)); + cl_git_pass(git_config_set_int32(config, "extensions.noop", 1)); + + git_config_free(config); + git_repository_free(repo); + + cl_git_pass(git_repository_open(&repo, "empty_bare.git")); + cl_assert(git_repository_path(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); + git_repository_free(repo); +} + +void test_repo_open__format_version_1_with_invalid_extension(void) +{ + git_repository *repo; + git_config *config; + + repo = cl_git_sandbox_init("empty_bare.git"); + + cl_git_pass(git_repository_open(&repo, "empty_bare.git")); + cl_git_pass(git_repository_config(&config, repo)); + + cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1)); + cl_git_pass(git_config_set_int32(config, "extensions.invalid", 1)); + + git_config_free(config); + git_repository_free(repo); + cl_git_fail(git_repository_open(&repo, "empty_bare.git")); + git_repository_free(repo); } void test_repo_open__standard_empty_repo_through_gitdir(void) @@ -129,6 +175,36 @@ git_repository_free(repo2); } +void test_repo_open__with_symlinked_config(void) +{ +#ifndef GIT_WIN32 + git_buf path = GIT_BUF_INIT; + git_repository *repo; + git_config *cfg; + int32_t value; + + cl_git_sandbox_init("empty_standard_repo"); + + /* Setup .gitconfig as symlink */ + cl_git_pass(git_futils_mkdir_r("home", 0777)); + cl_git_mkfile("home/.gitconfig.linked", "[global]\ntest = 4567\n"); + cl_must_pass(symlink(".gitconfig.linked", "home/.gitconfig")); + cl_git_pass(git_path_prettify(&path, "home", NULL)); + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_int32(&value, cfg, "global.test")); + cl_assert_equal_i(4567, value); + + git_config_free(cfg); + git_repository_free(repo); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + cl_sandbox_set_search_path_defaults(); + git_buf_dispose(&path); +#endif +} + void test_repo_open__from_git_new_workdir(void) { #ifndef GIT_WIN32 @@ -247,7 +323,9 @@ for (scan = bad_links; *scan != NULL; scan++) { make_gitlink_dir("alternate", *scan); + repo = NULL; cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); + cl_assert(repo == NULL); } git_futils_rmdir_r("invalid", NULL, GIT_RMDIR_REMOVE_FILES); diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/repo_helpers.c libgit2-1.1.0+dfsg.1/tests/repo/repo_helpers.c --- libgit2-0.28.5+dfsg.1/tests/repo/repo_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/repo_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -21,21 +21,6 @@ git_buf_dispose(&head_path); } -int filesystem_supports_symlinks(const char *path) -{ - struct stat st; - bool support = 0; - - if (p_symlink("target", path) == 0) { - if (p_lstat(path, &st) == 0 && S_ISLNK(st.st_mode)) - support = 1; - - p_unlink(path); - } - - return support; -} - void create_tmp_global_config(const char *dirname, const char *key, const char *val) { git_buf path = GIT_BUF_INIT; diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/repo_helpers.h libgit2-1.1.0+dfsg.1/tests/repo/repo_helpers.h --- libgit2-0.28.5+dfsg.1/tests/repo/repo_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/repo_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -4,5 +4,4 @@ extern void make_head_unborn(git_repository* repo, const char *target); extern void delete_head(git_repository* repo); -extern int filesystem_supports_symlinks(const char *path); extern void create_tmp_global_config(const char *path, const char *key, const char *val); diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/setters.c libgit2-1.1.0+dfsg.1/tests/repo/setters.c --- libgit2-0.28.5+dfsg.1/tests/repo/setters.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/setters.c 2020-10-12 18:53:06.000000000 +0000 @@ -5,7 +5,7 @@ #include "posix.h" #include "util.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/shallow.c libgit2-1.1.0+dfsg.1/tests/repo/shallow.c --- libgit2-0.28.5+dfsg.1/tests/repo/shallow.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/shallow.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo; diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/state.c libgit2-1.1.0+dfsg.1/tests/repo/state.c --- libgit2-0.28.5+dfsg.1/tests/repo/state.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/state.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "buffer.h" #include "refs.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" static git_repository *_repo; static git_buf _path; diff -Nru libgit2-0.28.5+dfsg.1/tests/repo/template.c libgit2-1.1.0+dfsg.1/tests/repo/template.c --- libgit2-0.28.5+dfsg.1/tests/repo/template.c 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/repo/template.c 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,295 @@ +#include "clar_libgit2.h" + +#include "futils.h" +#include "repo/repo_helpers.h" + +#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) + +static git_repository *_repo = NULL; +static mode_t g_umask = 0; +static git_buf _global_path = GIT_BUF_INIT; + +static const char *fixture_repo; +static const char *fixture_templates; + +void test_repo_template__initialize(void) +{ + _repo = NULL; + + /* load umask if not already loaded */ + if (!g_umask) { + g_umask = p_umask(022); + (void)p_umask(g_umask); + } +} + +void test_repo_template__cleanup(void) +{ + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, + _global_path.ptr); + git_buf_dispose(&_global_path); + + cl_fixture_cleanup("tmp_global_path"); + + if (fixture_repo) { + cl_fixture_cleanup(fixture_repo); + fixture_repo = NULL; + } + + if (fixture_templates) { + cl_fixture_cleanup(fixture_templates); + fixture_templates = NULL; + } + + git_repository_free(_repo); + _repo = NULL; +} + +static void assert_hooks_match( + const char *template_dir, + const char *repo_dir, + const char *hook_path, + bool core_filemode) +{ + git_buf expected = GIT_BUF_INIT; + git_buf actual = GIT_BUF_INIT; + struct stat expected_st, st; + + cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path)); + cl_git_pass(git_path_lstat(expected.ptr, &expected_st)); + + cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); + cl_git_pass(git_path_lstat(actual.ptr, &st)); + + cl_assert(expected_st.st_size == st.st_size); + + if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { + mode_t expected_mode = + GIT_MODE_TYPE(expected_st.st_mode) | + (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask); + + if (!core_filemode) { + CLEAR_FOR_CORE_FILEMODE(expected_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); + } + + cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o"); + } + + git_buf_dispose(&expected); + git_buf_dispose(&actual); +} + +static void assert_mode_seems_okay( + const char *base, const char *path, + git_filemode_t expect_mode, bool expect_setgid, bool core_filemode) +{ + git_buf full = GIT_BUF_INIT; + struct stat st; + + cl_git_pass(git_buf_joinpath(&full, base, path)); + cl_git_pass(git_path_lstat(full.ptr, &st)); + git_buf_dispose(&full); + + if (!core_filemode) { + CLEAR_FOR_CORE_FILEMODE(expect_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); + expect_setgid = false; + } + + if (S_ISGID != 0) + cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); + + cl_assert_equal_b( + GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); + + cl_assert_equal_i_fmt( + GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); +} + +static void setup_repo(const char *name, git_repository_init_options *opts) +{ + cl_git_pass(git_repository_init_ext(&_repo, name, opts)); + fixture_repo = name; +} + +static void setup_templates(const char *name, bool setup_globally) +{ + git_buf path = GIT_BUF_INIT; + + cl_fixture_sandbox("template"); + if (strcmp(name, "template")) + cl_must_pass(p_rename("template", name)); + + fixture_templates = name; + + /* + * Create a symlink from link.sample to update.sample if the filesystem + * supports it. + */ + cl_git_pass(git_buf_join3(&path, '/', name, "hooks", "link.sample")); +#ifdef GIT_WIN32 + cl_git_mkfile(path.ptr, "#!/bin/sh\necho hello, world\n"); +#else + cl_must_pass(p_symlink("update.sample", path.ptr)); +#endif + + git_buf_clear(&path); + + /* Create a file starting with a dot */ + cl_git_pass(git_buf_join3(&path, '/', name, "hooks", ".dotfile")); + cl_git_mkfile(path.ptr, "something\n"); + + git_buf_clear(&path); + + if (setup_globally) { + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), name)); + create_tmp_global_config("tmp_global_path", "init.templatedir", path.ptr); + } + + git_buf_dispose(&path); +} + +static void validate_templates(git_repository *repo, const char *template_path) +{ + git_buf path = GIT_BUF_INIT, expected = GIT_BUF_INIT, actual = GIT_BUF_INIT; + int filemode; + + cl_git_pass(git_buf_joinpath(&path, template_path, "description")); + cl_git_pass(git_futils_readbuffer(&expected, path.ptr)); + + git_buf_clear(&path); + + cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "description")); + cl_git_pass(git_futils_readbuffer(&actual, path.ptr)); + + cl_assert_equal_s(expected.ptr, actual.ptr); + + filemode = cl_repo_get_bool(repo, "core.filemode"); + + assert_hooks_match( + template_path, git_repository_path(repo), + "hooks/update.sample", filemode); + assert_hooks_match( + template_path, git_repository_path(repo), + "hooks/link.sample", filemode); + assert_hooks_match( + template_path, git_repository_path(repo), + "hooks/.dotfile", filemode); + + git_buf_dispose(&expected); + git_buf_dispose(&actual); + git_buf_dispose(&path); +} + +void test_repo_template__external_templates_specified_in_options(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = "template"; + + setup_templates("template", false); + setup_repo("templated.git", &opts); + + validate_templates(_repo, "template"); +} + +void test_repo_template__external_templates_specified_in_config(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + + setup_templates("template", true); + setup_repo("templated.git", &opts); + + validate_templates(_repo, "template"); +} + +void test_repo_template__external_templates_with_leading_dot(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + + setup_templates(".template_with_leading_dot", true); + setup_repo("templated.git", &opts); + + validate_templates(_repo, ".template_with_leading_dot"); +} + +void test_repo_template__extended_with_template_and_shared_mode(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + const char *repo_path; + int filemode; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = "template"; + opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; + + setup_templates("template", false); + setup_repo("init_shared_from_tpl", &opts); + + filemode = cl_repo_get_bool(_repo, "core.filemode"); + + repo_path = git_repository_path(_repo); + assert_mode_seems_okay(repo_path, "hooks", + GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); + assert_mode_seems_okay(repo_path, "info", + GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); + assert_mode_seems_okay(repo_path, "description", + GIT_FILEMODE_BLOB, false, filemode); + + validate_templates(_repo, "template"); +} + +void test_repo_template__templated_head_is_used(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_buf head = GIT_BUF_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + + setup_templates("template", true); + cl_git_mkfile("template/HEAD", "foobar\n"); + setup_repo("repo", &opts); + + cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD")); + cl_assert_equal_s("foobar\n", head.ptr); + + git_buf_dispose(&head); +} + +void test_repo_template__initial_head_option_overrides_template_head(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_buf head = GIT_BUF_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.initial_head = "manual"; + + setup_templates("template", true); + cl_git_mkfile("template/HEAD", "foobar\n"); + setup_repo("repo", &opts); + + cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD")); + cl_assert_equal_s("ref: refs/heads/manual\n", head.ptr); + + git_buf_dispose(&head); +} + +void test_repo_template__empty_template_path(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = ""; + + setup_repo("foo", &opts); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/reset/hard.c libgit2-1.1.0+dfsg.1/tests/reset/hard.c --- libgit2-0.28.5+dfsg.1/tests/reset/hard.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/reset/hard.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "reset_helpers.h" #include "path.h" -#include "fileops.h" +#include "futils.h" static git_repository *repo; static git_object *target; diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/attr/attr4 libgit2-1.1.0+dfsg.1/tests/resources/attr/attr4 --- libgit2-0.28.5+dfsg.1/tests/resources/attr/attr4 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/attr/attr4 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,7 @@ +# This is a comment + # This is also a comment +*.java diff=java -crlf myAttr + + NoMyAttr.java !myAttr + + README caveat=unspecified Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/1d/81379086fd6d91ee027e883cf6f4703a107dfb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/1d/81379086fd6d91ee027e883cf6f4703a107dfb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/34/73c3e21e76492d09b80b7c75569edc275dffcf and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/34/73c3e21e76492d09b80b7c75569edc275dffcf differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/40/fcae7fb84378fdb037dc6a3ccbb33669c3f26d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/40/fcae7fb84378fdb037dc6a3ccbb33669c3f26d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/46/ef45f4ae55c1f5dca64b9e1d7ca77c1798069b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/46/ef45f4ae55c1f5dca64b9e1d7ca77c1798069b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/4b/0ca755f5bfd69ed6074f268b05bb0542a42c68 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/4b/0ca755f5bfd69ed6074f268b05bb0542a42c68 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/4d/8400b7ce2d15ef5045c2775ed33e82a326786e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/4d/8400b7ce2d15ef5045c2775ed33e82a326786e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/6b/52ee554131a5e7bacd15553fbd22408c5a8a6f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/6b/52ee554131a5e7bacd15553fbd22408c5a8a6f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/70/2c7aa5250abc42be69ef78ee8fa47a346cb2ce and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/70/2c7aa5250abc42be69ef78ee8fa47a346cb2ce differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/77/c796837eb003c81d2cd8a6577ef4e7edc61222 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/77/c796837eb003c81d2cd8a6577ef4e7edc61222 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/7e/135d94af53b6c5edbae6a77df8a0f09375e823 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/7e/135d94af53b6c5edbae6a77df8a0f09375e823 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/92/5bddd7a536a66eecb32faa41abd5bc9c192311 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/92/5bddd7a536a66eecb32faa41abd5bc9c192311 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/a3/4ead35680be7b9704fc4c6d750d182e228e02b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/a3/4ead35680be7b9704fc4c6d750d182e228e02b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/a4/641ad869ffad601aa8347e0770e949bb6d90df and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/a4/641ad869ffad601aa8347e0770e949bb6d90df differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/ba/9089263dce882885ad84513f31495bf9d31132 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/ba/9089263dce882885ad84513f31495bf9d31132 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/c3/8d3c99946b74173f9b037279f07d505195563f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/c3/8d3c99946b74173f9b037279f07d505195563f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/c4/c13c153a611418325c70d6e630fed373546c4d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/c4/c13c153a611418325c70d6e630fed373546c4d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d2/bc4f27cbb72260eeec350087d81a60a122efe9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d2/bc4f27cbb72260eeec350087d81a60a122efe9 differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d3/c7316f0075debfe53b25e58f56b0a4b46e18c3 libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d3/c7316f0075debfe53b25e58f56b0a4b46e18c3 --- libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d3/c7316f0075debfe53b25e58f56b0a4b46e18c3 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d3/c7316f0075debfe53b25e58f56b0a4b46e18c3 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,4 @@ +xm“ÉΣH„çÌSÔÝš†b©*¤îQ³Û`³c7öÅl ¿—§wæÖyH)?)R©PF1].Ý ƒ…¿–¹ª@ž‰ YÄ•EEKˆ•„ Ws…¼KBŽ¥®Ù\ @Hàêšg9ÈU¹P| ª!/p"Ì!ÉD$Š„a +LeëÒN3Ч ÈÙ ø^OÓÏ9ËéRLóõ[1]þP +ˆP€`Ã@†¡>ôsàRÍ@ÉæEûÈFð½ø ?µûoð­Zÿ m®Í½kÀß¿JÖŒ \ÃÁΰ¥0òµßœè¼Ý[–$Y‘¤Rï4Mß«Ë9?ò¶{·–·äÙ.µÅ)æuià>$¥9{ÿs +¤X€w‰¦Oçi®&EÔ4‘<ÏVWr}fJ¥ewHÖÄ}«ü™eo¦ÖÖ £}ȼ1<ñrï'ÆÝG§‹Þ„·Ä"î';LëkÞDNoÕ­¢sÙ0Ú݃4+ºnŸò¸¯ XõUÒyð%èUUùaïŸlkñò°¬§MrzûvìÙuvÌCØ{”âñn6t¨?ýÙ“^I2:ÉgNG+§z©Ï®µš=WÌ=#Ì©ßÅæHbNj솇}Æøq( ƒ˜»Ž¯\)p×½ƒ·Cóôã\rÝ%+‡¡¹±e÷"Ùn§g $w¤3z¢>M•ˆ˜F`Òe¤R€N¢Îƒú»9´Èæ·*=O&]­t6È{Îa²žõR~Ìñ›°ËpiSÊNÃ’ Ý:ø@úu*ëBÏÖ¸ÛùÊ8²¸9^Ïr„)Ü´V +ÈÉü†¯Ý÷ ×:»lÛãM1`ˆØÏ|\k¸Kõ£©JÍh ¤ÜHpÖHzs%‹åRçûˆ÷v94Øóv_MAª(½E+QÑöf¥QsgA­÷Jî»6ÆFÎú/—xcòÒ+ߟհ«qœiäËáK苬Š_Æç'ÕÄÑŒG»UeÍQÀºÅy?!îkëØ{+0Æ’}7|cí^Cíż·£/FקXÖ( 29zÂ\6‡M`Ô£b¹ÏsÝ™F1½ÆÓcÞ¢ñËãt÷ƒ?y¨ÿ2£ÙêŸCIe òoËs¡þæÌIª \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d6/7268771ef5244f4aa224df29d4e4ae0bed2fd8 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d6/7268771ef5244f4aa224df29d4e4ae0bed2fd8 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d6/afeea2c4657c743dedab24a8a62da96f63547d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d6/afeea2c4657c743dedab24a8a62da96f63547d differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/d9/3e87a0863c7ec5e772f99e72ca9efddf0ca718 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/d9/3e87a0863c7ec5e772f99e72ca9efddf0ca718 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/f0/5190494260c2f6b6d045ac9bf27cb6d7e0abcc and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/f0/5190494260c2f6b6d045ac9bf27cb6d7e0abcc differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/f4/f4b926582a2c23c6e3ba05309eaa89244c1d68 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/f4/f4b926582a2c23c6e3ba05309eaa89244c1d68 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/objects/fa/01940156471352d5483b4f26b7c849dfaa7eef and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/objects/fa/01940156471352d5483b4f26b7c849dfaa7eef differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/refs/heads/master libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/refs/heads/master --- libgit2-0.28.5+dfsg.1/tests/resources/blametest.git/refs/heads/master 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/blametest.git/refs/heads/master 2020-10-12 18:53:06.000000000 +0000 @@ -1 +1 @@ -836bc00b06cb60eb0f629e237ad2b58adb2cfc7e +d93e87a0863c7ec5e772f99e72ca9efddf0ca718 diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/config/config12 libgit2-1.1.0+dfsg.1/tests/resources/config/config12 --- libgit2-0.28.5+dfsg.1/tests/resources/config/config12 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/config/config12 2020-10-12 18:53:06.000000000 +0000 @@ -11,3 +11,13 @@ multiline comment # with ;\n special chars \ and other stuff !@#" #^^^ back = "this is \ba phrase" + dollar = some $sign + multiquotes = !ls "x" \ + ls "# comment2" \ + $HOME + multiquotes2 = !ls "x" \ + ls "\"# comment2" \ + $HOME\" + multiquotes3 = hi "# ho" there "are #" more \ +quotes + quotecomment = hi "# ho" there "are #" more # and a real comment diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/config/config-oom libgit2-1.1.0+dfsg.1/tests/resources/config/config-oom --- libgit2-0.28.5+dfsg.1/tests/resources/config/config-oom 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/config/config-oom 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,40000 @@ +[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b +a=b diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/config libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/config --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/config 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/config 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true +[remote "origin"] + url = /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/HEAD libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/HEAD --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/HEAD 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ref: refs/heads/master diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/HEAD libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/HEAD --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/HEAD 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git +6b9d5748663795f573ea857276eb2a5f8330efa0 124f4293444614aa8da53be149792c2e43e9bfd9 Edward Thomson 1563721187 +0100 commit: subdir with no translation diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/refs/heads/master libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/refs/heads/master --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/refs/heads/master 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git +6b9d5748663795f573ea857276eb2a5f8330efa0 124f4293444614aa8da53be149792c2e43e9bfd9 Edward Thomson 1563721187 +0100 commit: subdir with no translation diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/refs/remotes/origin/HEAD libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/refs/remotes/origin/HEAD --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/logs/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/logs/refs/remotes/origin/HEAD 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/04/4bcd5c9bf5ebdd51e514a9a36457018f06f6e1 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/04/4bcd5c9bf5ebdd51e514a9a36457018f06f6e1 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/04/4bcd5c9bf5ebdd51e514a9a36457018f06f6e1 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/04/4bcd5c9bf5ebdd51e514a9a36457018f06f6e1 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +x-ŽÁjÃ0D{ÖWì½4H+Ù+C(É¡·þ„¤]aÓØJU…|}•˜Ã̃“ʺ. к·VE@²æÄv™ÑÈ”²ËvB½x=%‰êªl ÈsDÒÉx÷H¦!x3E9ÅA‡hPÆdU¸´¹Tøâk¨ {éký+ÛAžàµv©¬Ÿ`¬ŸŒC2|h¯µê´ŸlRá{Ù~/Ë]`zµÃ-Ì¥<ÄÝüÓ]×MÄ5¼?]ud†»ÔñÖòrõÄ&K! \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/04/de00b358f13389948756732158eaaaefa1448c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/04/de00b358f13389948756732158eaaaefa1448c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/09/7722be9b67b48dfe3b19396d02fd535300ee46 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/09/7722be9b67b48dfe3b19396d02fd535300ee46 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/0e/052888828a954ca17e5882638e3c6a083e75c0 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/0e/052888828a954ca17e5882638e3c6a083e75c0 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/12/4f4293444614aa8da53be149792c2e43e9bfd9 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/12/4f4293444614aa8da53be149792c2e43e9bfd9 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/12/4f4293444614aa8da53be149792c2e43e9bfd9 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/12/4f4293444614aa8da53be149792c2e43e9bfd9 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,4 @@ +x¥Ž] +Â0„}Î)ö]üm’‚ˆ/ÞÀ l“--ØDÒ¯ooàÓÌ|ÃIJ®KíÔ¡Uf`"Ǩ=Ùhº´ì­±Q*¶.80yñ¤Ê¹‡„ÞçŒpBo˜zíšp +ÆHžH +ÚÛ\*ÜÒ‹j‚û\Ö­d8s§wåoñK§XÖ (ì£Z©àá(•”¢Ó~¶ñŸ3bÛÇ´Tx-m†\ UÊÛƒÚR²xjöU× \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/16/78031ee023a23bd3515e4e1693b661a69f0a73 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/16/78031ee023a23bd3515e4e1693b661a69f0a73 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/16/c72b67861f8524a5bebc05cd20472d3fca00da and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/16/c72b67861f8524a5bebc05cd20472d3fca00da differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/18/c637c5d9aba6eed226ee1840cd1ca2e6c4e4c5 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/18/c637c5d9aba6eed226ee1840cd1ca2e6c4e4c5 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/20/3555c5676d75cd80d69b50beb1f4b588c59ceb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/20/3555c5676d75cd80d69b50beb1f4b588c59ceb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/23/f4582779e60bfa7f14750ad507399a58876611 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/23/f4582779e60bfa7f14750ad507399a58876611 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/2a/d3df895f68f4dda6a0a815c620b909bdd27c05 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/2a/d3df895f68f4dda6a0a815c620b909bdd27c05 differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/2b/55b4b94f655c857635b6a9005c056aa7de3532 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/2b/55b4b94f655c857635b6a9005c056aa7de3532 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/2b/55b4b94f655c857635b6a9005c056aa7de3532 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/2b/55b4b94f655c857635b6a9005c056aa7de3532 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +x-ŽKjÄ0D³Ö)z2tëcµa³™].¡O ›ÄV¢È„Éé£ µ¨zð RݶµƒÖøÔ›AvyIfLiò.²Ï…œPɘL0dÑõšì<ç¨=&b{Oñ.09o4Åœ¢ÃIË”Œ +G_jƒkþ -ÃYÆÚ¾ë~‘ðX§T·W ãØ°çÙ NˆjÐq²Kƒ·uÿ:Ö_óÇ£]na©õ.ž–÷áZ²Zk7!<#W½°ú²F \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/2b/d9d81b51a867352bab307b89cbb5b4a69adfe1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/2b/d9d81b51a867352bab307b89cbb5b4a69adfe1 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/2c/03f9f407b576eae80327864bab572e282a33ea and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/2c/03f9f407b576eae80327864bab572e282a33ea differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/33/cdead44e1c3ec178e39a4a69085280dbacf01b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/33/cdead44e1c3ec178e39a4a69085280dbacf01b differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/38/1cfe630df902bc29271a202d3277981180e4a6 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/38/1cfe630df902bc29271a202d3277981180e4a6 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/3f/96bdca0e37616026afaa325c148cec4aa62d04 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/3f/96bdca0e37616026afaa325c148cec4aa62d04 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/41/7786fc35b3c71aa546e3f95eb5da3c8dad8c41 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/41/7786fc35b3c71aa546e3f95eb5da3c8dad8c41 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/47/fbc2c28a18df0dc773276a253eb85c7516ca50 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/47/fbc2c28a18df0dc773276a253eb85c7516ca50 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/5a/fb6a14a864e30787857dd92af837e8cdd2cb1b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/5a/fb6a14a864e30787857dd92af837e8cdd2cb1b differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/68/03c385642cebc8103fddd526ef395d75678a7e libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/68/03c385642cebc8103fddd526ef395d75678a7e --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/68/03c385642cebc8103fddd526ef395d75678a7e 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/68/03c385642cebc8103fddd526ef395d75678a7e 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +x¥ÎKjÄ0ЬuŠ¾À},µ !dÉ &h·ZØ0²‚¬ÁäöQvÙgW¼‚¢¸–²u°ŸzËÚå9OAH¢v£ ÓB¬ØhÉ9!õEMö}œÑcžfÔ˜52vÙ%ëmä` /¬èÑ×Úà=ÔÜÖZŽºÃ‹ ýMoeãVšû3×ò +fr1ƒpÑ“Öjè8Úåêšäí.œ[_¡Ðþ Ÿ·K^©@ûèåükêÑ¡Yj \ No newline at end of file diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/69/597764abeaa1a403ebf589d2ea579c6a8f877e libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/69/597764abeaa1a403ebf589d2ea579c6a8f877e --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/69/597764abeaa1a403ebf589d2ea579c6a8f877e 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/69/597764abeaa1a403ebf589d2ea579c6a8f877e 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +xÎÑÂ0 €až3…ßOwr“&­%„`†NàÄŽˆ -JÃ!¶1|¿þ´Îsi`ݸkUÈ¢r.*{z¤‘Ägr>ɱcòbn\ui êcæ.x"’‚DÎ,–ÞN“Ã,†ïí¼V˜þu©Õ’.umgØëÌåzLÛïãü=@×[kðƒ¢IŸÇ¦ßismbY¸>!—«næJ“LÅ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/6a/e3e9c11a51f0aabebcffcbd5c00f4beed143c9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/6a/e3e9c11a51f0aabebcffcbd5c00f4beed143c9 differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/6b/9d5748663795f573ea857276eb2a5f8330efa0 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/6b/9d5748663795f573ea857276eb2a5f8330efa0 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/6b/9d5748663795f573ea857276eb2a5f8330efa0 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/6b/9d5748663795f573ea857276eb2a5f8330efa0 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +x¥ŽKÂ0CYç³Gªòk>B°à\`Ò™Ò.Ú 0ˆëS7`g?Ë–‡º,³€íÝN3°q1”³·¤=GN:e[Räb¡ 3{6êŽWÇÐxLÁ³Ó1ÅÔG¢lqLnkDv(¦(|ÊT\è…à:ÕåQW8ðF?êÄßà纡.G0}0ÎzìµÑZmt;+üçŒ:Aw›EÚ\žÂõY¦Sm \ No newline at end of file diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/6c/589757f65a970a6cc07c71c3f3d2528c611cbc libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/6c/589757f65a970a6cc07c71c3f3d2528c611cbc --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/6c/589757f65a970a6cc07c71c3f3d2528c611cbc 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/6c/589757f65a970a6cc07c71c3f3d2528c611cbc 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +x-ŽKNÃ0„Yçÿµò;Ž„PYp‚rÿ5j#Ç€¸=nÅnF3ói¸¬ëÒÀ…ñ©UUp$“dKÑbN£Ž¼)OL)`šPfµÃ'VÝpCV‰‘Y$ÏSÊÕ³³cÔqVIÑÎ:àW»” +çoÝàÜêÂ×ZÚ^tÅåvâýðÓGÑW°Á9gLš2<kÌÀM+¼Ko |\ʺ—­;ó®Núþݱîï£õ>$8˜Ð1ÛìeU eÃú órÓ}ø.Q¯ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/72/10e91413baa3d9b90215e970ae53397ecc526e and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/72/10e91413baa3d9b90215e970ae53397ecc526e differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/77/afe26d93c49279ca90604c125496920753fede and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/77/afe26d93c49279ca90604c125496920753fede differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/78/db270c1841841f75a8157321bdcb50ab12e6c3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/78/db270c1841841f75a8157321bdcb50ab12e6c3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/79/9770d1cff46753a57db7a066159b5610da6e3a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/79/9770d1cff46753a57db7a066159b5610da6e3a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/7c/ce67e58173e2b01f7db124ceaabe3183d19c49 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/7c/ce67e58173e2b01f7db124ceaabe3183d19c49 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/85/340755cfe5e28c2835781978bb1cece91b3d0f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/85/340755cfe5e28c2835781978bb1cece91b3d0f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/92/0e90a663bea5d740989d5f935f6dfb473a0c5d and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/92/0e90a663bea5d740989d5f935f6dfb473a0c5d differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/96/87e444bcbb85645cb496080434c292f1b57182 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/96/87e444bcbb85645cb496080434c292f1b57182 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/96/87e444bcbb85645cb496080434c292f1b57182 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/96/87e444bcbb85645cb496080434c292f1b57182 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +x¥ÎAJ1@Q×9Eí…!©T:™Y Þ¢ºRí´ÐMªAoïˆGpûŸ/mß7LùÁº*L¬Q‹„À)¬žyÑEÖU–šÄû•Õ(JqÜõfP2Q©Œ1¥”%¥™‰âL•æ¬Ó$QS Ž»¶¯,Ÿ‡xѾoãz|xzÿ³·ó°¾±ñIÚþ 0{ŠS@xôè½»ë}Õô_w©U+H»Ùï¾50†'û2÷ÿ=T‰ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/97/449da2d225557c558ac244384d487e66c3e591 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/97/449da2d225557c558ac244384d487e66c3e591 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/9a/6c3533fef19abd6eec8e61206b5c51982b80d9 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/9a/6c3533fef19abd6eec8e61206b5c51982b80d9 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/9d/29b5bb165bf65637ffcb5ededb82ddd7c3fd13 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/9d/29b5bb165bf65637ffcb5ededb82ddd7c3fd13 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/a2/34455d62297f1856c4603686150c59fcb0aafe and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/a2/34455d62297f1856c4603686150c59fcb0aafe differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +xKÊÉOR02aH.ÊIãåÂ$œž  \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/aa/f083a9cb53dac3669dcfa0e48921580d629ec7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/aa/f083a9cb53dac3669dcfa0e48921580d629ec7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/af/6fcf6da196f615d7cda269b55b5c4ecfb4a5b3 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/af/6fcf6da196f615d7cda269b55b5c4ecfb4a5b3 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/bb/29a7b46b5d4ba3ea17b238ae561b81d59dc818 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/bb/29a7b46b5d4ba3ea17b238ae561b81d59dc818 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/c3/e11722855ff260bd27418988ac1467c4e9e73a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/c3/e11722855ff260bd27418988ac1467c4e9e73a differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/c8/d0b1ebcaccdd8f968c4aae3c2175e7fed651fe libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/c8/d0b1ebcaccdd8f968c4aae3c2175e7fed651fe --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/c8/d0b1ebcaccdd8f968c4aae3c2175e7fed651fe 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/c8/d0b1ebcaccdd8f968c4aae3c2175e7fed651fe 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,2 @@ +x-ŽKnÃ0C»Ö)f8Ðod (‚tѤ4#؈e²ú9~• ;$˜öR–õK«ÌàIûˆ1*‡1;tfÌ9EdbŠ“&¢1™LʈÏPyk ­‰0ù˜‘#*FeƒÆY¥š²tÙ±á«Í{…Û7opkuI÷º·^¹„e½¦cøéÀ3ñ”ÕZ?™ NRI)Òócã +ïÔ[ó^Ž}ëãÎ|¨+?ƒwîƒÆTÆX ƒ´#Þˆ ,¿Lê°æ!Õ5C^V>Ä=ßR~ \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/cd/574f5a2baa4c79504f8837b730fa0b11defe99 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/cd/574f5a2baa4c79504f8837b730fa0b11defe99 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/cd/d3dacc5c0501d5ea57bbdf90e3d80176606139 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/cd/d3dacc5c0501d5ea57bbdf90e3d80176606139 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/d1/1e7ef63ba7db1db3b1b99cdbafc57a8549f8a4 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/d1/1e7ef63ba7db1db3b1b99cdbafc57a8549f8a4 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/dc/88e3b917de821e25962bea7ec1f55c4ce2112c and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/dc/88e3b917de821e25962bea7ec1f55c4ce2112c differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/de/5bfa165999d9d6c6dbafad2a7e709f93ec30fd and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/de/5bfa165999d9d6c6dbafad2a7e709f93ec30fd differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/e0/be8c0fa467f0a554484347c12802799d6c04fa and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/e0/be8c0fa467f0a554484347c12802799d6c04fa differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/e1/379fd9942d04e7e80892b866d37bdb7da9e4e1 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/e1/379fd9942d04e7e80892b866d37bdb7da9e4e1 differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/e5/062da7d7802cf492975eda580f09ac4876bd88 libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/e5/062da7d7802cf492975eda580f09ac4876bd88 --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/e5/062da7d7802cf492975eda580f09ac4876bd88 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/e5/062da7d7802cf492975eda580f09ac4876bd88 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +x¥QŠ1DýÎ)új'd2"‹û)þxNÒÃÆ,3¯ï¸xÿª^AQ•j)×ÆÛU›D`ŽÔiJÖ»>Fc:D´&Rr.†ì1#÷ÎDõÇ“Ü¥,œ­H’î‚PÏ–}Á™€9rPGÅ6Ö ~ó“§ —±–¹Þa/ }«ƒü·Iµü€¶DÎx$k´ˆj¡ËØ&_Ö¨GÂæZ–¿×›ÌðÜ›Áñ|šÕ ǸUë \ No newline at end of file Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/ea/030d3c6cec212069eca698cabaa5b4550f1511 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/ea/030d3c6cec212069eca698cabaa5b4550f1511 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/ea/a6ce5bc192f4c3c19354e7434c01e4686e95d7 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/ea/a6ce5bc192f4c3c19354e7434c01e4686e95d7 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87ceb and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/ef/0dcd356d77221e9c27f4f3928ad28e80b87ceb differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/f2/b745d7f47d114a3a6b31a7b628e61e804d1a58 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/f2/b745d7f47d114a3a6b31a7b628e61e804d1a58 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/f4/d25b796d86387205a5498175d66e91d1e5006a and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/f4/d25b796d86387205a5498175d66e91d1e5006a differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/fa/1385d99a319b43c06f5309d1aae9fdd3adea46 and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/fa/1385d99a319b43c06f5309d1aae9fdd3adea46 differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/fe/085d9ace90cc675b87df15e1aeed0c3a31407f and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/fe/085d9ace90cc675b87df15e1aeed0c3a31407f differ Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/objects/fe/ab3713c4659bb22700042b3c55b8d60d0a952b and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/objects/fe/ab3713c4659bb22700042b3c55b8d60d0a952b differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/packed-refs libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/packed-refs --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/packed-refs 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/packed-refs 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1,3 @@ +# pack-refs with: peeled fully-peeled sorted +9687e444bcbb85645cb496080434c292f1b57182 refs/remotes/origin/empty-files +6b9d5748663795f573ea857276eb2a5f8330efa0 refs/remotes/origin/master diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/heads/empty-files libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/heads/empty-files --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/heads/empty-files 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/heads/empty-files 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +9687e444bcbb85645cb496080434c292f1b57182 diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/heads/master libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/heads/master --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/heads/master 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +124f4293444614aa8da53be149792c2e43e9bfd9 diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/remotes/origin/HEAD libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/remotes/origin/HEAD --- libgit2-0.28.5+dfsg.1/tests/resources/crlf.git/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/crlf.git/refs/remotes/origin/HEAD 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +ref: refs/remotes/origin/master Binary files /tmp/tmp4GomiV/yzjCuY61vq/libgit2-0.28.5+dfsg.1/tests/resources/testrepo.git/objects/pack/multi-pack-index and /tmp/tmp4GomiV/e74VJJGyUw/libgit2-1.1.0+dfsg.1/tests/resources/testrepo.git/objects/pack/multi-pack-index differ diff -Nru libgit2-0.28.5+dfsg.1/tests/resources/testrepo.git/refs/blobs/annotated_tag_to_blob libgit2-1.1.0+dfsg.1/tests/resources/testrepo.git/refs/blobs/annotated_tag_to_blob --- libgit2-0.28.5+dfsg.1/tests/resources/testrepo.git/refs/blobs/annotated_tag_to_blob 1970-01-01 00:00:00.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/resources/testrepo.git/refs/blobs/annotated_tag_to_blob 2020-10-12 18:53:06.000000000 +0000 @@ -0,0 +1 @@ +521d87c1ec3aef9824daf6d96cc0ae3710766d91 diff -Nru libgit2-0.28.5+dfsg.1/tests/revert/bare.c libgit2-1.1.0+dfsg.1/tests/revert/bare.c --- libgit2-0.28.5+dfsg.1/tests/revert/bare.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/revert/bare.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "git2/revert.h" #include "../merge/merge_helpers.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/revert/workdir.c libgit2-1.1.0+dfsg.1/tests/revert/workdir.c --- libgit2-0.28.5+dfsg.1/tests/revert/workdir.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/revert/workdir.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" #include "git2/revert.h" #include "../merge/merge_helpers.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/revwalk/basic.c libgit2-1.1.0+dfsg.1/tests/revwalk/basic.c --- libgit2-0.28.5+dfsg.1/tests/revwalk/basic.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/revwalk/basic.c 2020-10-12 18:53:06.000000000 +0000 @@ -400,6 +400,24 @@ cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 2)); } +void test_revwalk_basic__push_range_merge_base(void) +{ + revwalk_basic_setup_walk(NULL); + + git_revwalk_reset(_walk); + git_revwalk_sorting(_walk, 0); + cl_git_fail_with(GIT_EINVALIDSPEC, git_revwalk_push_range(_walk, "HEAD...HEAD~2")); +} + +void test_revwalk_basic__push_range_no_range(void) +{ + revwalk_basic_setup_walk(NULL); + + git_revwalk_reset(_walk); + git_revwalk_sorting(_walk, 0); + cl_git_fail_with(GIT_EINVALIDSPEC, git_revwalk_push_range(_walk, "HEAD")); +} + void test_revwalk_basic__push_mixed(void) { git_oid oid; diff -Nru libgit2-0.28.5+dfsg.1/tests/stash/apply.c libgit2-1.1.0+dfsg.1/tests/stash/apply.c --- libgit2-0.28.5+dfsg.1/tests/stash/apply.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stash/apply.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "stash_helpers.h" static git_signature *signature; diff -Nru libgit2-0.28.5+dfsg.1/tests/stash/drop.c libgit2-1.1.0+dfsg.1/tests/stash/drop.c --- libgit2-0.28.5+dfsg.1/tests/stash/drop.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stash/drop.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "stash_helpers.h" #include "refs.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/stash/foreach.c libgit2-1.1.0+dfsg.1/tests/stash/foreach.c --- libgit2-0.28.5+dfsg.1/tests/stash/foreach.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stash/foreach.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "stash_helpers.h" struct callback_data diff -Nru libgit2-0.28.5+dfsg.1/tests/stash/save.c libgit2-1.1.0+dfsg.1/tests/stash/save.c --- libgit2-0.28.5+dfsg.1/tests/stash/save.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stash/save.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "stash_helpers.h" static git_repository *repo; @@ -283,6 +283,26 @@ assert_object_oid("refs/stash@{1}", NULL, GIT_OBJECT_COMMIT); } +void test_stash_save__multiline_message(void) +{ + const char *msg = "This\n\nis a multiline message\n"; + const git_reflog_entry *entry; + git_reflog *reflog; + + assert_object_oid("refs/stash@{0}", NULL, GIT_OBJECT_COMMIT); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, msg, GIT_STASH_DEFAULT)); + + cl_git_pass(git_reflog_read(&reflog, repo, "refs/stash")); + cl_assert(entry = git_reflog_entry_byindex(reflog, 0)); + cl_assert_equal_s(git_reflog_entry_message(entry), "On master: This is a multiline message"); + + assert_object_oid("refs/stash@{0}", git_oid_tostr_s(&stash_tip_oid), GIT_OBJECT_COMMIT); + assert_commit_message_contains("refs/stash@{0}", msg); + + git_reflog_free(reflog); +} + void test_stash_save__cannot_stash_when_there_are_no_local_change(void) { git_index *index; diff -Nru libgit2-0.28.5+dfsg.1/tests/stash/stash_helpers.c libgit2-1.1.0+dfsg.1/tests/stash/stash_helpers.c --- libgit2-0.28.5+dfsg.1/tests/stash/stash_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stash/stash_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "stash_helpers.h" void setup_stash(git_repository *repo, git_signature *signature) diff -Nru libgit2-0.28.5+dfsg.1/tests/status/ignore.c libgit2-1.1.0+dfsg.1/tests/status/ignore.c --- libgit2-0.28.5+dfsg.1/tests/status/ignore.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/status/ignore.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1259 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "git2/attr.h" -#include "ignore.h" -#include "attr.h" -#include "status_helpers.h" - -static git_repository *g_repo = NULL; - -void test_status_ignore__initialize(void) -{ -} - -void test_status_ignore__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void assert_ignored_( - bool expected, const char *filepath, const char *file, int line) -{ - int is_ignored = 0; - cl_git_expect( - git_status_should_ignore(&is_ignored, g_repo, filepath), 0, file, line); - clar__assert( - (expected != 0) == (is_ignored != 0), - file, line, "expected != is_ignored", filepath, 1); -} -#define assert_ignored(expected, filepath) \ - assert_ignored_(expected, filepath, __FILE__, __LINE__) -#define assert_is_ignored(filepath) \ - assert_ignored_(true, filepath, __FILE__, __LINE__) -#define refute_is_ignored(filepath) \ - assert_ignored_(false, filepath, __FILE__, __LINE__) - -void test_status_ignore__0(void) -{ - struct { - const char *path; - int expected; - } test_cases[] = { - /* pattern "ign" from .gitignore */ - { "file", 0 }, - { "ign", 1 }, - { "sub", 0 }, - { "sub/file", 0 }, - { "sub/ign", 1 }, - { "sub/ign/file", 1 }, - { "sub/ign/sub", 1 }, - { "sub/ign/sub/file", 1 }, - { "sub/sub", 0 }, - { "sub/sub/file", 0 }, - { "sub/sub/ign", 1 }, - { "sub/sub/sub", 0 }, - /* pattern "dir/" from .gitignore */ - { "dir", 1 }, - { "dir/", 1 }, - { "sub/dir", 1 }, - { "sub/dir/", 1 }, - { "sub/dir/file", 1 }, /* contained in ignored parent */ - { "sub/sub/dir", 0 }, /* dir is not actually a dir, but a file */ - { NULL, 0 } - }, *one_test; - - g_repo = cl_git_sandbox_init("attr"); - - for (one_test = test_cases; one_test->path != NULL; one_test++) - assert_ignored(one_test->expected, one_test->path); - - /* confirm that ignore files were cached */ - cl_assert(git_attr_cache__is_cached( - g_repo, GIT_ATTR_FILE__FROM_FILE, ".git/info/exclude")); - cl_assert(git_attr_cache__is_cached( - g_repo, GIT_ATTR_FILE__FROM_FILE, ".gitignore")); -} - - -void test_status_ignore__1(void) -{ - g_repo = cl_git_sandbox_init("attr"); - - cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n"); - git_attr_cache_flush(g_repo); - - assert_is_ignored("root_test4.txt"); - refute_is_ignored("sub/subdir_test2.txt"); - assert_is_ignored("dir"); - assert_is_ignored("dir/"); - refute_is_ignored("sub/dir"); - refute_is_ignored("sub/dir/"); -} - -void test_status_ignore__empty_repo_with_gitignore_rewrite(void) -{ - status_entry_single st; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile( - "empty_standard_repo/look-ma.txt", "I'm going to be ignored!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 1); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - refute_is_ignored("look-ma.txt"); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 2); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - refute_is_ignored("look-ma.txt"); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 2); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - assert_is_ignored("look-ma.txt"); -} - -void test_status_ignore__ignore_pattern_contains_space(void) -{ - unsigned int flags; - const mode_t mode = 0777; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n"); - - cl_git_mkfile( - "empty_standard_repo/foo bar.txt", "I'm going to be ignored!"); - - cl_git_pass(git_status_file(&flags, g_repo, "foo bar.txt")); - cl_assert(flags == GIT_STATUS_IGNORED); - - cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", mode)); - cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!"); - - cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt")); - cl_assert(flags == GIT_STATUS_WT_NEW); -} - -void test_status_ignore__ignore_pattern_ignorecase(void) -{ - unsigned int flags; - bool ignore_case; - git_index *index; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_rewritefile("empty_standard_repo/.gitignore", "a.txt\n"); - - cl_git_mkfile("empty_standard_repo/A.txt", "Differs in case"); - - cl_git_pass(git_repository_index(&index, g_repo)); - ignore_case = (git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0; - git_index_free(index); - - cl_git_pass(git_status_file(&flags, g_repo, "A.txt")); - cl_assert(flags == ignore_case ? GIT_STATUS_IGNORED : GIT_STATUS_WT_NEW); -} - -void test_status_ignore__subdirectories(void) -{ - status_entry_single st; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile( - "empty_standard_repo/ignore_me", "I'm going to be ignored!"); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert_equal_i(2, st.count); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - assert_is_ignored("ignore_me"); - - /* I've changed libgit2 so that the behavior here now differs from - * core git but seems to make more sense. In core git, the following - * items are skipped completed, even if --ignored is passed to status. - * It you mirror these steps and run "git status -uall --ignored" then - * you will not see "test/ignore_me/" in the results. - * - * However, we had a couple reports of this as a bug, plus there is a - * similar circumstance where we were differing for core git when you - * used a rooted path for an ignore, so I changed this behavior. - */ - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/test/ignore_me", 0775)); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file2", "Me, too!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert_equal_i(3, st.count); - - cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - assert_is_ignored("test/ignore_me/file"); -} - -static void make_test_data(const char *reponame, const char **files) -{ - const char **scan; - size_t repolen = strlen(reponame) + 1; - - g_repo = cl_git_sandbox_init(reponame); - - for (scan = files; *scan != NULL; ++scan) { - cl_git_pass(git_futils_mkdir_relative( - *scan + repolen, reponame, - 0777, GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST, NULL)); - cl_git_mkfile(*scan, "contents"); - } -} - -static const char *test_repo_1 = "empty_standard_repo"; -static const char *test_files_1[] = { - "empty_standard_repo/dir/a/ignore_me", - "empty_standard_repo/dir/b/ignore_me", - "empty_standard_repo/dir/ignore_me", - "empty_standard_repo/ignore_also/file", - "empty_standard_repo/ignore_me", - "empty_standard_repo/test/ignore_me/file", - "empty_standard_repo/test/ignore_me/file2", - "empty_standard_repo/test/ignore_me/and_me/file", - NULL -}; - -void test_status_ignore__subdirectories_recursion(void) -{ - /* Let's try again with recursing into ignored dirs turned on */ - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths_r[] = { - ".gitignore", - "dir/a/ignore_me", - "dir/b/ignore_me", - "dir/ignore_me", - "ignore_also/file", - "ignore_me", - "test/ignore_me/and_me/file", - "test/ignore_me/file", - "test/ignore_me/file2", - }; - static const unsigned int statuses_r[] = { - GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - }; - static const char *paths_nr[] = { - ".gitignore", - "dir/a/ignore_me", - "dir/b/ignore_me", - "dir/ignore_me", - "ignore_also/", - "ignore_me", - "test/ignore_me/", - }; - static const unsigned int statuses_nr[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - }; - - make_test_data(test_repo_1, test_files_1); - cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n/ignore_also\n"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 9; - counts.expected_paths = paths_r; - counts.expected_statuses = statuses_r; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 7; - counts.expected_paths = paths_nr; - counts.expected_statuses = statuses_nr; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_ignore__subdirectories_not_at_root(void) -{ - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths_1[] = { - "dir/.gitignore", - "dir/a/ignore_me", - "dir/b/ignore_me", - "dir/ignore_me", - "ignore_also/file", - "ignore_me", - "test/.gitignore", - "test/ignore_me/and_me/file", - "test/ignore_me/file", - "test/ignore_me/file2", - }; - static const unsigned int statuses_1[] = { - GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, - }; - - make_test_data(test_repo_1, test_files_1); - cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "ignore_me\n/ignore_also\n"); - cl_git_rewritefile("empty_standard_repo/test/.gitignore", "and_me\n"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 10; - counts.expected_paths = paths_1; - counts.expected_statuses = statuses_1; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_ignore__leading_slash_ignores(void) -{ - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths_2[] = { - "dir/.gitignore", - "dir/a/ignore_me", - "dir/b/ignore_me", - "dir/ignore_me", - "ignore_also/file", - "ignore_me", - "test/.gitignore", - "test/ignore_me/and_me/file", - "test/ignore_me/file", - "test/ignore_me/file2", - }; - static const unsigned int statuses_2[] = { - GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, - GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, - }; - - make_test_data(test_repo_1, test_files_1); - - cl_fake_home(); - cl_git_mkfile("home/.gitignore", "/ignore_me\n"); - { - git_config *cfg; - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string( - cfg, "core.excludesfile", "~/.gitignore")); - git_config_free(cfg); - } - - cl_git_rewritefile("empty_standard_repo/.git/info/exclude", "/ignore_also\n"); - cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "/ignore_me\n"); - cl_git_rewritefile("empty_standard_repo/test/.gitignore", "/and_me\n"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 10; - counts.expected_paths = paths_2; - counts.expected_statuses = statuses_2; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_ignore__contained_dir_with_matching_name(void) -{ - static const char *test_files[] = { - "empty_standard_repo/subdir_match/aaa/subdir_match/file", - "empty_standard_repo/subdir_match/zzz_ignoreme", - NULL - }; - static const char *expected_paths[] = { - "subdir_match/.gitignore", - "subdir_match/aaa/subdir_match/file", - "subdir_match/zzz_ignoreme", - }; - static const unsigned int expected_statuses[] = { - GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED - }; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/subdir_match/.gitignore", "*_ignoreme\n"); - - refute_is_ignored("subdir_match/aaa/subdir_match/file"); - assert_is_ignored("subdir_match/zzz_ignoreme"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 3; - counts.expected_paths = expected_paths; - counts.expected_statuses = expected_statuses; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_ignore__trailing_slash_star(void) -{ - static const char *test_files[] = { - "empty_standard_repo/file", - "empty_standard_repo/subdir/file", - "empty_standard_repo/subdir/sub2/sub3/file", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/subdir/.gitignore", "/**/*\n"); - - refute_is_ignored("file"); - assert_is_ignored("subdir/sub2/sub3/file"); - assert_is_ignored("subdir/file"); -} - -void test_status_ignore__adding_internal_ignores(void) -{ - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - refute_is_ignored("one.txt"); - refute_is_ignored("two.bar"); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.nomatch\n")); - - refute_is_ignored("one.txt"); - refute_is_ignored("two.bar"); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.txt\n")); - - assert_is_ignored("one.txt"); - refute_is_ignored("two.bar"); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.bar\n")); - - assert_is_ignored("one.txt"); - assert_is_ignored("two.bar"); - - cl_git_pass(git_ignore_clear_internal_rules(g_repo)); - - refute_is_ignored("one.txt"); - refute_is_ignored("two.bar"); - - cl_git_pass(git_ignore_add_rule( - g_repo, "multiple\n*.rules\n# comment line\n*.bar\n")); - - refute_is_ignored("one.txt"); - assert_is_ignored("two.bar"); -} - -void test_status_ignore__add_internal_as_first_thing(void) -{ - const char *add_me = "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_ignore_add_rule(g_repo, add_me)); - - assert_is_ignored("one.tmp"); - refute_is_ignored("two.bar"); -} - -void test_status_ignore__internal_ignores_inside_deep_paths(void) -{ - const char *add_me = "Debug\nthis/is/deep\npatterned*/dir\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_ignore_add_rule(g_repo, add_me)); - - assert_is_ignored("Debug"); - assert_is_ignored("and/Debug"); - assert_is_ignored("really/Debug/this/file"); - assert_is_ignored("Debug/what/I/say"); - - refute_is_ignored("and/NoDebug"); - refute_is_ignored("NoDebug/this"); - refute_is_ignored("please/NoDebug/this"); - - assert_is_ignored("this/is/deep"); - /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ - refute_is_ignored("and/this/is/deep"); - assert_is_ignored("this/is/deep/too"); - /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ - refute_is_ignored("but/this/is/deep/and/ignored"); - - refute_is_ignored("this/is/not/deep"); - refute_is_ignored("is/this/not/as/deep"); - refute_is_ignored("this/is/deepish"); - refute_is_ignored("xthis/is/deep"); -} - -void test_status_ignore__automatically_ignore_bad_files(void) -{ - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - assert_is_ignored(".git"); - assert_is_ignored("this/file/."); - assert_is_ignored("path/../funky"); - refute_is_ignored("path/whatever.c"); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.c\n")); - - assert_is_ignored(".git"); - assert_is_ignored("this/file/."); - assert_is_ignored("path/../funky"); - assert_is_ignored("path/whatever.c"); - - cl_git_pass(git_ignore_clear_internal_rules(g_repo)); - - assert_is_ignored(".git"); - assert_is_ignored("this/file/."); - assert_is_ignored("path/../funky"); - refute_is_ignored("path/whatever.c"); -} - -void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void) -{ - status_entry_single st; - char *test_cases[] = { - "!file", - "#blah", - "[blah]", - "[attr]", - "[attr]blah", - NULL - }; - int i; - - for (i = 0; *(test_cases + i) != NULL; i++) { - git_buf file = GIT_BUF_INIT; - char *file_name = *(test_cases + i); - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name)); - cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); - cl_assert(st.count == 1); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, repo, file_name)); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_sandbox_cleanup(); - git_buf_dispose(&file); - } -} - -void test_status_ignore__issue_1766_negated_ignores(void) -{ - unsigned int status; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/a", 0775)); - cl_git_mkfile( - "empty_standard_repo/a/.gitignore", "*\n!.gitignore\n"); - cl_git_mkfile( - "empty_standard_repo/a/ignoreme", "I should be ignored\n"); - - refute_is_ignored("a/.gitignore"); - assert_is_ignored("a/ignoreme"); - - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/b", 0775)); - cl_git_mkfile( - "empty_standard_repo/b/.gitignore", "*\n!.gitignore\n"); - cl_git_mkfile( - "empty_standard_repo/b/ignoreme", "I should be ignored\n"); - - refute_is_ignored("b/.gitignore"); - assert_is_ignored("b/ignoreme"); - - /* shouldn't have changed results from first couple either */ - refute_is_ignored("a/.gitignore"); - assert_is_ignored("a/ignoreme"); - - /* status should find the two ignore files and nothing else */ - - cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore")); - cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme")); - cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore")); - cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme")); - cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); - - { - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths[] = { - "a/.gitignore", - "a/ignoreme", - "b/.gitignore", - "b/ignoreme", - }; - static const unsigned int statuses[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - }; - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 4; - counts.expected_paths = paths; - counts.expected_statuses = statuses; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - } -} - -static void add_one_to_index(const char *file) -{ - git_index *index; - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_add_bypath(index, file)); - git_index_free(index); -} - -/* Some further broken scenarios that have been reported */ -void test_status_ignore__more_breakage(void) -{ - static const char *test_files[] = { - "empty_standard_repo/d1/pfx-d2/d3/d4/d5/tracked", - "empty_standard_repo/d1/pfx-d2/d3/d4/d5/untracked", - "empty_standard_repo/d1/pfx-d2/d3/d4/untracked", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "/d1/pfx-*\n" - "!/d1/pfx-d2/\n" - "/d1/pfx-d2/*\n" - "!/d1/pfx-d2/d3/\n" - "/d1/pfx-d2/d3/*\n" - "!/d1/pfx-d2/d3/d4/\n"); - add_one_to_index("d1/pfx-d2/d3/d4/d5/tracked"); - - { - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *files[] = { - ".gitignore", - "d1/pfx-d2/d3/d4/d5/tracked", - "d1/pfx-d2/d3/d4/d5/untracked", - "d1/pfx-d2/d3/d4/untracked", - }; - static const unsigned int statuses[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - }; - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 4; - counts.expected_paths = files; - counts.expected_statuses = statuses; - opts.flags = GIT_STATUS_OPT_DEFAULTS | - GIT_STATUS_OPT_INCLUDE_IGNORED | - GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - } - - refute_is_ignored("d1/pfx-d2/d3/d4/d5/tracked"); - refute_is_ignored("d1/pfx-d2/d3/d4/d5/untracked"); - refute_is_ignored("d1/pfx-d2/d3/d4/untracked"); -} - -void test_status_ignore__negative_ignores_inside_ignores(void) -{ - static const char *test_files[] = { - "empty_standard_repo/top/mid/btm/tracked", - "empty_standard_repo/top/mid/btm/untracked", - "empty_standard_repo/zoo/bar", - "empty_standard_repo/zoo/foo/bar", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "top\n" - "!top/mid/btm\n" - "zoo/*\n" - "!zoo/bar\n" - "!zoo/foo/bar\n"); - add_one_to_index("top/mid/btm/tracked"); - - { - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *files[] = { - ".gitignore", "top/mid/btm/tracked", "top/mid/btm/untracked", - "zoo/bar", "zoo/foo/bar", - }; - static const unsigned int statuses[] = { - GIT_STATUS_WT_NEW, GIT_STATUS_INDEX_NEW, GIT_STATUS_IGNORED, - GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, - }; - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 5; - counts.expected_paths = files; - counts.expected_statuses = statuses; - opts.flags = GIT_STATUS_OPT_DEFAULTS | - GIT_STATUS_OPT_INCLUDE_IGNORED | - GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - } - - assert_is_ignored("top/mid/btm/tracked"); - assert_is_ignored("top/mid/btm/untracked"); - refute_is_ignored("foo/bar"); -} - -void test_status_ignore__negative_ignores_in_slash_star(void) -{ - git_status_options status_opts = GIT_STATUS_OPTIONS_INIT; - git_status_list *list; - int found_look_ma = 0, found_what_about = 0; - size_t i; - static const char *test_files[] = { - "empty_standard_repo/bin/look-ma.txt", - "empty_standard_repo/bin/what-about-me.txt", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "bin/*\n" - "!bin/w*\n"); - - assert_is_ignored("bin/look-ma.txt"); - refute_is_ignored("bin/what-about-me.txt"); - - status_opts.flags = GIT_STATUS_OPT_DEFAULTS; - cl_git_pass(git_status_list_new(&list, g_repo, &status_opts)); - for (i = 0; i < git_status_list_entrycount(list); i++) { - const git_status_entry *entry = git_status_byindex(list, i); - - if (!strcmp("bin/look-ma.txt", entry->index_to_workdir->new_file.path)) - found_look_ma = 1; - - if (!strcmp("bin/what-about-me.txt", entry->index_to_workdir->new_file.path)) - found_what_about = 1; - } - git_status_list_free(list); - - cl_assert(found_look_ma); - cl_assert(found_what_about); -} - -void test_status_ignore__negative_ignores_without_trailing_slash_inside_ignores(void) -{ - git_status_options status_opts = GIT_STATUS_OPTIONS_INIT; - git_status_list *list; - int found_parent_file = 0, found_parent_child1_file = 0, found_parent_child2_file = 0; - size_t i; - static const char *test_files[] = { - "empty_standard_repo/parent/file.txt", - "empty_standard_repo/parent/force.txt", - "empty_standard_repo/parent/child1/file.txt", - "empty_standard_repo/parent/child2/file.txt", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "parent/*\n" - "!parent/force.txt\n" - "!parent/child1\n" - "!parent/child2/\n"); - - add_one_to_index("parent/force.txt"); - - assert_is_ignored("parent/file.txt"); - refute_is_ignored("parent/force.txt"); - refute_is_ignored("parent/child1/file.txt"); - refute_is_ignored("parent/child2/file.txt"); - - status_opts.flags = GIT_STATUS_OPT_DEFAULTS; - cl_git_pass(git_status_list_new(&list, g_repo, &status_opts)); - for (i = 0; i < git_status_list_entrycount(list); i++) { - const git_status_entry *entry = git_status_byindex(list, i); - - if (!entry->index_to_workdir) - continue; - - if (!strcmp("parent/file.txt", entry->index_to_workdir->new_file.path)) - found_parent_file = 1; - - if (!strcmp("parent/force.txt", entry->index_to_workdir->new_file.path)) - found_parent_file = 1; - - if (!strcmp("parent/child1/file.txt", entry->index_to_workdir->new_file.path)) - found_parent_child1_file = 1; - - if (!strcmp("parent/child2/file.txt", entry->index_to_workdir->new_file.path)) - found_parent_child2_file = 1; - } - git_status_list_free(list); - - cl_assert(found_parent_file); - cl_assert(found_parent_child1_file); - cl_assert(found_parent_child2_file); -} - -void test_status_ignore__negative_directory_ignores(void) -{ - static const char *test_files[] = { - "empty_standard_repo/parent/child1/bar.txt", - "empty_standard_repo/parent/child2/bar.txt", - "empty_standard_repo/parent/child3/foo.txt", - "empty_standard_repo/parent/child4/bar.txt", - "empty_standard_repo/parent/nested/child5/bar.txt", - "empty_standard_repo/parent/nested/child6/bar.txt", - "empty_standard_repo/parent/nested/child7/bar.txt", - "empty_standard_repo/padded_parent/child8/bar.txt", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "foo.txt\n" - "parent/child1\n" - "parent/child2\n" - "parent/child4\n" - "parent/nested/child5\n" - "nested/child6\n" - "nested/child7\n" - "padded_parent/child8\n" - /* test simple exact match */ - "!parent/child1\n" - /* test negating file without negating dir */ - "!parent/child2/bar.txt\n" - /* test negative pattern on dir with its content - * being ignored */ - "!parent/child3\n" - /* test with partial match at end */ - "!child4\n" - /* test with partial match with '/' at end */ - "!nested/child5\n" - /* test with complete match */ - "!nested/child6\n" - /* test with trailing '/' */ - "!child7/\n" - /* test with partial dir match */ - "!_parent/child8\n"); - - refute_is_ignored("parent/child1/bar.txt"); - assert_is_ignored("parent/child2/bar.txt"); - assert_is_ignored("parent/child3/foo.txt"); - refute_is_ignored("parent/child4/bar.txt"); - assert_is_ignored("parent/nested/child5/bar.txt"); - refute_is_ignored("parent/nested/child6/bar.txt"); - refute_is_ignored("parent/nested/child7/bar.txt"); - assert_is_ignored("padded_parent/child8/bar.txt"); -} - -void test_status_ignore__unignore_entry_in_ignored_dir(void) -{ - static const char *test_files[] = { - "empty_standard_repo/bar.txt", - "empty_standard_repo/parent/bar.txt", - "empty_standard_repo/parent/child/bar.txt", - "empty_standard_repo/nested/parent/child/bar.txt", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "bar.txt\n" - "!parent/child/bar.txt\n"); - - assert_is_ignored("bar.txt"); - assert_is_ignored("parent/bar.txt"); - refute_is_ignored("parent/child/bar.txt"); - assert_is_ignored("nested/parent/child/bar.txt"); -} - -void test_status_ignore__do_not_unignore_basename_prefix(void) -{ - static const char *test_files[] = { - "empty_standard_repo/foo_bar.txt", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "foo_bar.txt\n" - "!bar.txt\n"); - - assert_is_ignored("foo_bar.txt"); -} - -void test_status_ignore__filename_with_cr(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\r\n"); - - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); - cl_assert_equal_i(1, ignored); - - cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\n"); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn")); - cl_assert_equal_i(1, ignored); - - cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\n"); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn")); - cl_assert_equal_i(1, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r")); - cl_assert_equal_i(0, ignored); - - cl_git_mkfile("empty_standard_repo/.gitignore", "Ico\rn\r\r\n"); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Ico\rn\r")); - cl_assert_equal_i(1, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); - cl_assert_equal_i(0, ignored); - - cl_git_mkfile("empty_standard_repo/.gitignore", "Icon\r\n"); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon\r")); - cl_assert_equal_i(0, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "Icon")); - cl_assert_equal_i(1, ignored); -} - -void test_status_ignore__subdir_doesnt_match_above(void) -{ - int ignored, icase = 0, error; - git_config *cfg; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_repository_config_snapshot(&cfg, g_repo)); - error = git_config_get_bool(&icase, cfg, "core.ignorecase"); - git_config_free(cfg); - if (error == GIT_ENOTFOUND) - error = 0; - - cl_git_pass(error); - - cl_git_pass(p_mkdir("empty_standard_repo/src", 0777)); - cl_git_pass(p_mkdir("empty_standard_repo/src/src", 0777)); - cl_git_mkfile("empty_standard_repo/src/.gitignore", "src\n"); - cl_git_mkfile("empty_standard_repo/.gitignore", ""); - - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/test.txt")); - cl_assert_equal_i(0, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/src/test.txt")); - cl_assert_equal_i(1, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/foo/test.txt")); - cl_assert_equal_i(0, ignored); - - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "SRC/src/test.txt")); - cl_assert_equal_i(icase, ignored); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "src/SRC/test.txt")); - cl_assert_equal_i(icase, ignored); -} - -void test_status_ignore__negate_exact_previous(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile("empty_standard_repo/.gitignore", "*.com\ntags\n!tags/\n.buildpath"); - cl_git_mkfile("empty_standard_repo/.buildpath", ""); - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, ".buildpath")); - cl_assert_equal_i(1, ignored); -} - -void test_status_ignore__negate_starstar(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile("empty_standard_repo/.gitignore", - "code/projects/**/packages/*\n" - "!code/projects/**/packages/repositories.config"); - - cl_git_pass(git_futils_mkdir_r("empty_standard_repo/code/projects/foo/bar/packages", 0777)); - cl_git_mkfile("empty_standard_repo/code/projects/foo/bar/packages/repositories.config", ""); - - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "code/projects/foo/bar/packages/repositories.config")); - cl_assert_equal_i(0, ignored); -} - -void test_status_ignore__ignore_all_toplevel_dirs_include_files(void) -{ - static const char *test_files[] = { - "empty_standard_repo/README.md", - "empty_standard_repo/src/main.c", - "empty_standard_repo/src/foo/foo.c", - "empty_standard_repo/dist/foo.o", - "empty_standard_repo/dist/main.o", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "/*/\n" - "!/src\n"); - - assert_is_ignored("dist/foo.o"); - assert_is_ignored("dist/main.o"); - - refute_is_ignored("README.md"); - refute_is_ignored("src/foo.c"); - refute_is_ignored("src/foo/foo.c"); -} - -void test_status_ignore__subdir_ignore_all_toplevel_dirs_include_files(void) -{ - static const char *test_files[] = { - "empty_standard_repo/project/README.md", - "empty_standard_repo/project/src/main.c", - "empty_standard_repo/project/src/foo/foo.c", - "empty_standard_repo/project/dist/foo.o", - "empty_standard_repo/project/dist/main.o", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/project/.gitignore", - "/*/\n" - "!/src\n"); - - assert_is_ignored("project/dist/foo.o"); - assert_is_ignored("project/dist/main.o"); - - refute_is_ignored("project/src/foo.c"); - refute_is_ignored("project/src/foo/foo.c"); - refute_is_ignored("project/README.md"); -} - -void test_status_ignore__subdir_ignore_everything_except_certain_files(void) -{ - static const char *test_files[] = { - "empty_standard_repo/project/README.md", - "empty_standard_repo/project/some_file", - "empty_standard_repo/project/src/main.c", - "empty_standard_repo/project/src/foo/foo.c", - "empty_standard_repo/project/dist/foo.o", - "empty_standard_repo/project/dist/main.o", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/project/.gitignore", - "/*\n" - "!/src\n" - "!README.md\n"); - - assert_is_ignored("project/some_file"); - assert_is_ignored("project/dist/foo.o"); - assert_is_ignored("project/dist/main.o"); - - refute_is_ignored("project/README.md"); - refute_is_ignored("project/src/foo.c"); - refute_is_ignored("project/src/foo/foo.c"); -} - -void test_status_ignore__deeper(void) -{ - const char *test_files[] = { - "empty_standard_repo/foo.data", - "empty_standard_repo/bar.data", - "empty_standard_repo/dont_ignore/foo.data", - "empty_standard_repo/dont_ignore/bar.data", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile("empty_standard_repo/.gitignore", - "*.data\n" - "!dont_ignore/*.data\n"); - - assert_is_ignored("foo.data"); - assert_is_ignored("bar.data"); - - refute_is_ignored("dont_ignore/foo.data"); - refute_is_ignored("dont_ignore/bar.data"); -} - -void test_status_ignore__unignored_dir_with_ignored_contents(void) -{ - static const char *test_files[] = { - "empty_standard_repo/dir/a.test", - "empty_standard_repo/dir/subdir/a.test", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "*.test\n" - "!dir/*\n"); - - refute_is_ignored("dir/a.test"); - assert_is_ignored("dir/subdir/a.test"); -} - -void test_status_ignore__unignored_subdirs(void) -{ - static const char *test_files[] = { - "empty_standard_repo/dir/a.test", - "empty_standard_repo/dir/subdir/a.test", - NULL - }; - - make_test_data("empty_standard_repo", test_files); - cl_git_mkfile( - "empty_standard_repo/.gitignore", - "dir/*\n" - "!dir/*/\n"); - - assert_is_ignored("dir/a.test"); - refute_is_ignored("dir/subdir/a.test"); -} - -void test_status_ignore__override_nested_wildcard_unignore(void) -{ - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - const git_status_entry *status; - - cl_git_pass(git_futils_mkdir_r("empty_standard_repo/dir", 0777)); - cl_git_pass(git_futils_mkdir_r("empty_standard_repo/dir/subdir", 0777)); - cl_git_mkfile("empty_standard_repo/.gitignore", "a.test\n"); - cl_git_mkfile("empty_standard_repo/dir/.gitignore", "!*.test\n"); - cl_git_mkfile("empty_standard_repo/dir/subdir/.gitignore", "a.test\n"); - cl_git_mkfile("empty_standard_repo/dir/a.test", "pong"); - cl_git_mkfile("empty_standard_repo/dir/subdir/a.test", "pong"); - - opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - - cl_git_pass(git_status_list_new(&statuslist, repo, &opts)); - cl_assert_equal_sz(4, git_status_list_entrycount(statuslist)); - - status = git_status_byindex(statuslist, 0); - cl_assert(status != NULL); - cl_assert_equal_s(".gitignore", status->index_to_workdir->old_file.path); - cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); - - status = git_status_byindex(statuslist, 1); - cl_assert(status != NULL); - cl_assert_equal_s("dir/.gitignore", status->index_to_workdir->old_file.path); - cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); - - status = git_status_byindex(statuslist, 2); - cl_assert(status != NULL); - cl_assert_equal_s("dir/a.test", status->index_to_workdir->old_file.path); - cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); - - status = git_status_byindex(statuslist, 3); - cl_assert(status != NULL); - cl_assert_equal_s("dir/subdir/.gitignore", status->index_to_workdir->old_file.path); - cl_assert_equal_i(GIT_STATUS_WT_NEW, status->status); - - git_status_list_free(statuslist); -} diff -Nru libgit2-0.28.5+dfsg.1/tests/status/status_helpers.h libgit2-1.1.0+dfsg.1/tests/status/status_helpers.h --- libgit2-0.28.5+dfsg.1/tests/status/status_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/status/status_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -9,6 +9,7 @@ const char** expected_paths; int expected_entry_count; const char *file; + const char *func; int line; bool debug; } status_entry_counts; @@ -18,6 +19,7 @@ (counts).expected_statuses = (statuses); \ (counts).expected_paths = (paths); \ (counts).file = __FILE__; \ + (counts).func = __func__; \ (counts).line = __LINE__; \ } while (0) diff -Nru libgit2-0.28.5+dfsg.1/tests/status/submodules.c libgit2-1.1.0+dfsg.1/tests/status/submodules.c --- libgit2-0.28.5+dfsg.1/tests/status/submodules.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/status/submodules.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "status_helpers.h" #include "../submodule/submodule_helpers.h" @@ -71,12 +71,12 @@ int idx = counts->entry_count++; clar__assert_equal( - counts->file, counts->line, + counts->file, counts->func, counts->line, "Status path mismatch", 1, "%s", counts->expected_paths[idx], p); clar__assert_equal( - counts->file, counts->line, + counts->file, counts->func, counts->line, "Status code mismatch", 1, "%o", counts->expected_statuses[idx], s); diff -Nru libgit2-0.28.5+dfsg.1/tests/status/worktree.c libgit2-1.1.0+dfsg.1/tests/status/worktree.c --- libgit2-0.28.5+dfsg.1/tests/status/worktree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/status/worktree.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include "fileops.h" +#include "futils.h" #include "ignore.h" #include "status_data.h" #include "posix.h" @@ -949,7 +949,7 @@ void test_status_worktree__long_filenames(void) { - char path[260*4+1]; + char path[260*4+1] = {0}; const char *expected_paths[] = {path}; const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW}; diff -Nru libgit2-0.28.5+dfsg.1/tests/status/worktree_init.c libgit2-1.1.0+dfsg.1/tests/status/worktree_init.c --- libgit2-0.28.5+dfsg.1/tests/status/worktree_init.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/status/worktree_init.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "git2/sys/repository.h" -#include "fileops.h" +#include "futils.h" #include "ignore.h" #include "status_helpers.h" #include "posix.h" diff -Nru libgit2-0.28.5+dfsg.1/tests/stream/deprecated.c libgit2-1.1.0+dfsg.1/tests/stream/deprecated.c --- libgit2-0.28.5+dfsg.1/tests/stream/deprecated.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/stream/deprecated.c 2020-10-12 18:53:06.000000000 +0000 @@ -1,19 +1,18 @@ -#undef GIT_DEPRECATE_HARD - #include "clar_libgit2.h" #include "git2/sys/stream.h" #include "streams/tls.h" #include "streams/socket.h" #include "stream.h" -static git_stream test_stream; -static int ctor_called; - void test_stream_deprecated__cleanup(void) { cl_git_pass(git_stream_register(GIT_STREAM_TLS | GIT_STREAM_STANDARD, NULL)); } +#ifndef GIT_DEPRECATE_HARD +static git_stream test_stream; +static int ctor_called; + static int test_stream_init(git_stream **out, const char *host, const char *port) { GIT_UNUSED(host); @@ -24,9 +23,11 @@ return 0; } +#endif void test_stream_deprecated__register_tls(void) { +#ifndef GIT_DEPRECATE_HARD git_stream *stream; int error; @@ -55,4 +56,5 @@ cl_assert(&test_stream != stream); git_stream_free(stream); +#endif } diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/add.c libgit2-1.1.0+dfsg.1/tests/submodule/add.c --- libgit2-0.28.5+dfsg.1/tests/submodule/add.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/add.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,8 +3,9 @@ #include "path.h" #include "submodule_helpers.h" #include "config/config_helpers.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" +#include "git2/sys/commit.h" static git_repository *g_repo = NULL; static const char *valid_blob_id = "fa49b077972391ad58037050f2a75f74e3671e92"; @@ -89,7 +90,7 @@ /* make sure we don't default to origin - rename origin -> test_remote */ cl_git_pass(git_remote_rename(&problems, g_repo, "origin", "test_remote")); cl_assert_equal_i(0, problems.count); - git_strarray_free(&problems); + git_strarray_dispose(&problems); cl_git_fail(git_remote_lookup(&remote, g_repo, "origin")); cl_git_pass( @@ -183,3 +184,68 @@ git_submodule_free(sm); git_buf_dispose(&name); } + +void test_submodule_add__submodule_clone(void) +{ + git_oid tree_id, commit_id; + git_signature *sig; + git_submodule *sm; + git_index *index; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + /* Create the submodule structure, clone into it and finalize */ + cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo-add", true)); + cl_git_pass(git_submodule_clone(NULL, sm, NULL)); + cl_git_pass(git_submodule_add_finalize(sm)); + + /* Create the submodule commit */ + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_signature_now(&sig, "Submoduler", "submoduler@local")); + cl_git_pass(git_commit_create_from_ids(&commit_id, g_repo, "HEAD", sig, sig, NULL, "A submodule\n", + &tree_id, 0, NULL)); + + assert_submodule_exists(g_repo, "testrepo-add"); + + git_signature_free(sig); + git_submodule_free(sm); + git_index_free(index); +} + +void test_submodule_add__submodule_clone_into_nonempty_dir_succeeds(void) +{ + git_submodule *sm; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(p_mkdir("empty_standard_repo/sm", 0777)); + cl_git_mkfile("empty_standard_repo/sm/foobar", ""); + + /* Create the submodule structure, clone into it and finalize */ + cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "sm", true)); + cl_git_pass(git_submodule_clone(NULL, sm, NULL)); + cl_git_pass(git_submodule_add_finalize(sm)); + + cl_assert(git_path_exists("empty_standard_repo/sm/foobar")); + + assert_submodule_exists(g_repo, "sm"); + + git_submodule_free(sm); +} + +void test_submodule_add__submodule_clone_twice_fails(void) +{ + git_submodule *sm; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + /* Create the submodule structure, clone into it and finalize */ + cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "sm", true)); + cl_git_pass(git_submodule_clone(NULL, sm, NULL)); + cl_git_pass(git_submodule_add_finalize(sm)); + + cl_git_fail(git_submodule_clone(NULL, sm, NULL)); + + git_submodule_free(sm); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/escape.c libgit2-1.1.0+dfsg.1/tests/submodule/escape.c --- libgit2-0.28.5+dfsg.1/tests/submodule/escape.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/escape.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/init.c libgit2-1.1.0+dfsg.1/tests/submodule/init.c --- libgit2-0.28.5+dfsg.1/tests/submodule/init.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/init.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/inject_option.c libgit2-1.1.0+dfsg.1/tests/submodule/inject_option.c --- libgit2-0.28.5+dfsg.1/tests/submodule/inject_option.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/inject_option.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" -#include "fileops.h" +#include "futils.h" #include "repository.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/lookup.c libgit2-1.1.0+dfsg.1/tests/submodule/lookup.c --- libgit2-0.28.5+dfsg.1/tests/submodule/lookup.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/lookup.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "submodule_helpers.h" #include "git2/sys/repository.h" #include "repository.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/modify.c libgit2-1.1.0+dfsg.1/tests/submodule/modify.c --- libgit2-0.28.5+dfsg.1/tests/submodule/modify.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/modify.c 2020-10-12 18:53:06.000000000 +0000 @@ -210,3 +210,24 @@ cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm)); git_submodule_free(sm); } + +void test_submodule_modify__set_relative_url(void) +{ + git_buf path = GIT_BUF_INIT; + git_repository *repo; + git_submodule *sm; + + cl_git_pass(git_submodule_set_url(g_repo, SM1, "../relative-url")); + cl_git_pass(git_submodule_lookup(&sm, g_repo, SM1)); + cl_git_pass(git_submodule_sync(sm)); + cl_git_pass(git_submodule_open(&repo, sm)); + + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), "relative-url")); + + assert_config_entry_value(g_repo, "submodule."SM1".url", path.ptr); + assert_config_entry_value(repo, "remote.origin.url", path.ptr); + + git_repository_free(repo); + git_submodule_free(sm); + git_buf_dispose(&path); +} diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/nosubs.c libgit2-1.1.0+dfsg.1/tests/submodule/nosubs.c --- libgit2-0.28.5+dfsg.1/tests/submodule/nosubs.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/nosubs.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "posix.h" -#include "fileops.h" +#include "futils.h" void test_submodule_nosubs__cleanup(void) { diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/repository_init.c libgit2-1.1.0+dfsg.1/tests/submodule/repository_init.c --- libgit2-0.28.5+dfsg.1/tests/submodule/repository_init.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/repository_init.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "path.h" #include "submodule_helpers.h" #include "config/config_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/status.c libgit2-1.1.0+dfsg.1/tests/submodule/status.c --- libgit2-0.28.5+dfsg.1/tests/submodule/status.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/status.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" -#include "fileops.h" +#include "futils.h" #include "iterator.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/submodule_helpers.c libgit2-1.1.0+dfsg.1/tests/submodule/submodule_helpers.c --- libgit2-0.28.5+dfsg.1/tests/submodule/submodule_helpers.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/submodule_helpers.c 2020-10-12 18:53:06.000000000 +0000 @@ -199,22 +199,22 @@ void assert__submodule_exists( git_repository *repo, const char *name, - const char *msg, const char *file, int line) + const char *msg, const char *file, const char *func, int line) { git_submodule *sm; int error = git_submodule_lookup(&sm, repo, name); if (error) - cl_git_report_failure(error, 0, file, line, msg); - cl_assert_at_line(sm != NULL, file, line); + cl_git_report_failure(error, 0, file, func, line, msg); + cl_assert_at_line(sm != NULL, file, func, line); git_submodule_free(sm); } void refute__submodule_exists( git_repository *repo, const char *name, int expected_error, - const char *msg, const char *file, int line) + const char *msg, const char *file, const char *func, int line) { clar__assert_equal( - file, line, msg, 1, "%i", + file, func, line, msg, 1, "%i", expected_error, (int)(git_submodule_lookup(NULL, repo, name))); } diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/submodule_helpers.h libgit2-1.1.0+dfsg.1/tests/submodule/submodule_helpers.h --- libgit2-0.28.5+dfsg.1/tests/submodule/submodule_helpers.h 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/submodule_helpers.h 2020-10-12 18:53:06.000000000 +0000 @@ -10,16 +10,16 @@ extern unsigned int get_submodule_status(git_repository *, const char *); -extern void assert__submodule_exists( - git_repository *, const char *, const char *, const char *, int); +extern void assert__submodule_exists(git_repository *, const char *, + const char *, const char *, const char *, int); #define assert_submodule_exists(repo,name) \ - assert__submodule_exists(repo, name, "git_submodule_lookup(" #name ") failed", __FILE__, __LINE__) + assert__submodule_exists(repo, name, "git_submodule_lookup(" #name ") failed", __FILE__, __func__, __LINE__) -extern void refute__submodule_exists( - git_repository *, const char *, int err, const char *, const char *, int); +extern void refute__submodule_exists(git_repository *, const char *, + int err, const char *, const char *, const char *, int); #define refute_submodule_exists(repo,name,code) \ - refute__submodule_exists(repo, name, code, "expected git_submodule_lookup(" #name ") to fail with error " #code, __FILE__, __LINE__) + refute__submodule_exists(repo, name, code, "expected git_submodule_lookup(" #name ") to fail with error " #code, __FILE__, __func__, __LINE__) extern void dump_submodules(git_repository *repo); diff -Nru libgit2-0.28.5+dfsg.1/tests/submodule/update.c libgit2-1.1.0+dfsg.1/tests/submodule/update.c --- libgit2-0.28.5+dfsg.1/tests/submodule/update.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/submodule/update.c 2020-10-12 18:53:06.000000000 +0000 @@ -2,7 +2,7 @@ #include "posix.h" #include "path.h" #include "submodule_helpers.h" -#include "fileops.h" +#include "futils.h" static git_repository *g_repo = NULL; diff -Nru libgit2-0.28.5+dfsg.1/tests/trace/windows/stacktrace.c libgit2-1.1.0+dfsg.1/tests/trace/windows/stacktrace.c --- libgit2-0.28.5+dfsg.1/tests/trace/windows/stacktrace.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/trace/windows/stacktrace.c 2020-10-12 18:53:06.000000000 +0000 @@ -132,7 +132,7 @@ *aux_id = aux_counter++; } -static void aux_cb_lookup__1(unsigned int aux_id, char *aux_msg, unsigned int aux_msg_len) +static void aux_cb_lookup__1(unsigned int aux_id, char *aux_msg, size_t aux_msg_len) { p_snprintf(aux_msg, aux_msg_len, "\tQQ%08x\n", aux_id); } diff -Nru libgit2-0.28.5+dfsg.1/tests/win32/longpath.c libgit2-1.1.0+dfsg.1/tests/win32/longpath.c --- libgit2-0.28.5+dfsg.1/tests/win32/longpath.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/win32/longpath.c 2020-10-12 18:53:06.000000000 +0000 @@ -3,7 +3,7 @@ #include "git2/clone.h" #include "clone.h" #include "buffer.h" -#include "fileops.h" +#include "futils.h" static git_buf path = GIT_BUF_INIT; diff -Nru libgit2-0.28.5+dfsg.1/tests/worktree/bare.c libgit2-1.1.0+dfsg.1/tests/worktree/bare.c --- libgit2-0.28.5+dfsg.1/tests/worktree/bare.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/worktree/bare.c 2020-10-12 18:53:06.000000000 +0000 @@ -28,7 +28,7 @@ cl_git_pass(git_worktree_list(&wts, g_repo)); cl_assert_equal_i(wts.count, 0); - git_strarray_free(&wts); + git_strarray_dispose(&wts); } void test_worktree_bare__add(void) @@ -48,7 +48,7 @@ cl_assert_equal_i(0, git_repository_is_bare(wtrepo)); cl_assert_equal_i(1, git_repository_is_worktree(wtrepo)); - git_strarray_free(&wts); + git_strarray_dispose(&wts); git_worktree_free(wt); git_repository_free(wtrepo); } diff -Nru libgit2-0.28.5+dfsg.1/tests/worktree/refs.c libgit2-1.1.0+dfsg.1/tests/worktree/refs.c --- libgit2-0.28.5+dfsg.1/tests/worktree/refs.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/worktree/refs.c 2020-10-12 18:53:06.000000000 +0000 @@ -56,8 +56,8 @@ } exit: - git_strarray_free(&refs); - git_strarray_free(&wtrefs); + git_strarray_dispose(&refs); + git_strarray_dispose(&wtrefs); cl_git_pass(error); } @@ -163,7 +163,10 @@ cl_git_pass(git_branch_lookup(&branch, fixture.repo, "testrepo-worktree", GIT_BRANCH_LOCAL)); cl_git_pass(git_reference_rename(&renamed, branch, "refs/heads/renamed", 0, NULL)); - cl_git_pass(git_repository_head(&head, fixture.worktree)); + + cl_git_pass(git_reference_lookup(&head, fixture.worktree, GIT_HEAD_FILE)); + cl_assert_equal_i(git_reference_type(head), GIT_REFERENCE_SYMBOLIC); + cl_assert_equal_s(git_reference_symbolic_target(head), "refs/heads/renamed"); git_reference_free(head); git_reference_free(branch); diff -Nru libgit2-0.28.5+dfsg.1/tests/worktree/repository.c libgit2-1.1.0+dfsg.1/tests/worktree/repository.c --- libgit2-0.28.5+dfsg.1/tests/worktree/repository.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/worktree/repository.c 2020-10-12 18:53:06.000000000 +0000 @@ -50,9 +50,12 @@ cl_assert(git_repository_head_detached(fixture.worktree)); cl_assert(git_repository_head_detached_for_worktree(fixture.repo, "testrepo-worktree")); - cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + + cl_assert_equal_oid(&ref->target.oid, &head->target.oid); git_reference_free(ref); + git_reference_free(head); } void test_worktree_repository__head_detached_fails_for_invalid_worktree(void) diff -Nru libgit2-0.28.5+dfsg.1/tests/worktree/worktree.c libgit2-1.1.0+dfsg.1/tests/worktree/worktree.c --- libgit2-0.28.5+dfsg.1/tests/worktree/worktree.c 2020-03-31 13:42:14.000000000 +0000 +++ libgit2-1.1.0+dfsg.1/tests/worktree/worktree.c 2020-10-12 18:53:06.000000000 +0000 @@ -30,7 +30,7 @@ cl_assert_equal_i(wts.count, 1); cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); - git_strarray_free(&wts); + git_strarray_dispose(&wts); } void test_worktree_worktree__list_with_invalid_worktree_dirs(void) @@ -42,7 +42,7 @@ }; git_buf path = GIT_BUF_INIT; git_strarray wts; - unsigned i, j, len; + size_t i, j, len; cl_git_pass(git_buf_printf(&path, "%s/worktrees/invalid", fixture.repo->commondir)); @@ -61,7 +61,7 @@ cl_git_pass(git_worktree_list(&wts, fixture.worktree)); cl_assert_equal_i(wts.count, 1); cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); - git_strarray_free(&wts); + git_strarray_dispose(&wts); for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) { git_buf_truncate(&path, len); @@ -81,7 +81,7 @@ cl_assert_equal_i(wts.count, 1); cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); - git_strarray_free(&wts); + git_strarray_dispose(&wts); } void test_worktree_worktree__list_without_worktrees(void) @@ -380,7 +380,7 @@ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); cl_assert_equal_s(git_worktree_name(wt), "testrepo-worktree"); - + git_worktree_free(wt); } @@ -581,45 +581,32 @@ git_worktree_free(wt); } -static int read_head_ref(git_repository *repo, const char *path, void *payload) +static int foreach_worktree_cb(git_repository *worktree, void *payload) { - git_vector *refs = (git_vector *) payload; - git_reference *head; - - GIT_UNUSED(repo); + int *counter = (int *)payload; - cl_git_pass(git_reference__read_head(&head, repo, path)); + switch (*counter) { + case 0: + cl_assert_equal_s(git_repository_path(fixture.repo), + git_repository_path(worktree)); + cl_assert(!git_repository_is_worktree(worktree)); + break; + case 1: + cl_assert_equal_s(git_repository_path(fixture.worktree), + git_repository_path(worktree)); + cl_assert(git_repository_is_worktree(worktree)); + break; + default: + cl_fail("more worktrees found than expected"); + } - git_vector_insert(refs, head); + (*counter)++; return 0; } -void test_worktree_worktree__foreach_head_gives_same_results_in_wt_and_repo(void) +void test_worktree_worktree__foreach_worktree_lists_all_worktrees(void) { - git_vector repo_refs = GIT_VECTOR_INIT, worktree_refs = GIT_VECTOR_INIT; - git_reference *heads[2]; - size_t i; - - cl_git_pass(git_reference_lookup(&heads[0], fixture.repo, GIT_HEAD_FILE)); - cl_git_pass(git_reference_lookup(&heads[1], fixture.worktree, GIT_HEAD_FILE)); - - cl_git_pass(git_repository_foreach_head(fixture.repo, read_head_ref, &repo_refs)); - cl_git_pass(git_repository_foreach_head(fixture.worktree, read_head_ref, &worktree_refs)); - - cl_assert_equal_i(repo_refs.length, ARRAY_SIZE(heads)); - cl_assert_equal_i(worktree_refs.length, ARRAY_SIZE(heads)); - - for (i = 0; i < ARRAY_SIZE(heads); i++) { - cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name); - cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name); - cl_assert_equal_s(heads[i]->name, ((git_reference *) worktree_refs.contents[i])->name); - - git_reference_free(heads[i]); - git_reference_free(repo_refs.contents[i]); - git_reference_free(worktree_refs.contents[i]); - } - - git_vector_free(&repo_refs); - git_vector_free(&worktree_refs); + int counter = 0; + cl_git_pass(git_repository_foreach_worktree(fixture.repo, foreach_worktree_cb, &counter)); }