mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-01 16:45:42 +00:00
Update upstream source from tag 'upstream/1.6.4+ds'
Update to upstream version '1.6.4+ds'
with Debian dir a2c791e8dc
This commit is contained in:
commit
6dbda115ac
8
.github/workflows/benchmark.yml
vendored
8
.github/workflows/benchmark.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
setup-script: ubuntu
|
||||
- name: "macOS"
|
||||
os: macos-10.15
|
||||
os: macos-11
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_GSSAPI=ON -DBUILD_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_CLI=ON -DCMAKE_BUILD_TYPE=Release
|
||||
@ -50,7 +50,7 @@ jobs:
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -66,9 +66,9 @@ jobs:
|
||||
- name: Benchmark
|
||||
run: |
|
||||
if [[ "$(uname -s)" == MINGW* ]]; then
|
||||
GIT2_CLI="$(cygpath -w $(pwd))\\build\\Release\\git2_cli"
|
||||
GIT2_CLI="$(cygpath -w $(pwd))\\build\\Release\\git2"
|
||||
else
|
||||
GIT2_CLI="$(pwd)/build/git2_cli"
|
||||
GIT2_CLI="$(pwd)/build/git2"
|
||||
fi
|
||||
|
||||
mkdir benchmark && cd benchmark
|
||||
|
145
.github/workflows/main.yml
vendored
145
.github/workflows/main.yml
vendored
@ -48,7 +48,7 @@ jobs:
|
||||
name: "Create container: ${{ matrix.container.name }}"
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -120,52 +120,9 @@ jobs:
|
||||
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
os: ubuntu-latest
|
||||
- name: "Linux (MemorySanitizer)"
|
||||
id: memorysanitizer
|
||||
container:
|
||||
name: 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 -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
os: ubuntu-latest
|
||||
- name: "Linux (UndefinedBehaviorSanitizer)"
|
||||
id: ubsanitizer
|
||||
container:
|
||||
name: 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 -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
os: ubuntu-latest
|
||||
- name: "Linux (ThreadSanitizer)"
|
||||
id: threadsanitizer
|
||||
container:
|
||||
name: focal
|
||||
env:
|
||||
CC: clang-10
|
||||
CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
|
||||
CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
|
||||
os: ubuntu-latest
|
||||
- name: "macOS"
|
||||
id: macos
|
||||
os: macos-10.15
|
||||
os: macos-11
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
|
||||
@ -176,19 +133,25 @@ jobs:
|
||||
- name: "Windows (amd64, Visual Studio)"
|
||||
id: windows-amd64-vs
|
||||
os: windows-2019
|
||||
setup-script: win32
|
||||
env:
|
||||
ARCH: amd64
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
|
||||
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
|
||||
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
|
||||
BUILD_TEMP: D:\Temp
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
- name: "Windows (x86, Visual Studio)"
|
||||
id: windows-x86-vs
|
||||
os: windows-2019
|
||||
setup-script: win32
|
||||
env:
|
||||
ARCH: x86
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
|
||||
CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
|
||||
BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
|
||||
BUILD_TEMP: D:\Temp
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
- name: "Windows (amd64, mingw)"
|
||||
@ -215,13 +178,88 @@ jobs:
|
||||
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
|
||||
|
||||
# Sanitizers
|
||||
- name: "Sanitizer (Memory)"
|
||||
id: memorysanitizer
|
||||
container:
|
||||
name: 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 -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
os: ubuntu-latest
|
||||
- name: "Sanitizer (UndefinedBehavior)"
|
||||
id: ubsanitizer
|
||||
container:
|
||||
name: 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 -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
os: ubuntu-latest
|
||||
- name: "Sanitizer (Thread)"
|
||||
id: threadsanitizer
|
||||
container:
|
||||
name: focal
|
||||
env:
|
||||
CC: clang-10
|
||||
CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
|
||||
CMAKE_OPTIONS: -DCMAKE_PREFIX_PATH=/usr/local -DUSE_HTTPS=OpenSSL -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
|
||||
os: ubuntu-latest
|
||||
|
||||
# Experimental: SHA256 support
|
||||
- name: "Linux (SHA256, Xenial, Clang, OpenSSL)"
|
||||
id: xenial-clang-openssl
|
||||
container:
|
||||
name: xenial
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DEXPERIMENTAL_SHA256=ON
|
||||
os: ubuntu-latest
|
||||
- name: "macOS (SHA256)"
|
||||
id: macos
|
||||
os: macos-11
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON -DEXPERIMENTAL_SHA256=ON
|
||||
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
setup-script: osx
|
||||
- name: "Windows (SHA256, amd64, Visual Studio)"
|
||||
id: windows-amd64-vs
|
||||
os: windows-2019
|
||||
env:
|
||||
ARCH: amd64
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DEXPERIMENTAL_SHA256=ON
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
fail-fast: false
|
||||
env: ${{ matrix.platform.env }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
name: "Build: ${{ matrix.platform.name }}"
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -251,6 +289,10 @@ jobs:
|
||||
- name: Build and test
|
||||
run: |
|
||||
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
|
||||
export GITTEST_GITHUB_SSH_KEY="${{ secrets.GITTEST_GITHUB_SSH_KEY }}"
|
||||
export GITTEST_GITHUB_SSH_PUBKEY="${{ secrets.GITTEST_GITHUB_SSH_PUBKEY }}"
|
||||
export GITTEST_GITHUB_SSH_PASSPHRASE="${{ secrets.GITTEST_GITHUB_SSH_PASSPHRASE }}"
|
||||
export GITTEST_GITHUB_SSH_REMOTE_HOSTKEY="${{ secrets.GITTEST_GITHUB_SSH_REMOTE_HOSTKEY }}"
|
||||
|
||||
if [ -n "${{ matrix.platform.container.name }}" ]; then
|
||||
mkdir build
|
||||
@ -291,12 +333,13 @@ jobs:
|
||||
test_results:
|
||||
name: Test results
|
||||
needs: [ build ]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download test results
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Generate test summary
|
||||
uses: test-summary/action@v1
|
||||
uses: test-summary/action@v2
|
||||
with:
|
||||
paths: 'test-results-*/*.xml'
|
||||
|
||||
@ -313,7 +356,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -332,7 +375,7 @@ jobs:
|
||||
cm doc api.docurium
|
||||
git checkout gh-pages
|
||||
zip --exclude .git/\* --exclude .gitignore --exclude .gitattributes -r api-documentation.zip .
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload artifact
|
||||
with:
|
||||
name: api-documentation
|
||||
|
44
.github/workflows/nightly.yml
vendored
44
.github/workflows/nightly.yml
vendored
@ -154,7 +154,7 @@ jobs:
|
||||
SKIP_SSH_TESTS: true
|
||||
os: ubuntu-latest
|
||||
- name: "macOS"
|
||||
os: macos-10.15
|
||||
os: macos-11
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON
|
||||
@ -265,13 +265,43 @@ jobs:
|
||||
RUN_INVASIVE_TESTS: true
|
||||
SKIP_PROXY_TESTS: true
|
||||
os: ubuntu-latest
|
||||
|
||||
# Experimental: SHA256 support
|
||||
- name: "Linux (SHA256, Xenial, Clang, OpenSSL)"
|
||||
id: xenial-clang-openssl
|
||||
container:
|
||||
name: xenial
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
|
||||
os: ubuntu-latest
|
||||
- name: "macOS (SHA256)"
|
||||
id: macos
|
||||
os: macos-10.15
|
||||
env:
|
||||
CC: clang
|
||||
CMAKE_OPTIONS: -DREGEX_BACKEND=regcomp_l -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=leaks -DUSE_GSSAPI=ON -DEXPERIMENTAL_SHA256=ON
|
||||
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
setup-script: osx
|
||||
- name: "Windows (SHA256, amd64, Visual Studio)"
|
||||
id: windows-amd64-vs
|
||||
os: windows-2019
|
||||
env:
|
||||
ARCH: amd64
|
||||
CMAKE_GENERATOR: Visual Studio 16 2019
|
||||
CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DEXPERIMENTAL_SHA256=ON
|
||||
SKIP_SSH_TESTS: true
|
||||
SKIP_NEGOTIATE_TESTS: true
|
||||
fail-fast: false
|
||||
name: "Build ${{ matrix.platform.name }}"
|
||||
env: ${{ matrix.platform.env }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
name: "Build ${{ matrix.platform.name }}"
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -333,7 +363,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
@ -358,13 +388,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: 'cpp'
|
||||
|
||||
@ -376,4 +406,4 @@ jobs:
|
||||
cmake --build .
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
project(libgit2 VERSION "1.5.1" LANGUAGES C)
|
||||
project(libgit2 VERSION "1.6.4" LANGUAGES C)
|
||||
|
||||
# Add find modules to the path
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||
@ -15,6 +15,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||
# Build options
|
||||
#
|
||||
|
||||
# Experimental features
|
||||
option(EXPERIMENTAL_SHA256 "Enable experimental SHA256 support (for R&D/testing)" OFF)
|
||||
|
||||
# Optional subsystems
|
||||
option(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
|
||||
option(BUILD_TESTS "Build Tests using the Clar suite" ON)
|
||||
@ -107,6 +110,7 @@ include(IdeSplitSources)
|
||||
include(FeatureSummary)
|
||||
include(EnableWarnings)
|
||||
include(DefaultCFlags)
|
||||
include(ExperimentalFeatures)
|
||||
|
||||
|
||||
#
|
||||
|
30
COPYING
30
COPYING
@ -1184,3 +1184,33 @@ 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The built-in git_fs_path_basename_r() function is based on the
|
||||
Android implementation, BSD licensed:
|
||||
|
||||
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.
|
||||
|
11
README.md
11
README.md
@ -4,8 +4,8 @@ libgit2 - the Git linkable library
|
||||
| Build Status | |
|
||||
| ------------ | - |
|
||||
| **main** branch CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush) |
|
||||
| **v1.4 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.4) |
|
||||
| **v1.3 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.3) |
|
||||
| **v1.6 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.6) |
|
||||
| **v1.5 branch** CI builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22CI+Build%22+event%3Apush+branch%3Amaint%2Fv1.5) |
|
||||
| **Nightly** builds | [](https://github.com/libgit2/libgit2/actions?query=workflow%3A%22Nightly+Build%22) [](https://scan.coverity.com/projects/639) |
|
||||
|
||||
`libgit2` is a portable, pure C implementation of the Git core methods
|
||||
@ -25,8 +25,9 @@ and on Git hosting providers like [GitHub](https://github.com/),
|
||||
We perform the merge every time you click "merge pull request".
|
||||
|
||||
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special
|
||||
Linking Exception). This basically means that you can link it (unmodified)
|
||||
with any kind of software without having to release its source code.
|
||||
Linking Exception). This means that you can link against the library with any
|
||||
kind of software without making that software fall under the GPL.
|
||||
Changes to libgit2 would still be covered under its GPL license.
|
||||
Additionally, the example code has been released to the public domain (see the
|
||||
[separate license](examples/COPYING) for more information).
|
||||
|
||||
@ -395,7 +396,7 @@ Here are the bindings to libgit2 that are currently available:
|
||||
* Pharo Smalltalk
|
||||
* libgit2-pharo-bindings <https://github.com/pharo-vcs/libgit2-pharo-bindings>
|
||||
* PHP
|
||||
* php-git <https://github.com/libgit2/php-git>
|
||||
* php-git2 <https://github.com/RogerGee/php-git2>
|
||||
* Python
|
||||
* pygit2 <https://github.com/libgit2/pygit2>
|
||||
* R
|
||||
|
20
ci/build.sh
20
ci/build.sh
@ -13,16 +13,30 @@ BUILD_PATH=${BUILD_PATH:=$PATH}
|
||||
CMAKE=$(which cmake)
|
||||
CMAKE_GENERATOR=${CMAKE_GENERATOR:-Unix Makefiles}
|
||||
|
||||
indent() { sed "s/^/ /"; }
|
||||
|
||||
cygfullpath() {
|
||||
result=$(echo "${1}" | tr \; \\n | while read -r element; do
|
||||
if [ "${last}" != "" ]; then echo -n ":"; fi
|
||||
echo -n $(cygpath "${element}")
|
||||
last="${element}"
|
||||
done)
|
||||
if [ "${result}" = "" ]; then exit 1; fi
|
||||
echo "${result}"
|
||||
}
|
||||
|
||||
if [[ "$(uname -s)" == MINGW* ]]; then
|
||||
BUILD_PATH=$(cygpath "$BUILD_PATH")
|
||||
BUILD_PATH=$(cygfullpath "${BUILD_PATH}")
|
||||
fi
|
||||
|
||||
indent() { sed "s/^/ /"; }
|
||||
|
||||
echo "Source directory: ${SOURCE_DIR}"
|
||||
echo "Build directory: ${BUILD_DIR}"
|
||||
echo ""
|
||||
|
||||
echo "Platform:"
|
||||
uname -s | indent
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
echo "macOS version:"
|
||||
sw_vers | indent
|
||||
@ -40,7 +54,7 @@ echo "Kernel version:"
|
||||
uname -a 2>&1 | indent
|
||||
|
||||
echo "CMake version:"
|
||||
env PATH="${BUILD_PATH}" "${CMAKE}" --version 2>&1 | indent
|
||||
env PATH="${BUILD_PATH}" "${CMAKE}" --version | head -1 2>&1 | indent
|
||||
|
||||
if test -n "${CC}"; then
|
||||
echo "Compiler version:"
|
||||
|
@ -7,11 +7,13 @@ RUN apt-get update && \
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
gettext \
|
||||
gcc \
|
||||
git \
|
||||
krb5-user \
|
||||
libcurl4-gnutls-dev \
|
||||
libexpat1-dev \
|
||||
libgcrypt20-dev \
|
||||
libintl-perl \
|
||||
libkrb5-dev \
|
||||
libpcre3-dev \
|
||||
libssl-dev \
|
||||
@ -28,7 +30,17 @@ RUN apt-get update && \
|
||||
&& \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM apt AS mbedtls
|
||||
FROM apt AS git
|
||||
RUN cd /tmp && \
|
||||
curl --location --silent --show-error https://github.com/git/git/archive/refs/tags/v2.39.1.tar.gz | \
|
||||
tar -xz && \
|
||||
cd git-2.39.1 && \
|
||||
make && \
|
||||
make prefix=/usr install && \
|
||||
cd .. && \
|
||||
rm -rf git-2.39.1
|
||||
|
||||
FROM git AS mbedtls
|
||||
RUN cd /tmp && \
|
||||
curl --location --silent --show-error https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-2.16.2.tar.gz | \
|
||||
tar -xz && \
|
||||
|
@ -11,9 +11,9 @@ BUILD_TEMP=$(cygpath $BUILD_TEMP)
|
||||
|
||||
case "$ARCH" in
|
||||
amd64)
|
||||
MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
|
||||
MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-01-23/mingw-x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
|
||||
x86)
|
||||
MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
|
||||
MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-01-23/mingw-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
|
||||
esac
|
||||
|
||||
if [ -z "$MINGW_URI" ]; then
|
||||
|
27
ci/setup-win32-build.sh
Executable file
27
ci/setup-win32-build.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
echo "##############################################################################"
|
||||
echo "## Downloading libssh2"
|
||||
echo "##############################################################################"
|
||||
|
||||
BUILD_TEMP=${BUILD_TEMP:=$TEMP}
|
||||
BUILD_TEMP=$(cygpath $BUILD_TEMP)
|
||||
|
||||
case "$ARCH" in
|
||||
amd64)
|
||||
LIBSSH2_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-02-01/libssh2-20230201-amd64.zip";;
|
||||
x86)
|
||||
LIBSSH2_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-02-01-v2/libssh2-20230201-x86.zip";;
|
||||
esac
|
||||
|
||||
if [ -z "$LIBSSH2_URI" ]; then
|
||||
echo "No URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BUILD_TEMP"
|
||||
|
||||
curl -s -L "$LIBSSH2_URI" -o "$BUILD_TEMP"/libssh2-"$ARCH".zip
|
||||
unzip -q "$BUILD_TEMP"/libssh2-"$ARCH".zip -d "$BUILD_TEMP"
|
129
ci/test.sh
129
ci/test.sh
@ -13,22 +13,52 @@ fi
|
||||
|
||||
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||
BUILD_DIR=$(pwd)
|
||||
BUILD_PATH=${BUILD_PATH:=$PATH}
|
||||
CTEST=$(which ctest)
|
||||
TMPDIR=${TMPDIR:-/tmp}
|
||||
USER=${USER:-$(whoami)}
|
||||
|
||||
HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
|
||||
export CLAR_HOMEDIR=${HOME}
|
||||
|
||||
SUCCESS=1
|
||||
CONTINUE_ON_FAILURE=0
|
||||
|
||||
cleanup() {
|
||||
echo "Cleaning up..."
|
||||
|
||||
if [ ! -z "$GITDAEMON_PID" ]; then
|
||||
echo "Stopping git daemon..."
|
||||
kill $GITDAEMON_PID
|
||||
if [ ! -z "$GIT_STANDARD_PID" ]; then
|
||||
echo "Stopping git daemon (standard)..."
|
||||
kill $GIT_STANDARD_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$GIT_NAMESPACE_PID" ]; then
|
||||
echo "Stopping git daemon (namespace)..."
|
||||
kill $GIT_NAMESPACE_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$GIT_SHA256_PID" ]; then
|
||||
echo "Stopping git daemon (sha256)..."
|
||||
kill $GIT_SHA256_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$PROXY_BASIC_PID" ]; then
|
||||
echo "Stopping proxy (Basic)..."
|
||||
kill $PROXY_BASIC_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$PROXY_NTLM_PID" ]; then
|
||||
echo "Stopping proxy (NTLM)..."
|
||||
kill $PROXY_NTLM_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$HTTP_PID" ]; then
|
||||
echo "Stopping HTTP server..."
|
||||
kill $HTTP_PID
|
||||
fi
|
||||
|
||||
if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then
|
||||
echo "Stopping SSH..."
|
||||
echo "Stopping SSH server..."
|
||||
kill $(cat "${SSHD_DIR}/pid")
|
||||
fi
|
||||
|
||||
@ -52,7 +82,11 @@ run_test() {
|
||||
|
||||
RETURN_CODE=0
|
||||
|
||||
CLAR_SUMMARY="${BUILD_DIR}/results_${1}.xml" ctest -V -R "^${1}$" || RETURN_CODE=$? && true
|
||||
(
|
||||
export PATH="${BUILD_PATH}"
|
||||
export CLAR_SUMMARY="${BUILD_DIR}/results_${1}.xml"
|
||||
"${CTEST}" -V -R "^${1}$"
|
||||
) || RETURN_CODE=$? && true
|
||||
|
||||
if [ "$RETURN_CODE" -eq 0 ]; then
|
||||
FAILED=0
|
||||
@ -73,48 +107,81 @@ run_test() {
|
||||
fi
|
||||
}
|
||||
|
||||
indent() { sed "s/^/ /"; }
|
||||
|
||||
cygfullpath() {
|
||||
result=$(echo "${1}" | tr \; \\n | while read -r element; do
|
||||
if [ "${last}" != "" ]; then echo -n ":"; fi
|
||||
echo -n $(cygpath "${element}")
|
||||
last="${element}"
|
||||
done)
|
||||
if [ "${result}" = "" ]; then exit 1; fi
|
||||
echo "${result}"
|
||||
}
|
||||
|
||||
if [[ "$(uname -s)" == MINGW* ]]; then
|
||||
BUILD_PATH=$(cygfullpath "$BUILD_PATH")
|
||||
fi
|
||||
|
||||
|
||||
# Configure the test environment; run them early so that we're certain
|
||||
# that they're started by the time we need them.
|
||||
|
||||
echo "CTest version:"
|
||||
env PATH="${BUILD_PATH}" "${CTEST}" --version | head -1 2>&1 | indent
|
||||
|
||||
echo ""
|
||||
|
||||
echo "##############################################################################"
|
||||
echo "## Configuring test environment"
|
||||
echo "##############################################################################"
|
||||
|
||||
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" >/dev/null
|
||||
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null &
|
||||
GITDAEMON_PID=$!
|
||||
disown $GITDAEMON_PID
|
||||
echo "Starting git daemon (standard)..."
|
||||
GIT_STANDARD_DIR=`mktemp -d ${TMPDIR}/git_standard.XXXXXXXX`
|
||||
git init --bare "${GIT_STANDARD_DIR}/test.git" >/dev/null
|
||||
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="${GIT_STANDARD_DIR}" "${GIT_STANDARD_DIR}" 2>/dev/null &
|
||||
GIT_STANDARD_PID=$!
|
||||
|
||||
echo "Starting git daemon (namespace)..."
|
||||
GIT_NAMESPACE_DIR=`mktemp -d ${TMPDIR}/git_namespace.XXXXXXXX`
|
||||
cp -R "${SOURCE_DIR}/tests/resources/namespace.git" "${GIT_NAMESPACE_DIR}/namespace.git"
|
||||
GIT_NAMESPACE="name1" git daemon --listen=localhost --port=9419 --export-all --enable=receive-pack --base-path="${GIT_NAMESPACE_DIR}" "${GIT_NAMESPACE_DIR}" &
|
||||
GIT_NAMESPACE_PID=$!
|
||||
|
||||
echo "Starting git daemon (sha256)..."
|
||||
GIT_SHA256_DIR=`mktemp -d ${TMPDIR}/git_sha256.XXXXXXXX`
|
||||
cp -R "${SOURCE_DIR}/tests/resources/testrepo_256.git" "${GIT_SHA256_DIR}/testrepo_256.git"
|
||||
git daemon --listen=localhost --port=9420 --export-all --enable=receive-pack --base-path="${GIT_SHA256_DIR}" "${GIT_SHA256_DIR}" &
|
||||
GIT_SHA256_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 &
|
||||
PROXY_BASIC_PID=$!
|
||||
|
||||
echo ""
|
||||
echo "Starting HTTP proxy (NTLM)..."
|
||||
java -jar poxyproxy.jar --address 127.0.0.1 --port 8090 --credentials foo:bar --auth-type ntlm --quiet &
|
||||
PROXY_NTLM_PID=$!
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_NTLM_TESTS" -o -z "$SKIP_ONLINE_TESTS" ]; then
|
||||
curl --location --silent --show-error https://github.com/ethomson/poxygit/releases/download/v0.5.1/poxygit-0.5.1.jar >poxygit.jar
|
||||
|
||||
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}" &
|
||||
HTTP_DIR=`mktemp -d ${TMPDIR}/http.XXXXXXXX`
|
||||
git init --bare "${HTTP_DIR}/test.git"
|
||||
java -jar poxygit.jar --address 127.0.0.1 --port 9000 --credentials foo:baz --quiet "${HTTP_DIR}" &
|
||||
HTTP_PID=$!
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_SSH_TESTS" ]; then
|
||||
echo ""
|
||||
echo "Starting ssh daemon..."
|
||||
HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
|
||||
echo "Starting SSH server..."
|
||||
SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
|
||||
git init --bare "${SSHD_DIR}/test.git" >/dev/null
|
||||
cat >"${SSHD_DIR}/sshd_config" <<-EOF
|
||||
@ -219,12 +286,30 @@ fi
|
||||
|
||||
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
|
||||
echo ""
|
||||
echo "Running gitdaemon tests"
|
||||
echo "Running gitdaemon (standard) tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_URL="git://localhost/test.git"
|
||||
run_test gitdaemon
|
||||
unset GITTEST_REMOTE_URL
|
||||
|
||||
echo ""
|
||||
echo "Running gitdaemon (namespace) tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_URL="git://localhost:9419/namespace.git"
|
||||
export GITTEST_REMOTE_BRANCH="four"
|
||||
run_test gitdaemon_namespace
|
||||
unset GITTEST_REMOTE_URL
|
||||
unset GITTEST_REMOTE_BRANCH
|
||||
|
||||
echo ""
|
||||
echo "Running gitdaemon (sha256) tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_URL="git://localhost:9420/testrepo_256.git"
|
||||
run_test gitdaemon_sha256
|
||||
unset GITTEST_REMOTE_URL
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_PROXY_TESTS" ]; then
|
||||
@ -348,7 +433,7 @@ if [ -z "$SKIP_FUZZERS" ]; then
|
||||
echo "## Running fuzzers"
|
||||
echo "##############################################################################"
|
||||
|
||||
ctest -V -R 'fuzzer'
|
||||
env PATH="${BUILD_PATH}" "${CTEST}" -V -R 'fuzzer'
|
||||
fi
|
||||
|
||||
cleanup
|
||||
|
23
cmake/ExperimentalFeatures.cmake
Normal file
23
cmake/ExperimentalFeatures.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
# Experimental feature support for libgit2 - developers can opt in to
|
||||
# experimental functionality, like sha256 support. When experimental
|
||||
# functionality is enabled, we set both a cmake flag *and* a compile
|
||||
# definition. The cmake flag is used to generate `experimental.h`,
|
||||
# which will be installed by a `make install`. But the compile definition
|
||||
# is used by the libgit2 sources to detect the functionality at library
|
||||
# build time. This allows us to have an in-tree `experimental.h` with
|
||||
# *no* experiments enabled. This lets us support users who build without
|
||||
# cmake and cannot generate the `experimental.h` file.
|
||||
|
||||
if(EXPERIMENTAL_SHA256)
|
||||
add_feature_info("SHA256 API" ON "experimental SHA256 APIs")
|
||||
|
||||
set(EXPERIMENTAL 1)
|
||||
set(GIT_EXPERIMENTAL_SHA256 1)
|
||||
add_definitions(-DGIT_EXPERIMENTAL_SHA256=1)
|
||||
else()
|
||||
add_feature_info("SHA256 API" OFF "experimental SHA256 APIs")
|
||||
endif()
|
||||
|
||||
if(EXPERIMENTAL)
|
||||
set(LIBGIT2_FILENAME "${LIBGIT2_FILENAME}-experimental")
|
||||
endif()
|
@ -1,13 +1,154 @@
|
||||
v1.5.1
|
||||
v1.6.4
|
||||
------
|
||||
|
||||
🔒 This is a security release to address CVE-2023-22742: when compiled using the optional, included libssh2 backend, libgit2 fails to verify SSH keys by default.
|
||||
## What's Changed
|
||||
|
||||
When using an SSH remote with the optional, included libssh2 backend, libgit2 does not perform certificate checking by default. Prior versions of libgit2 require the caller to set the `certificate_check` field of libgit2's `git_remote_callbacks` structure - if a certificate check callback is not set, libgit2 does not perform any certificate checking. This means that by default - without configuring a certificate check callback, clients will not perform validation on the server SSH keys and may be subject to a man-in-the-middle attack.
|
||||
### Bug fixes
|
||||
* config: return `GIT_ENOTFOUND` for missing programdata by @ethomson in https://github.com/libgit2/libgit2/pull/6547
|
||||
|
||||
The libgit2 security team would like to thank the Julia and Rust security teams for responsibly disclosing this vulnerability and assisting with fixing the vulnerability.
|
||||
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.6.3...v1.6.4
|
||||
|
||||
All users of the v1.5 release line are recommended to upgrade.
|
||||
v1.6.3
|
||||
------
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* odb: restore `git_odb_open` by @ethomson in https://github.com/libgit2/libgit2/pull/6520
|
||||
* Ensure that `git_index_add_all` handles ignored directories by @ethomson in https://github.com/libgit2/libgit2/pull/6521
|
||||
* pack: use 64 bits for the number of objects by @carlosmn in https://github.com/libgit2/libgit2/pull/6530
|
||||
|
||||
### Build and CI improvements
|
||||
|
||||
* Remove unused wditer variable by @georgthegreat in https://github.com/libgit2/libgit2/pull/6518
|
||||
* fs_path: let root run the ownership tests by @ethomson in https://github.com/libgit2/libgit2/pull/6513
|
||||
* sysdir: Do not declare win32 functions on non-win32 platforms by @Batchyx in https://github.com/libgit2/libgit2/pull/6527
|
||||
* cmake: don't include `include/git2` by @ethomson in https://github.com/libgit2/libgit2/pull/6529
|
||||
|
||||
## New Contributors
|
||||
* @georgthegreat made their first contribution in https://github.com/libgit2/libgit2/pull/6518
|
||||
|
||||
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.6.2...v1.6.3
|
||||
|
||||
v1.6.2
|
||||
------
|
||||
|
||||
## What's Changed
|
||||
### Bug fixes
|
||||
|
||||
* remote: always populate old id in update tips by @ethomson in https://github.com/libgit2/libgit2/pull/6506
|
||||
The update tips callback would not always be properly provided with an empty (`0000000...`) OID for new refs.
|
||||
|
||||
* Revert #6503 by @ethomson in https://github.com/libgit2/libgit2/pull/6511
|
||||
The certificate callback added port information for callbacks in #6503, but the format was ambiguous with IPv6 addresses. Revert this change temporarily.
|
||||
|
||||
* Add `git_odb_backend_loose` back by @ethomson in https://github.com/libgit2/libgit2/pull/6512
|
||||
During SHA256 refactoring, the `git_odb_backend_loose` API was accidentally removed. Add it back.
|
||||
|
||||
* meta: configure pkg-config .pc correctly by @ethomson in https://github.com/libgit2/libgit2/pull/6514
|
||||
During SHA256 refactoring, the pkg-config `.pc` file was erroneously renamed to `git2` instead of `libgit2`. Repair this.
|
||||
|
||||
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.6.1...v1.6.2
|
||||
|
||||
v1.6
|
||||
----
|
||||
|
||||
This is release v1.6.1, "Hubbeliges Krokodil". This release adds experimental SHA256 support and includes many new features and bugfixes. This release replaces libgit2 v1.6.0, which did not correctly update its version number(s).
|
||||
|
||||
## What's Changed
|
||||
|
||||
### New features
|
||||
|
||||
* **Support for bare repositories with SHA256 support (experimental)** by @ethomson in https://github.com/libgit2/libgit2/pull/6191
|
||||
You can configure experimental SHA256 support in libgit2 with `cmake -DEXPERIMENTAL_SHA256=ON` during project setup. This is useful for considering future integrations, work on clients, and work on language bindings. At present, working with bare repositories should largely work, including remote operations. But many pieces of functionality - including working with the index - are not yet supported. As a result, **libgit2 with SHA256 support should not be used in production or released with package distribution.**
|
||||
|
||||
* **Support the notion of a home directory separately from global configuration directory** by @ethomson in https://github.com/libgit2/libgit2/pull/6455 and https://github.com/libgit2/libgit2/pull/6456
|
||||
Callers and language bindings can now configure the home directory that libgit2 uses for file lookups (eg, the `.ssh` directory). This configuration is separate from the git global configuration path.
|
||||
|
||||
* **stash: partial stash specific files** by @gitkraken-jacobw in https://github.com/libgit2/libgit2/pull/6330
|
||||
A stash can be created with only specific files, using a pathspec. This is similar to the `git stash push` command.
|
||||
|
||||
* **push: revparse refspec source, so you can push things that are not refs** by @sven-of-cord in https://github.com/libgit2/libgit2/pull/6362
|
||||
Pushes can be performed using refspecs instead of only references.
|
||||
|
||||
* **Support OpenSSL3** by @ethomson in https://github.com/libgit2/libgit2/pull/6464 and https://github.com/libgit2/libgit2/pull/6471
|
||||
OpenSSL 3 is now supported, both when compiled directly and dynamically loaded.
|
||||
|
||||
### Bug fixes
|
||||
* winhttp: support long custom headers by @kcsaul in https://github.com/libgit2/libgit2/pull/6363
|
||||
* Fix memory leak by @csware in https://github.com/libgit2/libgit2/pull/6382
|
||||
* Don't fail the whole clone if you can't find a default branch by @torvalds in https://github.com/libgit2/libgit2/pull/6369
|
||||
* #6366: When a worktree is missing, return `GIT_ENOTFOUND`. by @arroz in https://github.com/libgit2/libgit2/pull/6395
|
||||
* commit-graph: only verify csum on `git_commit_graph_open()`. by @derrickstolee in https://github.com/libgit2/libgit2/pull/6420
|
||||
* Ignore missing 'safe.directory' config during ownership checks by @kcsaul in https://github.com/libgit2/libgit2/pull/6408
|
||||
* Fix leak in `git_tag_create_from_buffer` by @julianmesa-gitkraken in https://github.com/libgit2/libgit2/pull/6421
|
||||
* http: Update httpclient options when reusing an existing connection. by @slackner in https://github.com/libgit2/libgit2/pull/6416
|
||||
* Add support for `safe.directory *` by @csware in https://github.com/libgit2/libgit2/pull/6429
|
||||
* URL parsing for google-compatible URLs by @ethomson in https://github.com/libgit2/libgit2/pull/6326
|
||||
* Fixes #6433: `git_submodule_update` fails to update configured but missing submodule by @tagesuhu in https://github.com/libgit2/libgit2/pull/6434
|
||||
* transport: fix capabilities calculation by @russell in https://github.com/libgit2/libgit2/pull/6435
|
||||
* push: use resolved oid as the source by @ethomson in https://github.com/libgit2/libgit2/pull/6452
|
||||
* Use `git_clone__submodule` to avoid file checks in workdir by @abizjak in https://github.com/libgit2/libgit2/pull/6444
|
||||
* #6422: handle dangling symbolic refs gracefully by @arroz in https://github.com/libgit2/libgit2/pull/6423
|
||||
* `diff_file`: Fix crash when freeing a patch representing an empty untracked file by @jorio in https://github.com/libgit2/libgit2/pull/6475
|
||||
* clone: clean up options on failure by @ethomson in https://github.com/libgit2/libgit2/pull/6479
|
||||
* stash: update strarray usage by @ethomson in https://github.com/libgit2/libgit2/pull/6487
|
||||
* #6491: Sets `oid_type` on repos open with `git_repository_open_bare` by @arroz in https://github.com/libgit2/libgit2/pull/6492
|
||||
* Handle Win32 shares by @ethomson in https://github.com/libgit2/libgit2/pull/6493
|
||||
* Make failure to connect to ssh-agent non-fatal by @fxcoudert in https://github.com/libgit2/libgit2/pull/6497
|
||||
* odb: don't unconditionally add `oid_type` to stream by @ethomson in https://github.com/libgit2/libgit2/pull/6499
|
||||
* Pass hostkey & port to host verify callback by @fxcoudert in https://github.com/libgit2/libgit2/pull/6503
|
||||
|
||||
### Code cleanups
|
||||
* meta: update version number to v1.6.0-alpha by @ethomson in https://github.com/libgit2/libgit2/pull/6352
|
||||
* sha256: indirection for experimental functions by @ethomson in https://github.com/libgit2/libgit2/pull/6354
|
||||
* Delete `create.c.bak` by @lrm29 in https://github.com/libgit2/libgit2/pull/6398
|
||||
* Support non-cmake builds with an in-tree `experimental.h` by @ethomson in https://github.com/libgit2/libgit2/pull/6405
|
||||
|
||||
### Build and CI improvements
|
||||
* tests: skip flaky-ass googlesource tests by @ethomson in https://github.com/libgit2/libgit2/pull/6353
|
||||
* clar: remove ftrunacte from libgit2 tests by @boretrk in https://github.com/libgit2/libgit2/pull/6357
|
||||
* CI Improvements by @ethomson in https://github.com/libgit2/libgit2/pull/6403
|
||||
* fix compile on Windows with `-DWIN32_LEAN_AND_MEAN` by @christoph-cullmann in https://github.com/libgit2/libgit2/pull/6373
|
||||
* Fixes #6365 : Uppercase windows.h include fails build in case-sensitive OS by @Vinz2008 in https://github.com/libgit2/libgit2/pull/6377
|
||||
* ci: update version numbers of actions by @ethomson in https://github.com/libgit2/libgit2/pull/6448
|
||||
* thread: avoid warnings when building without threads by @ethomson in https://github.com/libgit2/libgit2/pull/6432
|
||||
* src: hide unused hmac() prototype by @0-wiz-0 in https://github.com/libgit2/libgit2/pull/6458
|
||||
* tests: update clar test runner by @ethomson in https://github.com/libgit2/libgit2/pull/6459
|
||||
* ci: always create test summaries, even on failure by @ethomson in https://github.com/libgit2/libgit2/pull/6460
|
||||
* Fix build failure with `-DEMBED_SSH_PATH` by @vicr123 in https://github.com/libgit2/libgit2/pull/6374
|
||||
* Define correct `off64_t` for AIX by @bzEq in https://github.com/libgit2/libgit2/pull/6376
|
||||
* Fix some warnings in main by @ethomson in https://github.com/libgit2/libgit2/pull/6480
|
||||
* strarray: remove deprecated declaration by @ethomson in https://github.com/libgit2/libgit2/pull/6486
|
||||
* tests: always unset `HTTP_PROXY` before starting tests by @ethomson in https://github.com/libgit2/libgit2/pull/6498
|
||||
|
||||
### Documentation improvements
|
||||
* add 2-clause BSD license to COPYING by @martinvonz in https://github.com/libgit2/libgit2/pull/6413
|
||||
* Add new PHP bindings project to language bindings section of README.md by @RogerGee in https://github.com/libgit2/libgit2/pull/6473
|
||||
* README: clarify the linking exception by @ethomson in https://github.com/libgit2/libgit2/pull/6494
|
||||
* Correct the definition of "empty" in the docs for `git_repository_is_empty` by @timrogers in https://github.com/libgit2/libgit2/pull/6500
|
||||
|
||||
## New Contributors
|
||||
* @christoph-cullmann made their first contribution in https://github.com/libgit2/libgit2/pull/6373
|
||||
* @Vinz2008 made their first contribution in https://github.com/libgit2/libgit2/pull/6377
|
||||
* @torvalds made their first contribution in https://github.com/libgit2/libgit2/pull/6369
|
||||
* @derrickstolee made their first contribution in https://github.com/libgit2/libgit2/pull/6420
|
||||
* @julianmesa-gitkraken made their first contribution in https://github.com/libgit2/libgit2/pull/6421
|
||||
* @slackner made their first contribution in https://github.com/libgit2/libgit2/pull/6416
|
||||
* @martinvonz made their first contribution in https://github.com/libgit2/libgit2/pull/6413
|
||||
* @tagesuhu made their first contribution in https://github.com/libgit2/libgit2/pull/6434
|
||||
* @russell made their first contribution in https://github.com/libgit2/libgit2/pull/6435
|
||||
* @sven-of-cord made their first contribution in https://github.com/libgit2/libgit2/pull/6362
|
||||
* @0-wiz-0 made their first contribution in https://github.com/libgit2/libgit2/pull/6458
|
||||
* @abizjak made their first contribution in https://github.com/libgit2/libgit2/pull/6444
|
||||
* @vicr123 made their first contribution in https://github.com/libgit2/libgit2/pull/6374
|
||||
* @bzEq made their first contribution in https://github.com/libgit2/libgit2/pull/6376
|
||||
* @gitkraken-jacobw made their first contribution in https://github.com/libgit2/libgit2/pull/6330
|
||||
* @fxcoudert made their first contribution in https://github.com/libgit2/libgit2/pull/6497
|
||||
* @timrogers made their first contribution in https://github.com/libgit2/libgit2/pull/6500
|
||||
|
||||
**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.5.0...v1.6.0
|
||||
|
||||
v1.5
|
||||
----
|
||||
|
@ -49,7 +49,7 @@ static void show_blob(const git_blob *blob)
|
||||
static void show_tree(const git_tree *tree)
|
||||
{
|
||||
size_t i, max_i = (int)git_tree_entrycount(tree);
|
||||
char oidstr[GIT_OID_HEXSZ + 1];
|
||||
char oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
const git_tree_entry *te;
|
||||
|
||||
for (i = 0; i < max_i; ++i) {
|
||||
@ -70,7 +70,7 @@ static void show_tree(const git_tree *tree)
|
||||
static void show_commit(const git_commit *commit)
|
||||
{
|
||||
unsigned int i, max_i;
|
||||
char oidstr[GIT_OID_HEXSZ + 1];
|
||||
char oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(oidstr, sizeof(oidstr), git_commit_tree_id(commit));
|
||||
printf("tree %s\n", oidstr);
|
||||
@ -90,7 +90,7 @@ static void show_commit(const git_commit *commit)
|
||||
|
||||
static void show_tag(const git_tag *tag)
|
||||
{
|
||||
char oidstr[GIT_OID_HEXSZ + 1];
|
||||
char oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(oidstr, sizeof(oidstr), git_tag_target_id(tag));;
|
||||
printf("object %s\n", oidstr);
|
||||
@ -125,7 +125,7 @@ int lg2_cat_file(git_repository *repo, int argc, char *argv[])
|
||||
{
|
||||
struct catfile_options o = { ".", NULL, 0, 0 };
|
||||
git_object *obj = NULL;
|
||||
char oidstr[GIT_OID_HEXSZ + 1];
|
||||
char oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
parse_opts(&o, argc, argv);
|
||||
|
||||
@ -133,7 +133,7 @@ int lg2_cat_file(git_repository *repo, int argc, char *argv[])
|
||||
"Could not resolve", o.rev);
|
||||
|
||||
if (o.verbose) {
|
||||
char oidstr[GIT_OID_HEXSZ + 1];
|
||||
char oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
git_oid_tostr(oidstr, sizeof(oidstr), git_object_id(obj));
|
||||
|
||||
printf("%s %s\n--\n",
|
||||
|
@ -15,17 +15,17 @@ static int progress_cb(const char *str, int len, void *data)
|
||||
*/
|
||||
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];
|
||||
char a_str[GIT_OID_SHA1_HEXSIZE+1], b_str[GIT_OID_SHA1_HEXSIZE+1];
|
||||
(void)data;
|
||||
|
||||
git_oid_fmt(b_str, b);
|
||||
b_str[GIT_OID_HEXSZ] = '\0';
|
||||
b_str[GIT_OID_SHA1_HEXSIZE] = '\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';
|
||||
a_str[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ static int show_ref(git_reference *ref, void *data)
|
||||
{
|
||||
git_repository *repo = data;
|
||||
git_reference *resolved = NULL;
|
||||
char hex[GIT_OID_HEXSZ+1];
|
||||
char hex[GIT_OID_SHA1_HEXSIZE+1];
|
||||
const git_oid *oid;
|
||||
git_object *obj;
|
||||
|
||||
@ -16,7 +16,7 @@ static int show_ref(git_reference *ref, void *data)
|
||||
|
||||
oid = git_reference_target(resolved ? resolved : ref);
|
||||
git_oid_fmt(hex, oid);
|
||||
hex[GIT_OID_HEXSZ] = 0;
|
||||
hex[GIT_OID_SHA1_HEXSIZE] = 0;
|
||||
check_lg2(git_object_lookup(&obj, repo, oid, GIT_OBJECT_ANY),
|
||||
"Unable to lookup object", hex);
|
||||
|
||||
|
@ -129,7 +129,7 @@ int lg2_general(git_repository *repo, int argc, char** argv)
|
||||
*/
|
||||
static void oid_parsing(git_oid *oid)
|
||||
{
|
||||
char out[GIT_OID_HEXSZ+1];
|
||||
char out[GIT_OID_SHA1_HEXSIZE+1];
|
||||
char hex[] = "4a202b346bb0fb0db7eff3cffeb3c70babbd2045";
|
||||
|
||||
printf("*Hex to Raw*\n");
|
||||
@ -142,7 +142,11 @@ static void oid_parsing(git_oid *oid)
|
||||
* this throughout the example for storing the value of the current SHA
|
||||
* key we're working with.
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(oid, hex, GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(oid, hex);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Once we've converted the string into the oid value, we can get the raw
|
||||
@ -152,7 +156,7 @@ static void oid_parsing(git_oid *oid)
|
||||
* char hex value.
|
||||
*/
|
||||
printf("\n*Raw to Hex*\n");
|
||||
out[GIT_OID_HEXSZ] = '\0';
|
||||
out[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
|
||||
/**
|
||||
* If you have a oid, you can easily get the hex value of the SHA as well.
|
||||
@ -173,7 +177,7 @@ static void oid_parsing(git_oid *oid)
|
||||
*/
|
||||
static void object_database(git_repository *repo, git_oid *oid)
|
||||
{
|
||||
char oid_hex[GIT_OID_HEXSZ+1] = { 0 };
|
||||
char oid_hex[GIT_OID_SHA1_HEXSIZE+1] = { 0 };
|
||||
const unsigned char *data;
|
||||
const char *str_type;
|
||||
int error;
|
||||
@ -266,7 +270,7 @@ static void commit_writing(git_repository *repo)
|
||||
git_tree *tree;
|
||||
git_commit *parent;
|
||||
git_signature *author, *committer;
|
||||
char oid_hex[GIT_OID_HEXSZ+1] = { 0 };
|
||||
char oid_hex[GIT_OID_SHA1_HEXSIZE+1] = { 0 };
|
||||
|
||||
printf("\n*Commit Writing*\n");
|
||||
|
||||
@ -287,9 +291,14 @@ static void commit_writing(git_repository *repo)
|
||||
* parents. Here we're creating oid objects to create the commit with,
|
||||
* but you can also use
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&tree_id, "f60079018b664e4e79329a7ef9559c8d9e0378d1", GIT_OID_SHA1);
|
||||
git_oid_fromstr(&parent_id, "5b5b025afb0b4c913b4c338a42934a3863bf3644", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&tree_id, "f60079018b664e4e79329a7ef9559c8d9e0378d1");
|
||||
git_tree_lookup(&tree, repo, &tree_id);
|
||||
git_oid_fromstr(&parent_id, "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
#endif
|
||||
git_tree_lookup(&tree, repo, &tree_id);
|
||||
git_commit_lookup(&parent, repo, &parent_id);
|
||||
|
||||
/**
|
||||
@ -345,7 +354,7 @@ static void commit_parsing(git_repository *repo)
|
||||
const git_signature *author, *cmtter;
|
||||
git_commit *commit, *parent;
|
||||
git_oid oid;
|
||||
char oid_hex[GIT_OID_HEXSZ+1];
|
||||
char oid_hex[GIT_OID_SHA1_HEXSIZE+1];
|
||||
const char *message;
|
||||
unsigned int parents, p;
|
||||
int error;
|
||||
@ -353,7 +362,11 @@ static void commit_parsing(git_repository *repo)
|
||||
|
||||
printf("\n*Commit Parsing*\n");
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&oid, "8496071c1b46c854b31185ea97743be6a8774479", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&oid, "8496071c1b46c854b31185ea97743be6a8774479");
|
||||
#endif
|
||||
|
||||
error = git_commit_lookup(&commit, repo, &oid);
|
||||
check_error(error, "looking up commit");
|
||||
@ -422,7 +435,11 @@ static void tag_parsing(git_repository *repo)
|
||||
* We create an oid for the tag object if we know the SHA and look it up
|
||||
* the same way that we would a commit (or any other object).
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&oid, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&oid, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
|
||||
#endif
|
||||
|
||||
error = git_tag_lookup(&tag, repo, &oid);
|
||||
check_error(error, "looking up tag");
|
||||
@ -470,7 +487,11 @@ static void tree_parsing(git_repository *repo)
|
||||
/**
|
||||
* Create the oid and lookup the tree object just like the other objects.
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&oid, "f60079018b664e4e79329a7ef9559c8d9e0378d1", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&oid, "f60079018b664e4e79329a7ef9559c8d9e0378d1");
|
||||
#endif
|
||||
git_tree_lookup(&tree, repo, &oid);
|
||||
|
||||
/**
|
||||
@ -524,7 +545,11 @@ static void blob_parsing(git_repository *repo)
|
||||
|
||||
printf("\n*Blob Parsing*\n");
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&oid, "1385f264afb75a56a5bec74243be9b367ba4ca08", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&oid, "1385f264afb75a56a5bec74243be9b367ba4ca08");
|
||||
#endif
|
||||
git_blob_lookup(&blob, repo, &oid);
|
||||
|
||||
/**
|
||||
@ -566,7 +591,11 @@ static void revwalking(git_repository *repo)
|
||||
|
||||
printf("\n*Revwalking*\n");
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_fromstr(&oid, "5b5b025afb0b4c913b4c338a42934a3863bf3644", GIT_OID_SHA1);
|
||||
#else
|
||||
git_oid_fromstr(&oid, "5b5b025afb0b4c913b4c338a42934a3863bf3644");
|
||||
#endif
|
||||
|
||||
/**
|
||||
* To use the revwalker, create a new walker, tell it how you want to sort
|
||||
@ -679,7 +708,7 @@ static void reference_listing(git_repository *repo)
|
||||
|
||||
for (i = 0; i < ref_list.count; ++i) {
|
||||
git_reference *ref;
|
||||
char oid_hex[GIT_OID_HEXSZ+1] = GIT_OID_HEX_ZERO;
|
||||
char oid_hex[GIT_OID_SHA1_HEXSIZE+1] = GIT_OID_SHA1_HEXZERO;
|
||||
const char *refname;
|
||||
|
||||
refname = ref_list.strings[i];
|
||||
|
@ -28,11 +28,18 @@ int lg2_index_pack(git_repository *repo, int argc, char **argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (git_indexer_new(&idx, ".", 0, NULL, NULL) < 0) {
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
error = git_indexer_new(&idx, ".", git_repository_oid_type(repo), NULL);
|
||||
#else
|
||||
error = git_indexer_new(&idx, ".", 0, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (error < 0) {
|
||||
puts("bad idx");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((fd = open(argv[1], 0)) < 0) {
|
||||
perror("open");
|
||||
return -1;
|
||||
|
@ -329,7 +329,7 @@ static void print_time(const git_time *intime, const char *prefix)
|
||||
/** Helper to print a commit object. */
|
||||
static void print_commit(git_commit *commit, struct log_options *opts)
|
||||
{
|
||||
char buf[GIT_OID_HEXSZ + 1];
|
||||
char buf[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
int i, count;
|
||||
const git_signature *sig;
|
||||
const char *scan, *eol;
|
||||
|
@ -34,7 +34,7 @@ static int use_remote(git_repository *repo, char *name)
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < refs_len; i++) {
|
||||
char oid[GIT_OID_HEXSZ + 1] = {0};
|
||||
char oid[GIT_OID_SHA1_HEXSIZE + 1] = {0};
|
||||
git_oid_fmt(oid, &refs[i]->oid);
|
||||
printf("%s\t%s\n", oid, refs[i]->name);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ int lg2_rev_list(git_repository *repo, int argc, char **argv)
|
||||
git_revwalk *walk;
|
||||
git_oid oid;
|
||||
git_sort_t sort;
|
||||
char buf[GIT_OID_HEXSZ+1];
|
||||
char buf[GIT_OID_SHA1_HEXSIZE+1];
|
||||
|
||||
check_lg2(revwalk_parse_options(&sort, &args), "parsing options", NULL);
|
||||
|
||||
@ -36,7 +36,7 @@ int lg2_rev_list(git_repository *repo, int argc, char **argv)
|
||||
|
||||
while (!git_revwalk_next(&oid, walk)) {
|
||||
git_oid_fmt(buf, &oid);
|
||||
buf[GIT_OID_HEXSZ] = '\0';
|
||||
buf[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
@ -140,8 +140,14 @@ static int revwalk_parse_revs(git_repository *repo, git_revwalk *walk, struct ar
|
||||
if (push_spec(repo, walk, curr, hide) == 0)
|
||||
continue;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if ((error = git_oid_fromstr(&oid, curr, GIT_OID_SHA1)))
|
||||
return error;
|
||||
#else
|
||||
if ((error = git_oid_fromstr(&oid, curr)))
|
||||
return error;
|
||||
#endif
|
||||
|
||||
if ((error = push_commit(walk, &oid, hide)))
|
||||
return error;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static void parse_opts(struct parse_state *ps, int argc, char *argv[])
|
||||
static int parse_revision(git_repository *repo, struct parse_state *ps)
|
||||
{
|
||||
git_revspec rs;
|
||||
char str[GIT_OID_HEXSZ + 1];
|
||||
char str[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
check_lg2(git_revparse(&rs, repo, ps->spec), "Could not parse", ps->spec);
|
||||
|
||||
|
@ -20,8 +20,8 @@ int lg2_show_index(git_repository *repo, int argc, char **argv)
|
||||
size_t i, ecount;
|
||||
char *dir = ".";
|
||||
size_t dirlen;
|
||||
char out[GIT_OID_HEXSZ+1];
|
||||
out[GIT_OID_HEXSZ] = '\0';
|
||||
char out[GIT_OID_SHA1_HEXSIZE+1];
|
||||
out[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
|
||||
if (argc > 2)
|
||||
fatal("usage: showindex [<repo-dir>]", NULL);
|
||||
|
@ -37,7 +37,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
git_commit_graph_entry e;
|
||||
git_str commit_graph_buf = GIT_STR_INIT;
|
||||
unsigned char hash[GIT_HASH_SHA1_SIZE];
|
||||
git_oid oid = {{0}};
|
||||
git_oid oid = GIT_OID_NONE;
|
||||
bool append_hash = false;
|
||||
|
||||
if (size < 4)
|
||||
@ -62,7 +62,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
memcpy(commit_graph_buf.ptr, data, size);
|
||||
memcpy(commit_graph_buf.ptr + size, hash, GIT_HASH_SHA1_SIZE);
|
||||
|
||||
memcpy(oid.id, hash, GIT_OID_RAWSZ);
|
||||
memcpy(oid.id, hash, GIT_OID_SHA1_SIZE);
|
||||
} else {
|
||||
git_str_attach_notowned(&commit_graph_buf, (char *)data, size);
|
||||
}
|
||||
@ -75,7 +75,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
goto cleanup;
|
||||
|
||||
/* Search for any oid, just to exercise that codepath. */
|
||||
if (git_commit_graph_entry_find(&e, &file, &oid, GIT_OID_HEXSZ) < 0)
|
||||
if (git_commit_graph_entry_find(&e, &file, &oid, GIT_OID_SHA1_HEXSIZE) < 0)
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
|
@ -36,7 +36,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
git_midx_entry e;
|
||||
git_str midx_buf = GIT_STR_INIT;
|
||||
unsigned char hash[GIT_HASH_SHA1_SIZE];
|
||||
git_oid oid = {{0}};
|
||||
git_oid oid = GIT_OID_NONE;
|
||||
bool append_hash = false;
|
||||
|
||||
if (size < 4)
|
||||
@ -61,7 +61,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
memcpy(midx_buf.ptr, data, size);
|
||||
memcpy(midx_buf.ptr + size, hash, GIT_HASH_SHA1_SIZE);
|
||||
|
||||
memcpy(oid.id, hash, GIT_OID_RAWSZ);
|
||||
memcpy(oid.id, hash, GIT_OID_SHA1_SIZE);
|
||||
} else {
|
||||
git_str_attach_notowned(&midx_buf, (char *)data, size);
|
||||
}
|
||||
@ -70,7 +70,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
goto cleanup;
|
||||
|
||||
/* Search for any oid, just to exercise that codepath. */
|
||||
if (git_midx_entry_find(&e, &idx, &oid, GIT_OID_HEXSZ) < 0)
|
||||
if (git_midx_entry_find(&e, &idx, &oid, GIT_OID_SHA1_HEXSIZE) < 0)
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
|
@ -39,7 +39,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
* to do.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(types); i++) {
|
||||
if (git_object__from_raw(&object, (const char *) data, size, types[i]) < 0)
|
||||
if (git_object__from_raw(&object, (const char *) data, size, types[i], GIT_OID_SHA1) < 0)
|
||||
continue;
|
||||
git_object_free(object);
|
||||
object = NULL;
|
||||
|
@ -36,10 +36,19 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||
fprintf(stderr, "Failed to limit maximum pack object count\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (git_odb_new(&odb, NULL) < 0) {
|
||||
fprintf(stderr, "Failed to create the odb\n");
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
if (git_odb_new(&odb) < 0) {
|
||||
fprintf(stderr, "Failed to create the odb\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (git_mempack_new(&mempack) < 0) {
|
||||
fprintf(stderr, "Failed to create the mempack\n");
|
||||
abort();
|
||||
@ -58,6 +67,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
git_str path = GIT_STR_INIT;
|
||||
git_oid oid;
|
||||
bool append_hash = false;
|
||||
int error;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
@ -73,7 +83,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (git_indexer_new(&indexer, ".", 0, odb, NULL) < 0) {
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
error = git_indexer_new(&indexer, ".", GIT_OID_SHA1, NULL);
|
||||
#else
|
||||
error = git_indexer_new(&indexer, ".", 0, odb, NULL);
|
||||
#endif
|
||||
|
||||
if (error < 0) {
|
||||
fprintf(stderr, "Failed to create the indexer: %s\n",
|
||||
git_error_last()->message);
|
||||
abort();
|
||||
@ -90,11 +106,19 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
if (git_indexer_append(indexer, data, size, &stats) < 0)
|
||||
goto cleanup;
|
||||
if (append_hash) {
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB, GIT_OID_SHA1) < 0) {
|
||||
fprintf(stderr, "Failed to compute the SHA1 hash\n");
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB) < 0) {
|
||||
fprintf(stderr, "Failed to compute the SHA1 hash\n");
|
||||
abort();
|
||||
}
|
||||
if (git_indexer_append(indexer, &oid.id, GIT_OID_RAWSZ, &stats) < 0) {
|
||||
#endif
|
||||
|
||||
if (git_indexer_append(indexer, &oid.id, GIT_OID_SHA1_SIZE, &stats) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "git2/diff.h"
|
||||
#include "git2/email.h"
|
||||
#include "git2/errors.h"
|
||||
#include "git2/experimental.h"
|
||||
#include "git2/filter.h"
|
||||
#include "git2/global.h"
|
||||
#include "git2/graph.h"
|
||||
|
@ -105,11 +105,6 @@ GIT_BEGIN_DECL
|
||||
*/
|
||||
#define GIT_PATH_MAX 4096
|
||||
|
||||
/**
|
||||
* The string representation of the null object ID.
|
||||
*/
|
||||
#define GIT_OID_HEX_ZERO "0000000000000000000000000000000000000000"
|
||||
|
||||
/**
|
||||
* Return the version of the libgit2 library
|
||||
* being currently used.
|
||||
@ -227,7 +222,9 @@ typedef enum {
|
||||
GIT_OPT_GET_EXTENSIONS,
|
||||
GIT_OPT_SET_EXTENSIONS,
|
||||
GIT_OPT_GET_OWNER_VALIDATION,
|
||||
GIT_OPT_SET_OWNER_VALIDATION
|
||||
GIT_OPT_SET_OWNER_VALIDATION,
|
||||
GIT_OPT_GET_HOMEDIR,
|
||||
GIT_OPT_SET_HOMEDIR
|
||||
} git_libgit2_opt_t;
|
||||
|
||||
/**
|
||||
@ -473,6 +470,16 @@ typedef enum {
|
||||
* > Set that repository directories should be owned by the current
|
||||
* > user. The default is to validate ownership.
|
||||
*
|
||||
* opts(GIT_OPT_GET_HOMEDIR, git_buf *out)
|
||||
* > Gets the current user's home directory, as it will be used
|
||||
* > for file lookups. The path is written to the `out` buffer.
|
||||
*
|
||||
* opts(GIT_OPT_SET_HOMEDIR, const char *path)
|
||||
* > Sets the directory used as the current user's home directory,
|
||||
* > for file lookups.
|
||||
* >
|
||||
* > - `path` directory of home directory.
|
||||
*
|
||||
* @param option Option key
|
||||
* @param ... value to set the option
|
||||
* @return 0 on success, <0 on failure
|
||||
|
@ -777,6 +777,12 @@ typedef git_trace_cb git_trace_callback;
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
# define GIT_OID_RAWSZ GIT_OID_SHA1_SIZE
|
||||
# define GIT_OID_HEXSZ GIT_OID_SHA1_HEXSIZE
|
||||
# define GIT_OID_HEX_ZERO GIT_OID_SHA1_HEXZERO
|
||||
#endif
|
||||
|
||||
GIT_EXTERN(int) git_oid_iszero(const git_oid *id);
|
||||
|
||||
/**@}*/
|
||||
|
@ -274,7 +274,7 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* Represents the known length of the `id` field, when
|
||||
* converted to a hex string. It is generally `GIT_OID_HEXSZ`, unless this
|
||||
* converted to a hex string. It is generally `GIT_OID_SHA1_HEXSIZE`, unless this
|
||||
* delta was created from reading a patch file, in which case it may be
|
||||
* abbreviated to something reasonable, like 7 characters.
|
||||
*/
|
||||
|
20
include/git2/experimental.h
Normal file
20
include/git2/experimental.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_experimental_h__
|
||||
#define INCLUDE_experimental_h__
|
||||
|
||||
/*
|
||||
* This file exists to support users who build libgit2 with a bespoke
|
||||
* build system and do not use our cmake configuration. Normally, cmake
|
||||
* will create `experimental.h` from the `experimental.h.in` file and
|
||||
* will include the generated file instead of this one. For non-cmake
|
||||
* users, we bundle this `experimental.h` file which will be used
|
||||
* instead.
|
||||
*/
|
||||
|
||||
#endif
|
@ -62,6 +62,19 @@ typedef int GIT_CALLBACK(git_indexer_progress_cb)(const git_indexer_progress *st
|
||||
typedef struct git_indexer_options {
|
||||
unsigned int version;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/** permissions to use creating packfile or 0 for defaults */
|
||||
unsigned int mode;
|
||||
|
||||
/**
|
||||
* object database from which to read base objects when
|
||||
* fixing thin packs. This can be NULL if there are no thin
|
||||
* packs; if a thin pack is encountered, an error will be
|
||||
* returned if there are bases missing.
|
||||
*/
|
||||
git_odb *odb;
|
||||
#endif
|
||||
|
||||
/** progress_cb function to call with progress information */
|
||||
git_indexer_progress_cb progress_cb;
|
||||
|
||||
@ -87,6 +100,21 @@ GIT_EXTERN(int) git_indexer_options_init(
|
||||
git_indexer_options *opts,
|
||||
unsigned int version);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/**
|
||||
* Create a new indexer instance
|
||||
*
|
||||
* @param out where to store the indexer instance
|
||||
* @param path to the directory where the packfile should be stored
|
||||
* @param oid_type the oid type to use for objects
|
||||
* @return 0 or an error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_indexer_new(
|
||||
git_indexer **out,
|
||||
const char *path,
|
||||
git_oid_t oid_type,
|
||||
git_indexer_options *opts);
|
||||
#else
|
||||
/**
|
||||
* Create a new indexer instance
|
||||
*
|
||||
@ -106,6 +134,7 @@ GIT_EXTERN(int) git_indexer_new(
|
||||
unsigned int mode,
|
||||
git_odb *odb,
|
||||
git_indexer_options *opts);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Add data to the indexer
|
||||
|
@ -225,6 +225,7 @@ GIT_EXTERN(int) git_object_peel(
|
||||
*/
|
||||
GIT_EXTERN(int) git_object_dup(git_object **dest, git_object *source);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/**
|
||||
* Analyzes a buffer of raw object content and determines its validity.
|
||||
* Tree, commit, and tag objects will be parsed and ensured that they
|
||||
@ -238,14 +239,39 @@ GIT_EXTERN(int) git_object_dup(git_object **dest, git_object *source);
|
||||
* @param valid Output pointer to set with validity of the object content
|
||||
* @param buf The contents to validate
|
||||
* @param len The length of the buffer
|
||||
* @param type The type of the object in the buffer
|
||||
* @param object_type The type of the object in the buffer
|
||||
* @param oid_type The object ID type for the OIDs in the given buffer
|
||||
* @return 0 on success or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_object_rawcontent_is_valid(
|
||||
int *valid,
|
||||
const char *buf,
|
||||
size_t len,
|
||||
git_object_t type);
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
#else
|
||||
/**
|
||||
* Analyzes a buffer of raw object content and determines its validity.
|
||||
* Tree, commit, and tag objects will be parsed and ensured that they
|
||||
* are valid, parseable content. (Blobs are always valid by definition.)
|
||||
* An error message will be set with an informative message if the object
|
||||
* is not valid.
|
||||
*
|
||||
* @warning This function is experimental and its signature may change in
|
||||
* the future.
|
||||
*
|
||||
* @param valid Output pointer to set with validity of the object content
|
||||
* @param buf The contents to validate
|
||||
* @param len The length of the buffer
|
||||
* @param object_type The type of the object in the buffer
|
||||
* @return 0 on success or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_object_rawcontent_is_valid(
|
||||
int *valid,
|
||||
const char *buf,
|
||||
size_t len,
|
||||
git_object_t object_type);
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
@ -38,6 +38,25 @@ typedef enum {
|
||||
*/
|
||||
typedef int GIT_CALLBACK(git_odb_foreach_cb)(const git_oid *id, void *payload);
|
||||
|
||||
/** Options for configuring a loose object backend. */
|
||||
typedef struct {
|
||||
unsigned int version; /**< version for the struct */
|
||||
|
||||
/**
|
||||
* Type of object IDs to use for this object database, or
|
||||
* 0 for default (currently SHA1).
|
||||
*/
|
||||
git_oid_t oid_type;
|
||||
} git_odb_options;
|
||||
|
||||
/* The current version of the diff options structure */
|
||||
#define GIT_ODB_OPTIONS_VERSION 1
|
||||
|
||||
/* Stack initializer for odb options. Alternatively use
|
||||
* `git_odb_options_init` programmatic initialization.
|
||||
*/
|
||||
#define GIT_ODB_OPTIONS_INIT { GIT_ODB_OPTIONS_VERSION }
|
||||
|
||||
/**
|
||||
* Create a new object database with no backends.
|
||||
*
|
||||
@ -46,9 +65,14 @@ typedef int GIT_CALLBACK(git_odb_foreach_cb)(const git_oid *id, void *payload);
|
||||
*
|
||||
* @param out location to store the database pointer, if opened.
|
||||
* Set to NULL if the open failed.
|
||||
* @param opts the options for this object database or NULL for defaults
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_new(git_odb **out, const git_odb_options *opts);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_new(git_odb **out);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a new object database and automatically add
|
||||
@ -64,9 +88,17 @@ GIT_EXTERN(int) git_odb_new(git_odb **out);
|
||||
* @param out location to store the database pointer, if opened.
|
||||
* Set to NULL if the open failed.
|
||||
* @param objects_dir path of the backends' "objects" directory.
|
||||
* @param opts the options for this object database or NULL for defaults
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_open(
|
||||
git_odb **out,
|
||||
const char *objects_dir,
|
||||
const git_odb_options *opts);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Add an on-disk alternate to an existing Object DB.
|
||||
@ -117,7 +149,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i
|
||||
* This method queries all available ODB backends
|
||||
* trying to match the 'len' first hexadecimal
|
||||
* characters of the 'short_id'.
|
||||
* The remaining (GIT_OID_HEXSZ-len)*4 bits of
|
||||
* The remaining (GIT_OID_SHA1_HEXSIZE-len)*4 bits of
|
||||
* 'short_id' must be 0s.
|
||||
* 'len' must be at least GIT_OID_MINPREFIXLEN,
|
||||
* and the prefix must be long enough to identify
|
||||
@ -218,7 +250,7 @@ typedef struct git_odb_expand_id {
|
||||
*
|
||||
* The given array will be updated in place: for each abbreviated ID that is
|
||||
* unique in the database, and of the given type (if specified),
|
||||
* the full object ID, object ID length (`GIT_OID_HEXSZ`) and type will be
|
||||
* the full object ID, object ID length (`GIT_OID_SHA1_HEXSIZE`) and type will be
|
||||
* written back to the array. For IDs that are not found (or are ambiguous),
|
||||
* the array entry will be zeroed.
|
||||
*
|
||||
@ -435,18 +467,28 @@ GIT_EXTERN(int) git_odb_write_multi_pack_index(
|
||||
git_odb *db);
|
||||
|
||||
/**
|
||||
* Determine the object-ID (sha1 hash) of a data buffer
|
||||
* Determine the object-ID (sha1 or sha256 hash) of a data buffer
|
||||
*
|
||||
* The resulting SHA-1 OID will be the identifier for the data
|
||||
* buffer as if the data buffer it were to written to the ODB.
|
||||
* The resulting OID will be the identifier for the data buffer as if
|
||||
* the data buffer it were to written to the ODB.
|
||||
*
|
||||
* @param out the resulting object-ID.
|
||||
* @param data data to hash
|
||||
* @param len size of the data
|
||||
* @param type of the data to hash
|
||||
* @param object_type of the data to hash
|
||||
* @param oid_type the oid type to hash to
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_hash(
|
||||
git_oid *out,
|
||||
const void *data,
|
||||
size_t len,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_hash(git_oid *out, const void *data, size_t len, git_object_t type);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read a file from disk and fill a git_oid with the object id
|
||||
@ -458,10 +500,19 @@ GIT_EXTERN(int) git_odb_hash(git_oid *out, const void *data, size_t len, git_obj
|
||||
*
|
||||
* @param out oid structure the result is written into.
|
||||
* @param path file to read and determine object id for
|
||||
* @param type the type of the object that will be hashed
|
||||
* @param object_type of the data to hash
|
||||
* @param oid_type the oid type to hash to
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_hashfile(
|
||||
git_oid *out,
|
||||
const char *path,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_hashfile(git_oid *out, const char *path, git_object_t type);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a copy of an odb_object
|
||||
|
@ -24,6 +24,26 @@ GIT_BEGIN_DECL
|
||||
* Constructors for in-box ODB backends.
|
||||
*/
|
||||
|
||||
/** Options for configuring a packfile object backend. */
|
||||
typedef struct {
|
||||
unsigned int version; /**< version for the struct */
|
||||
|
||||
/**
|
||||
* Type of object IDs to use for this object database, or
|
||||
* 0 for default (currently SHA1).
|
||||
*/
|
||||
git_oid_t oid_type;
|
||||
} git_odb_backend_pack_options;
|
||||
|
||||
/* The current version of the diff options structure */
|
||||
#define GIT_ODB_BACKEND_PACK_OPTIONS_VERSION 1
|
||||
|
||||
/* Stack initializer for odb pack backend options. Alternatively use
|
||||
* `git_odb_backend_pack_options_init` programmatic initialization.
|
||||
*/
|
||||
#define GIT_ODB_BACKEND_PACK_OPTIONS_INIT \
|
||||
{ GIT_ODB_BACKEND_PACK_OPTIONS_VERSION }
|
||||
|
||||
/**
|
||||
* Create a backend for the packfiles.
|
||||
*
|
||||
@ -32,27 +52,16 @@ GIT_BEGIN_DECL
|
||||
*
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
|
||||
|
||||
/**
|
||||
* Create a backend for loose objects
|
||||
*
|
||||
* @param out location to store the odb backend pointer
|
||||
* @param objects_dir the Git repository's objects directory
|
||||
* @param compression_level zlib compression level to use
|
||||
* @param do_fsync whether to do an fsync() after writing
|
||||
* @param dir_mode permissions to use creating a directory or 0 for defaults
|
||||
* @param file_mode permissions to use creating a file or 0 for defaults
|
||||
*
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_backend_loose(
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_backend_pack(
|
||||
git_odb_backend **out,
|
||||
const char *objects_dir,
|
||||
int compression_level,
|
||||
int do_fsync,
|
||||
unsigned int dir_mode,
|
||||
unsigned int file_mode);
|
||||
const git_odb_backend_pack_options *opts);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_backend_pack(
|
||||
git_odb_backend **out,
|
||||
const char *objects_dir);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a backend out of a single packfile
|
||||
@ -65,7 +74,82 @@ GIT_EXTERN(int) git_odb_backend_loose(
|
||||
*
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_backend_one_pack(
|
||||
git_odb_backend **out,
|
||||
const char *index_file,
|
||||
const git_odb_backend_pack_options *opts);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_backend_one_pack(
|
||||
git_odb_backend **out,
|
||||
const char *index_file);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GIT_ODB_BACKEND_LOOSE_FSYNC = (1 << 0)
|
||||
} git_odb_backend_loose_flag_t;
|
||||
|
||||
/** Options for configuring a loose object backend. */
|
||||
typedef struct {
|
||||
unsigned int version; /**< version for the struct */
|
||||
|
||||
/** A combination of the `git_odb_backend_loose_flag_t` types. */
|
||||
uint32_t flags;
|
||||
|
||||
/**
|
||||
* zlib compression level to use (0-9), where 1 is the fastest
|
||||
* at the expense of larger files, and 9 produces the best
|
||||
* compression at the expense of speed. 0 indicates that no
|
||||
* compression should be performed. -1 is the default (currently
|
||||
* optimizing for speed).
|
||||
*/
|
||||
int compression_level;
|
||||
|
||||
/** Permissions to use creating a directory or 0 for defaults */
|
||||
unsigned int dir_mode;
|
||||
|
||||
/** Permissions to use creating a file or 0 for defaults */
|
||||
unsigned int file_mode;
|
||||
|
||||
/**
|
||||
* Type of object IDs to use for this object database, or
|
||||
* 0 for default (currently SHA1).
|
||||
*/
|
||||
git_oid_t oid_type;
|
||||
} git_odb_backend_loose_options;
|
||||
|
||||
/* The current version of the diff options structure */
|
||||
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION 1
|
||||
|
||||
/* Stack initializer for odb loose backend options. Alternatively use
|
||||
* `git_odb_backend_loose_options_init` programmatic initialization.
|
||||
*/
|
||||
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT \
|
||||
{ GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION, 0, -1 }
|
||||
|
||||
/**
|
||||
* Create a backend for loose objects
|
||||
*
|
||||
* @param out location to store the odb backend pointer
|
||||
* @param objects_dir the Git repository's objects directory
|
||||
* @param opts options for the loose object backend or NULL
|
||||
*
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_odb_backend_loose(
|
||||
git_odb_backend **out,
|
||||
const char *objects_dir,
|
||||
git_odb_backend_loose_options *opts);
|
||||
#else
|
||||
GIT_EXTERN(int) git_odb_backend_loose(
|
||||
git_odb_backend **out,
|
||||
const char *objects_dir,
|
||||
int compression_level,
|
||||
int do_fsync,
|
||||
unsigned int dir_mode,
|
||||
unsigned int file_mode);
|
||||
#endif
|
||||
|
||||
/** Streaming mode */
|
||||
typedef enum {
|
||||
@ -87,6 +171,10 @@ struct git_odb_stream {
|
||||
unsigned int mode;
|
||||
void *hash_ctx;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_t oid_type;
|
||||
#endif
|
||||
|
||||
git_object_size_t declared_size;
|
||||
git_object_size_t received_bytes;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "experimental.h"
|
||||
|
||||
/**
|
||||
* @file git2/oid.h
|
||||
@ -19,11 +20,76 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/** Size (in bytes) of a raw/binary oid */
|
||||
#define GIT_OID_RAWSZ 20
|
||||
/** The type of object id. */
|
||||
typedef enum {
|
||||
|
||||
/** Size (in bytes) of a hex formatted oid */
|
||||
#define GIT_OID_HEXSZ (GIT_OID_RAWSZ * 2)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_OID_SHA1 = 1, /**< SHA1 */
|
||||
GIT_OID_SHA256 = 2 /**< SHA256 */
|
||||
#else
|
||||
GIT_OID_SHA1 = 1 /**< SHA1 */
|
||||
#endif
|
||||
|
||||
} git_oid_t;
|
||||
|
||||
/*
|
||||
* SHA1 is currently the only supported object ID type.
|
||||
*/
|
||||
|
||||
/** SHA1 is currently libgit2's default oid type. */
|
||||
#define GIT_OID_DEFAULT GIT_OID_SHA1
|
||||
|
||||
/** Size (in bytes) of a raw/binary sha1 oid */
|
||||
#define GIT_OID_SHA1_SIZE 20
|
||||
/** Size (in bytes) of a hex formatted sha1 oid */
|
||||
#define GIT_OID_SHA1_HEXSIZE (GIT_OID_SHA1_SIZE * 2)
|
||||
|
||||
/**
|
||||
* The binary representation of the null sha1 object ID.
|
||||
*/
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
# define GIT_OID_SHA1_ZERO { { 0 } }
|
||||
#else
|
||||
# define GIT_OID_SHA1_ZERO { GIT_OID_SHA1, { 0 } }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The string representation of the null sha1 object ID.
|
||||
*/
|
||||
#define GIT_OID_SHA1_HEXZERO "0000000000000000000000000000000000000000"
|
||||
|
||||
/*
|
||||
* Experimental SHA256 support is a breaking change to the API.
|
||||
* This exists for application compatibility testing.
|
||||
*/
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
|
||||
/** Size (in bytes) of a raw/binary sha256 oid */
|
||||
# define GIT_OID_SHA256_SIZE 32
|
||||
/** Size (in bytes) of a hex formatted sha256 oid */
|
||||
# define GIT_OID_SHA256_HEXSIZE (GIT_OID_SHA256_SIZE * 2)
|
||||
|
||||
/**
|
||||
* The binary representation of the null sha256 object ID.
|
||||
*/
|
||||
# define GIT_OID_SHA256_ZERO { GIT_OID_SHA256, { 0 } }
|
||||
|
||||
/**
|
||||
* The string representation of the null sha256 object ID.
|
||||
*/
|
||||
# define GIT_OID_SHA256_HEXZERO "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
#endif
|
||||
|
||||
/* Maximum possible object ID size in raw / hex string format. */
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
# define GIT_OID_MAX_SIZE GIT_OID_SHA1_SIZE
|
||||
# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA1_HEXSIZE
|
||||
#else
|
||||
# define GIT_OID_MAX_SIZE GIT_OID_SHA256_SIZE
|
||||
# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA256_HEXSIZE
|
||||
#endif
|
||||
|
||||
/** Minimum length (in number of hex characters,
|
||||
* i.e. packets of 4 bits) of an oid prefix */
|
||||
@ -31,29 +97,50 @@ GIT_BEGIN_DECL
|
||||
|
||||
/** Unique identity of any object (commit, tree, blob, tag). */
|
||||
typedef struct git_oid {
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/** type of object id */
|
||||
unsigned char type;
|
||||
#endif
|
||||
|
||||
/** raw binary formatted id */
|
||||
unsigned char id[GIT_OID_RAWSZ];
|
||||
unsigned char id[GIT_OID_MAX_SIZE];
|
||||
} git_oid;
|
||||
|
||||
/**
|
||||
* Parse a hex formatted object id into a git_oid.
|
||||
*
|
||||
* The appropriate number of bytes for the given object ID type will
|
||||
* be read from the string - 40 bytes for SHA1, 64 bytes for SHA256.
|
||||
* The given string need not be NUL terminated.
|
||||
*
|
||||
* @param out oid structure the result is written into.
|
||||
* @param str input hex string; must be pointing at the start of
|
||||
* the hex sequence and have at least the number of bytes
|
||||
* needed for an oid encoded in hex (40 bytes).
|
||||
* needed for an oid encoded in hex (40 bytes for sha1,
|
||||
* 256 bytes for sha256).
|
||||
* @param type the type of object id
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str, git_oid_t type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Parse a hex formatted null-terminated string into a git_oid.
|
||||
* Parse a hex formatted NUL-terminated string into a git_oid.
|
||||
*
|
||||
* @param out oid structure the result is written into.
|
||||
* @param str input hex string; must be null-terminated.
|
||||
* @param type the type of object id
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str, git_oid_t type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Parse N characters of a hex formatted object id into a git_oid.
|
||||
@ -64,9 +151,14 @@ GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
|
||||
* @param out oid structure the result is written into.
|
||||
* @param str input hex string of at least size `length`
|
||||
* @param length length of the input string
|
||||
* @param type the type of object id
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length, git_oid_t type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copy an already raw oid into a git_oid structure.
|
||||
@ -75,16 +167,21 @@ GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
|
||||
* @param raw the raw input bytes to be copied.
|
||||
* @return 0 on success or error code
|
||||
*/
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw, git_oid_t type);
|
||||
#else
|
||||
GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Format a git_oid into a hex string.
|
||||
*
|
||||
* @param out output hex string; must be pointing at the start of
|
||||
* the hex sequence and have at least the number of bytes
|
||||
* needed for an oid encoded in hex (40 bytes). Only the
|
||||
* oid digits are written; a '\\0' terminator must be added
|
||||
* by the caller if it is required.
|
||||
* needed for an oid encoded in hex (40 bytes for SHA1,
|
||||
* 64 bytes for SHA256). Only the 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
|
||||
*/
|
||||
@ -94,7 +191,7 @@ GIT_EXTERN(int) git_oid_fmt(char *out, const git_oid *id);
|
||||
* Format a git_oid into a partial hex string.
|
||||
*
|
||||
* @param out output hex string; you say how many bytes to write.
|
||||
* If the number of bytes is > GIT_OID_HEXSZ, extra bytes
|
||||
* If the number of bytes is > GIT_OID_SHA1_HEXSIZE, extra bytes
|
||||
* 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.
|
||||
@ -110,9 +207,10 @@ GIT_EXTERN(int) git_oid_nfmt(char *out, size_t n, const git_oid *id);
|
||||
*
|
||||
* @param out output hex string; must be pointing at the start of
|
||||
* the hex sequence and have at least the number of bytes
|
||||
* needed for an oid encoded in hex (41 bytes). Only the
|
||||
* oid digits are written; a '\\0' terminator must be added
|
||||
* by the caller if it is required.
|
||||
* needed for an oid encoded in hex (41 bytes for SHA1,
|
||||
* 65 bytes for SHA256). Only the 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
|
||||
*/
|
||||
@ -134,7 +232,9 @@ GIT_EXTERN(char *) git_oid_tostr_s(const git_oid *oid);
|
||||
/**
|
||||
* Format a git_oid into a buffer as a hex format c-string.
|
||||
*
|
||||
* If the buffer is smaller than GIT_OID_HEXSZ+1, then the resulting
|
||||
* If the buffer is smaller than the size of a hex-formatted oid string
|
||||
* plus an additional byte (GIT_OID_SHA_HEXSIZE + 1 for SHA1 or
|
||||
* GIT_OID_SHA256_HEXSIZE + 1 for SHA256), then the resulting
|
||||
* oid c-string will be truncated to n-1 characters (but will still be
|
||||
* NUL-byte terminated).
|
||||
*
|
||||
|
@ -351,6 +351,15 @@ typedef struct {
|
||||
* pointing to this URL.
|
||||
*/
|
||||
const char *origin_url;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/**
|
||||
*
|
||||
* Type of object IDs to use for this repository, or 0 for
|
||||
* default (currently SHA1).
|
||||
*/
|
||||
git_oid_t oid_type;
|
||||
#endif
|
||||
} git_repository_init_options;
|
||||
|
||||
#define GIT_REPOSITORY_INIT_OPTIONS_VERSION 1
|
||||
@ -456,7 +465,9 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo);
|
||||
* Check if a repository is empty
|
||||
*
|
||||
* An empty repository has just been initialized and contains no references
|
||||
* apart from HEAD, which must be pointing to the unborn master branch.
|
||||
* apart from HEAD, which must be pointing to the unborn master branch,
|
||||
* or the branch specified for the repository in the `init.defaultBranch`
|
||||
* configuration variable.
|
||||
*
|
||||
* @param repo Repo to test
|
||||
* @return 1 if the repository is empty, 0 if it isn't, error code
|
||||
@ -949,6 +960,14 @@ GIT_EXTERN(int) git_repository_ident(const char **name, const char **email, cons
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_set_ident(git_repository *repo, const char *name, const char *email);
|
||||
|
||||
/**
|
||||
* Gets the object type used by this repository.
|
||||
*
|
||||
* @param repo the repository
|
||||
* @return the object id type
|
||||
*/
|
||||
GIT_EXTERN(git_oid_t) git_repository_oid_type(git_repository *repo);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -44,7 +44,12 @@ typedef enum {
|
||||
* All ignored files are also stashed and then cleaned up from
|
||||
* the working directory
|
||||
*/
|
||||
GIT_STASH_INCLUDE_IGNORED = (1 << 2)
|
||||
GIT_STASH_INCLUDE_IGNORED = (1 << 2),
|
||||
|
||||
/**
|
||||
* All changes in the index and working directory are left intact
|
||||
*/
|
||||
GIT_STASH_KEEP_ALL = (1 << 3)
|
||||
} git_stash_flags;
|
||||
|
||||
/**
|
||||
@ -52,15 +57,10 @@ typedef enum {
|
||||
*
|
||||
* @param out Object id of the commit containing the stashed state.
|
||||
* This commit is also the target of the direct reference refs/stash.
|
||||
*
|
||||
* @param repo The owning repository.
|
||||
*
|
||||
* @param stasher The identity of the person performing the stashing.
|
||||
*
|
||||
* @param message Optional description along with the stashed state.
|
||||
*
|
||||
* @param flags Flags to control the stashing process. (see GIT_STASH_* above)
|
||||
*
|
||||
* @return 0 on success, GIT_ENOTFOUND where there's nothing to stash,
|
||||
* or error code.
|
||||
*/
|
||||
@ -71,6 +71,60 @@ GIT_EXTERN(int) git_stash_save(
|
||||
const char *message,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Stash save options structure
|
||||
*
|
||||
* Initialize with `GIT_STASH_SAVE_OPTIONS_INIT`. Alternatively, you can
|
||||
* use `git_stash_save_options_init`.
|
||||
*
|
||||
*/
|
||||
typedef struct git_stash_save_options {
|
||||
unsigned int version;
|
||||
|
||||
/** Flags to control the stashing process. (see GIT_STASH_* above) */
|
||||
uint32_t flags;
|
||||
|
||||
/** The identity of the person performing the stashing. */
|
||||
const git_signature *stasher;
|
||||
|
||||
/** Optional description along with the stashed state. */
|
||||
const char *message;
|
||||
|
||||
/** Optional paths that control which files are stashed. */
|
||||
git_strarray paths;
|
||||
} git_stash_save_options;
|
||||
|
||||
#define GIT_STASH_SAVE_OPTIONS_VERSION 1
|
||||
#define GIT_STASH_SAVE_OPTIONS_INIT { GIT_STASH_SAVE_OPTIONS_VERSION }
|
||||
|
||||
/**
|
||||
* Initialize git_stash_save_options structure
|
||||
*
|
||||
* Initializes a `git_stash_save_options` with default values. Equivalent to
|
||||
* creating an instance with `GIT_STASH_SAVE_OPTIONS_INIT`.
|
||||
*
|
||||
* @param opts The `git_stash_save_options` struct to initialize.
|
||||
* @param version The struct version; pass `GIT_STASH_SAVE_OPTIONS_VERSION`.
|
||||
* @return Zero on success; -1 on failure.
|
||||
*/
|
||||
GIT_EXTERN(int) git_stash_save_options_init(
|
||||
git_stash_save_options *opts, unsigned int version);
|
||||
|
||||
/**
|
||||
* Save the local modifications to a new stash, with options.
|
||||
*
|
||||
* @param out Object id of the commit containing the stashed state.
|
||||
* This commit is also the target of the direct reference refs/stash.
|
||||
* @param repo The owning repository.
|
||||
* @param opts The stash options.
|
||||
* @return 0 on success, GIT_ENOTFOUND where there's nothing to stash,
|
||||
* or error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_stash_save_with_opts(
|
||||
git_oid *out,
|
||||
git_repository *repo,
|
||||
const git_stash_save_options *opts);
|
||||
|
||||
/** Stash application flags. */
|
||||
typedef enum {
|
||||
GIT_STASH_APPLY_DEFAULT = 0,
|
||||
|
@ -36,19 +36,6 @@ typedef struct git_strarray {
|
||||
*/
|
||||
GIT_EXTERN(void) git_strarray_dispose(git_strarray *array);
|
||||
|
||||
/**
|
||||
* Copy a string array object from source to target.
|
||||
*
|
||||
* Note: target is overwritten and hence should be empty, otherwise its
|
||||
* contents are leaked. Call git_strarray_free() if necessary.
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
|
@ -36,7 +36,7 @@ struct git_odb_backend {
|
||||
void **, size_t *, git_object_t *, git_odb_backend *, const git_oid *);
|
||||
|
||||
/* To find a unique object given a prefix of its oid. The oid given
|
||||
* must be so that the remaining (GIT_OID_HEXSZ - len)*4 bits are 0s.
|
||||
* must be so that the remaining (GIT_OID_SHA1_HEXSIZE - len)*4 bits are 0s.
|
||||
*/
|
||||
int GIT_CALLBACK(read_prefix)(
|
||||
git_oid *, void **, size_t *, git_object_t *,
|
||||
|
@ -57,6 +57,18 @@ struct git_transport {
|
||||
unsigned int *capabilities,
|
||||
git_transport *transport);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
/**
|
||||
* Gets the object type for the remote repository.
|
||||
*
|
||||
* This function may be called after a successful call to
|
||||
* `connect()`.
|
||||
*/
|
||||
int GIT_CALLBACK(oid_type)(
|
||||
git_oid_t *object_type,
|
||||
git_transport *transport);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the list of available references in the remote repository.
|
||||
*
|
||||
|
@ -11,16 +11,16 @@
|
||||
* The version string for libgit2. This string follows semantic
|
||||
* versioning (v2) guidelines.
|
||||
*/
|
||||
#define LIBGIT2_VERSION "1.5.1"
|
||||
#define LIBGIT2_VERSION "1.6.4"
|
||||
|
||||
/** The major version number for this version of libgit2. */
|
||||
#define LIBGIT2_VER_MAJOR 1
|
||||
|
||||
/** The minor version number for this version of libgit2. */
|
||||
#define LIBGIT2_VER_MINOR 5
|
||||
#define LIBGIT2_VER_MINOR 6
|
||||
|
||||
/** The revision ("teeny") version number for this version of libgit2. */
|
||||
#define LIBGIT2_VER_REVISION 1
|
||||
#define LIBGIT2_VER_REVISION 4
|
||||
|
||||
/** The Windows DLL patch number for this version of libgit2. */
|
||||
#define LIBGIT2_VER_PATCH 0
|
||||
@ -34,6 +34,6 @@
|
||||
#define LIBGIT2_VER_PRERELEASE NULL
|
||||
|
||||
/** The library ABI soversion for this version of libgit2. */
|
||||
#define LIBGIT2_SOVERSION "1.5"
|
||||
#define LIBGIT2_SOVERSION "1.6"
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libgit2",
|
||||
"version": "1.5.1",
|
||||
"version": "1.6.4",
|
||||
"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 ."
|
||||
|
@ -170,12 +170,6 @@ if(ICONV_FOUND)
|
||||
endif()
|
||||
add_feature_info(iconv GIT_USE_ICONV "iconv encoding conversion support")
|
||||
|
||||
#
|
||||
# Configure support
|
||||
#
|
||||
|
||||
configure_file(features.h.in git2/sys/features.h)
|
||||
|
||||
#
|
||||
# Include child projects
|
||||
#
|
||||
|
@ -1,8 +1,10 @@
|
||||
set(CLI_INCLUDES
|
||||
"${libgit2_BINARY_DIR}/src"
|
||||
"${libgit2_BINARY_DIR}/src/util"
|
||||
"${libgit2_BINARY_DIR}/include"
|
||||
"${libgit2_SOURCE_DIR}/src/util"
|
||||
"${libgit2_SOURCE_DIR}/src/cli"
|
||||
"${libgit2_SOURCE_DIR}/include")
|
||||
"${libgit2_SOURCE_DIR}/include"
|
||||
"${LIBGIT2_DEPENDENCY_INCLUDES}")
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
file(GLOB CLI_SRC_OS win32/*.c)
|
||||
@ -39,6 +41,7 @@ target_link_libraries(git2_cli ${CLI_LIBGIT2_LIBRARY} ${LIBGIT2_SYSTEM_LIBS})
|
||||
|
||||
set_target_properties(git2_cli PROPERTIES C_STANDARD 90)
|
||||
set_target_properties(git2_cli PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
|
||||
set_target_properties(git2_cli PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
|
||||
|
||||
ide_split_sources(git2_cli)
|
||||
|
||||
|
@ -49,23 +49,39 @@ static void print_help(void)
|
||||
cli_opt_help_fprint(stdout, opts);
|
||||
}
|
||||
|
||||
static int hash_buf(git_odb *odb, git_str *buf, git_object_t type)
|
||||
static int hash_buf(
|
||||
git_odb *odb,
|
||||
git_str *buf,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
git_oid oid;
|
||||
|
||||
if (!literally) {
|
||||
int valid = 0;
|
||||
|
||||
if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, type) < 0 || !valid)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, object_type, oid_type) < 0 || !valid)
|
||||
return cli_error_git();
|
||||
#else
|
||||
GIT_UNUSED(oid_type);
|
||||
|
||||
if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, object_type) < 0 || !valid)
|
||||
return cli_error_git();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (write_object) {
|
||||
if (git_odb_write(&oid, odb, buf->ptr, buf->size, type) < 0)
|
||||
if (git_odb_write(&oid, odb, buf->ptr, buf->size, object_type) < 0)
|
||||
return cli_error_git();
|
||||
} else {
|
||||
if (git_odb_hash(&oid, buf->ptr, buf->size, type) < 0)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (git_odb_hash(&oid, buf->ptr, buf->size, object_type, GIT_OID_SHA1) < 0)
|
||||
return cli_error_git();
|
||||
#else
|
||||
if (git_odb_hash(&oid, buf->ptr, buf->size, object_type) < 0)
|
||||
return cli_error_git();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (printf("%s\n", git_oid_tostr_s(&oid)) < 0)
|
||||
@ -78,9 +94,10 @@ int cmd_hash_object(int argc, char **argv)
|
||||
{
|
||||
git_repository *repo = NULL;
|
||||
git_odb *odb = NULL;
|
||||
git_oid_t oid_type;
|
||||
git_str buf = GIT_STR_INIT;
|
||||
cli_opt invalid_opt;
|
||||
git_object_t type = GIT_OBJECT_BLOB;
|
||||
git_object_t object_type = GIT_OBJECT_BLOB;
|
||||
char **filename;
|
||||
int ret = 0;
|
||||
|
||||
@ -92,7 +109,7 @@ int cmd_hash_object(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type_name && (type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
|
||||
if (type_name && (object_type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
|
||||
return cli_error_usage("invalid object type '%s'", type_name);
|
||||
|
||||
if (write_object &&
|
||||
@ -102,6 +119,8 @@ int cmd_hash_object(int argc, char **argv)
|
||||
goto done;
|
||||
}
|
||||
|
||||
oid_type = git_repository_oid_type(repo);
|
||||
|
||||
/*
|
||||
* TODO: we're reading blobs, we shouldn't pull them all into main
|
||||
* memory, we should just stream them into the odb instead.
|
||||
@ -113,7 +132,7 @@ int cmd_hash_object(int argc, char **argv)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = hash_buf(odb, &buf, type)) != 0)
|
||||
if ((ret = hash_buf(odb, &buf, object_type, oid_type)) != 0)
|
||||
goto done;
|
||||
} else {
|
||||
for (filename = filenames; *filename; filename++) {
|
||||
@ -122,7 +141,7 @@ int cmd_hash_object(int argc, char **argv)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = hash_buf(odb, &buf, type)) != 0)
|
||||
if ((ret = hash_buf(odb, &buf, object_type, oid_type)) != 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "opt.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <Windows.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
# include <sys/ioctl.h>
|
||||
|
@ -8,21 +8,12 @@ set_target_properties(libgit2 PROPERTIES C_EXTENSIONS OFF)
|
||||
include(PkgBuildConfig)
|
||||
|
||||
set(LIBGIT2_INCLUDES
|
||||
"${PROJECT_BINARY_DIR}/src"
|
||||
"${PROJECT_BINARY_DIR}/src/util"
|
||||
"${PROJECT_BINARY_DIR}/include"
|
||||
"${PROJECT_SOURCE_DIR}/src/libgit2"
|
||||
"${PROJECT_SOURCE_DIR}/src/util"
|
||||
"${PROJECT_SOURCE_DIR}/include")
|
||||
|
||||
if(WIN32 AND EMBED_SSH_PATH)
|
||||
file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
|
||||
list(SORT SRC_SSH)
|
||||
target_sources(libgit2 PRIVATE ${SRC_SSH})
|
||||
|
||||
list(APPEND LIBGIT2_SYSTEM_INCLUDES "${EMBED_SSH_PATH}/include")
|
||||
file(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
|
||||
set(GIT_SSH 1)
|
||||
endif()
|
||||
|
||||
# Collect sourcefiles
|
||||
file(GLOB SRC_H
|
||||
"${PROJECT_SOURCE_DIR}/include/git2.h"
|
||||
@ -67,6 +58,7 @@ endif()
|
||||
|
||||
ide_split_sources(libgit2)
|
||||
list(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:util> $<TARGET_OBJECTS:libgit2> ${LIBGIT2_DEPENDENCY_OBJECTS})
|
||||
list(APPEND LIBGIT2_INCLUDES ${LIBGIT2_DEPENDENCY_INCLUDES})
|
||||
|
||||
target_include_directories(libgit2 PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||
target_include_directories(libgit2 SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
|
||||
@ -84,6 +76,7 @@ set(LIBGIT2_SYSTEM_LIBS ${LIBGIT2_SYSTEM_LIBS} PARENT_SCOPE)
|
||||
|
||||
add_library(libgit2package ${SRC_RC} ${LIBGIT2_OBJECTS})
|
||||
target_link_libraries(libgit2package ${LIBGIT2_SYSTEM_LIBS})
|
||||
target_include_directories(libgit2package SYSTEM PRIVATE ${LIBGIT2_INCLUDES})
|
||||
|
||||
set_target_properties(libgit2package PROPERTIES C_STANDARD 90)
|
||||
set_target_properties(libgit2package PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
@ -109,10 +102,10 @@ if(SONAME)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
pkg_build_config(NAME libgit2
|
||||
pkg_build_config(NAME "lib${LIBGIT2_FILENAME}"
|
||||
VERSION ${libgit2_VERSION}
|
||||
DESCRIPTION "The git library, take 2"
|
||||
LIBS_SELF git2
|
||||
LIBS_SELF ${LIBGIT2_FILENAME}
|
||||
PRIVATE_LIBS ${LIBGIT2_PC_LIBS}
|
||||
REQUIRES ${LIBGIT2_PC_REQUIRES})
|
||||
|
||||
@ -122,10 +115,26 @@ if(MSVC_IDE)
|
||||
set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
|
||||
endif()
|
||||
|
||||
# support experimental features and functionality
|
||||
|
||||
configure_file(experimental.h.in "${PROJECT_BINARY_DIR}/include/git2/experimental.h")
|
||||
|
||||
# translate filenames in the git2.h so that they match the install directory
|
||||
# (allows for side-by-side installs of libgit2 and libgit2-experimental.)
|
||||
|
||||
FILE(READ "${PROJECT_SOURCE_DIR}/include/git2.h" LIBGIT2_INCLUDE)
|
||||
STRING(REGEX REPLACE "#include \"git2\/" "#include \"${LIBGIT2_FILENAME}/" LIBGIT2_INCLUDE "${LIBGIT2_INCLUDE}")
|
||||
FILE(WRITE "${PROJECT_BINARY_DIR}/include/${LIBGIT2_FILENAME}.h" ${LIBGIT2_INCLUDE})
|
||||
|
||||
# Install
|
||||
|
||||
install(TARGETS libgit2package
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2/
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBGIT2_FILENAME}")
|
||||
install(FILES ${PROJECT_BINARY_DIR}/include/git2/experimental.h
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBGIT2_FILENAME}")
|
||||
install(FILES "${PROJECT_BINARY_DIR}/include/${LIBGIT2_FILENAME}.h"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
@ -40,7 +40,7 @@ static int annotated_commit_init(
|
||||
goto done;
|
||||
|
||||
git_oid_fmt(annotated_commit->id_str, git_commit_id(commit));
|
||||
annotated_commit->id_str[GIT_OID_HEXSZ] = '\0';
|
||||
annotated_commit->id_str[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
|
||||
if (!description)
|
||||
description = annotated_commit->id_str;
|
||||
|
@ -41,7 +41,7 @@ struct git_annotated_commit {
|
||||
const char *ref_name;
|
||||
const char *remote_url;
|
||||
|
||||
char id_str[GIT_OID_HEXSZ+1];
|
||||
char id_str[GIT_OID_SHA1_HEXSIZE+1];
|
||||
};
|
||||
|
||||
extern int git_annotated_commit_from_head(git_annotated_commit **out,
|
||||
|
@ -135,7 +135,7 @@ int git_attr_file__load(
|
||||
break;
|
||||
case GIT_ATTR_FILE_SOURCE_INDEX: {
|
||||
if ((error = attr_file_oid_from_index(&id, repo, entry->path)) < 0 ||
|
||||
(error = git_blob_lookup(&blob, repo, &id)) < 0)
|
||||
(error = git_blob_lookup(&blob, repo, &id)) < 0)
|
||||
return error;
|
||||
|
||||
/* Do not assume that data straight from the ODB is NULL-terminated;
|
||||
|
@ -300,7 +300,7 @@ static int attr_cache__lookup_path(
|
||||
|
||||
/* expand leading ~/ as needed */
|
||||
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') {
|
||||
if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2])))
|
||||
if (! (error = git_sysdir_expand_homedir_file(&buf, &cfgval[2])))
|
||||
*out = git_str_detach(&buf);
|
||||
} else if (cfgval) {
|
||||
*out = git__strdup(cfgval);
|
||||
|
@ -72,6 +72,8 @@ static git_blame_hunk *new_hunk(
|
||||
hunk->final_start_line_number = start;
|
||||
hunk->orig_start_line_number = orig_start;
|
||||
hunk->orig_path = path ? git__strdup(path) : NULL;
|
||||
git_oid_clear(&hunk->orig_commit_id, GIT_OID_SHA1);
|
||||
git_oid_clear(&hunk->final_commit_id, GIT_OID_SHA1);
|
||||
|
||||
return hunk;
|
||||
}
|
||||
|
@ -52,11 +52,12 @@ void git_blob__free(void *_blob)
|
||||
git__free(blob);
|
||||
}
|
||||
|
||||
int git_blob__parse_raw(void *_blob, const char *data, size_t size)
|
||||
int git_blob__parse_raw(void *_blob, const char *data, size_t size, git_oid_t oid_type)
|
||||
{
|
||||
git_blob *blob = (git_blob *) _blob;
|
||||
|
||||
GIT_ASSERT_ARG(blob);
|
||||
GIT_UNUSED(oid_type);
|
||||
|
||||
blob->raw = 1;
|
||||
blob->data.raw.data = data;
|
||||
@ -64,11 +65,12 @@ int git_blob__parse_raw(void *_blob, const char *data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_blob__parse(void *_blob, git_odb_object *odb_obj)
|
||||
int git_blob__parse(void *_blob, git_odb_object *odb_obj, git_oid_t oid_type)
|
||||
{
|
||||
git_blob *blob = (git_blob *) _blob;
|
||||
|
||||
GIT_ASSERT_ARG(blob);
|
||||
GIT_UNUSED(oid_type);
|
||||
|
||||
git_cached_obj_incref((git_cached_obj *)odb_obj);
|
||||
blob->raw = 0;
|
||||
|
@ -36,8 +36,8 @@ struct git_blob {
|
||||
} while(0)
|
||||
|
||||
void git_blob__free(void *blob);
|
||||
int git_blob__parse(void *blob, git_odb_object *obj);
|
||||
int git_blob__parse_raw(void *blob, const char *data, size_t size);
|
||||
int git_blob__parse(void *blob, git_odb_object *obj, git_oid_t oid_type);
|
||||
int git_blob__parse_raw(void *blob, const char *data, size_t size, git_oid_t oid_type);
|
||||
int git_blob__getbuf(git_str *buffer, git_blob *blob);
|
||||
|
||||
extern int git_blob__create_from_paths(
|
||||
|
@ -134,9 +134,9 @@ int git_branch_create(
|
||||
const git_commit *commit,
|
||||
int force)
|
||||
{
|
||||
char commit_id[GIT_OID_HEXSZ + 1];
|
||||
char commit_id[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(commit_id, GIT_OID_HEXSZ + 1, git_commit_id(commit));
|
||||
git_oid_tostr(commit_id, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit));
|
||||
return create_branch(ref_out, repository, branch_name, commit, commit_id, force);
|
||||
}
|
||||
|
||||
|
@ -106,10 +106,10 @@ static int cherrypick_state_cleanup(git_repository *repo)
|
||||
|
||||
static int cherrypick_seterr(git_commit *commit, const char *fmt)
|
||||
{
|
||||
char commit_oidstr[GIT_OID_HEXSZ + 1];
|
||||
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_error_set(GIT_ERROR_CHERRYPICK, fmt,
|
||||
git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit)));
|
||||
git_oid_tostr(commit_oidstr, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit)));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -173,7 +173,7 @@ int git_cherrypick(
|
||||
git_cherrypick_options opts;
|
||||
git_reference *our_ref = NULL;
|
||||
git_commit *our_commit = NULL;
|
||||
char commit_oidstr[GIT_OID_HEXSZ + 1];
|
||||
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
const char *commit_msg, *commit_summary;
|
||||
git_str their_label = GIT_STR_INIT;
|
||||
git_index *index = NULL;
|
||||
|
@ -282,7 +282,11 @@ static int update_head_to_branch(
|
||||
reflog_message)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((retcode = git_remote__default_branch(&default_branch, remote)) < 0)
|
||||
retcode = git_remote__default_branch(&default_branch, remote);
|
||||
|
||||
if (retcode == GIT_ENOTFOUND)
|
||||
retcode = 0;
|
||||
else if (retcode)
|
||||
goto cleanup;
|
||||
|
||||
if (!git_remote__matching_refspec(remote, git_str_cstr(&default_branch)))
|
||||
@ -389,12 +393,19 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
|
||||
return error;
|
||||
}
|
||||
|
||||
static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch)
|
||||
static int clone_into(
|
||||
git_repository *repo,
|
||||
git_remote *_remote,
|
||||
const git_fetch_options *opts,
|
||||
const git_checkout_options *co_opts,
|
||||
const char *branch)
|
||||
{
|
||||
int error;
|
||||
git_str reflog_message = GIT_STR_INIT;
|
||||
git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
|
||||
git_fetch_options fetch_opts;
|
||||
git_remote *remote;
|
||||
git_oid_t oid_type;
|
||||
|
||||
GIT_ASSERT_ARG(repo);
|
||||
GIT_ASSERT_ARG(_remote);
|
||||
@ -410,8 +421,25 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
|
||||
memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
|
||||
fetch_opts.update_fetchhead = 0;
|
||||
fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
|
||||
|
||||
if ((error = git_remote_connect_options__from_fetch_opts(&connect_opts, remote, &fetch_opts)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
git_str_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
|
||||
|
||||
/*
|
||||
* Connect to the server so that we can identify the remote
|
||||
* object format.
|
||||
*/
|
||||
|
||||
if ((error = git_remote_connect_ext(remote, GIT_DIRECTION_FETCH,
|
||||
&connect_opts)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((error = git_remote_oid_type(&oid_type, remote)) < 0 ||
|
||||
(error = git_repository__set_objectformat(repo, oid_type)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_str_cstr(&reflog_message))) != 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -419,6 +447,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch
|
||||
|
||||
cleanup:
|
||||
git_remote_free(remote);
|
||||
git_remote_connect_options_dispose(&connect_opts);
|
||||
git_str_dispose(&reflog_message);
|
||||
|
||||
return error;
|
||||
|
@ -56,11 +56,13 @@ static int git_commit__create_buffer_internal(
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(tree);
|
||||
|
||||
git_oid__writebuf(out, "tree ", tree);
|
||||
if (git_object__write_oid_header(out, "tree ", tree) < 0)
|
||||
goto on_error;
|
||||
|
||||
for (i = 0; i < git_array_size(*parents); i++) {
|
||||
parent = git_array_get(*parents, i);
|
||||
git_oid__writebuf(out, "parent ", parent);
|
||||
if (git_object__write_oid_header(out, "parent ", parent) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
git_signature__writebuf(out, "author ", author);
|
||||
@ -388,7 +390,11 @@ int git_commit_amend(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int commit_parse(git_commit *commit, const char *data, size_t size, unsigned int flags)
|
||||
static int commit_parse(
|
||||
git_commit *commit,
|
||||
const char *data,
|
||||
size_t size,
|
||||
git_commit__parse_options *opts)
|
||||
{
|
||||
const char *buffer_start = data, *buffer;
|
||||
const char *buffer_end = buffer_start + size;
|
||||
@ -399,6 +405,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
|
||||
|
||||
GIT_ASSERT_ARG(commit);
|
||||
GIT_ASSERT_ARG(data);
|
||||
GIT_ASSERT_ARG(opts);
|
||||
|
||||
buffer = buffer_start;
|
||||
|
||||
@ -407,11 +414,14 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
|
||||
GIT_ERROR_CHECK_ARRAY(commit->parent_ids);
|
||||
|
||||
/* The tree is always the first field */
|
||||
if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
|
||||
if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
|
||||
if (!(opts->flags & GIT_COMMIT_PARSE_QUICK)) {
|
||||
if (git_object__parse_oid_header(&commit->tree_id,
|
||||
&buffer, buffer_end, "tree ",
|
||||
opts->oid_type) < 0)
|
||||
goto bad_buffer;
|
||||
} else {
|
||||
size_t tree_len = strlen("tree ") + GIT_OID_HEXSZ + 1;
|
||||
size_t tree_len = strlen("tree ") + git_oid_hexsize(opts->oid_type) + 1;
|
||||
|
||||
if (buffer + tree_len > buffer_end)
|
||||
goto bad_buffer;
|
||||
buffer += tree_len;
|
||||
@ -421,14 +431,16 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
|
||||
* TODO: commit grafts!
|
||||
*/
|
||||
|
||||
while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
|
||||
while (git_object__parse_oid_header(&parent_id,
|
||||
&buffer, buffer_end, "parent ",
|
||||
opts->oid_type) == 0) {
|
||||
git_oid *new_id = git_array_alloc(commit->parent_ids);
|
||||
GIT_ERROR_CHECK_ALLOC(new_id);
|
||||
|
||||
git_oid_cpy(new_id, &parent_id);
|
||||
}
|
||||
|
||||
if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
|
||||
if (!opts || !(opts->flags & GIT_COMMIT_PARSE_QUICK)) {
|
||||
commit->author = git__malloc(sizeof(git_signature));
|
||||
GIT_ERROR_CHECK_ALLOC(commit->author);
|
||||
|
||||
@ -452,7 +464,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
|
||||
if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < 0)
|
||||
return error;
|
||||
|
||||
if (flags & GIT_COMMIT_PARSE_QUICK)
|
||||
if (opts && opts->flags & GIT_COMMIT_PARSE_QUICK)
|
||||
return 0;
|
||||
|
||||
/* Parse add'l header entries */
|
||||
@ -497,19 +509,39 @@ bad_buffer:
|
||||
return GIT_EINVALID;
|
||||
}
|
||||
|
||||
int git_commit__parse_raw(void *commit, const char *data, size_t size)
|
||||
int git_commit__parse(
|
||||
void *commit,
|
||||
git_odb_object *odb_obj,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
return commit_parse(commit, data, size, 0);
|
||||
git_commit__parse_options parse_options = {0};
|
||||
parse_options.oid_type = oid_type;
|
||||
|
||||
return git_commit__parse_ext(commit, odb_obj, &parse_options);
|
||||
}
|
||||
|
||||
int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags)
|
||||
int git_commit__parse_raw(
|
||||
void *commit,
|
||||
const char *data,
|
||||
size_t size,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags);
|
||||
git_commit__parse_options parse_options = {0};
|
||||
parse_options.oid_type = oid_type;
|
||||
|
||||
return commit_parse(commit, data, size, &parse_options);
|
||||
}
|
||||
|
||||
int git_commit__parse(void *_commit, git_odb_object *odb_obj)
|
||||
int git_commit__parse_ext(
|
||||
git_commit *commit,
|
||||
git_odb_object *odb_obj,
|
||||
git_commit__parse_options *parse_opts)
|
||||
{
|
||||
return git_commit__parse_ext(_commit, odb_obj, 0);
|
||||
return commit_parse(
|
||||
commit,
|
||||
git_odb_object_data(odb_obj),
|
||||
git_odb_object_size(odb_obj),
|
||||
parse_opts);
|
||||
}
|
||||
|
||||
#define GIT_COMMIT_GETTER(_rvalue, _name, _return, _invalid) \
|
||||
@ -979,11 +1011,14 @@ int git_commit_create_with_signature(
|
||||
git_str commit = GIT_STR_INIT;
|
||||
git_commit *parsed;
|
||||
git_array_oid_t parents = GIT_ARRAY_INIT;
|
||||
git_commit__parse_options parse_opts = {0};
|
||||
|
||||
parse_opts.oid_type = repo->oid_type;
|
||||
|
||||
/* 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 (commit_parse(parsed, commit_content, strlen(commit_content), 0) < 0) {
|
||||
if (commit_parse(parsed, commit_content, strlen(commit_content), &parse_opts) < 0) {
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -33,6 +33,16 @@ struct git_commit {
|
||||
char *body;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
git_oid_t oid_type;
|
||||
unsigned int flags;
|
||||
} git_commit__parse_options;
|
||||
|
||||
typedef enum {
|
||||
/** Only parse parents and committer info */
|
||||
GIT_COMMIT_PARSE_QUICK = (1 << 0)
|
||||
} git_commit__parse_flags;
|
||||
|
||||
int git_commit__header_field(
|
||||
git_str *out,
|
||||
const git_commit *commit,
|
||||
@ -56,14 +66,22 @@ int git_commit__create_buffer(
|
||||
size_t parent_count,
|
||||
const git_commit *parents[]);
|
||||
|
||||
int git_commit__parse(
|
||||
void *commit,
|
||||
git_odb_object *obj,
|
||||
git_oid_t oid_type);
|
||||
|
||||
int git_commit__parse_raw(
|
||||
void *commit,
|
||||
const char *data,
|
||||
size_t size,
|
||||
git_oid_t oid_type);
|
||||
|
||||
int git_commit__parse_ext(
|
||||
git_commit *commit,
|
||||
git_odb_object *odb_obj,
|
||||
git_commit__parse_options *parse_opts);
|
||||
|
||||
void git_commit__free(void *commit);
|
||||
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
|
||||
|
@ -138,19 +138,19 @@ static int commit_graph_parse_oid_lookup(
|
||||
struct git_commit_graph_chunk *chunk_oid_lookup)
|
||||
{
|
||||
uint32_t i;
|
||||
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
|
||||
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_SHA1_SIZE] = {0};
|
||||
|
||||
if (chunk_oid_lookup->offset == 0)
|
||||
return commit_graph_error("missing OID Lookup chunk");
|
||||
if (chunk_oid_lookup->length == 0)
|
||||
return commit_graph_error("empty OID Lookup chunk");
|
||||
if (chunk_oid_lookup->length != file->num_commits * GIT_OID_RAWSZ)
|
||||
if (chunk_oid_lookup->length != file->num_commits * GIT_OID_SHA1_SIZE)
|
||||
return commit_graph_error("OID Lookup chunk has wrong length");
|
||||
|
||||
file->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
|
||||
prev_oid = zero_oid;
|
||||
for (i = 0; i < file->num_commits; ++i, oid += GIT_OID_RAWSZ) {
|
||||
if (git_oid_raw_cmp(prev_oid, oid) >= 0)
|
||||
for (i = 0; i < file->num_commits; ++i, oid += GIT_OID_SHA1_SIZE) {
|
||||
if (git_oid_raw_cmp(prev_oid, oid, GIT_OID_SHA1_SIZE) >= 0)
|
||||
return commit_graph_error("OID Lookup index is non-monotonic");
|
||||
prev_oid = oid;
|
||||
}
|
||||
@ -167,7 +167,7 @@ static int commit_graph_parse_commit_data(
|
||||
return commit_graph_error("missing Commit Data chunk");
|
||||
if (chunk_commit_data->length == 0)
|
||||
return commit_graph_error("empty Commit Data chunk");
|
||||
if (chunk_commit_data->length != file->num_commits * (GIT_OID_RAWSZ + 16))
|
||||
if (chunk_commit_data->length != file->num_commits * (GIT_OID_SHA1_SIZE + 16))
|
||||
return commit_graph_error("Commit Data chunk has wrong length");
|
||||
|
||||
file->commit_data = data + chunk_commit_data->offset;
|
||||
@ -200,8 +200,7 @@ int git_commit_graph_file_parse(
|
||||
const unsigned char *chunk_hdr;
|
||||
struct git_commit_graph_chunk *last_chunk;
|
||||
uint32_t i;
|
||||
off64_t last_chunk_offset, chunk_offset, trailer_offset;
|
||||
unsigned char checksum[GIT_HASH_SHA1_SIZE];
|
||||
uint64_t last_chunk_offset, chunk_offset, trailer_offset;
|
||||
size_t checksum_size;
|
||||
int error;
|
||||
struct git_commit_graph_chunk chunk_oid_fanout = {0}, chunk_oid_lookup = {0},
|
||||
@ -210,7 +209,7 @@ int git_commit_graph_file_parse(
|
||||
|
||||
GIT_ASSERT_ARG(file);
|
||||
|
||||
if (size < sizeof(struct git_commit_graph_header) + GIT_OID_RAWSZ)
|
||||
if (size < sizeof(struct git_commit_graph_header) + GIT_OID_SHA1_SIZE)
|
||||
return commit_graph_error("commit-graph is too short");
|
||||
|
||||
hdr = ((struct git_commit_graph_header *)data);
|
||||
@ -227,23 +226,18 @@ int git_commit_graph_file_parse(
|
||||
* headers, and a special zero chunk.
|
||||
*/
|
||||
last_chunk_offset = sizeof(struct git_commit_graph_header) + (1 + hdr->chunks) * 12;
|
||||
trailer_offset = size - GIT_OID_RAWSZ;
|
||||
trailer_offset = size - GIT_OID_SHA1_SIZE;
|
||||
checksum_size = GIT_HASH_SHA1_SIZE;
|
||||
|
||||
if (trailer_offset < last_chunk_offset)
|
||||
return commit_graph_error("wrong commit-graph size");
|
||||
memcpy(file->checksum, (data + trailer_offset), checksum_size);
|
||||
|
||||
if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
|
||||
return commit_graph_error("could not calculate signature");
|
||||
if (memcmp(checksum, file->checksum, checksum_size) != 0)
|
||||
return commit_graph_error("index signature mismatch");
|
||||
|
||||
chunk_hdr = data + sizeof(struct git_commit_graph_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))));
|
||||
chunk_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32
|
||||
| ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
|
||||
if (chunk_offset < last_chunk_offset)
|
||||
return commit_graph_error("chunks are non-monotonic");
|
||||
if (chunk_offset >= trailer_offset)
|
||||
@ -331,9 +325,29 @@ error:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_commit_graph_validate(git_commit_graph *cgraph) {
|
||||
unsigned char checksum[GIT_HASH_SHA1_SIZE];
|
||||
size_t checksum_size = GIT_HASH_SHA1_SIZE;
|
||||
size_t trailer_offset = cgraph->file->graph_map.len - checksum_size;
|
||||
|
||||
if (cgraph->file->graph_map.len < checksum_size)
|
||||
return commit_graph_error("map length too small");
|
||||
|
||||
if (git_hash_buf(checksum, cgraph->file->graph_map.data, trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
|
||||
return commit_graph_error("could not calculate signature");
|
||||
if (memcmp(checksum, cgraph->file->checksum, checksum_size) != 0)
|
||||
return commit_graph_error("index signature mismatch");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_commit_graph_open(git_commit_graph **cgraph_out, const char *objects_dir)
|
||||
{
|
||||
return git_commit_graph_new(cgraph_out, objects_dir, true);
|
||||
int error = git_commit_graph_new(cgraph_out, objects_dir, true);
|
||||
if (!error) {
|
||||
return git_commit_graph_validate(*cgraph_out);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path)
|
||||
@ -436,15 +450,15 @@ static int git_commit_graph_entry_get_byindex(
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
commit_data = file->commit_data + pos * (GIT_OID_RAWSZ + 4 * sizeof(uint32_t));
|
||||
git_oid_fromraw(&e->tree_oid, commit_data);
|
||||
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ)));
|
||||
commit_data = file->commit_data + pos * (GIT_OID_SHA1_SIZE + 4 * sizeof(uint32_t));
|
||||
git_oid__fromraw(&e->tree_oid, commit_data, GIT_OID_SHA1);
|
||||
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE)));
|
||||
e->parent_indices[1] = ntohl(
|
||||
*((uint32_t *)(commit_data + GIT_OID_RAWSZ + sizeof(uint32_t))));
|
||||
*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + sizeof(uint32_t))));
|
||||
e->parent_count = (e->parent_indices[0] != GIT_COMMIT_GRAPH_MISSING_PARENT)
|
||||
+ (e->parent_indices[1] != GIT_COMMIT_GRAPH_MISSING_PARENT);
|
||||
e->generation = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 2 * sizeof(uint32_t))));
|
||||
e->commit_time = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ + 3 * sizeof(uint32_t))));
|
||||
e->generation = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + 2 * sizeof(uint32_t))));
|
||||
e->commit_time = ntohl(*((uint32_t *)(commit_data + GIT_OID_SHA1_SIZE + 3 * sizeof(uint32_t))));
|
||||
|
||||
e->commit_time |= (e->generation & UINT64_C(0x3)) << UINT64_C(32);
|
||||
e->generation >>= 2u;
|
||||
@ -471,7 +485,7 @@ static int git_commit_graph_entry_get_byindex(
|
||||
}
|
||||
}
|
||||
|
||||
git_oid_fromraw(&e->sha1, &file->oid_lookup[pos * GIT_OID_RAWSZ]);
|
||||
git_oid__fromraw(&e->sha1, &file->oid_lookup[pos * GIT_OID_SHA1_SIZE], GIT_OID_SHA1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -524,27 +538,27 @@ int git_commit_graph_entry_find(
|
||||
hi = ntohl(file->oid_fanout[(int)short_oid->id[0]]);
|
||||
lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(file->oid_fanout[(int)short_oid->id[0] - 1]));
|
||||
|
||||
pos = git_pack__lookup_sha1(file->oid_lookup, GIT_OID_RAWSZ, lo, hi, short_oid->id);
|
||||
pos = git_pack__lookup_id(file->oid_lookup, GIT_OID_SHA1_SIZE, lo, hi, short_oid->id, GIT_OID_SHA1);
|
||||
|
||||
if (pos >= 0) {
|
||||
/* An object matching exactly the oid was found */
|
||||
found = 1;
|
||||
current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
|
||||
current = file->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
|
||||
} else {
|
||||
/* No object was found */
|
||||
/* pos refers to the object with the "closest" oid to short_oid */
|
||||
pos = -1 - pos;
|
||||
if (pos < (int)file->num_commits) {
|
||||
current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
|
||||
current = file->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
|
||||
|
||||
if (!git_oid_raw_ncmp(short_oid->id, current, len))
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)file->num_commits) {
|
||||
if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int)file->num_commits) {
|
||||
/* Check for ambiguousity */
|
||||
const unsigned char *next = current + GIT_OID_RAWSZ;
|
||||
const unsigned char *next = current + GIT_OID_SHA1_SIZE;
|
||||
|
||||
if (!git_oid_raw_ncmp(short_oid->id, next, len))
|
||||
found = 2;
|
||||
@ -712,7 +726,8 @@ int git_commit_graph_writer_add_index_file(
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = git_mwindow_get_pack(&p, idx_path);
|
||||
/* TODO: SHA256 */
|
||||
error = git_mwindow_get_pack(&p, idx_path, 0);
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -1020,7 +1035,7 @@ static int commit_graph_write(
|
||||
git_vector_foreach (&w->commits, i, packed_commit) {
|
||||
error = git_str_put(&oid_lookup,
|
||||
(const char *)&packed_commit->sha1.id,
|
||||
GIT_OID_RAWSZ);
|
||||
GIT_OID_SHA1_SIZE);
|
||||
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
@ -1037,7 +1052,7 @@ static int commit_graph_write(
|
||||
|
||||
error = git_str_put(&commit_data,
|
||||
(const char *)&packed_commit->tree_oid.id,
|
||||
GIT_OID_RAWSZ);
|
||||
GIT_OID_SHA1_SIZE);
|
||||
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
@ -106,6 +106,9 @@ struct git_commit_graph {
|
||||
/** Create a new commit-graph, optionally opening the underlying file. */
|
||||
int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir, bool open_file);
|
||||
|
||||
/** Validate the checksum of a commit graph */
|
||||
int git_commit_graph_validate(git_commit_graph *cgraph);
|
||||
|
||||
/** Open and validate a commit-graph file. */
|
||||
int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *path);
|
||||
|
||||
|
@ -124,13 +124,17 @@ static int commit_quick_parse(
|
||||
{
|
||||
git_oid *parent_oid;
|
||||
git_commit *commit;
|
||||
git_commit__parse_options parse_opts = {
|
||||
GIT_OID_SHA1,
|
||||
GIT_COMMIT_PARSE_QUICK
|
||||
};
|
||||
size_t i;
|
||||
|
||||
commit = git__calloc(1, sizeof(*commit));
|
||||
GIT_ERROR_CHECK_ALLOC(commit);
|
||||
commit->object.repo = walk->repo;
|
||||
|
||||
if (git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK) < 0) {
|
||||
if (git_commit__parse_ext(commit, obj, &parse_opts) < 0) {
|
||||
git__free(commit);
|
||||
return -1;
|
||||
}
|
||||
@ -172,7 +176,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
|
||||
if (cgraph_file) {
|
||||
git_commit_graph_entry e;
|
||||
|
||||
error = git_commit_graph_entry_find(&e, cgraph_file, &commit->oid, GIT_OID_RAWSZ);
|
||||
error = git_commit_graph_entry_find(&e, cgraph_file, &commit->oid, GIT_OID_SHA1_SIZE);
|
||||
if (error == 0 && git__is_uint16(e.parent_count)) {
|
||||
size_t i;
|
||||
commit->generation = (uint32_t)e.generation;
|
||||
|
@ -860,7 +860,7 @@ static int git_config__parse_path(git_str *out, const char *value)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
|
||||
return git_sysdir_expand_homedir_file(out, value[1] ? &value[2] : NULL);
|
||||
}
|
||||
|
||||
return git_str_sets(out, value);
|
||||
@ -1174,9 +1174,12 @@ int git_config__find_programdata(git_str *path)
|
||||
GIT_FS_PATH_OWNER_CURRENT_USER |
|
||||
GIT_FS_PATH_OWNER_ADMINISTRATOR;
|
||||
bool is_safe;
|
||||
int error;
|
||||
|
||||
if (git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
|
||||
git_fs_path_owner_is(&is_safe, path->ptr, owner_level) < 0)
|
||||
if ((error = git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_fs_path_owner_is(&is_safe, path->ptr, owner_level) < 0)
|
||||
return -1;
|
||||
|
||||
if (!is_safe) {
|
||||
|
@ -528,7 +528,7 @@ static int included_path(git_str *out, const char *dir, const char *path)
|
||||
{
|
||||
/* From the user's home */
|
||||
if (path[0] == '~' && path[1] == '/')
|
||||
return git_sysdir_expand_global_file(out, &path[1]);
|
||||
return git_sysdir_expand_homedir_file(out, &path[1]);
|
||||
|
||||
return git_fs_path_join_unrooted(out, path, dir, NULL);
|
||||
}
|
||||
@ -616,7 +616,7 @@ static int do_match_gitdir(
|
||||
git_fs_path_dirname_r(&pattern, cfg_file);
|
||||
git_str_joinpath(&pattern, pattern.ptr, condition + 2);
|
||||
} else if (condition[0] == '~' && git_fs_path_is_dirsep(condition[1]))
|
||||
git_sysdir_expand_global_file(&pattern, condition + 1);
|
||||
git_sysdir_expand_homedir_file(&pattern, condition + 1);
|
||||
else if (!git_fs_path_is_absolute(condition))
|
||||
git_str_joinpath(&pattern, "**", condition);
|
||||
else
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "git2/describe.h"
|
||||
#include "git2/strarray.h"
|
||||
#include "git2/diff.h"
|
||||
#include "git2/status.h"
|
||||
|
||||
@ -19,6 +18,7 @@
|
||||
#include "refs.h"
|
||||
#include "repository.h"
|
||||
#include "revwalk.h"
|
||||
#include "strarray.h"
|
||||
#include "tag.h"
|
||||
#include "vector.h"
|
||||
#include "wildmatch.h"
|
||||
@ -368,7 +368,7 @@ static int find_unique_abbrev_size(
|
||||
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
|
||||
return error;
|
||||
|
||||
while (size < GIT_OID_HEXSZ) {
|
||||
while (size < GIT_OID_SHA1_HEXSIZE) {
|
||||
if ((error = git_odb_exists_prefix(&dummy, odb, oid_in, size)) == 0) {
|
||||
*out = (int) size;
|
||||
return 0;
|
||||
@ -383,7 +383,7 @@ static int find_unique_abbrev_size(
|
||||
}
|
||||
|
||||
/* If we didn't find any shorter prefix, we have to do the whole thing */
|
||||
*out = GIT_OID_HEXSZ;
|
||||
*out = GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -397,7 +397,7 @@ static int show_suffix(
|
||||
{
|
||||
int error, size = 0;
|
||||
|
||||
char hex_oid[GIT_OID_HEXSZ];
|
||||
char hex_oid[GIT_OID_SHA1_HEXSIZE];
|
||||
|
||||
if ((error = find_unique_abbrev_size(&size, repo, id, abbrev_size)) < 0)
|
||||
return error;
|
||||
@ -414,7 +414,7 @@ static int show_suffix(
|
||||
#define MAX_CANDIDATES_TAGS FLAG_BITS - 1
|
||||
|
||||
static int describe_not_found(const git_oid *oid, const char *message_format) {
|
||||
char oid_str[GIT_OID_HEXSZ + 1];
|
||||
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
git_oid_tostr(oid_str, sizeof(oid_str), oid);
|
||||
|
||||
git_error_set(GIT_ERROR_DESCRIBE, message_format, oid_str);
|
||||
@ -525,7 +525,7 @@ static int describe(
|
||||
if (annotated_cnt && (git_pqueue_size(&list) == 0)) {
|
||||
/*
|
||||
if (debug) {
|
||||
char oid_str[GIT_OID_HEXSZ + 1];
|
||||
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
git_oid_tostr(oid_str, sizeof(oid_str), &c->oid);
|
||||
|
||||
fprintf(stderr, "finished search at %s\n", oid_str);
|
||||
@ -592,7 +592,7 @@ static int describe(
|
||||
"head", "lightweight", "annotated",
|
||||
};
|
||||
|
||||
char oid_str[GIT_OID_HEXSZ + 1];
|
||||
char oid_str[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
if (debug) {
|
||||
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
|
||||
@ -816,7 +816,7 @@ static int git_describe__format(
|
||||
|
||||
/* If we didn't find *any* tags, we fall back to the commit's id */
|
||||
if (result->fallback_to_id) {
|
||||
char hex_oid[GIT_OID_HEXSZ + 1] = {0};
|
||||
char hex_oid[GIT_OID_SHA1_HEXSIZE + 1] = {0};
|
||||
int size = 0;
|
||||
|
||||
if ((error = find_unique_abbrev_size(
|
||||
|
@ -290,7 +290,7 @@ static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
|
||||
(error = git_hash_init(ctx)) < 0)
|
||||
return error;
|
||||
|
||||
for (i = 0; i < GIT_OID_RAWSZ; i++) {
|
||||
for (i = 0; i < GIT_OID_SHA1_SIZE; i++) {
|
||||
carry += result->id[i] + hash.id[i];
|
||||
result->id[i] = (unsigned char)carry;
|
||||
carry >>= 8;
|
||||
@ -381,6 +381,10 @@ int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opt
|
||||
if ((error = (flush_hunk(&args.result, &args.ctx))) < 0)
|
||||
goto out;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
args.result.type = GIT_OID_SHA1;
|
||||
#endif
|
||||
|
||||
git_oid_cpy(out, &args.result);
|
||||
|
||||
out:
|
||||
|
@ -144,6 +144,7 @@ int git_diff_file_content__init_from_src(
|
||||
|
||||
if (!src->blob && !src->buf) {
|
||||
fc->flags |= GIT_DIFF_FLAG__NO_DATA;
|
||||
git_oid_clear(&fc->file->id, GIT_OID_SHA1);
|
||||
} else {
|
||||
fc->flags |= GIT_DIFF_FLAG__LOADED;
|
||||
fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
@ -153,7 +154,7 @@ int git_diff_file_content__init_from_src(
|
||||
git_blob_dup((git_blob **)&fc->blob, (git_blob *) src->blob);
|
||||
fc->file->size = git_blob_rawsize(src->blob);
|
||||
git_oid_cpy(&fc->file->id, git_blob_id(src->blob));
|
||||
fc->file->id_abbrev = GIT_OID_HEXSZ;
|
||||
fc->file->id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
fc->map.len = (size_t)fc->file->size;
|
||||
fc->map.data = (char *)git_blob_rawcontent(src->blob);
|
||||
@ -161,10 +162,10 @@ int git_diff_file_content__init_from_src(
|
||||
fc->flags |= GIT_DIFF_FLAG__FREE_BLOB;
|
||||
} else {
|
||||
int error;
|
||||
if ((error = git_odb_hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB)) < 0)
|
||||
if ((error = git_odb__hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB, GIT_OID_SHA1)) < 0)
|
||||
return error;
|
||||
fc->file->size = src->buflen;
|
||||
fc->file->id_abbrev = GIT_OID_HEXSZ;
|
||||
fc->file->id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
fc->map.len = src->buflen;
|
||||
fc->map.data = (char *)src->buf;
|
||||
@ -177,7 +178,7 @@ int git_diff_file_content__init_from_src(
|
||||
static int diff_file_content_commit_to_str(
|
||||
git_diff_file_content *fc, bool check_status)
|
||||
{
|
||||
char oid[GIT_OID_HEXSZ+1];
|
||||
char oid[GIT_OID_SHA1_HEXSIZE+1];
|
||||
git_str content = GIT_STR_INIT;
|
||||
const char *status = "";
|
||||
|
||||
@ -347,6 +348,13 @@ static int diff_file_content_load_workdir_file(
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* if file is empty, don't attempt to mmap or readbuffer */
|
||||
if (fc->file->size == 0) {
|
||||
fc->map.len = 0;
|
||||
fc->map.data = git_str__initstr;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
|
||||
diff_file_content_binary_by_size(fc))
|
||||
goto cleanup;
|
||||
@ -410,8 +418,9 @@ static int diff_file_content_load_workdir(
|
||||
|
||||
/* once data is loaded, update OID if we didn't have it previously */
|
||||
if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) {
|
||||
error = git_odb_hash(
|
||||
&fc->file->id, fc->map.data, fc->map.len, GIT_OBJECT_BLOB);
|
||||
error = git_odb__hash(
|
||||
&fc->file->id, fc->map.data, fc->map.len,
|
||||
GIT_OBJECT_BLOB, GIT_OID_SHA1);
|
||||
fc->file->flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,9 @@ static git_diff_delta *diff_delta__alloc(
|
||||
}
|
||||
delta->status = status;
|
||||
|
||||
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
|
||||
git_oid_clear(&delta->new_file.id, GIT_OID_SHA1);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
@ -188,13 +191,15 @@ static int diff_delta__from_one(
|
||||
delta->old_file.size = entry->file_size;
|
||||
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
||||
git_oid_cpy(&delta->old_file.id, &entry->id);
|
||||
delta->old_file.id_abbrev = GIT_OID_HEXSZ;
|
||||
git_oid_clear(&delta->new_file.id, GIT_OID_SHA1);
|
||||
delta->old_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
} else /* ADDED, IGNORED, UNTRACKED */ {
|
||||
delta->new_file.mode = entry->mode;
|
||||
delta->new_file.size = entry->file_size;
|
||||
delta->new_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
||||
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
|
||||
git_oid_cpy(&delta->new_file.id, &entry->id);
|
||||
delta->new_file.id_abbrev = GIT_OID_HEXSZ;
|
||||
delta->new_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
}
|
||||
|
||||
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
@ -249,14 +254,14 @@ static int diff_delta__from_two(
|
||||
delta->old_file.size = old_entry->file_size;
|
||||
delta->old_file.mode = old_mode;
|
||||
git_oid_cpy(&delta->old_file.id, old_id);
|
||||
delta->old_file.id_abbrev = GIT_OID_HEXSZ;
|
||||
delta->old_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID |
|
||||
GIT_DIFF_FLAG_EXISTS;
|
||||
}
|
||||
|
||||
if (!git_index_entry_is_conflict(new_entry)) {
|
||||
git_oid_cpy(&delta->new_file.id, new_id);
|
||||
delta->new_file.id_abbrev = GIT_OID_HEXSZ;
|
||||
delta->new_file.id_abbrev = GIT_OID_SHA1_HEXSIZE;
|
||||
delta->new_file.size = new_entry->file_size;
|
||||
delta->new_file.mode = new_mode;
|
||||
delta->old_file.flags |= GIT_DIFF_FLAG_EXISTS;
|
||||
@ -598,6 +603,7 @@ int git_diff__oid_for_file(
|
||||
entry.mode = mode;
|
||||
entry.file_size = (uint32_t)size;
|
||||
entry.path = (char *)path;
|
||||
git_oid_clear(&entry.id, GIT_OID_SHA1);
|
||||
|
||||
return git_diff__oid_for_entry(out, diff, &entry, mode, NULL);
|
||||
}
|
||||
@ -618,7 +624,7 @@ int git_diff__oid_for_entry(
|
||||
GIT_ASSERT(d->type == GIT_DIFF_TYPE_GENERATED);
|
||||
diff = (git_diff_generated *)d;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
git_oid_clear(out, GIT_OID_SHA1);
|
||||
|
||||
if (git_repository_workdir_path(&full_path, diff->base.repo, entry.path) < 0)
|
||||
return -1;
|
||||
@ -654,7 +660,7 @@ int git_diff__oid_for_entry(
|
||||
git_error_clear();
|
||||
}
|
||||
} else if (S_ISLNK(mode)) {
|
||||
error = git_odb__hashlink(out, full_path.ptr);
|
||||
error = git_odb__hashlink(out, full_path.ptr, GIT_OID_SHA1);
|
||||
diff->base.perf.oid_calculations++;
|
||||
} else if (!git__is_sizet(entry.file_size)) {
|
||||
git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'",
|
||||
@ -669,7 +675,8 @@ int git_diff__oid_for_entry(
|
||||
error = fd;
|
||||
else {
|
||||
error = git_odb__hashfd_filtered(
|
||||
out, fd, (size_t)entry.file_size, GIT_OBJECT_BLOB, fl);
|
||||
out, fd, (size_t)entry.file_size,
|
||||
GIT_OBJECT_BLOB, GIT_OID_SHA1, fl);
|
||||
p_close(fd);
|
||||
diff->base.perf.oid_calculations++;
|
||||
}
|
||||
@ -778,7 +785,7 @@ static int maybe_modified(
|
||||
git_diff_generated *diff,
|
||||
diff_in_progress *info)
|
||||
{
|
||||
git_oid noid;
|
||||
git_oid noid = GIT_OID_SHA1_ZERO;
|
||||
git_delta_t status = GIT_DELTA_MODIFIED;
|
||||
const git_index_entry *oitem = info->oitem;
|
||||
const git_index_entry *nitem = info->nitem;
|
||||
@ -792,8 +799,6 @@ static int maybe_modified(
|
||||
if (!diff_pathspec_match(&matched_pathspec, diff, oitem))
|
||||
return 0;
|
||||
|
||||
memset(&noid, 0, sizeof(noid));
|
||||
|
||||
/* on platforms with no symlinks, preserve mode of existing symlinks */
|
||||
if (S_ISLNK(omode) && S_ISREG(nmode) && new_is_workdir &&
|
||||
!(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS))
|
||||
@ -1695,11 +1700,11 @@ int git_diff__commit(
|
||||
*out = NULL;
|
||||
|
||||
if ((parents = git_commit_parentcount(commit)) > 1) {
|
||||
char commit_oidstr[GIT_OID_HEXSZ + 1];
|
||||
char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
error = -1;
|
||||
git_error_set(GIT_ERROR_INVALID, "commit %s is a merge commit",
|
||||
git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit)));
|
||||
git_oid_tostr(commit_oidstr, GIT_OID_SHA1_HEXSIZE + 1, git_commit_id(commit)));
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ static int diff_print_info_init__common(
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pi->id_strlen > GIT_OID_HEXSZ)
|
||||
pi->id_strlen = GIT_OID_HEXSZ;
|
||||
if (pi->id_strlen > GIT_OID_SHA1_HEXSIZE)
|
||||
pi->id_strlen = GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
memset(&pi->line, 0, sizeof(pi->line));
|
||||
pi->line.old_lineno = -1;
|
||||
@ -212,7 +212,7 @@ static int diff_print_one_raw(
|
||||
git_str *out = pi->buf;
|
||||
int id_abbrev;
|
||||
char code = git_diff_status_char(delta->status);
|
||||
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
|
||||
char start_oid[GIT_OID_SHA1_HEXSIZE+1], end_oid[GIT_OID_SHA1_HEXSIZE+1];
|
||||
|
||||
GIT_UNUSED(progress);
|
||||
|
||||
@ -235,7 +235,7 @@ static int diff_print_one_raw(
|
||||
git_oid_tostr(end_oid, pi->id_strlen + 1, &delta->new_file.id);
|
||||
|
||||
git_str_printf(
|
||||
out, (pi->id_strlen <= GIT_OID_HEXSZ) ?
|
||||
out, (pi->id_strlen <= GIT_OID_SHA1_HEXSIZE) ?
|
||||
":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
|
||||
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
|
||||
|
||||
@ -273,7 +273,7 @@ static int diff_print_oid_range(
|
||||
git_str *out, const git_diff_delta *delta, int id_strlen,
|
||||
bool print_index)
|
||||
{
|
||||
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
|
||||
char start_oid[GIT_OID_SHA1_HEXSIZE+1], end_oid[GIT_OID_SHA1_HEXSIZE+1];
|
||||
|
||||
if (delta->old_file.mode &&
|
||||
id_strlen > delta->old_file.id_abbrev) {
|
||||
|
@ -364,6 +364,7 @@ static int insert_delete_side_of_split(
|
||||
memset(&deleted->new_file, 0, sizeof(deleted->new_file));
|
||||
deleted->new_file.path = deleted->old_file.path;
|
||||
deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
git_oid_clear(&deleted->new_file.id, GIT_OID_SHA1);
|
||||
|
||||
return git_vector_insert(onto, deleted);
|
||||
}
|
||||
@ -397,6 +398,7 @@ static int apply_splits_and_deletes(
|
||||
memset(&delta->old_file, 0, sizeof(delta->old_file));
|
||||
delta->old_file.path = delta->new_file.path;
|
||||
delta->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
|
||||
}
|
||||
|
||||
/* clean up delta before inserting into new list */
|
||||
@ -995,6 +997,7 @@ find_best_matches:
|
||||
memset(&src->new_file, 0, sizeof(src->new_file));
|
||||
src->new_file.path = src->old_file.path;
|
||||
src->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
git_oid_clear(&src->new_file.id, GIT_OID_SHA1);
|
||||
|
||||
num_updates++;
|
||||
|
||||
@ -1020,6 +1023,7 @@ find_best_matches:
|
||||
memset(&src->old_file, 0, sizeof(src->old_file));
|
||||
src->old_file.path = src->new_file.path;
|
||||
src->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;
|
||||
git_oid_clear(&src->old_file.id, GIT_OID_SHA1);
|
||||
|
||||
src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT;
|
||||
num_rewrites--;
|
||||
|
@ -130,11 +130,11 @@ static int append_header(
|
||||
const git_signature *author,
|
||||
git_email_create_options *opts)
|
||||
{
|
||||
char id[GIT_OID_HEXSZ];
|
||||
char id[GIT_OID_SHA1_HEXSIZE];
|
||||
int error;
|
||||
|
||||
if ((error = git_oid_fmt(id, commit_id)) < 0 ||
|
||||
(error = git_str_printf(out, "From %.*s %s\n", GIT_OID_HEXSZ, id, EMAIL_TIMESTAMP)) < 0 ||
|
||||
(error = git_str_printf(out, "From %.*s %s\n", GIT_OID_SHA1_HEXSIZE, id, EMAIL_TIMESTAMP)) < 0 ||
|
||||
(error = git_str_printf(out, "From: %s <%s>\n", author->name, author->email)) < 0 ||
|
||||
(error = append_date(out, &author->when)) < 0 ||
|
||||
(error = append_subject(out, patch_idx, patch_count, summary, opts)) < 0)
|
||||
|
13
src/libgit2/experimental.h.in
Normal file
13
src/libgit2/experimental.h.in
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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_experimental_h__
|
||||
#define INCLUDE_experimental_h__
|
||||
|
||||
#cmakedefine GIT_EXPERIMENTAL_SHA256 1
|
||||
|
||||
#endif
|
@ -13,6 +13,7 @@
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/remote.h"
|
||||
|
||||
#include "oid.h"
|
||||
#include "remote.h"
|
||||
#include "refspec.h"
|
||||
#include "pack.h"
|
||||
@ -75,7 +76,7 @@ static int maybe_want_oid(git_remote *remote, git_refspec *spec)
|
||||
oid_head = git__calloc(1, sizeof(git_remote_head));
|
||||
GIT_ERROR_CHECK_ALLOC(oid_head);
|
||||
|
||||
git_oid_fromstr(&oid_head->oid, spec->src);
|
||||
git_oid__fromstr(&oid_head->oid, spec->src, GIT_OID_SHA1);
|
||||
|
||||
if (spec->dst) {
|
||||
oid_head->name = git__strdup(spec->dst);
|
||||
@ -94,7 +95,6 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
|
||||
git_remote_head **heads;
|
||||
git_refspec tagspec, head, *spec;
|
||||
int error = 0;
|
||||
git_odb *odb;
|
||||
size_t i, heads_len;
|
||||
unsigned int remote_caps;
|
||||
unsigned int oid_mask = GIT_REMOTE_CAPABILITY_TIP_OID |
|
||||
@ -125,9 +125,6 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((error = git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote)) < 0 ||
|
||||
(error = git_remote_capabilities(&remote_caps, remote)) < 0)
|
||||
goto cleanup;
|
||||
@ -140,7 +137,7 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
|
||||
|
||||
/* Handle explicitly specified OID specs */
|
||||
git_vector_foreach(&remote->active_refspecs, i, spec) {
|
||||
if (!git_oid__is_hexstr(spec->src))
|
||||
if (!git_oid__is_hexstr(spec->src, GIT_OID_SHA1))
|
||||
continue;
|
||||
|
||||
if (!(remote_caps & oid_mask)) {
|
||||
|
@ -105,7 +105,7 @@ static int fetchhead_ref_write(
|
||||
git_filebuf *file,
|
||||
git_fetchhead_ref *fetchhead_ref)
|
||||
{
|
||||
char oid[GIT_OID_HEXSZ + 1];
|
||||
char oid[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
const char *type, *name;
|
||||
int head = 0;
|
||||
|
||||
@ -113,7 +113,7 @@ static int fetchhead_ref_write(
|
||||
GIT_ASSERT_ARG(fetchhead_ref);
|
||||
|
||||
git_oid_fmt(oid, &fetchhead_ref->oid);
|
||||
oid[GIT_OID_HEXSZ] = '\0';
|
||||
oid[GIT_OID_SHA1_HEXSIZE] = '\0';
|
||||
|
||||
if (git__prefixcmp(fetchhead_ref->ref_name, GIT_REFS_HEADS_DIR) == 0) {
|
||||
type = "branch ";
|
||||
@ -196,13 +196,13 @@ static int fetchhead_ref_parse(
|
||||
*is_merge = 1;
|
||||
}
|
||||
|
||||
if (strlen(oid_str) != GIT_OID_HEXSZ) {
|
||||
if (strlen(oid_str) != GIT_OID_SHA1_HEXSIZE) {
|
||||
git_error_set(GIT_ERROR_FETCHHEAD,
|
||||
"invalid object ID in FETCH_HEAD line %"PRIuZ, line_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_oid_fromstr(oid, oid_str) < 0) {
|
||||
if (git_oid__fromstr(oid, oid_str, GIT_OID_SHA1) < 0) {
|
||||
const git_error *oid_err = git_error_last();
|
||||
const char *err_msg = oid_err ? oid_err->message : "invalid object ID";
|
||||
|
||||
|
@ -42,7 +42,7 @@ static int ident_find_id(
|
||||
static int ident_insert_id(
|
||||
git_str *to, const git_str *from, const git_filter_source *src)
|
||||
{
|
||||
char oid[GIT_OID_HEXSZ+1];
|
||||
char oid[GIT_OID_SHA1_HEXSIZE+1];
|
||||
const char *id_start, *id_end, *from_end = from->ptr + from->size;
|
||||
size_t need_size;
|
||||
|
||||
@ -57,7 +57,7 @@ static int ident_insert_id(
|
||||
return GIT_PASSTHROUGH;
|
||||
|
||||
need_size = (size_t)(id_start - from->ptr) +
|
||||
5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
|
||||
5 /* "$Id: " */ + GIT_OID_SHA1_HEXSIZE + 2 /* " $" */ +
|
||||
(size_t)(from_end - id_end);
|
||||
|
||||
if (git_str_grow(to, need_size) < 0)
|
||||
@ -65,7 +65,7 @@ static int ident_insert_id(
|
||||
|
||||
git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
|
||||
git_str_put(to, "$Id: ", 5);
|
||||
git_str_put(to, oid, GIT_OID_HEXSZ);
|
||||
git_str_put(to, oid, GIT_OID_SHA1_HEXSIZE);
|
||||
git_str_put(to, " $", 2);
|
||||
git_str_put(to, id_end, (size_t)(from_end - id_end));
|
||||
|
||||
|
@ -74,7 +74,7 @@ struct entry_short {
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t file_size;
|
||||
unsigned char oid[GIT_OID_RAWSZ];
|
||||
unsigned char oid[GIT_OID_SHA1_SIZE];
|
||||
uint16_t flags;
|
||||
char path[1]; /* arbitrary length */
|
||||
};
|
||||
@ -88,7 +88,7 @@ struct entry_long {
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
uint32_t file_size;
|
||||
unsigned char oid[GIT_OID_RAWSZ];
|
||||
unsigned char oid[GIT_OID_SHA1_SIZE];
|
||||
uint16_t flags;
|
||||
uint16_t flags_extended;
|
||||
char path[1]; /* arbitrary length */
|
||||
@ -2354,14 +2354,16 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!lost->mode[i])
|
||||
continue;
|
||||
if (size < 20) {
|
||||
if (size < GIT_OID_SHA1_SIZE) {
|
||||
index_entry_reuc_free(lost);
|
||||
return index_error_invalid("reading reuc entry oid");
|
||||
}
|
||||
|
||||
git_oid_fromraw(&lost->oid[i], (const unsigned char *) buffer);
|
||||
size -= 20;
|
||||
buffer += 20;
|
||||
if (git_oid__fromraw(&lost->oid[i], (const unsigned char *) buffer, GIT_OID_SHA1) < 0)
|
||||
return -1;
|
||||
|
||||
size -= GIT_OID_SHA1_SIZE;
|
||||
buffer += GIT_OID_SHA1_SIZE;
|
||||
}
|
||||
|
||||
/* entry was read successfully - insert into reuc vector */
|
||||
@ -2482,7 +2484,7 @@ static int read_entry(
|
||||
entry.file_size = ntohl(source.file_size);
|
||||
entry.flags = ntohs(source.flags);
|
||||
|
||||
if (git_oid_fromraw(&entry.id, source.oid) < 0)
|
||||
if (git_oid__fromraw(&entry.id, source.oid, GIT_OID_SHA1) < 0)
|
||||
return -1;
|
||||
|
||||
if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) {
|
||||
@ -2805,7 +2807,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
|
||||
ondisk.uid = htonl(entry->uid);
|
||||
ondisk.gid = htonl(entry->gid);
|
||||
ondisk.file_size = htonl((uint32_t)entry->file_size);
|
||||
git_oid_raw_cpy(ondisk.oid, entry->id.id);
|
||||
git_oid_raw_cpy(ondisk.oid, entry->id.id, GIT_OID_SHA1_SIZE);
|
||||
ondisk.flags = htons(entry->flags);
|
||||
|
||||
if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
|
||||
@ -2968,7 +2970,7 @@ static int create_reuc_extension_data(git_str *reuc_buf, git_index_reuc_entry *r
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_RAWSZ)) < 0)
|
||||
if (reuc->mode[i] && (error = git_str_put(reuc_buf, (char *)&reuc->oid[i].id, GIT_OID_SHA1_SIZE)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -3395,7 +3397,6 @@ int git_index_add_all(
|
||||
{
|
||||
int error;
|
||||
git_repository *repo;
|
||||
git_iterator *wditer = NULL;
|
||||
git_pathspec ps;
|
||||
bool no_fnmatch = (flags & GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH) != 0;
|
||||
|
||||
@ -3421,7 +3422,6 @@ int git_index_add_all(
|
||||
git_error_set_after_callback(error);
|
||||
|
||||
cleanup:
|
||||
git_iterator_free(wditer);
|
||||
git_pathspec__clear(&ps);
|
||||
|
||||
return error;
|
||||
@ -3509,7 +3509,8 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
|
||||
GIT_DIFF_RECURSE_UNTRACKED_DIRS;
|
||||
|
||||
if (flags == GIT_INDEX_ADD_FORCE)
|
||||
opts.flags |= GIT_DIFF_INCLUDE_IGNORED;
|
||||
opts.flags |= GIT_DIFF_INCLUDE_IGNORED |
|
||||
GIT_DIFF_RECURSE_IGNORED_DIRS;
|
||||
}
|
||||
|
||||
if ((error = git_diff_index_to_workdir(&diff, repo, index, &opts)) < 0)
|
||||
|
@ -42,6 +42,7 @@ struct git_indexer {
|
||||
have_delta :1,
|
||||
do_fsync :1,
|
||||
do_verify :1;
|
||||
git_oid_t oid_type;
|
||||
struct git_pack_header hdr;
|
||||
struct git_pack_file *pack;
|
||||
unsigned int mode;
|
||||
@ -55,8 +56,8 @@ struct git_indexer {
|
||||
git_vector deltas;
|
||||
unsigned int fanout[256];
|
||||
git_hash_ctx hash_ctx;
|
||||
unsigned char checksum[GIT_HASH_SHA1_SIZE];
|
||||
char name[(GIT_HASH_SHA1_SIZE * 2) + 1];
|
||||
unsigned char checksum[GIT_HASH_MAX_SIZE];
|
||||
char name[(GIT_HASH_MAX_SIZE * 2) + 1];
|
||||
git_indexer_progress_cb progress_cb;
|
||||
void *progress_payload;
|
||||
char objbuf[8*1024];
|
||||
@ -68,7 +69,7 @@ struct git_indexer {
|
||||
git_odb *odb;
|
||||
|
||||
/* Fields for calculating the packfile trailer (hash of everything before it) */
|
||||
char inbuf[GIT_OID_RAWSZ];
|
||||
char inbuf[GIT_HASH_MAX_SIZE];
|
||||
size_t inbuf_len;
|
||||
git_hash_ctx trailer;
|
||||
};
|
||||
@ -136,17 +137,33 @@ int git_indexer_init_options(git_indexer_options *opts, unsigned int version)
|
||||
}
|
||||
#endif
|
||||
|
||||
int git_indexer_new(
|
||||
git_indexer **out,
|
||||
const char *prefix,
|
||||
unsigned int mode,
|
||||
git_odb *odb,
|
||||
git_indexer_options *in_opts)
|
||||
GIT_INLINE(git_hash_algorithm_t) indexer_hash_algorithm(git_indexer *idx)
|
||||
{
|
||||
switch (idx->oid_type) {
|
||||
case GIT_OID_SHA1:
|
||||
return GIT_HASH_ALGORITHM_SHA1;
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
case GIT_OID_SHA256:
|
||||
return GIT_HASH_ALGORITHM_SHA256;
|
||||
#endif
|
||||
}
|
||||
|
||||
return GIT_HASH_ALGORITHM_NONE;
|
||||
}
|
||||
|
||||
static int indexer_new(
|
||||
git_indexer **out,
|
||||
const char *prefix,
|
||||
git_oid_t oid_type,
|
||||
unsigned int mode,
|
||||
git_odb *odb,
|
||||
git_indexer_options *in_opts)
|
||||
{
|
||||
git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
|
||||
git_indexer *idx;
|
||||
git_str path = GIT_STR_INIT, tmp_path = GIT_STR_INIT;
|
||||
static const char suff[] = "/pack";
|
||||
git_hash_algorithm_t checksum_type;
|
||||
int error, fd = -1;
|
||||
|
||||
if (in_opts)
|
||||
@ -154,14 +171,17 @@ int git_indexer_new(
|
||||
|
||||
idx = git__calloc(1, sizeof(git_indexer));
|
||||
GIT_ERROR_CHECK_ALLOC(idx);
|
||||
idx->oid_type = oid_type;
|
||||
idx->odb = odb;
|
||||
idx->progress_cb = opts.progress_cb;
|
||||
idx->progress_payload = opts.progress_cb_payload;
|
||||
idx->mode = mode ? mode : GIT_PACK_FILE_MODE;
|
||||
git_str_init(&idx->entry_data, 0);
|
||||
|
||||
if ((error = git_hash_ctx_init(&idx->hash_ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
|
||||
(error = git_hash_ctx_init(&idx->trailer, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
|
||||
checksum_type = indexer_hash_algorithm(idx);
|
||||
|
||||
if ((error = git_hash_ctx_init(&idx->hash_ctx, checksum_type)) < 0 ||
|
||||
(error = git_hash_ctx_init(&idx->trailer, checksum_type)) < 0 ||
|
||||
(error = git_oidmap_new(&idx->expected_oids)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -179,7 +199,7 @@ int git_indexer_new(
|
||||
if (fd < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = git_packfile_alloc(&idx->pack, git_str_cstr(&tmp_path));
|
||||
error = git_packfile_alloc(&idx->pack, git_str_cstr(&tmp_path), oid_type);
|
||||
git_str_dispose(&tmp_path);
|
||||
|
||||
if (error < 0)
|
||||
@ -208,6 +228,33 @@ cleanup:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_indexer_new(
|
||||
git_indexer **out,
|
||||
const char *prefix,
|
||||
git_oid_t oid_type,
|
||||
git_indexer_options *opts)
|
||||
{
|
||||
return indexer_new(
|
||||
out,
|
||||
prefix,
|
||||
oid_type,
|
||||
opts ? opts->mode : 0,
|
||||
opts ? opts->odb : NULL,
|
||||
opts);
|
||||
}
|
||||
#else
|
||||
int git_indexer_new(
|
||||
git_indexer **out,
|
||||
const char *prefix,
|
||||
unsigned int mode,
|
||||
git_odb *odb,
|
||||
git_indexer_options *opts)
|
||||
{
|
||||
return indexer_new(out, prefix, GIT_OID_SHA1, mode, odb, opts);
|
||||
}
|
||||
#endif
|
||||
|
||||
void git_indexer__set_fsync(git_indexer *idx, int do_fsync)
|
||||
{
|
||||
idx->do_fsync = !!do_fsync;
|
||||
@ -272,7 +319,7 @@ static int advance_delta_offset(git_indexer *idx, git_object_t type)
|
||||
GIT_ASSERT_ARG(type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA);
|
||||
|
||||
if (type == GIT_OBJECT_REF_DELTA) {
|
||||
idx->off += GIT_OID_RAWSZ;
|
||||
idx->off += git_oid_size(idx->oid_type);
|
||||
} else {
|
||||
off64_t base_off;
|
||||
int error = get_delta_base(&base_off, idx->pack, &w, &idx->off, type, idx->entry_start);
|
||||
@ -356,7 +403,7 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
|
||||
obj->type != GIT_OBJECT_TAG)
|
||||
return 0;
|
||||
|
||||
if (git_object__from_raw(&object, obj->data, obj->len, obj->type) < 0) {
|
||||
if (git_object__from_raw(&object, obj->data, obj->len, obj->type, idx->oid_type) < 0) {
|
||||
/*
|
||||
* parse_raw returns EINVALID on invalid data; downgrade
|
||||
* that to a normal -1 error code.
|
||||
@ -444,6 +491,11 @@ static int store_object(git_indexer *idx)
|
||||
git__free(pentry);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
oid.type = idx->oid_type;
|
||||
#endif
|
||||
|
||||
entry_size = idx->off - entry_start;
|
||||
if (entry_start > UINT31_MAX) {
|
||||
entry->offset = UINT32_MAX;
|
||||
@ -463,16 +515,16 @@ static int store_object(git_indexer *idx)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
git_oid_cpy(&pentry->sha1, &oid);
|
||||
git_oid_cpy(&pentry->id, &oid);
|
||||
pentry->offset = entry_start;
|
||||
|
||||
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));
|
||||
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->id)) {
|
||||
git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->id));
|
||||
git__free(pentry);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ((error = git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry)) < 0) {
|
||||
if ((error = git_oidmap_set(idx->pack->idx_cache, &pentry->id, pentry)) < 0) {
|
||||
git__free(pentry);
|
||||
git_error_set_oom();
|
||||
goto on_error;
|
||||
@ -517,8 +569,8 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent
|
||||
|
||||
pentry->offset = entry_start;
|
||||
|
||||
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->sha1) ||
|
||||
git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry) < 0) {
|
||||
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->id) ||
|
||||
git_oidmap_set(idx->pack->idx_cache, &pentry->id, pentry) < 0) {
|
||||
git_error_set(GIT_ERROR_INDEXER, "cannot insert object into pack");
|
||||
return -1;
|
||||
}
|
||||
@ -544,7 +596,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, off64_t entry_start)
|
||||
entry = git__calloc(1, sizeof(*entry));
|
||||
GIT_ERROR_CHECK_ALLOC(entry);
|
||||
|
||||
if (git_odb__hashobj(&oid, obj) < 0) {
|
||||
if (git_odb__hashobj(&oid, obj, idx->oid_type) < 0) {
|
||||
git_error_set(GIT_ERROR_INDEXER, "failed to hash object");
|
||||
goto on_error;
|
||||
}
|
||||
@ -552,7 +604,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, off64_t entry_start)
|
||||
pentry = git__calloc(1, sizeof(struct git_pack_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(pentry);
|
||||
|
||||
git_oid_cpy(&pentry->sha1, &oid);
|
||||
git_oid_cpy(&pentry->id, &oid);
|
||||
git_oid_cpy(&entry->oid, &oid);
|
||||
entry->crc = crc32(0L, Z_NULL, 0);
|
||||
|
||||
@ -578,34 +630,38 @@ static int do_progress_callback(git_indexer *idx, git_indexer_progress *stats)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Hash everything but the last 20B of input */
|
||||
/* Hash everything but the checksum trailer */
|
||||
static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
|
||||
{
|
||||
size_t to_expell, to_keep;
|
||||
size_t oid_size = git_oid_size(idx->oid_type);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
/* Easy case, dump the buffer and the data minus the last 20 bytes */
|
||||
if (size >= GIT_OID_RAWSZ) {
|
||||
/*
|
||||
* Easy case, dump the buffer and the data minus the trailing
|
||||
* checksum (SHA1 or SHA256).
|
||||
*/
|
||||
if (size >= oid_size) {
|
||||
git_hash_update(&idx->trailer, idx->inbuf, idx->inbuf_len);
|
||||
git_hash_update(&idx->trailer, data, size - GIT_OID_RAWSZ);
|
||||
git_hash_update(&idx->trailer, data, size - oid_size);
|
||||
|
||||
data += size - GIT_OID_RAWSZ;
|
||||
memcpy(idx->inbuf, data, GIT_OID_RAWSZ);
|
||||
idx->inbuf_len = GIT_OID_RAWSZ;
|
||||
data += size - oid_size;
|
||||
memcpy(idx->inbuf, data, oid_size);
|
||||
idx->inbuf_len = oid_size;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can just append */
|
||||
if (idx->inbuf_len + size <= GIT_OID_RAWSZ) {
|
||||
if (idx->inbuf_len + size <= oid_size) {
|
||||
memcpy(idx->inbuf + idx->inbuf_len, data, size);
|
||||
idx->inbuf_len += size;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We need to partially drain the buffer and then append */
|
||||
to_keep = GIT_OID_RAWSZ - size;
|
||||
to_keep = oid_size - size;
|
||||
to_expell = idx->inbuf_len - to_keep;
|
||||
|
||||
git_hash_update(&idx->trailer, idx->inbuf, to_expell);
|
||||
@ -724,12 +780,14 @@ static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
|
||||
{
|
||||
git_packfile_stream *stream = &idx->stream;
|
||||
off64_t entry_start = idx->off;
|
||||
size_t entry_size;
|
||||
size_t oid_size, entry_size;
|
||||
git_object_t type;
|
||||
git_mwindow *w = NULL;
|
||||
int error;
|
||||
|
||||
if (idx->pack->mwf.size <= idx->off + 20)
|
||||
oid_size = git_oid_size(idx->oid_type);
|
||||
|
||||
if (idx->pack->mwf.size <= idx->off + (long long)oid_size)
|
||||
return GIT_EBUFS;
|
||||
|
||||
if (!idx->have_stream) {
|
||||
@ -900,7 +958,7 @@ static int index_path(git_str *path, git_indexer *idx, const char *suffix)
|
||||
slash--;
|
||||
|
||||
if (git_str_grow(path, slash + 1 + strlen(prefix) +
|
||||
GIT_OID_HEXSZ + strlen(suffix) + 1) < 0)
|
||||
git_oid_hexsize(idx->oid_type) + strlen(suffix) + 1) < 0)
|
||||
return -1;
|
||||
|
||||
git_str_truncate(path, slash);
|
||||
@ -917,7 +975,7 @@ static int index_path(git_str *path, git_indexer *idx, const char *suffix)
|
||||
*/
|
||||
static int seek_back_trailer(git_indexer *idx)
|
||||
{
|
||||
idx->pack->mwf.size -= GIT_OID_RAWSZ;
|
||||
idx->pack->mwf.size -= git_oid_size(idx->oid_type);
|
||||
return git_mwindow_free_all(&idx->pack->mwf);
|
||||
}
|
||||
|
||||
@ -926,15 +984,17 @@ static int inject_object(git_indexer *idx, git_oid *id)
|
||||
git_odb_object *obj = NULL;
|
||||
struct entry *entry = NULL;
|
||||
struct git_pack_entry *pentry = NULL;
|
||||
unsigned char empty_checksum[GIT_HASH_SHA1_SIZE] = {0};
|
||||
unsigned char empty_checksum[GIT_HASH_MAX_SIZE] = {0};
|
||||
unsigned char hdr[64];
|
||||
git_str buf = GIT_STR_INIT;
|
||||
off64_t entry_start;
|
||||
const void *data;
|
||||
size_t len, hdr_len;
|
||||
size_t checksum_size = GIT_HASH_SHA1_SIZE;
|
||||
size_t checksum_size;
|
||||
int error;
|
||||
|
||||
checksum_size = git_hash_size(indexer_hash_algorithm(idx));
|
||||
|
||||
if ((error = seek_back_trailer(idx)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -977,12 +1037,12 @@ static int inject_object(git_indexer *idx, git_oid *id)
|
||||
if ((error = append_to_pack(idx, empty_checksum, checksum_size)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
idx->pack->mwf.size += GIT_OID_RAWSZ;
|
||||
idx->pack->mwf.size += git_oid_size(idx->oid_type);
|
||||
|
||||
pentry = git__calloc(1, sizeof(struct git_pack_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(pentry);
|
||||
|
||||
git_oid_cpy(&pentry->sha1, id);
|
||||
git_oid_cpy(&pentry->id, id);
|
||||
git_oid_cpy(&entry->oid, id);
|
||||
idx->off = entry_start + hdr_len + len;
|
||||
|
||||
@ -1040,13 +1100,13 @@ static int fix_thin_pack(git_indexer *idx, git_indexer_progress *stats)
|
||||
}
|
||||
|
||||
/* curpos now points to the base information, which is an OID */
|
||||
base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left);
|
||||
base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, git_oid_size(idx->oid_type), &left);
|
||||
if (base_info == NULL) {
|
||||
git_error_set(GIT_ERROR_INDEXER, "failed to map delta information");
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_oid_fromraw(&base, base_info);
|
||||
git_oid__fromraw(&base, base_info, idx->oid_type);
|
||||
git_mwindow_close(&w);
|
||||
|
||||
if (has_entry(idx, &base))
|
||||
@ -1168,10 +1228,10 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
|
||||
struct git_pack_idx_header hdr;
|
||||
git_str filename = GIT_STR_INIT;
|
||||
struct entry *entry;
|
||||
unsigned char checksum[GIT_HASH_SHA1_SIZE];
|
||||
unsigned char checksum[GIT_HASH_MAX_SIZE];
|
||||
git_filebuf index_file = {0};
|
||||
void *packfile_trailer;
|
||||
size_t checksum_size = GIT_HASH_SHA1_SIZE;
|
||||
size_t checksum_size;
|
||||
bool mismatch;
|
||||
|
||||
if (!idx->parsed_header) {
|
||||
@ -1179,6 +1239,9 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
|
||||
return -1;
|
||||
}
|
||||
|
||||
checksum_size = git_hash_size(indexer_hash_algorithm(idx));
|
||||
GIT_ASSERT(checksum_size);
|
||||
|
||||
/* Test for this before resolve_deltas(), as it plays with idx->off */
|
||||
if (idx->off + (ssize_t)checksum_size < idx->pack->mwf.size) {
|
||||
git_error_set(GIT_ERROR_INDEXER, "unexpected data at the end of the pack");
|
||||
@ -1269,7 +1332,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
|
||||
|
||||
/* Write out the object names (SHA-1 hashes) */
|
||||
git_vector_foreach(&idx->objects, i, entry) {
|
||||
git_filebuf_write(&index_file, &entry->oid.id, GIT_OID_RAWSZ);
|
||||
git_filebuf_write(&index_file, &entry->oid.id, git_oid_size(idx->oid_type));
|
||||
}
|
||||
|
||||
/* Write out the CRC32 values */
|
||||
|
@ -1271,7 +1271,7 @@ static int filesystem_iterator_entry_hash(
|
||||
int error;
|
||||
|
||||
if (S_ISDIR(entry->st.st_mode)) {
|
||||
memset(&entry->id, 0, GIT_OID_RAWSZ);
|
||||
memset(&entry->id, 0, GIT_OID_SHA1_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1281,7 +1281,7 @@ static int filesystem_iterator_entry_hash(
|
||||
|
||||
if (!(error = git_str_joinpath(&fullpath, iter->root, entry->path)) &&
|
||||
!(error = git_path_validate_str_length(iter->base.repo, &fullpath)))
|
||||
error = git_odb_hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB);
|
||||
error = git_odb__hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB, GIT_OID_SHA1);
|
||||
|
||||
git_str_dispose(&fullpath);
|
||||
return error;
|
||||
@ -1529,6 +1529,8 @@ static void filesystem_iterator_set_current(
|
||||
|
||||
if (iter->base.flags & GIT_ITERATOR_INCLUDE_HASH)
|
||||
git_oid_cpy(&iter->entry.id, &entry->id);
|
||||
else
|
||||
git_oid_clear(&iter->entry.id, GIT_OID_SHA1);
|
||||
|
||||
iter->entry.path = entry->path;
|
||||
|
||||
|
@ -414,6 +414,25 @@ int git_libgit2_opts(int key, ...)
|
||||
git_repository__validate_ownership = (va_arg(ap, int) != 0);
|
||||
break;
|
||||
|
||||
case GIT_OPT_GET_HOMEDIR:
|
||||
{
|
||||
git_buf *out = va_arg(ap, git_buf *);
|
||||
git_str str = GIT_STR_INIT;
|
||||
const git_str *tmp;
|
||||
|
||||
if ((error = git_buf_tostr(&str, out)) < 0 ||
|
||||
(error = git_sysdir_get(&tmp, GIT_SYSDIR_HOME)) < 0 ||
|
||||
(error = git_str_put(&str, tmp->ptr, tmp->size)) < 0)
|
||||
break;
|
||||
|
||||
error = git_buf_fromstr(out, &str);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIT_OPT_SET_HOMEDIR:
|
||||
error = git_sysdir_set(GIT_SYSDIR_HOME, va_arg(ap, const char *));
|
||||
break;
|
||||
|
||||
default:
|
||||
git_error_set(GIT_ERROR_INVALID, "invalid option key");
|
||||
error = -1;
|
||||
|
@ -611,13 +611,13 @@ int git_repository_mergehead_foreach(
|
||||
buffer = merge_head_file.ptr;
|
||||
|
||||
while ((line = git__strsep(&buffer, "\n")) != NULL) {
|
||||
if (strlen(line) != GIT_OID_HEXSZ) {
|
||||
if (strlen(line) != GIT_OID_SHA1_HEXSIZE) {
|
||||
git_error_set(GIT_ERROR_INVALID, "unable to parse OID - invalid length");
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((error = git_oid_fromstr(&oid, line)) < 0)
|
||||
if ((error = git_oid__fromstr(&oid, line, GIT_OID_SHA1)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((error = cb(&oid, payload)) != 0) {
|
||||
@ -1061,7 +1061,7 @@ static int index_entry_similarity_calc(
|
||||
const git_merge_options *opts)
|
||||
{
|
||||
git_blob *blob;
|
||||
git_diff_file diff_file = {{{0}}};
|
||||
git_diff_file diff_file = { GIT_OID_SHA1_ZERO };
|
||||
git_object_size_t blobsize;
|
||||
int error;
|
||||
|
||||
|
@ -115,19 +115,19 @@ static int midx_parse_oid_lookup(
|
||||
struct git_midx_chunk *chunk_oid_lookup)
|
||||
{
|
||||
uint32_t i;
|
||||
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
|
||||
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_SHA1_SIZE] = {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 * GIT_OID_RAWSZ)
|
||||
if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_SHA1_SIZE)
|
||||
return midx_error("OID Lookup chunk has wrong length");
|
||||
|
||||
idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
|
||||
prev_oid = zero_oid;
|
||||
for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_RAWSZ) {
|
||||
if (git_oid_raw_cmp(prev_oid, oid) >= 0)
|
||||
for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_SHA1_SIZE) {
|
||||
if (git_oid_raw_cmp(prev_oid, oid, GIT_OID_SHA1_SIZE) >= 0)
|
||||
return midx_error("OID Lookup index is non-monotonic");
|
||||
prev_oid = oid;
|
||||
}
|
||||
@ -188,7 +188,7 @@ int git_midx_parse(
|
||||
|
||||
GIT_ASSERT_ARG(idx);
|
||||
|
||||
if (size < sizeof(struct git_midx_header) + GIT_OID_RAWSZ)
|
||||
if (size < sizeof(struct git_midx_header) + GIT_OID_SHA1_SIZE)
|
||||
return midx_error("multi-pack index is too short");
|
||||
|
||||
hdr = ((struct git_midx_header *)data);
|
||||
@ -365,7 +365,7 @@ bool git_midx_needs_refresh(
|
||||
}
|
||||
|
||||
checksum_size = GIT_HASH_SHA1_SIZE;
|
||||
bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - GIT_OID_RAWSZ);
|
||||
bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - GIT_OID_SHA1_SIZE);
|
||||
p_close(fd);
|
||||
|
||||
if (bytes_read != (ssize_t)checksum_size)
|
||||
@ -392,27 +392,27 @@ int git_midx_entry_find(
|
||||
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, GIT_OID_RAWSZ, lo, hi, short_oid->id);
|
||||
pos = git_pack__lookup_id(idx->oid_lookup, GIT_OID_SHA1_SIZE, lo, hi, short_oid->id, GIT_OID_SHA1);
|
||||
|
||||
if (pos >= 0) {
|
||||
/* An object matching exactly the oid was found */
|
||||
found = 1;
|
||||
current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
|
||||
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
|
||||
} else {
|
||||
/* No object was found */
|
||||
/* pos refers to the object with the "closest" oid to short_oid */
|
||||
pos = -1 - pos;
|
||||
if (pos < (int)idx->num_objects) {
|
||||
current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
|
||||
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE);
|
||||
|
||||
if (!git_oid_raw_ncmp(short_oid->id, current, len))
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) {
|
||||
if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int)idx->num_objects) {
|
||||
/* Check for ambiguousity */
|
||||
const unsigned char *next = current + GIT_OID_RAWSZ;
|
||||
const unsigned char *next = current + GIT_OID_SHA1_SIZE;
|
||||
|
||||
if (!git_oid_raw_ncmp(short_oid->id, next, len))
|
||||
found = 2;
|
||||
@ -443,7 +443,7 @@ int git_midx_entry_find(
|
||||
return midx_error("invalid index into the packfile names table");
|
||||
e->pack_index = pack_index;
|
||||
e->offset = offset;
|
||||
git_oid_fromraw(&e->sha1, current);
|
||||
git_oid__fromraw(&e->sha1, current, GIT_OID_SHA1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -459,7 +459,7 @@ int git_midx_foreach_entry(
|
||||
GIT_ASSERT_ARG(idx);
|
||||
|
||||
for (i = 0; i < idx->num_objects; ++i) {
|
||||
if ((error = git_oid_fromraw(&oid, &idx->oid_lookup[i * GIT_OID_RAWSZ])) < 0)
|
||||
if ((error = git_oid__fromraw(&oid, &idx->oid_lookup[i * GIT_OID_SHA1_SIZE], GIT_OID_SHA1)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = cb(&oid, data)) != 0)
|
||||
@ -549,7 +549,8 @@ int git_midx_writer_add(
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = git_mwindow_get_pack(&p, git_str_cstr(&idx_path_buf));
|
||||
/* TODO: SHA256 */
|
||||
error = git_mwindow_get_pack(&p, git_str_cstr(&idx_path_buf), 0);
|
||||
git_str_dispose(&idx_path_buf);
|
||||
if (error < 0)
|
||||
return error;
|
||||
@ -748,7 +749,7 @@ static int midx_write(
|
||||
|
||||
/* Fill the OID Lookup table. */
|
||||
git_vector_foreach (&object_entries, i, entry) {
|
||||
error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_RAWSZ);
|
||||
error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_SHA1_SIZE);
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -61,7 +61,10 @@ int git_mwindow_global_init(void)
|
||||
return git_runtime_shutdown_register(git_mwindow_global_shutdown);
|
||||
}
|
||||
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
|
||||
int git_mwindow_get_pack(
|
||||
struct git_pack_file **out,
|
||||
const char *path,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
struct git_pack_file *pack;
|
||||
char *packname;
|
||||
@ -86,7 +89,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
|
||||
}
|
||||
|
||||
/* If we didn't find it, we need to create it */
|
||||
if ((error = git_packfile_alloc(&pack, path)) < 0) {
|
||||
if ((error = git_packfile_alloc(&pack, path, oid_type)) < 0) {
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
return error;
|
||||
}
|
||||
|
@ -48,7 +48,10 @@ void git_mwindow_close(git_mwindow **w_cursor);
|
||||
extern int git_mwindow_global_init(void);
|
||||
|
||||
struct git_pack_file; /* just declaration to avoid cyclical includes */
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path);
|
||||
int git_mwindow_get_pack(
|
||||
struct git_pack_file **out,
|
||||
const char *path,
|
||||
git_oid_t oid_type);
|
||||
int git_mwindow_put_pack(struct git_pack_file *pack);
|
||||
|
||||
#endif
|
||||
|
@ -460,7 +460,7 @@ int git_note_commit_read(
|
||||
{
|
||||
int error;
|
||||
git_tree *tree = NULL;
|
||||
char target[GIT_OID_HEXSZ + 1];
|
||||
char target[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(target, sizeof(target), oid);
|
||||
|
||||
@ -507,7 +507,7 @@ int git_note_commit_create(
|
||||
{
|
||||
int error;
|
||||
git_tree *tree = NULL;
|
||||
char target[GIT_OID_HEXSZ + 1];
|
||||
char target[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(target, sizeof(target), oid);
|
||||
|
||||
@ -578,7 +578,7 @@ int git_note_commit_remove(
|
||||
{
|
||||
int error;
|
||||
git_tree *tree = NULL;
|
||||
char target[GIT_OID_HEXSZ + 1];
|
||||
char target[GIT_OID_SHA1_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(target, sizeof(target), oid);
|
||||
|
||||
@ -698,12 +698,12 @@ static int process_entry_path(
|
||||
buf.ptr[j] = '\0';
|
||||
buf.size = j;
|
||||
|
||||
if (j != GIT_OID_HEXSZ) {
|
||||
if (j != GIT_OID_SHA1_HEXSIZE) {
|
||||
/* This is not a note entry */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
error = git_oid_fromstr(annotated_object_id, buf.ptr);
|
||||
error = git_oid__fromstr(annotated_object_id, buf.ptr, GIT_OID_SHA1);
|
||||
|
||||
cleanup:
|
||||
git_str_dispose(&buf);
|
||||
|
@ -21,15 +21,14 @@
|
||||
|
||||
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 */
|
||||
size_t size; /* size in bytes of the object structure */
|
||||
|
||||
int (*parse)(void *self, git_odb_object *obj);
|
||||
int (*parse_raw)(void *self, const char *data, size_t size);
|
||||
int (*parse)(void *self, git_odb_object *obj, git_oid_t oid_type);
|
||||
int (*parse_raw)(void *self, const char *data, size_t size, git_oid_t oid_type);
|
||||
void (*free)(void *self);
|
||||
} git_object_def;
|
||||
|
||||
@ -61,7 +60,8 @@ int git_object__from_raw(
|
||||
git_object **object_out,
|
||||
const char *data,
|
||||
size_t size,
|
||||
git_object_t type)
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
git_object_def *def;
|
||||
git_object *object;
|
||||
@ -72,12 +72,15 @@ int git_object__from_raw(
|
||||
*object_out = NULL;
|
||||
|
||||
/* Validate type match */
|
||||
if (type != GIT_OBJECT_BLOB && type != GIT_OBJECT_TREE && type != GIT_OBJECT_COMMIT && type != GIT_OBJECT_TAG) {
|
||||
if (object_type != GIT_OBJECT_BLOB &&
|
||||
object_type != GIT_OBJECT_TREE &&
|
||||
object_type != GIT_OBJECT_COMMIT &&
|
||||
object_type != GIT_OBJECT_TAG) {
|
||||
git_error_set(GIT_ERROR_INVALID, "the requested type is invalid");
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
if ((object_size = git_object__size(type)) == 0) {
|
||||
if ((object_size = git_object__size(object_type)) == 0) {
|
||||
git_error_set(GIT_ERROR_INVALID, "the requested type is invalid");
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
@ -86,15 +89,15 @@ int git_object__from_raw(
|
||||
object = git__calloc(1, object_size);
|
||||
GIT_ERROR_CHECK_ALLOC(object);
|
||||
object->cached.flags = GIT_CACHE_STORE_PARSED;
|
||||
object->cached.type = type;
|
||||
if ((error = git_odb_hash(&object->cached.oid, data, size, type)) < 0)
|
||||
object->cached.type = object_type;
|
||||
if ((error = git_odb__hash(&object->cached.oid, data, size, object_type, oid_type)) < 0)
|
||||
return error;
|
||||
|
||||
/* Parse raw object data */
|
||||
def = &git_objects_table[type];
|
||||
def = &git_objects_table[object_type];
|
||||
GIT_ASSERT(def->free && def->parse_raw);
|
||||
|
||||
if ((error = def->parse_raw(object, data, size)) < 0) {
|
||||
if ((error = def->parse_raw(object, data, size, oid_type)) < 0) {
|
||||
def->free(object);
|
||||
return error;
|
||||
}
|
||||
@ -144,7 +147,7 @@ int git_object__from_odb_object(
|
||||
def = &git_objects_table[odb_obj->cached.type];
|
||||
GIT_ASSERT(def->free && def->parse);
|
||||
|
||||
if ((error = def->parse(object, odb_obj)) < 0) {
|
||||
if ((error = def->parse(object, odb_obj, repo->oid_type)) < 0) {
|
||||
/*
|
||||
* parse returns EINVALID on invalid data; downgrade
|
||||
* that to a normal -1 error code.
|
||||
@ -193,10 +196,10 @@ int git_object_lookup_prefix(
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (len > GIT_OID_HEXSZ)
|
||||
len = GIT_OID_HEXSZ;
|
||||
if (len > GIT_OID_SHA1_HEXSIZE)
|
||||
len = GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
if (len == GIT_OID_HEXSZ) {
|
||||
if (len == GIT_OID_SHA1_HEXSIZE) {
|
||||
git_cached_obj *cached = NULL;
|
||||
|
||||
/* We want to match the full id : we can first look up in the cache,
|
||||
@ -230,11 +233,11 @@ int git_object_lookup_prefix(
|
||||
error = git_odb_read(&odb_obj, odb, id);
|
||||
}
|
||||
} else {
|
||||
git_oid short_oid = {{ 0 }};
|
||||
git_oid short_oid = GIT_OID_SHA1_ZERO;
|
||||
|
||||
git_oid__cpy_prefix(&short_oid, id, len);
|
||||
|
||||
/* If len < GIT_OID_HEXSZ (a strict short oid was given), we have
|
||||
/* If len < GIT_OID_SHA1_HEXSIZE (a strict short oid was given), we have
|
||||
* 2 options :
|
||||
* - We always search in the cache first. If we find that short oid is
|
||||
* ambiguous, we can stop. But in all the other cases, we must then
|
||||
@ -259,7 +262,7 @@ int git_object_lookup_prefix(
|
||||
}
|
||||
|
||||
int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_object_t type) {
|
||||
return git_object_lookup_prefix(object_out, repo, id, GIT_OID_HEXSZ, type);
|
||||
return git_object_lookup_prefix(object_out, repo, id, GIT_OID_SHA1_HEXSIZE, type);
|
||||
}
|
||||
|
||||
void git_object_free(git_object *object)
|
||||
@ -358,12 +361,11 @@ static int dereference_object(git_object **dereferenced, git_object *obj)
|
||||
static int peel_error(int error, const git_oid *oid, git_object_t type)
|
||||
{
|
||||
const char *type_name;
|
||||
char hex_oid[GIT_OID_HEXSZ + 1];
|
||||
char hex_oid[GIT_OID_MAX_HEXSIZE + 1];
|
||||
|
||||
type_name = git_object_type2string(type);
|
||||
|
||||
git_oid_fmt(hex_oid, oid);
|
||||
hex_oid[GIT_OID_HEXSZ] = '\0';
|
||||
git_oid_nfmt(hex_oid, GIT_OID_MAX_HEXSIZE + 1, oid);
|
||||
|
||||
git_error_set(GIT_ERROR_OBJECT, "the git_object of id '%s' can not be "
|
||||
"successfully peeled into a %s (git_object_t=%i).", hex_oid, type_name, type);
|
||||
@ -502,7 +504,7 @@ static int git_object__short_id(git_str *out, const git_object *obj)
|
||||
{
|
||||
git_repository *repo;
|
||||
int len = GIT_ABBREV_DEFAULT, error;
|
||||
git_oid id = {{0}};
|
||||
git_oid id = GIT_OID_SHA1_ZERO;
|
||||
git_odb *odb;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
@ -516,12 +518,16 @@ static int git_object__short_id(git_str *out, const git_object *obj)
|
||||
if ((error = git_repository_odb(&odb, repo)) < 0)
|
||||
return error;
|
||||
|
||||
while (len < GIT_OID_HEXSZ) {
|
||||
while (len < GIT_OID_SHA1_HEXSIZE) {
|
||||
/* set up short oid */
|
||||
memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
|
||||
if (len & 1)
|
||||
id.id[len / 2] &= 0xf0;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
id.type = GIT_OID_SHA1;
|
||||
#endif
|
||||
|
||||
error = git_odb_exists_prefix(NULL, odb, &id, len);
|
||||
if (error != GIT_EAMBIGUOUS)
|
||||
break;
|
||||
@ -573,21 +579,29 @@ int git_object_rawcontent_is_valid(
|
||||
int *valid,
|
||||
const char *buf,
|
||||
size_t len,
|
||||
git_object_t type)
|
||||
git_object_t object_type
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
, git_oid_t oid_type
|
||||
#endif
|
||||
)
|
||||
{
|
||||
git_object *obj = NULL;
|
||||
int error;
|
||||
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid_t oid_type = GIT_OID_SHA1;
|
||||
#endif
|
||||
|
||||
GIT_ASSERT_ARG(valid);
|
||||
GIT_ASSERT_ARG(buf);
|
||||
|
||||
/* Blobs are always valid; don't bother parsing. */
|
||||
if (type == GIT_OBJECT_BLOB) {
|
||||
if (object_type == GIT_OBJECT_BLOB) {
|
||||
*valid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = git_object__from_raw(&obj, buf, len, type);
|
||||
error = git_object__from_raw(&obj, buf, len, object_type, oid_type);
|
||||
git_object_free(obj);
|
||||
|
||||
if (error == 0) {
|
||||
@ -600,3 +614,53 @@ int git_object_rawcontent_is_valid(
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_object__parse_oid_header(
|
||||
git_oid *oid,
|
||||
const char **buffer_out,
|
||||
const char *buffer_end,
|
||||
const char *header,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
const size_t sha_len = git_oid_hexsize(oid_type);
|
||||
const size_t header_len = strlen(header);
|
||||
|
||||
const char *buffer = *buffer_out;
|
||||
|
||||
if (buffer + (header_len + sha_len + 1) > buffer_end)
|
||||
return -1;
|
||||
|
||||
if (memcmp(buffer, header, header_len) != 0)
|
||||
return -1;
|
||||
|
||||
if (buffer[header_len + sha_len] != '\n')
|
||||
return -1;
|
||||
|
||||
if (git_oid__fromstr(oid, buffer + header_len, oid_type) < 0)
|
||||
return -1;
|
||||
|
||||
*buffer_out = buffer + (header_len + sha_len + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_object__write_oid_header(
|
||||
git_str *buf,
|
||||
const char *header,
|
||||
const git_oid *oid)
|
||||
{
|
||||
size_t hex_size = git_oid_hexsize(git_oid_type(oid));
|
||||
char hex_oid[GIT_OID_MAX_HEXSIZE];
|
||||
|
||||
if (!hex_size) {
|
||||
git_error_set(GIT_ERROR_INVALID, "unknown type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_oid_fmt(hex_oid, oid);
|
||||
git_str_puts(buf, header);
|
||||
git_str_put(buf, hex_oid, hex_size);
|
||||
git_str_putc(buf, '\n');
|
||||
|
||||
return git_str_oom(buf) ? -1 : 0;
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ int git_object__from_raw(
|
||||
git_object **object_out,
|
||||
const char *data,
|
||||
size_t size,
|
||||
git_object_t type);
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
|
||||
int git_object__from_odb_object(
|
||||
git_object **object_out,
|
||||
@ -45,9 +46,17 @@ int git_object__resolve_to_type(git_object **obj, git_object_t type);
|
||||
|
||||
git_object_t git_object_stringn2type(const char *str, size_t len);
|
||||
|
||||
int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
|
||||
int git_object__parse_oid_header(
|
||||
git_oid *oid,
|
||||
const char **buffer_out,
|
||||
const char *buffer_end,
|
||||
const char *header,
|
||||
git_oid_t oid_type);
|
||||
|
||||
void git_oid__writebuf(git_str *buf, const char *header, const git_oid *oid);
|
||||
int git_object__write_oid_header(
|
||||
git_str *buf,
|
||||
const char *header,
|
||||
const git_oid *oid);
|
||||
|
||||
bool git_object__is_valid(
|
||||
git_repository *repo, const git_oid *id, git_object_t expected_type);
|
||||
|
@ -105,11 +105,12 @@ int git_odb__format_object_header(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_odb__hashobj(git_oid *id, git_rawobj *obj)
|
||||
int git_odb__hashobj(git_oid *id, git_rawobj *obj, git_oid_t oid_type)
|
||||
{
|
||||
git_str_vec vec[2];
|
||||
char header[64];
|
||||
size_t hdrlen;
|
||||
git_hash_algorithm_t algorithm;
|
||||
int error;
|
||||
|
||||
GIT_ASSERT_ARG(id);
|
||||
@ -120,6 +121,11 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(algorithm = git_oid_algorithm(oid_type))) {
|
||||
git_error_set(GIT_ERROR_INVALID, "unknown oid type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!obj->data && obj->len != 0) {
|
||||
git_error_set(GIT_ERROR_INVALID, "invalid object");
|
||||
return -1;
|
||||
@ -134,7 +140,11 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj)
|
||||
vec[1].data = obj->data;
|
||||
vec[1].len = obj->len;
|
||||
|
||||
return git_hash_vec(id->id, vec, 2, GIT_HASH_ALGORITHM_SHA1);
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
id->type = oid_type;
|
||||
#endif
|
||||
|
||||
return git_hash_vec(id->id, vec, 2, algorithm);
|
||||
}
|
||||
|
||||
|
||||
@ -195,24 +205,35 @@ void git_odb_object_free(git_odb_object *object)
|
||||
git_cached_obj_decref(object);
|
||||
}
|
||||
|
||||
int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
|
||||
int git_odb__hashfd(
|
||||
git_oid *out,
|
||||
git_file fd,
|
||||
size_t size,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
size_t hdr_len;
|
||||
char hdr[64], buffer[GIT_BUFSIZE_FILEIO];
|
||||
git_hash_ctx ctx;
|
||||
git_hash_algorithm_t algorithm;
|
||||
ssize_t read_len = 0;
|
||||
int error = 0;
|
||||
|
||||
if (!git_object_typeisloose(type)) {
|
||||
if (!git_object_typeisloose(object_type)) {
|
||||
git_error_set(GIT_ERROR_INVALID, "invalid object type for hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1)) < 0)
|
||||
if (!(algorithm = git_oid_algorithm(oid_type))) {
|
||||
git_error_set(GIT_ERROR_INVALID, "unknown oid type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = git_hash_ctx_init(&ctx, algorithm)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_odb__format_object_header(&hdr_len, hdr,
|
||||
sizeof(hdr), size, type)) < 0)
|
||||
sizeof(hdr), size, object_type)) < 0)
|
||||
goto done;
|
||||
|
||||
if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0)
|
||||
@ -237,19 +258,28 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
|
||||
|
||||
error = git_hash_final(out->id, &ctx);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = oid_type;
|
||||
#endif
|
||||
|
||||
done:
|
||||
git_hash_ctx_cleanup(&ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_odb__hashfd_filtered(
|
||||
git_oid *out, git_file fd, size_t size, git_object_t type, git_filter_list *fl)
|
||||
git_oid *out,
|
||||
git_file fd,
|
||||
size_t size,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type,
|
||||
git_filter_list *fl)
|
||||
{
|
||||
int error;
|
||||
git_str raw = GIT_STR_INIT;
|
||||
|
||||
if (!fl)
|
||||
return git_odb__hashfd(out, fd, size, type);
|
||||
return git_odb__hashfd(out, fd, size, object_type, oid_type);
|
||||
|
||||
/* size of data is used in header, so we have to read the whole file
|
||||
* into memory to apply filters before beginning to calculate the hash
|
||||
@ -261,7 +291,7 @@ int git_odb__hashfd_filtered(
|
||||
error = git_filter_list__convert_buf(&post, fl, &raw);
|
||||
|
||||
if (!error)
|
||||
error = git_odb_hash(out, post.ptr, post.size, type);
|
||||
error = git_odb__hash(out, post.ptr, post.size, object_type, oid_type);
|
||||
|
||||
git_str_dispose(&post);
|
||||
}
|
||||
@ -269,7 +299,7 @@ int git_odb__hashfd_filtered(
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_odb__hashlink(git_oid *out, const char *path)
|
||||
int git_odb__hashlink(git_oid *out, const char *path, git_oid_t oid_type)
|
||||
{
|
||||
struct stat st;
|
||||
int size;
|
||||
@ -303,20 +333,24 @@ int git_odb__hashlink(git_oid *out, const char *path)
|
||||
GIT_ASSERT(read_len <= size);
|
||||
link_data[read_len] = '\0';
|
||||
|
||||
result = git_odb_hash(out, link_data, read_len, GIT_OBJECT_BLOB);
|
||||
result = git_odb__hash(out, link_data, read_len, GIT_OBJECT_BLOB, oid_type);
|
||||
git__free(link_data);
|
||||
} else {
|
||||
int fd = git_futils_open_ro(path);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
result = git_odb__hashfd(out, fd, size, GIT_OBJECT_BLOB);
|
||||
result = git_odb__hashfd(out, fd, size, GIT_OBJECT_BLOB, oid_type);
|
||||
p_close(fd);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int git_odb_hashfile(git_oid *out, const char *path, git_object_t type)
|
||||
int git_odb__hashfile(
|
||||
git_oid *out,
|
||||
const char *path,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
uint64_t size;
|
||||
int fd, error = 0;
|
||||
@ -333,14 +367,38 @@ int git_odb_hashfile(git_oid *out, const char *path, git_object_t type)
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = git_odb__hashfd(out, fd, (size_t)size, type);
|
||||
error = git_odb__hashfd(out, fd, (size_t)size, object_type, oid_type);
|
||||
|
||||
done:
|
||||
p_close(fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_odb_hash(git_oid *id, const void *data, size_t len, git_object_t type)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_hashfile(
|
||||
git_oid *out,
|
||||
const char *path,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
return git_odb__hashfile(out, path, object_type, oid_type);
|
||||
}
|
||||
#else
|
||||
int git_odb_hashfile(
|
||||
git_oid *out,
|
||||
const char *path,
|
||||
git_object_t object_type)
|
||||
{
|
||||
return git_odb__hashfile(out, path, object_type, GIT_OID_SHA1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int git_odb__hash(
|
||||
git_oid *id,
|
||||
const void *data,
|
||||
size_t len,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
git_rawobj raw;
|
||||
|
||||
@ -348,11 +406,32 @@ int git_odb_hash(git_oid *id, const void *data, size_t len, git_object_t type)
|
||||
|
||||
raw.data = (void *)data;
|
||||
raw.len = len;
|
||||
raw.type = type;
|
||||
raw.type = object_type;
|
||||
|
||||
return git_odb__hashobj(id, &raw);
|
||||
return git_odb__hashobj(id, &raw, oid_type);
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_hash(
|
||||
git_oid *out,
|
||||
const void *data,
|
||||
size_t len,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
return git_odb__hash(out, data, len, object_type, oid_type);
|
||||
}
|
||||
#else
|
||||
int git_odb_hash(
|
||||
git_oid *out,
|
||||
const void *data,
|
||||
size_t len,
|
||||
git_object_t type)
|
||||
{
|
||||
return git_odb__hash(out, data, len, type, GIT_OID_SHA1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* FAKE WSTREAM
|
||||
*/
|
||||
@ -442,11 +521,28 @@ static int backend_sort_cmp(const void *a, const void *b)
|
||||
return (backend_b->priority - backend_a->priority);
|
||||
}
|
||||
|
||||
int git_odb_new(git_odb **out)
|
||||
static void normalize_options(
|
||||
git_odb_options *opts,
|
||||
const git_odb_options *given_opts)
|
||||
{
|
||||
git_odb_options init = GIT_ODB_OPTIONS_INIT;
|
||||
|
||||
if (given_opts)
|
||||
memcpy(opts, given_opts, sizeof(git_odb_options));
|
||||
else
|
||||
memcpy(opts, &init, sizeof(git_odb_options));
|
||||
|
||||
if (!opts->oid_type)
|
||||
opts->oid_type = GIT_OID_DEFAULT;
|
||||
}
|
||||
|
||||
int git_odb__new(git_odb **out, const git_odb_options *opts)
|
||||
{
|
||||
git_odb *db = git__calloc(1, sizeof(*db));
|
||||
GIT_ERROR_CHECK_ALLOC(db);
|
||||
|
||||
normalize_options(&db->options, opts);
|
||||
|
||||
if (git_mutex_init(&db->lock) < 0) {
|
||||
git__free(db);
|
||||
return -1;
|
||||
@ -468,6 +564,18 @@ int git_odb_new(git_odb **out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_new(git_odb **out, const git_odb_options *opts)
|
||||
{
|
||||
return git_odb__new(out, opts);
|
||||
}
|
||||
#else
|
||||
int git_odb_new(git_odb **out)
|
||||
{
|
||||
return git_odb__new(out, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_backend_internal(
|
||||
git_odb *odb, git_odb_backend *backend,
|
||||
int priority, bool is_alternate, ino_t disk_inode)
|
||||
@ -575,6 +683,8 @@ int git_odb__add_default_backends(
|
||||
struct stat st;
|
||||
ino_t inode;
|
||||
git_odb_backend *loose, *packed;
|
||||
git_odb_backend_loose_options loose_opts = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
|
||||
git_odb_backend_pack_options pack_opts = GIT_ODB_BACKEND_PACK_OPTIONS_INIT;
|
||||
|
||||
/* TODO: inodes are not really relevant on Win32, so we need to find
|
||||
* a cross-platform workaround for this */
|
||||
@ -609,14 +719,29 @@ int git_odb__add_default_backends(
|
||||
git_mutex_unlock(&db->lock);
|
||||
#endif
|
||||
|
||||
if (db->do_fsync)
|
||||
loose_opts.flags |= GIT_ODB_BACKEND_LOOSE_FSYNC;
|
||||
|
||||
loose_opts.oid_type = db->options.oid_type;
|
||||
pack_opts.oid_type = db->options.oid_type;
|
||||
|
||||
/* add the loose object backend */
|
||||
if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
|
||||
if (git_odb__backend_loose(&loose, objects_dir, &loose_opts) < 0 ||
|
||||
add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0)
|
||||
return -1;
|
||||
|
||||
/* add the packed file backend */
|
||||
if (git_odb_backend_pack(&packed, objects_dir) < 0 ||
|
||||
add_backend_internal(db, packed, git_odb__packed_priority, as_alternates, inode) < 0)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (git_odb_backend_pack(&packed, objects_dir, &pack_opts) < 0)
|
||||
return -1;
|
||||
#else
|
||||
GIT_UNUSED(pack_opts);
|
||||
|
||||
if (git_odb_backend_pack(&packed, objects_dir) < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (add_backend_internal(db, packed, git_odb__packed_priority, as_alternates, inode) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_mutex_lock(&db->lock) < 0) {
|
||||
@ -707,7 +832,10 @@ int git_odb_set_commit_graph(git_odb *odb, git_commit_graph *cgraph)
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_odb_open(git_odb **out, const char *objects_dir)
|
||||
int git_odb__open(
|
||||
git_odb **out,
|
||||
const char *objects_dir,
|
||||
const git_odb_options *opts)
|
||||
{
|
||||
git_odb *db;
|
||||
|
||||
@ -716,7 +844,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
|
||||
|
||||
*out = NULL;
|
||||
|
||||
if (git_odb_new(&db) < 0)
|
||||
if (git_odb__new(&db, opts) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_odb__add_default_backends(db, objects_dir, 0, 0) < 0) {
|
||||
@ -728,6 +856,25 @@ int git_odb_open(git_odb **out, const char *objects_dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
|
||||
int git_odb_open(
|
||||
git_odb **out,
|
||||
const char *objects_dir,
|
||||
const git_odb_options *opts)
|
||||
{
|
||||
return git_odb__open(out, objects_dir, opts);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int git_odb_open(git_odb **out, const char *objects_dir)
|
||||
{
|
||||
return git_odb__open(out, objects_dir, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int git_odb__set_caps(git_odb *odb, int caps)
|
||||
{
|
||||
if (caps == GIT_ODB_CAP_FROM_OWNER) {
|
||||
@ -914,7 +1061,7 @@ static int odb_exists_prefix_1(git_oid *out, git_odb *db,
|
||||
{
|
||||
size_t i;
|
||||
int error = GIT_ENOTFOUND, num_found = 0;
|
||||
git_oid last_found = {{0}}, found;
|
||||
git_oid last_found = GIT_OID_NONE, found;
|
||||
|
||||
if ((error = git_mutex_lock(&db->lock)) < 0) {
|
||||
git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
|
||||
@ -965,7 +1112,7 @@ int git_odb_exists_prefix(
|
||||
git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
|
||||
{
|
||||
int error;
|
||||
git_oid key = {{0}};
|
||||
git_oid key = GIT_OID_NONE;
|
||||
|
||||
GIT_ASSERT_ARG(db);
|
||||
GIT_ASSERT_ARG(short_id);
|
||||
@ -973,7 +1120,7 @@ int git_odb_exists_prefix(
|
||||
if (len < GIT_OID_MINPREFIXLEN)
|
||||
return git_odb__error_ambiguous("prefix length too short");
|
||||
|
||||
if (len >= GIT_OID_HEXSZ) {
|
||||
if (len >= git_oid_hexsize(db->options.oid_type)) {
|
||||
if (git_odb_exists(db, short_id)) {
|
||||
if (out)
|
||||
git_oid_cpy(out, short_id);
|
||||
@ -1002,11 +1149,13 @@ int git_odb_expand_ids(
|
||||
git_odb_expand_id *ids,
|
||||
size_t count)
|
||||
{
|
||||
size_t i;
|
||||
size_t hex_size, i;
|
||||
|
||||
GIT_ASSERT_ARG(db);
|
||||
GIT_ASSERT_ARG(ids);
|
||||
|
||||
hex_size = git_oid_hexsize(db->options.oid_type);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
git_odb_expand_id *query = &ids[i];
|
||||
int error = GIT_EAMBIGUOUS;
|
||||
@ -1015,13 +1164,13 @@ int git_odb_expand_ids(
|
||||
query->type = GIT_OBJECT_ANY;
|
||||
|
||||
/* if we have a short OID, expand it first */
|
||||
if (query->length >= GIT_OID_MINPREFIXLEN && query->length < GIT_OID_HEXSZ) {
|
||||
if (query->length >= GIT_OID_MINPREFIXLEN && query->length < hex_size) {
|
||||
git_oid actual_id;
|
||||
|
||||
error = odb_exists_prefix_1(&actual_id, db, &query->id, query->length, false);
|
||||
if (!error) {
|
||||
git_oid_cpy(&query->id, &actual_id);
|
||||
query->length = GIT_OID_HEXSZ;
|
||||
query->length = (unsigned short)hex_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1029,7 +1178,7 @@ int git_odb_expand_ids(
|
||||
* now we ought to have a 40-char OID, either because we've expanded it
|
||||
* or because the user passed a full OID. Ensure its type is right.
|
||||
*/
|
||||
if (query->length >= GIT_OID_HEXSZ) {
|
||||
if (query->length >= hex_size) {
|
||||
git_object_t actual_type;
|
||||
|
||||
error = odb_otype_fast(&actual_type, db, &query->id);
|
||||
@ -1049,7 +1198,7 @@ int git_odb_expand_ids(
|
||||
/* the object is missing or ambiguous */
|
||||
case GIT_ENOTFOUND:
|
||||
case GIT_EAMBIGUOUS:
|
||||
memset(&query->id, 0, sizeof(git_oid));
|
||||
git_oid_clear(&query->id, db->options.oid_type);
|
||||
query->length = 0;
|
||||
query->type = 0;
|
||||
break;
|
||||
@ -1157,7 +1306,7 @@ int git_odb__read_header_or_object(
|
||||
error = odb_read_header_1(len_p, type_p, db, id, true);
|
||||
|
||||
if (error == GIT_ENOTFOUND)
|
||||
return git_odb__error_notfound("cannot read header for", id, GIT_OID_HEXSZ);
|
||||
return git_odb__error_notfound("cannot read header for", id, git_oid_hexsize(db->options.oid_type));
|
||||
|
||||
/* we found the header; return early */
|
||||
if (!error)
|
||||
@ -1179,8 +1328,11 @@ int git_odb__read_header_or_object(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
|
||||
bool only_refreshed)
|
||||
static int odb_read_1(
|
||||
git_odb_object **out,
|
||||
git_odb *db,
|
||||
const git_oid *id,
|
||||
bool only_refreshed)
|
||||
{
|
||||
size_t i;
|
||||
git_rawobj raw;
|
||||
@ -1224,7 +1376,7 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
if (git_odb__strict_hash_verification) {
|
||||
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
|
||||
if ((error = git_odb__hash(&hashed, raw.data, raw.len, raw.type, db->options.oid_type)) < 0)
|
||||
goto out;
|
||||
|
||||
if (!git_oid_equal(id, &hashed)) {
|
||||
@ -1268,7 +1420,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
|
||||
error = odb_read_1(out, db, id, true);
|
||||
|
||||
if (error == GIT_ENOTFOUND)
|
||||
return git_odb__error_notfound("no match for id", id, GIT_OID_HEXSZ);
|
||||
return git_odb__error_notfound("no match for id", id, git_oid_hexsize(git_oid_type(id)));
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -1305,7 +1457,7 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
|
||||
{
|
||||
size_t i;
|
||||
int error = 0;
|
||||
git_oid found_full_oid = {{0}};
|
||||
git_oid found_full_oid = GIT_OID_NONE;
|
||||
git_rawobj raw = {0};
|
||||
void *data = NULL;
|
||||
bool found = false;
|
||||
@ -1365,7 +1517,7 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
|
||||
if (git_odb__strict_hash_verification) {
|
||||
git_oid hash;
|
||||
|
||||
if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type)) < 0)
|
||||
if ((error = git_odb__hash(&hash, raw.data, raw.len, raw.type, db->options.oid_type)) < 0)
|
||||
goto out;
|
||||
|
||||
if (!git_oid_equal(&found_full_oid, &hash)) {
|
||||
@ -1391,19 +1543,22 @@ out:
|
||||
int git_odb_read_prefix(
|
||||
git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len)
|
||||
{
|
||||
git_oid key = {{0}};
|
||||
git_oid key = GIT_OID_NONE;
|
||||
size_t hex_size;
|
||||
int error;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(db);
|
||||
|
||||
hex_size = git_oid_hexsize(db->options.oid_type);
|
||||
|
||||
if (len < GIT_OID_MINPREFIXLEN)
|
||||
return git_odb__error_ambiguous("prefix length too short");
|
||||
|
||||
if (len > GIT_OID_HEXSZ)
|
||||
len = GIT_OID_HEXSZ;
|
||||
if (len > hex_size)
|
||||
len = hex_size;
|
||||
|
||||
if (len == GIT_OID_HEXSZ) {
|
||||
if (len == hex_size) {
|
||||
*out = git_cache_get_raw(odb_cache(db), short_id);
|
||||
if (*out != NULL)
|
||||
return 0;
|
||||
@ -1463,7 +1618,7 @@ int git_odb_write(
|
||||
GIT_ASSERT_ARG(oid);
|
||||
GIT_ASSERT_ARG(db);
|
||||
|
||||
if ((error = git_odb_hash(oid, data, len, type)) < 0)
|
||||
if ((error = git_odb__hash(oid, data, len, type, db->options.oid_type)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_oid_is_zero(oid))
|
||||
@ -1564,10 +1719,13 @@ int git_odb_open_wstream(
|
||||
ctx = git__malloc(sizeof(git_hash_ctx));
|
||||
GIT_ERROR_CHECK_ALLOC(ctx);
|
||||
|
||||
if ((error = git_hash_ctx_init(ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
|
||||
(error = hash_header(ctx, size, type)) < 0)
|
||||
if ((error = git_hash_ctx_init(ctx, git_oid_algorithm(db->options.oid_type))) < 0 ||
|
||||
(error = hash_header(ctx, size, type)) < 0)
|
||||
goto done;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
(*stream)->oid_type = db->options.oid_type;
|
||||
#endif
|
||||
(*stream)->hash_ctx = ctx;
|
||||
(*stream)->declared_size = size;
|
||||
(*stream)->received_bytes = 0;
|
||||
@ -1612,6 +1770,10 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
|
||||
|
||||
git_hash_final(out->id, stream->hash_ctx);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = stream->oid_type;
|
||||
#endif
|
||||
|
||||
if (git_odb__freshen(stream->backend->odb, out))
|
||||
return 0;
|
||||
|
||||
@ -1786,10 +1948,11 @@ int git_odb_refresh(struct git_odb *db)
|
||||
|
||||
int git_odb__error_mismatch(const git_oid *expected, const git_oid *actual)
|
||||
{
|
||||
char expected_oid[GIT_OID_HEXSZ + 1], actual_oid[GIT_OID_HEXSZ + 1];
|
||||
char expected_oid[GIT_OID_MAX_HEXSIZE + 1],
|
||||
actual_oid[GIT_OID_MAX_HEXSIZE + 1];
|
||||
|
||||
git_oid_tostr(expected_oid, sizeof(expected_oid), expected);
|
||||
git_oid_tostr(actual_oid, sizeof(actual_oid), actual);
|
||||
git_oid_tostr(expected_oid, git_oid_hexsize(git_oid_type(expected)) + 1, expected);
|
||||
git_oid_tostr(actual_oid, git_oid_hexsize(git_oid_type(actual)) + 1, actual);
|
||||
|
||||
git_error_set(GIT_ERROR_ODB, "object hash mismatch - expected %s but got %s",
|
||||
expected_oid, actual_oid);
|
||||
@ -1801,7 +1964,7 @@ int git_odb__error_notfound(
|
||||
const char *message, const git_oid *oid, size_t oid_len)
|
||||
{
|
||||
if (oid != NULL) {
|
||||
char oid_str[GIT_OID_HEXSZ + 1];
|
||||
char oid_str[GIT_OID_MAX_HEXSIZE + 1];
|
||||
git_oid_tostr(oid_str, oid_len+1, oid);
|
||||
git_error_set(GIT_ERROR_ODB, "object not found - %s (%.*s)",
|
||||
message, (int) oid_len, oid_str);
|
||||
@ -1819,7 +1982,7 @@ static int error_null_oid(int error, const char *message)
|
||||
|
||||
int git_odb__error_ambiguous(const char *message)
|
||||
{
|
||||
git_error_set(GIT_ERROR_ODB, "ambiguous SHA1 prefix - %s", message);
|
||||
git_error_set(GIT_ERROR_ODB, "ambiguous OID prefix - %s", message);
|
||||
return GIT_EAMBIGUOUS;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "git2/odb.h"
|
||||
#include "git2/odb_backend.h"
|
||||
#include "git2/oid.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/sys/commit_graph.h"
|
||||
@ -46,6 +47,7 @@ struct git_odb_object {
|
||||
struct git_odb {
|
||||
git_refcount rc;
|
||||
git_mutex lock; /* protects backends */
|
||||
git_odb_options options;
|
||||
git_vector backends;
|
||||
git_cache own_cache;
|
||||
git_commit_graph *cgraph;
|
||||
@ -72,7 +74,7 @@ int git_odb__add_default_backends(
|
||||
* Hash a git_rawobj internally.
|
||||
* The `git_rawobj` is supposed to be previously initialized
|
||||
*/
|
||||
int git_odb__hashobj(git_oid *id, git_rawobj *obj);
|
||||
int git_odb__hashobj(git_oid *id, git_rawobj *obj, git_oid_t oid_type);
|
||||
|
||||
/*
|
||||
* Format the object header such as it would appear in the on-disk object
|
||||
@ -89,14 +91,24 @@ int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, g
|
||||
* The fd is never closed, not even on error. It must be opened and closed
|
||||
* by the caller
|
||||
*/
|
||||
int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type);
|
||||
int git_odb__hashfd(
|
||||
git_oid *out,
|
||||
git_file fd,
|
||||
size_t size,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
|
||||
/*
|
||||
* Hash an open file descriptor applying an array of filters
|
||||
* Acts just like git_odb__hashfd with the addition of filters...
|
||||
*/
|
||||
int git_odb__hashfd_filtered(
|
||||
git_oid *out, git_file fd, size_t len, git_object_t type, git_filter_list *fl);
|
||||
git_oid *out,
|
||||
git_file fd,
|
||||
size_t len,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type,
|
||||
git_filter_list *fl);
|
||||
|
||||
/*
|
||||
* Hash a `path`, assuming it could be a POSIX symlink: if the path is a
|
||||
@ -106,7 +118,7 @@ int git_odb__hashfd_filtered(
|
||||
* 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);
|
||||
int git_odb__hashlink(git_oid *out, const char *path, git_oid_t oid_type);
|
||||
|
||||
/**
|
||||
* Generate a GIT_EMISMATCH error for the ODB.
|
||||
@ -146,4 +158,31 @@ int git_odb__freshen(git_odb *db, const git_oid *id);
|
||||
/* fully free the object; internal method, DO NOT EXPORT */
|
||||
void git_odb_object__free(void *object);
|
||||
|
||||
/* SHA256 support */
|
||||
|
||||
int git_odb__new(git_odb **out, const git_odb_options *opts);
|
||||
|
||||
int git_odb__open(
|
||||
git_odb **out,
|
||||
const char *objects_dir,
|
||||
const git_odb_options *opts);
|
||||
|
||||
int git_odb__hash(
|
||||
git_oid *out,
|
||||
const void *data,
|
||||
size_t len,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
|
||||
int git_odb__hashfile(
|
||||
git_oid *out,
|
||||
const char *path,
|
||||
git_object_t object_type,
|
||||
git_oid_t oid_type);
|
||||
|
||||
GIT_EXTERN(int) git_odb__backend_loose(
|
||||
git_odb_backend **out,
|
||||
const char *objects_dir,
|
||||
git_odb_backend_loose_options *opts);
|
||||
|
||||
#endif
|
||||
|
@ -46,10 +46,8 @@ typedef struct {
|
||||
typedef struct loose_backend {
|
||||
git_odb_backend parent;
|
||||
|
||||
int object_zlib_level; /** loose object zlib compression level. */
|
||||
int fsync_object_files; /** loose object file fsync flag. */
|
||||
mode_t object_file_mode;
|
||||
mode_t object_dir_mode;
|
||||
git_odb_backend_loose_options options;
|
||||
size_t oid_hexsize;
|
||||
|
||||
size_t objects_dirlen;
|
||||
char objects_dir[GIT_FLEX_ARRAY];
|
||||
@ -59,13 +57,19 @@ typedef struct loose_backend {
|
||||
* in order to locate objects matching a short oid.
|
||||
*/
|
||||
typedef struct {
|
||||
loose_backend *backend;
|
||||
|
||||
size_t dir_len;
|
||||
unsigned char short_oid[GIT_OID_HEXSZ]; /* hex formatted oid to match */
|
||||
|
||||
/* Hex formatted oid to match (and its length) */
|
||||
unsigned char short_oid[GIT_OID_MAX_HEXSIZE];
|
||||
size_t short_oid_len;
|
||||
int found; /* number of matching
|
||||
* objects already found */
|
||||
unsigned char res_oid[GIT_OID_HEXSZ]; /* hex formatted oid of
|
||||
* the object found */
|
||||
|
||||
/* Number of matching objects found so far */
|
||||
int found;
|
||||
|
||||
/* Hex formatted oid of the object found */
|
||||
unsigned char res_oid[GIT_OID_MAX_HEXSIZE];
|
||||
} loose_locate_object_state;
|
||||
|
||||
|
||||
@ -78,20 +82,17 @@ typedef struct {
|
||||
static int object_file_name(
|
||||
git_str *name, const loose_backend *be, const git_oid *id)
|
||||
{
|
||||
size_t alloclen;
|
||||
|
||||
/* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
|
||||
if (git_str_grow(name, alloclen) < 0)
|
||||
return -1;
|
||||
/* append loose object filename: aa/aaa... (41 bytes plus NUL) */
|
||||
size_t path_size = be->oid_hexsize + 1;
|
||||
|
||||
git_str_set(name, be->objects_dir, be->objects_dirlen);
|
||||
git_fs_path_to_dir(name);
|
||||
|
||||
/* loose object filename: aa/aaa... (41 bytes) */
|
||||
if (git_str_grow_by(name, path_size + 1) < 0)
|
||||
return -1;
|
||||
|
||||
git_oid_pathfmt(name->ptr + name->size, id);
|
||||
name->size += GIT_OID_HEXSZ + 1;
|
||||
name->size += path_size;
|
||||
name->ptr[name->size] = '\0';
|
||||
|
||||
return 0;
|
||||
@ -100,7 +101,9 @@ static int object_file_name(
|
||||
static int object_mkdir(const git_str *name, const loose_backend *be)
|
||||
{
|
||||
return git_futils_mkdir_relative(
|
||||
name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode,
|
||||
name->ptr + be->objects_dirlen,
|
||||
be->objects_dir,
|
||||
be->options.dir_mode,
|
||||
GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR, NULL);
|
||||
}
|
||||
|
||||
@ -461,8 +464,9 @@ static int locate_object(
|
||||
/* Explore an entry of a directory and see if it matches a short oid */
|
||||
static int fn_locate_object_short_oid(void *state, git_str *pathbuf) {
|
||||
loose_locate_object_state *sstate = (loose_locate_object_state *)state;
|
||||
size_t hex_size = sstate->backend->oid_hexsize;
|
||||
|
||||
if (git_str_len(pathbuf) - sstate->dir_len != GIT_OID_HEXSZ - 2) {
|
||||
if (git_str_len(pathbuf) - sstate->dir_len != hex_size - 2) {
|
||||
/* Entry cannot be an object. Continue to next entry */
|
||||
return 0;
|
||||
}
|
||||
@ -477,7 +481,9 @@ static int fn_locate_object_short_oid(void *state, git_str *pathbuf) {
|
||||
if (!sstate->found) {
|
||||
sstate->res_oid[0] = sstate->short_oid[0];
|
||||
sstate->res_oid[1] = sstate->short_oid[1];
|
||||
memcpy(sstate->res_oid+2, pathbuf->ptr+sstate->dir_len, GIT_OID_HEXSZ-2);
|
||||
memcpy(sstate->res_oid + 2,
|
||||
pathbuf->ptr+sstate->dir_len,
|
||||
hex_size - 2);
|
||||
}
|
||||
sstate->found++;
|
||||
}
|
||||
@ -503,7 +509,7 @@ static int locate_object_short_oid(
|
||||
int error;
|
||||
|
||||
/* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, backend->oid_hexsize);
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
|
||||
if (git_str_grow(object_location, alloc_len) < 0)
|
||||
return -1;
|
||||
@ -527,6 +533,7 @@ static int locate_object_short_oid(
|
||||
return git_odb__error_notfound("no matching loose object for prefix",
|
||||
short_oid, len);
|
||||
|
||||
state.backend = backend;
|
||||
state.dir_len = git_str_len(object_location);
|
||||
state.short_oid_len = len;
|
||||
state.found = 0;
|
||||
@ -545,12 +552,12 @@ static int locate_object_short_oid(
|
||||
return git_odb__error_ambiguous("multiple matches in loose objects");
|
||||
|
||||
/* Convert obtained hex formatted oid to raw */
|
||||
error = git_oid_fromstr(res_oid, (char *)state.res_oid);
|
||||
error = git_oid__fromstr(res_oid, (char *)state.res_oid, backend->options.oid_type);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Update the location according to the oid obtained */
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, backend->oid_hexsize);
|
||||
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
|
||||
|
||||
git_str_truncate(object_location, dir_len);
|
||||
@ -559,20 +566,12 @@ static int locate_object_short_oid(
|
||||
|
||||
git_oid_pathfmt(object_location->ptr + dir_len, res_oid);
|
||||
|
||||
object_location->size += GIT_OID_HEXSZ + 1;
|
||||
object_location->size += backend->oid_hexsize + 1;
|
||||
object_location->ptr[object_location->size] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
* LOOSE BACKEND PUBLIC API
|
||||
@ -595,7 +594,7 @@ static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_o
|
||||
|
||||
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
|
||||
error = git_odb__error_notfound("no matching loose object",
|
||||
oid, GIT_OID_HEXSZ);
|
||||
oid, ((struct loose_backend *)backend)->oid_hexsize);
|
||||
} else if ((error = read_header_loose(&raw, &object_path)) == 0) {
|
||||
*len_p = raw.len;
|
||||
*type_p = raw.type;
|
||||
@ -617,7 +616,7 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *typ
|
||||
|
||||
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
|
||||
error = git_odb__error_notfound("no matching loose object",
|
||||
oid, GIT_OID_HEXSZ);
|
||||
oid, ((struct loose_backend *)backend)->oid_hexsize);
|
||||
} else if ((error = read_loose(&raw, &object_path)) == 0) {
|
||||
*buffer_p = raw.data;
|
||||
*len_p = raw.len;
|
||||
@ -634,17 +633,19 @@ static int loose_backend__read_prefix(
|
||||
void **buffer_p,
|
||||
size_t *len_p,
|
||||
git_object_t *type_p,
|
||||
git_odb_backend *backend,
|
||||
git_odb_backend *_backend,
|
||||
const git_oid *short_oid,
|
||||
size_t len)
|
||||
{
|
||||
struct loose_backend *backend = (struct loose_backend *)_backend;
|
||||
int error = 0;
|
||||
|
||||
GIT_ASSERT_ARG(len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_HEXSZ);
|
||||
GIT_ASSERT_ARG(len >= GIT_OID_MINPREFIXLEN &&
|
||||
len <= backend->oid_hexsize);
|
||||
|
||||
if (len == GIT_OID_HEXSZ) {
|
||||
if (len == backend->oid_hexsize) {
|
||||
/* We can fall back to regular read method */
|
||||
error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid);
|
||||
error = loose_backend__read(buffer_p, len_p, type_p, _backend, short_oid);
|
||||
if (!error)
|
||||
git_oid_cpy(out_oid, short_oid);
|
||||
} else {
|
||||
@ -703,15 +704,18 @@ static int loose_backend__exists_prefix(
|
||||
}
|
||||
|
||||
struct foreach_state {
|
||||
struct loose_backend *backend;
|
||||
size_t dir_len;
|
||||
git_odb_foreach_cb cb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
GIT_INLINE(int) filename_to_oid(struct loose_backend *backend, git_oid *oid, const char *ptr)
|
||||
{
|
||||
int v, i = 0;
|
||||
if (strlen(ptr) != GIT_OID_HEXSZ+1)
|
||||
int v;
|
||||
size_t i = 0;
|
||||
|
||||
if (strlen(ptr) != backend->oid_hexsize + 1)
|
||||
return -1;
|
||||
|
||||
if (ptr[2] != '/') {
|
||||
@ -725,7 +729,7 @@ GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
oid->id[0] = (unsigned char) v;
|
||||
|
||||
ptr += 3;
|
||||
for (i = 0; i < 38; i += 2) {
|
||||
for (i = 0; i < backend->oid_hexsize - 2; i += 2) {
|
||||
v = (git__fromhex(ptr[i]) << 4) | git__fromhex(ptr[i + 1]);
|
||||
if (v < 0)
|
||||
return -1;
|
||||
@ -733,6 +737,10 @@ GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
oid->id[1 + i/2] = (unsigned char) v;
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
oid->type = backend->options.oid_type;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -741,7 +749,7 @@ static int foreach_object_dir_cb(void *_state, git_str *path)
|
||||
git_oid oid;
|
||||
struct foreach_state *state = (struct foreach_state *) _state;
|
||||
|
||||
if (filename_to_oid(&oid, path->ptr + state->dir_len) < 0)
|
||||
if (filename_to_oid(state->backend, &oid, path->ptr + state->dir_len) < 0)
|
||||
return 0;
|
||||
|
||||
return git_error_set_after_callback_function(
|
||||
@ -778,6 +786,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
|
||||
return -1;
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.backend = backend;
|
||||
state.cb = cb;
|
||||
state.data = data;
|
||||
state.dir_len = git_str_len(&buf);
|
||||
@ -825,9 +834,10 @@ static void loose_backend__writestream_free(git_odb_stream *_stream)
|
||||
static int filebuf_flags(loose_backend *backend)
|
||||
{
|
||||
int flags = GIT_FILEBUF_TEMPORARY |
|
||||
(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT);
|
||||
(backend->options.compression_level << GIT_FILEBUF_DEFLATE_SHIFT);
|
||||
|
||||
if (backend->fsync_object_files || git_repository__fsync_gitdir)
|
||||
if ((backend->options.flags & GIT_ODB_BACKEND_LOOSE_FSYNC) ||
|
||||
git_repository__fsync_gitdir)
|
||||
flags |= GIT_FILEBUF_FSYNC;
|
||||
|
||||
return flags;
|
||||
@ -863,7 +873,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
|
||||
|
||||
if (git_str_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
|
||||
git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
|
||||
backend->object_file_mode) < 0 ||
|
||||
backend->options.file_mode) < 0 ||
|
||||
stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
|
||||
{
|
||||
git_filebuf_cleanup(&stream->fbuf);
|
||||
@ -997,6 +1007,7 @@ static int loose_backend__readstream(
|
||||
loose_readstream *stream = NULL;
|
||||
git_hash_ctx *hash_ctx = NULL;
|
||||
git_str object_path = GIT_STR_INIT;
|
||||
git_hash_algorithm_t algorithm;
|
||||
obj_hdr hdr;
|
||||
int error = 0;
|
||||
|
||||
@ -1013,7 +1024,7 @@ static int loose_backend__readstream(
|
||||
|
||||
if (locate_object(&object_path, backend, oid) < 0) {
|
||||
error = git_odb__error_notfound("no matching loose object",
|
||||
oid, GIT_OID_HEXSZ);
|
||||
oid, backend->oid_hexsize);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -1023,9 +1034,11 @@ static int loose_backend__readstream(
|
||||
hash_ctx = git__malloc(sizeof(git_hash_ctx));
|
||||
GIT_ERROR_CHECK_ALLOC(hash_ctx);
|
||||
|
||||
if ((error = git_hash_ctx_init(hash_ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
|
||||
(error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
|
||||
(error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
|
||||
algorithm = git_oid_algorithm(backend->options.oid_type);
|
||||
|
||||
if ((error = git_hash_ctx_init(hash_ctx, algorithm)) < 0 ||
|
||||
(error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
|
||||
(error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
|
||||
goto done;
|
||||
|
||||
/* check for a packlike loose object */
|
||||
@ -1081,7 +1094,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
|
||||
|
||||
if (git_str_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
|
||||
git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
|
||||
backend->object_file_mode) < 0)
|
||||
backend->options.file_mode) < 0)
|
||||
{
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
@ -1124,13 +1137,34 @@ static void loose_backend__free(git_odb_backend *_backend)
|
||||
git__free(_backend);
|
||||
}
|
||||
|
||||
int git_odb_backend_loose(
|
||||
static void normalize_options(
|
||||
git_odb_backend_loose_options *opts,
|
||||
const git_odb_backend_loose_options *given_opts)
|
||||
{
|
||||
git_odb_backend_loose_options init = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
|
||||
|
||||
if (given_opts)
|
||||
memcpy(opts, given_opts, sizeof(git_odb_backend_loose_options));
|
||||
else
|
||||
memcpy(opts, &init, sizeof(git_odb_backend_loose_options));
|
||||
|
||||
if (opts->compression_level < 0)
|
||||
opts->compression_level = Z_BEST_SPEED;
|
||||
|
||||
if (opts->dir_mode == 0)
|
||||
opts->dir_mode = GIT_OBJECT_DIR_MODE;
|
||||
|
||||
if (opts->file_mode == 0)
|
||||
opts->file_mode = GIT_OBJECT_FILE_MODE;
|
||||
|
||||
if (opts->oid_type == 0)
|
||||
opts->oid_type = GIT_OID_DEFAULT;
|
||||
}
|
||||
|
||||
int git_odb__backend_loose(
|
||||
git_odb_backend **backend_out,
|
||||
const char *objects_dir,
|
||||
int compression_level,
|
||||
int do_fsync,
|
||||
unsigned int dir_mode,
|
||||
unsigned int file_mode)
|
||||
git_odb_backend_loose_options *opts)
|
||||
{
|
||||
loose_backend *backend;
|
||||
size_t objects_dirlen, alloclen;
|
||||
@ -1148,22 +1182,12 @@ int git_odb_backend_loose(
|
||||
backend->parent.version = GIT_ODB_BACKEND_VERSION;
|
||||
backend->objects_dirlen = objects_dirlen;
|
||||
memcpy(backend->objects_dir, objects_dir, objects_dirlen);
|
||||
|
||||
if (backend->objects_dir[backend->objects_dirlen - 1] != '/')
|
||||
backend->objects_dir[backend->objects_dirlen++] = '/';
|
||||
|
||||
if (compression_level < 0)
|
||||
compression_level = Z_BEST_SPEED;
|
||||
|
||||
if (dir_mode == 0)
|
||||
dir_mode = GIT_OBJECT_DIR_MODE;
|
||||
|
||||
if (file_mode == 0)
|
||||
file_mode = GIT_OBJECT_FILE_MODE;
|
||||
|
||||
backend->object_zlib_level = compression_level;
|
||||
backend->fsync_object_files = do_fsync;
|
||||
backend->object_dir_mode = dir_mode;
|
||||
backend->object_file_mode = file_mode;
|
||||
normalize_options(&backend->options, opts);
|
||||
backend->oid_hexsize = git_oid_hexsize(backend->options.oid_type);
|
||||
|
||||
backend->parent.read = &loose_backend__read;
|
||||
backend->parent.write = &loose_backend__write;
|
||||
@ -1180,3 +1204,37 @@ int git_odb_backend_loose(
|
||||
*backend_out = (git_odb_backend *)backend;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_backend_loose(
|
||||
git_odb_backend **backend_out,
|
||||
const char *objects_dir,
|
||||
git_odb_backend_loose_options *opts)
|
||||
{
|
||||
return git_odb__backend_loose(backend_out, objects_dir, opts);
|
||||
}
|
||||
#else
|
||||
int git_odb_backend_loose(
|
||||
git_odb_backend **backend_out,
|
||||
const char *objects_dir,
|
||||
int compression_level,
|
||||
int do_fsync,
|
||||
unsigned int dir_mode,
|
||||
unsigned int file_mode)
|
||||
{
|
||||
git_odb_backend_loose_flag_t flags = 0;
|
||||
git_odb_backend_loose_options opts = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
|
||||
|
||||
if (do_fsync)
|
||||
flags |= GIT_ODB_BACKEND_LOOSE_FSYNC;
|
||||
|
||||
opts.flags = flags;
|
||||
opts.compression_level = compression_level;
|
||||
opts.dir_mode = dir_mode;
|
||||
opts.file_mode = file_mode;
|
||||
opts.oid_type = GIT_OID_DEFAULT;
|
||||
|
||||
return git_odb__backend_loose(backend_out, objects_dir, &opts);
|
||||
}
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
struct pack_backend {
|
||||
git_odb_backend parent;
|
||||
git_odb_backend_pack_options opts;
|
||||
git_midx_file *midx;
|
||||
git_vector midx_packs;
|
||||
git_vector packs;
|
||||
@ -95,24 +96,24 @@ struct pack_writepack {
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* # pack_backend__exists / pack_backend__exists_prefix
|
||||
* | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the
|
||||
* | Check if the given oid (or an oid prefix) exists in any of the
|
||||
* | packs that have been loaded for our ODB.
|
||||
* |
|
||||
* |-# pack_entry_find / pack_entry_find_prefix
|
||||
* | If there is a multi-pack-index present, search the SHA1 oid in that
|
||||
* | If there is a multi-pack-index present, search the oid in that
|
||||
* | index first. If it is not found there, iterate through all the unindexed
|
||||
* | packs that have been preloaded (starting by the pack where the latest
|
||||
* | object was found) to try to find the OID in one of them.
|
||||
* |
|
||||
* |-# git_midx_entry_find
|
||||
* | Search for the SHA1 oid in the multi-pack-index. See
|
||||
* | Search for the oid in the multi-pack-index. See
|
||||
* | <https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt>
|
||||
* | for specifics on the multi-pack-index format and how do we find
|
||||
* | entries in it.
|
||||
* |
|
||||
* |-# git_pack_entry_find
|
||||
* | Check the index of an individual unindexed pack to see if the SHA1
|
||||
* | OID can be found. If we can find the offset to that SHA1 inside of the
|
||||
* | Check the index of an individual unindexed pack to see if the
|
||||
* | OID can be found. If we can find the offset to that inside of the
|
||||
* | index, that means the object is contained inside of the packfile and
|
||||
* | we can stop searching. Before returning, we verify that the
|
||||
* | packfile behind the index we are searching still exists on disk.
|
||||
@ -141,13 +142,13 @@ struct pack_writepack {
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* # pack_backend__read / pack_backend__read_prefix
|
||||
* | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the
|
||||
* | Check if the given oid (or an oid prefix) exists in any of the
|
||||
* | packs that have been loaded for our ODB. If it does, open the packfile and
|
||||
* | read from it.
|
||||
* |
|
||||
* |-# git_packfile_unpack
|
||||
* Armed with a packfile and the offset within it, we can finally unpack
|
||||
* the object pointed at by the SHA1 oid. This involves mmapping part of
|
||||
* the object pointed at by the oid. This involves mmapping part of
|
||||
* the `.pack` file, and uncompressing the object within it (if it is
|
||||
* stored in the undelfitied representation), or finding a base object and
|
||||
* applying some deltas to its uncompressed representation (if it is stored
|
||||
@ -177,7 +178,7 @@ static int pack_entry_find(struct git_pack_entry *e,
|
||||
* a prefix of an identifier.
|
||||
* Sets GIT_EAMBIGUOUS if short oid is ambiguous.
|
||||
* This method assumes that len is between
|
||||
* GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
|
||||
* GIT_OID_MINPREFIXLEN and the hexsize for the hash type.
|
||||
*/
|
||||
static int pack_entry_find_prefix(
|
||||
struct git_pack_entry *e,
|
||||
@ -251,7 +252,7 @@ static int packfile_load__cb(void *data, git_str *path)
|
||||
if (git_vector_search2(NULL, &backend->packs, packfile_byname_search_cmp, &index_prefix) == 0)
|
||||
return 0;
|
||||
|
||||
error = git_mwindow_get_pack(&pack, path->ptr);
|
||||
error = git_mwindow_get_pack(&pack, path->ptr, backend->opts.oid_type);
|
||||
|
||||
/* ignore missing .pack file as git does */
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
@ -270,33 +271,34 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
|
||||
{
|
||||
struct git_pack_file *last_found = backend->last_found, *p;
|
||||
git_midx_entry midx_entry;
|
||||
size_t oid_hexsize = git_oid_hexsize(backend->opts.oid_type);
|
||||
size_t i;
|
||||
|
||||
if (backend->midx &&
|
||||
git_midx_entry_find(&midx_entry, backend->midx, oid, GIT_OID_HEXSZ) == 0 &&
|
||||
git_midx_entry_find(&midx_entry, backend->midx, oid, oid_hexsize) == 0 &&
|
||||
midx_entry.pack_index < git_vector_length(&backend->midx_packs)) {
|
||||
e->offset = midx_entry.offset;
|
||||
git_oid_cpy(&e->sha1, &midx_entry.sha1);
|
||||
git_oid_cpy(&e->id, &midx_entry.sha1);
|
||||
e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (last_found &&
|
||||
git_pack_entry_find(e, last_found, oid, GIT_OID_HEXSZ) == 0)
|
||||
git_pack_entry_find(e, last_found, oid, oid_hexsize) == 0)
|
||||
return 0;
|
||||
|
||||
git_vector_foreach(&backend->packs, i, p) {
|
||||
if (p == last_found)
|
||||
continue;
|
||||
|
||||
if (git_pack_entry_find(e, p, oid, GIT_OID_HEXSZ) == 0) {
|
||||
if (git_pack_entry_find(e, p, oid, oid_hexsize) == 0) {
|
||||
backend->last_found = p;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return git_odb__error_notfound(
|
||||
"failed to find pack entry", oid, GIT_OID_HEXSZ);
|
||||
"failed to find pack entry", oid, oid_hexsize);
|
||||
}
|
||||
|
||||
static int pack_entry_find_prefix(
|
||||
@ -307,7 +309,7 @@ static int pack_entry_find_prefix(
|
||||
{
|
||||
int error;
|
||||
size_t i;
|
||||
git_oid found_full_oid = {{0}};
|
||||
git_oid found_full_oid = GIT_OID_SHA1_ZERO;
|
||||
bool found = false;
|
||||
struct git_pack_file *last_found = backend->last_found, *p;
|
||||
git_midx_entry midx_entry;
|
||||
@ -318,9 +320,9 @@ static int pack_entry_find_prefix(
|
||||
return error;
|
||||
if (!error && midx_entry.pack_index < git_vector_length(&backend->midx_packs)) {
|
||||
e->offset = midx_entry.offset;
|
||||
git_oid_cpy(&e->sha1, &midx_entry.sha1);
|
||||
git_oid_cpy(&e->id, &midx_entry.sha1);
|
||||
e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index);
|
||||
git_oid_cpy(&found_full_oid, &e->sha1);
|
||||
git_oid_cpy(&found_full_oid, &e->id);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@ -330,9 +332,9 @@ static int pack_entry_find_prefix(
|
||||
if (error == GIT_EAMBIGUOUS)
|
||||
return error;
|
||||
if (!error) {
|
||||
if (found && git_oid_cmp(&e->sha1, &found_full_oid))
|
||||
if (found && git_oid_cmp(&e->id, &found_full_oid))
|
||||
return git_odb__error_ambiguous("found multiple pack entries");
|
||||
git_oid_cpy(&found_full_oid, &e->sha1);
|
||||
git_oid_cpy(&found_full_oid, &e->id);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@ -345,9 +347,9 @@ static int pack_entry_find_prefix(
|
||||
if (error == GIT_EAMBIGUOUS)
|
||||
return error;
|
||||
if (!error) {
|
||||
if (found && git_oid_cmp(&e->sha1, &found_full_oid))
|
||||
if (found && git_oid_cmp(&e->id, &found_full_oid))
|
||||
return git_odb__error_ambiguous("found multiple pack entries");
|
||||
git_oid_cpy(&found_full_oid, &e->sha1);
|
||||
git_oid_cpy(&found_full_oid, &e->id);
|
||||
found = true;
|
||||
backend->last_found = p;
|
||||
}
|
||||
@ -425,7 +427,10 @@ static int process_multi_pack_index_pack(
|
||||
}
|
||||
|
||||
/* Pack was not found. Allocate a new one. */
|
||||
error = git_mwindow_get_pack(&pack, git_str_cstr(&pack_path));
|
||||
error = git_mwindow_get_pack(
|
||||
&pack,
|
||||
git_str_cstr(&pack_path),
|
||||
backend->opts.oid_type);
|
||||
git_str_dispose(&pack_path);
|
||||
if (error < 0)
|
||||
return error;
|
||||
@ -596,32 +601,33 @@ static int pack_backend__read_prefix(
|
||||
void **buffer_p,
|
||||
size_t *len_p,
|
||||
git_object_t *type_p,
|
||||
git_odb_backend *backend,
|
||||
git_odb_backend *_backend,
|
||||
const git_oid *short_oid,
|
||||
size_t len)
|
||||
{
|
||||
struct pack_backend *backend = (struct pack_backend *)_backend;
|
||||
int error = 0;
|
||||
|
||||
if (len < GIT_OID_MINPREFIXLEN)
|
||||
error = git_odb__error_ambiguous("prefix length too short");
|
||||
|
||||
else if (len >= GIT_OID_HEXSZ) {
|
||||
else if (len >= git_oid_hexsize(backend->opts.oid_type)) {
|
||||
/* We can fall back to regular read method */
|
||||
error = pack_backend__read(buffer_p, len_p, type_p, backend, short_oid);
|
||||
error = pack_backend__read(buffer_p, len_p, type_p, _backend, short_oid);
|
||||
if (!error)
|
||||
git_oid_cpy(out_oid, short_oid);
|
||||
} else {
|
||||
struct git_pack_entry e;
|
||||
git_rawobj raw = {NULL};
|
||||
|
||||
if ((error = pack_entry_find_prefix(
|
||||
&e, (struct pack_backend *)backend, short_oid, len)) == 0 &&
|
||||
(error = git_packfile_unpack(&raw, e.p, &e.offset)) == 0)
|
||||
if ((error = pack_entry_find_prefix(&e,
|
||||
backend, short_oid, len)) == 0 &&
|
||||
(error = git_packfile_unpack(&raw, e.p, &e.offset)) == 0)
|
||||
{
|
||||
*buffer_p = raw.data;
|
||||
*len_p = raw.len;
|
||||
*type_p = raw.type;
|
||||
git_oid_cpy(out_oid, &e.sha1);
|
||||
git_oid_cpy(out_oid, &e.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -642,7 +648,7 @@ static int pack_backend__exists_prefix(
|
||||
struct git_pack_entry e = {0};
|
||||
|
||||
error = pack_entry_find_prefix(&e, pb, short_id, len);
|
||||
git_oid_cpy(out, &e.sha1);
|
||||
git_oid_cpy(out, &e.id);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -712,6 +718,7 @@ static int pack_backend__writepack(struct git_odb_writepack **out,
|
||||
git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
|
||||
struct pack_backend *backend;
|
||||
struct pack_writepack *writepack;
|
||||
int error;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(_backend);
|
||||
@ -726,11 +733,20 @@ static int pack_backend__writepack(struct git_odb_writepack **out,
|
||||
writepack = git__calloc(1, sizeof(struct pack_writepack));
|
||||
GIT_ERROR_CHECK_ALLOC(writepack);
|
||||
|
||||
if (git_indexer_new(&writepack->indexer,
|
||||
backend->pack_folder, 0, odb, &opts) < 0) {
|
||||
git__free(writepack);
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
opts.odb = odb;
|
||||
|
||||
error = git_indexer_new(&writepack->indexer,
|
||||
backend->pack_folder,
|
||||
backend->opts.oid_type,
|
||||
&opts);
|
||||
#else
|
||||
error = git_indexer_new(&writepack->indexer,
|
||||
backend->pack_folder, 0, odb, &opts);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
writepack->parent.backend = _backend;
|
||||
writepack->parent.append = pack_backend__writepack_append;
|
||||
@ -840,7 +856,10 @@ static void pack_backend__free(git_odb_backend *_backend)
|
||||
git__free(backend);
|
||||
}
|
||||
|
||||
static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
|
||||
static int pack_backend__alloc(
|
||||
struct pack_backend **out,
|
||||
size_t initial_size,
|
||||
const git_odb_backend_pack_options *opts)
|
||||
{
|
||||
struct pack_backend *backend = git__calloc(1, sizeof(struct pack_backend));
|
||||
GIT_ERROR_CHECK_ALLOC(backend);
|
||||
@ -849,12 +868,19 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
|
||||
git__free(backend);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_vector_init(&backend->packs, initial_size, packfile_sort__cb) < 0) {
|
||||
git_vector_free(&backend->midx_packs);
|
||||
git__free(backend);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opts)
|
||||
memcpy(&backend->opts, opts, sizeof(git_odb_backend_pack_options));
|
||||
|
||||
if (!backend->opts.oid_type)
|
||||
backend->opts.oid_type = GIT_OID_DEFAULT;
|
||||
|
||||
backend->parent.version = GIT_ODB_BACKEND_VERSION;
|
||||
|
||||
backend->parent.read = &pack_backend__read;
|
||||
@ -873,17 +899,31 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_backend_one_pack(
|
||||
git_odb_backend **backend_out,
|
||||
const char *idx,
|
||||
const git_odb_backend_pack_options *opts)
|
||||
#else
|
||||
int git_odb_backend_one_pack(
|
||||
git_odb_backend **backend_out,
|
||||
const char *idx)
|
||||
#endif
|
||||
{
|
||||
struct pack_backend *backend = NULL;
|
||||
struct git_pack_file *packfile = NULL;
|
||||
|
||||
if (pack_backend__alloc(&backend, 1) < 0)
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
git_odb_backend_pack_options *opts = NULL;
|
||||
#endif
|
||||
|
||||
git_oid_t oid_type = opts ? opts->oid_type : 0;
|
||||
|
||||
if (pack_backend__alloc(&backend, 1, opts) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_mwindow_get_pack(&packfile, idx) < 0 ||
|
||||
git_vector_insert(&backend->packs, packfile) < 0)
|
||||
{
|
||||
if (git_mwindow_get_pack(&packfile, idx, oid_type) < 0 ||
|
||||
git_vector_insert(&backend->packs, packfile) < 0) {
|
||||
pack_backend__free((git_odb_backend *)backend);
|
||||
return -1;
|
||||
}
|
||||
@ -892,18 +932,30 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_odb_backend_pack(
|
||||
git_odb_backend **backend_out,
|
||||
const char *objects_dir,
|
||||
const git_odb_backend_pack_options *opts)
|
||||
#else
|
||||
int git_odb_backend_pack(
|
||||
git_odb_backend **backend_out,
|
||||
const char *objects_dir)
|
||||
#endif
|
||||
{
|
||||
int error = 0;
|
||||
struct pack_backend *backend = NULL;
|
||||
git_str path = GIT_STR_INIT;
|
||||
|
||||
if (pack_backend__alloc(&backend, 8) < 0)
|
||||
#ifndef GIT_EXPERIMENTAL_SHA256
|
||||
git_odb_backend_pack_options *opts = NULL;
|
||||
#endif
|
||||
|
||||
if (pack_backend__alloc(&backend, 8, opts) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(error = git_str_joinpath(&path, objects_dir, "pack")) &&
|
||||
git_fs_path_isdir(git_str_cstr(&path)))
|
||||
{
|
||||
git_fs_path_isdir(git_str_cstr(&path))) {
|
||||
backend->pack_folder = git_str_detach(&path);
|
||||
error = pack_backend__refresh((git_odb_backend *)backend);
|
||||
}
|
||||
|
@ -14,13 +14,13 @@
|
||||
#include <limits.h>
|
||||
|
||||
const git_oid git_oid__empty_blob_sha1 =
|
||||
{{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
|
||||
0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
|
||||
GIT_OID_INIT(GIT_OID_SHA1,
|
||||
{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
|
||||
0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 });
|
||||
const git_oid git_oid__empty_tree_sha1 =
|
||||
{{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
|
||||
|
||||
static char to_hex[] = "0123456789abcdef";
|
||||
GIT_OID_INIT(GIT_OID_SHA1,
|
||||
{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 });
|
||||
|
||||
static int oid_error_invalid(const char *msg)
|
||||
{
|
||||
@ -28,21 +28,31 @@ static int oid_error_invalid(const char *msg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
|
||||
int git_oid__fromstrn(
|
||||
git_oid *out,
|
||||
const char *str,
|
||||
size_t length,
|
||||
git_oid_t type)
|
||||
{
|
||||
size_t p;
|
||||
size_t size, p;
|
||||
int v;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(str);
|
||||
|
||||
if (!(size = git_oid_size(type)))
|
||||
return oid_error_invalid("unknown type");
|
||||
|
||||
if (!length)
|
||||
return oid_error_invalid("too short");
|
||||
|
||||
if (length > GIT_OID_HEXSZ)
|
||||
if (length > git_oid_hexsize(type))
|
||||
return oid_error_invalid("too long");
|
||||
|
||||
memset(out->id, 0, GIT_OID_RAWSZ);
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = type;
|
||||
#endif
|
||||
memset(out->id, 0, size);
|
||||
|
||||
for (p = 0; p < length; p++) {
|
||||
v = git__fromhex(str[p]);
|
||||
@ -55,87 +65,128 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_oid__fromstrp(git_oid *out, const char *str, git_oid_t type)
|
||||
{
|
||||
return git_oid__fromstrn(out, str, strlen(str), type);
|
||||
}
|
||||
|
||||
int git_oid__fromstr(git_oid *out, const char *str, git_oid_t type)
|
||||
{
|
||||
return git_oid__fromstrn(out, str, git_oid_hexsize(type), type);
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_oid_fromstrn(
|
||||
git_oid *out,
|
||||
const char *str,
|
||||
size_t length,
|
||||
git_oid_t type)
|
||||
{
|
||||
return git_oid__fromstrn(out, str, length, type);
|
||||
}
|
||||
|
||||
int git_oid_fromstrp(git_oid *out, const char *str, git_oid_t type)
|
||||
{
|
||||
return git_oid_fromstrn(out, str, strlen(str), type);
|
||||
}
|
||||
|
||||
int git_oid_fromstr(git_oid *out, const char *str, git_oid_t type)
|
||||
{
|
||||
return git_oid_fromstrn(out, str, git_oid_hexsize(type), type);
|
||||
}
|
||||
#else
|
||||
int git_oid_fromstrn(
|
||||
git_oid *out,
|
||||
const char *str,
|
||||
size_t length)
|
||||
{
|
||||
return git_oid__fromstrn(out, str, length, GIT_OID_SHA1);
|
||||
}
|
||||
|
||||
int git_oid_fromstrp(git_oid *out, const char *str)
|
||||
{
|
||||
return git_oid_fromstrn(out, str, strlen(str));
|
||||
return git_oid__fromstrn(out, str, strlen(str), GIT_OID_SHA1);
|
||||
}
|
||||
|
||||
int git_oid_fromstr(git_oid *out, const char *str)
|
||||
{
|
||||
return git_oid_fromstrn(out, str, GIT_OID_HEXSZ);
|
||||
}
|
||||
|
||||
GIT_INLINE(char) *fmt_one(char *str, unsigned int val)
|
||||
{
|
||||
*str++ = to_hex[val >> 4];
|
||||
*str++ = to_hex[val & 0xf];
|
||||
return str;
|
||||
return git_oid__fromstrn(out, str, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int git_oid_nfmt(char *str, size_t n, const git_oid *oid)
|
||||
{
|
||||
size_t i, max_i;
|
||||
size_t hex_size;
|
||||
|
||||
if (!oid) {
|
||||
memset(str, 0, n);
|
||||
return 0;
|
||||
}
|
||||
if (n > GIT_OID_HEXSZ) {
|
||||
memset(&str[GIT_OID_HEXSZ], 0, n - GIT_OID_HEXSZ);
|
||||
n = GIT_OID_HEXSZ;
|
||||
|
||||
if (!(hex_size = git_oid_hexsize(git_oid_type(oid))))
|
||||
return oid_error_invalid("unknown type");
|
||||
|
||||
if (n > hex_size) {
|
||||
memset(&str[hex_size], 0, n - hex_size);
|
||||
n = hex_size;
|
||||
}
|
||||
|
||||
max_i = n / 2;
|
||||
|
||||
for (i = 0; i < max_i; i++)
|
||||
str = fmt_one(str, oid->id[i]);
|
||||
|
||||
if (n & 1)
|
||||
*str++ = to_hex[oid->id[i] >> 4];
|
||||
|
||||
git_oid_fmt_substr(str, oid, 0, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_oid_fmt(char *str, const git_oid *oid)
|
||||
{
|
||||
return git_oid_nfmt(str, GIT_OID_HEXSZ, oid);
|
||||
return git_oid_nfmt(str, git_oid_hexsize(git_oid_type(oid)), oid);
|
||||
}
|
||||
|
||||
int git_oid_pathfmt(char *str, const git_oid *oid)
|
||||
{
|
||||
size_t i;
|
||||
size_t hex_size;
|
||||
|
||||
str = fmt_one(str, oid->id[0]);
|
||||
*str++ = '/';
|
||||
for (i = 1; i < sizeof(oid->id); i++)
|
||||
str = fmt_one(str, oid->id[i]);
|
||||
if (!(hex_size = git_oid_hexsize(git_oid_type(oid))))
|
||||
return oid_error_invalid("unknown type");
|
||||
|
||||
git_oid_fmt_substr(str, oid, 0, 2);
|
||||
str[2] = '/';
|
||||
git_oid_fmt_substr(&str[3], oid, 2, (hex_size - 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *git_oid_tostr_s(const git_oid *oid)
|
||||
{
|
||||
char *str = GIT_THREADSTATE->oid_fmt;
|
||||
git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
|
||||
git_oid_nfmt(str, git_oid_hexsize(git_oid_type(oid)) + 1, oid);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *git_oid_allocfmt(const git_oid *oid)
|
||||
{
|
||||
char *str = git__malloc(GIT_OID_HEXSZ + 1);
|
||||
if (!str)
|
||||
size_t hex_size = git_oid_hexsize(git_oid_type(oid));
|
||||
char *str = git__malloc(hex_size + 1);
|
||||
|
||||
if (!hex_size || !str)
|
||||
return NULL;
|
||||
git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
|
||||
|
||||
if (git_oid_nfmt(str, hex_size + 1, oid) < 0) {
|
||||
git__free(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char *git_oid_tostr(char *out, size_t n, const git_oid *oid)
|
||||
{
|
||||
size_t hex_size;
|
||||
|
||||
if (!out || n == 0)
|
||||
return "";
|
||||
|
||||
if (n > GIT_OID_HEXSZ + 1)
|
||||
n = GIT_OID_HEXSZ + 1;
|
||||
hex_size = oid ? git_oid_hexsize(git_oid_type(oid)) : 0;
|
||||
|
||||
if (n > hex_size + 1)
|
||||
n = hex_size + 1;
|
||||
|
||||
git_oid_nfmt(out, n - 1, oid); /* allow room for terminating NUL */
|
||||
out[n - 1] = '\0';
|
||||
@ -143,51 +194,44 @@ char *git_oid_tostr(char *out, size_t n, const git_oid *oid)
|
||||
return out;
|
||||
}
|
||||
|
||||
int git_oid__parse(
|
||||
git_oid *oid, const char **buffer_out,
|
||||
const char *buffer_end, const char *header)
|
||||
int git_oid__fromraw(git_oid *out, const unsigned char *raw, git_oid_t type)
|
||||
{
|
||||
const size_t sha_len = GIT_OID_HEXSZ;
|
||||
const size_t header_len = strlen(header);
|
||||
size_t size;
|
||||
|
||||
const char *buffer = *buffer_out;
|
||||
|
||||
if (buffer + (header_len + sha_len + 1) > buffer_end)
|
||||
return -1;
|
||||
|
||||
if (memcmp(buffer, header, header_len) != 0)
|
||||
return -1;
|
||||
|
||||
if (buffer[header_len + sha_len] != '\n')
|
||||
return -1;
|
||||
|
||||
if (git_oid_fromstr(oid, buffer + header_len) < 0)
|
||||
return -1;
|
||||
|
||||
*buffer_out = buffer + (header_len + sha_len + 1);
|
||||
if (!(size = git_oid_size(type)))
|
||||
return oid_error_invalid("unknown type");
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = type;
|
||||
#endif
|
||||
memcpy(out->id, raw, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_oid__writebuf(git_str *buf, const char *header, const git_oid *oid)
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
int git_oid_fromraw(git_oid *out, const unsigned char *raw, git_oid_t type)
|
||||
{
|
||||
char hex_oid[GIT_OID_HEXSZ];
|
||||
|
||||
git_oid_fmt(hex_oid, oid);
|
||||
git_str_puts(buf, header);
|
||||
git_str_put(buf, hex_oid, GIT_OID_HEXSZ);
|
||||
git_str_putc(buf, '\n');
|
||||
return git_oid__fromraw(out, raw, type);
|
||||
}
|
||||
|
||||
#else
|
||||
int git_oid_fromraw(git_oid *out, const unsigned char *raw)
|
||||
{
|
||||
memcpy(out->id, raw, sizeof(out->id));
|
||||
return 0;
|
||||
return git_oid__fromraw(out, raw, GIT_OID_SHA1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int git_oid_cpy(git_oid *out, const git_oid *src)
|
||||
{
|
||||
return git_oid_raw_cpy(out->id, src->id);
|
||||
size_t size;
|
||||
|
||||
if (!(size = git_oid_size(git_oid_type(src))))
|
||||
return oid_error_invalid("unknown type");
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = src->type;
|
||||
#endif
|
||||
|
||||
return git_oid_raw_cpy(out->id, src->id, size);
|
||||
}
|
||||
|
||||
int git_oid_cmp(const git_oid *a, const git_oid *b)
|
||||
@ -202,6 +246,11 @@ int git_oid_equal(const git_oid *a, const git_oid *b)
|
||||
|
||||
int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (oid_a->type != oid_b->type)
|
||||
return oid_a->type - oid_b->type;
|
||||
#endif
|
||||
|
||||
return git_oid_raw_ncmp(oid_a->id, oid_b->id, len);
|
||||
}
|
||||
|
||||
@ -209,9 +258,10 @@ int git_oid_strcmp(const git_oid *oid_a, const char *str)
|
||||
{
|
||||
const unsigned char *a;
|
||||
unsigned char strval;
|
||||
long size = (long)git_oid_size(git_oid_type(oid_a));
|
||||
int hexval;
|
||||
|
||||
for (a = oid_a->id; *str && (a - oid_a->id) < GIT_OID_RAWSZ; ++a) {
|
||||
for (a = oid_a->id; *str && (a - oid_a->id) < size; ++a) {
|
||||
if ((hexval = git__fromhex(*str++)) < 0)
|
||||
return -1;
|
||||
strval = (unsigned char)(hexval << 4);
|
||||
@ -235,8 +285,16 @@ int git_oid_streq(const git_oid *oid_a, const char *str)
|
||||
int git_oid_is_zero(const git_oid *oid_a)
|
||||
{
|
||||
const unsigned char *a = oid_a->id;
|
||||
unsigned int i;
|
||||
for (i = 0; i < GIT_OID_RAWSZ; ++i, ++a)
|
||||
size_t size = git_oid_size(git_oid_type(oid_a)), i;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (!oid_a->type)
|
||||
return 1;
|
||||
else if (!size)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < size; ++i, ++a)
|
||||
if (*a != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
@ -393,7 +451,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
|
||||
idx = 0;
|
||||
is_leaf = false;
|
||||
|
||||
for (i = 0; i < GIT_OID_HEXSZ; ++i) {
|
||||
for (i = 0; i < GIT_OID_SHA1_HEXSIZE; ++i) {
|
||||
int c = git__fromhex(text_oid[i]);
|
||||
trie_node *node;
|
||||
|
||||
|
@ -9,11 +9,120 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "git2/experimental.h"
|
||||
#include "git2/oid.h"
|
||||
#include "hash.h"
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
# define GIT_OID_NONE { 0, { 0 } }
|
||||
# define GIT_OID_INIT(type, ...) { type, __VA_ARGS__ }
|
||||
#else
|
||||
# define GIT_OID_NONE { { 0 } }
|
||||
# define GIT_OID_INIT(type, ...) { __VA_ARGS__ }
|
||||
#endif
|
||||
|
||||
extern const git_oid git_oid__empty_blob_sha1;
|
||||
extern const git_oid git_oid__empty_tree_sha1;
|
||||
|
||||
GIT_INLINE(git_oid_t) git_oid_type(const git_oid *oid)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
return oid->type;
|
||||
#else
|
||||
GIT_UNUSED(oid);
|
||||
return GIT_OID_SHA1;
|
||||
#endif
|
||||
}
|
||||
|
||||
GIT_INLINE(size_t) git_oid_size(git_oid_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GIT_OID_SHA1:
|
||||
return GIT_OID_SHA1_SIZE;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
case GIT_OID_SHA256:
|
||||
return GIT_OID_SHA256_SIZE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(size_t) git_oid_hexsize(git_oid_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GIT_OID_SHA1:
|
||||
return GIT_OID_SHA1_HEXSIZE;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
case GIT_OID_SHA256:
|
||||
return GIT_OID_SHA256_HEXSIZE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(const char *) git_oid_type_name(git_oid_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GIT_OID_SHA1:
|
||||
return "sha1";
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
case GIT_OID_SHA256:
|
||||
return "sha256";
|
||||
#endif
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
GIT_INLINE(git_oid_t) git_oid_type_fromstr(const char *name)
|
||||
{
|
||||
if (strcmp(name, "sha1") == 0)
|
||||
return GIT_OID_SHA1;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (strcmp(name, "sha256") == 0)
|
||||
return GIT_OID_SHA256;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(git_oid_t) git_oid_type_fromstrn(const char *name, size_t len)
|
||||
{
|
||||
if (len == CONST_STRLEN("sha1") && strncmp(name, "sha1", len) == 0)
|
||||
return GIT_OID_SHA1;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (len == CONST_STRLEN("sha256") && strncmp(name, "sha256", len) == 0)
|
||||
return GIT_OID_SHA256;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(git_hash_algorithm_t) git_oid_algorithm(git_oid_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GIT_OID_SHA1:
|
||||
return GIT_HASH_ALGORITHM_SHA1;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
case GIT_OID_SHA256:
|
||||
return GIT_HASH_ALGORITHM_SHA256;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a git_oid into a newly allocated c-string.
|
||||
*
|
||||
@ -25,13 +134,42 @@ extern const git_oid git_oid__empty_tree_sha1;
|
||||
*/
|
||||
char *git_oid_allocfmt(const git_oid *id);
|
||||
|
||||
/**
|
||||
* Format the requested nibbles of an object id.
|
||||
*
|
||||
* @param str the string to write into
|
||||
* @param oid the oid structure to format
|
||||
* @param start the starting number of nibbles
|
||||
* @param count the number of nibbles to format
|
||||
*/
|
||||
GIT_INLINE(void) git_oid_fmt_substr(
|
||||
char *str,
|
||||
const git_oid *oid,
|
||||
size_t start,
|
||||
size_t count)
|
||||
{
|
||||
static char hex[] = "0123456789abcdef";
|
||||
size_t i, end = start + count, min = start / 2, max = end / 2;
|
||||
|
||||
if (start & 1)
|
||||
*str++ = hex[oid->id[min++] & 0x0f];
|
||||
|
||||
for (i = min; i < max; i++) {
|
||||
*str++ = hex[oid->id[i] >> 4];
|
||||
*str++ = hex[oid->id[i] & 0x0f];
|
||||
}
|
||||
|
||||
if (end & 1)
|
||||
*str++ = hex[oid->id[i] >> 4];
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_oid_raw_ncmp(
|
||||
const unsigned char *sha1,
|
||||
const unsigned char *sha2,
|
||||
size_t len)
|
||||
{
|
||||
if (len > GIT_OID_HEXSZ)
|
||||
len = GIT_OID_HEXSZ;
|
||||
if (len > GIT_OID_MAX_HEXSIZE)
|
||||
len = GIT_OID_MAX_HEXSIZE;
|
||||
|
||||
while (len > 1) {
|
||||
if (*sha1 != *sha2)
|
||||
@ -50,16 +188,18 @@ GIT_INLINE(int) git_oid_raw_ncmp(
|
||||
|
||||
GIT_INLINE(int) git_oid_raw_cmp(
|
||||
const unsigned char *sha1,
|
||||
const unsigned char *sha2)
|
||||
const unsigned char *sha2,
|
||||
size_t size)
|
||||
{
|
||||
return memcmp(sha1, sha2, GIT_OID_RAWSZ);
|
||||
return memcmp(sha1, sha2, size);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_oid_raw_cpy(
|
||||
unsigned char *dst,
|
||||
const unsigned char *src)
|
||||
const unsigned char *src,
|
||||
size_t size)
|
||||
{
|
||||
memcpy(dst, src, GIT_OID_RAWSZ);
|
||||
memcpy(dst, src, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -72,19 +212,30 @@ GIT_INLINE(int) git_oid_raw_cpy(
|
||||
*/
|
||||
GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
|
||||
{
|
||||
return git_oid_raw_cmp(a->id, b->id);
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
if (a->type != b->type)
|
||||
return a->type - b->type;
|
||||
|
||||
return git_oid_raw_cmp(a->id, b->id, git_oid_size(a->type));
|
||||
#else
|
||||
return git_oid_raw_cmp(a->id, b->id, git_oid_size(GIT_OID_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
GIT_INLINE(void) git_oid__cpy_prefix(
|
||||
git_oid *out, const git_oid *id, size_t len)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = id->type;
|
||||
#endif
|
||||
|
||||
memcpy(&out->id, id->id, (len + 1) / 2);
|
||||
|
||||
if (len & 1)
|
||||
out->id[len / 2] &= 0xF0;
|
||||
}
|
||||
|
||||
GIT_INLINE(bool) git_oid__is_hexstr(const char *str)
|
||||
GIT_INLINE(bool) git_oid__is_hexstr(const char *str, git_oid_t type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -93,7 +244,30 @@ GIT_INLINE(bool) git_oid__is_hexstr(const char *str)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (i == GIT_OID_HEXSZ);
|
||||
return (i == git_oid_hexsize(type));
|
||||
}
|
||||
|
||||
GIT_INLINE(void) git_oid_clear(git_oid *out, git_oid_t type)
|
||||
{
|
||||
memset(out->id, 0, git_oid_size(type));
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
out->type = type;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* SHA256 support */
|
||||
|
||||
int git_oid__fromstr(git_oid *out, const char *str, git_oid_t type);
|
||||
|
||||
int git_oid__fromstrp(git_oid *out, const char *str, git_oid_t type);
|
||||
|
||||
int git_oid__fromstrn(
|
||||
git_oid *out,
|
||||
const char *str,
|
||||
size_t length,
|
||||
git_oid_t type);
|
||||
|
||||
int git_oid__fromraw(git_oid *out, const unsigned char *raw, git_oid_t type);
|
||||
|
||||
#endif
|
||||
|
@ -347,8 +347,8 @@ static int write_object(
|
||||
goto done;
|
||||
|
||||
if (type == GIT_OBJECT_REF_DELTA) {
|
||||
if ((error = write_cb(po->delta->id.id, GIT_OID_RAWSZ, cb_data)) < 0 ||
|
||||
(error = git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ)) < 0)
|
||||
if ((error = write_cb(po->delta->id.id, GIT_OID_SHA1_SIZE, cb_data)) < 0 ||
|
||||
(error = git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_SHA1_SIZE)) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -668,7 +668,7 @@ static int write_pack(git_packbuilder *pb,
|
||||
if ((error = git_hash_final(entry_oid.id, &pb->ctx)) < 0)
|
||||
goto done;
|
||||
|
||||
error = write_cb(entry_oid.id, GIT_OID_RAWSZ, cb_data);
|
||||
error = write_cb(entry_oid.id, GIT_OID_SHA1_SIZE, cb_data);
|
||||
|
||||
done:
|
||||
/* if callback cancelled writing, we must still free delta_data */
|
||||
@ -1407,7 +1407,18 @@ int git_packbuilder_write(
|
||||
opts.progress_cb = progress_cb;
|
||||
opts.progress_cb_payload = progress_cb_payload;
|
||||
|
||||
if ((error = git_indexer_new(&indexer, path, mode, pb->odb, &opts)) < 0)
|
||||
/* TODO: SHA256 */
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
opts.mode = mode;
|
||||
opts.odb = pb->odb;
|
||||
|
||||
error = git_indexer_new(&indexer, path, GIT_OID_SHA1, &opts);
|
||||
#else
|
||||
error = git_indexer_new(&indexer, path, mode, pb->odb, &opts);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!git_repository__configmap_lookup(&t, pb->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t)
|
||||
|
@ -32,7 +32,7 @@ static int packfile_unpack_compressed(
|
||||
* Throws GIT_EAMBIGUOUSOIDPREFIX if short oid
|
||||
* is ambiguous within the pack.
|
||||
* This method assumes that len is between
|
||||
* GIT_OID_MINPREFIXLEN and GIT_OID_HEXSZ.
|
||||
* GIT_OID_MINPREFIXLEN and the oid type's hexsize.
|
||||
*/
|
||||
static int pack_entry_find_offset(
|
||||
off64_t *offset_out,
|
||||
@ -186,9 +186,9 @@ static int cache_add(
|
||||
|
||||
static void pack_index_free(struct git_pack_file *p)
|
||||
{
|
||||
if (p->oids) {
|
||||
git__free(p->oids);
|
||||
p->oids = NULL;
|
||||
if (p->ids) {
|
||||
git__free(p->ids);
|
||||
p->ids = NULL;
|
||||
}
|
||||
if (p->index_map.data) {
|
||||
git_futils_mmap_free(&p->index_map);
|
||||
@ -200,11 +200,12 @@ static void pack_index_free(struct git_pack_file *p)
|
||||
static int pack_index_check_locked(const char *path, struct git_pack_file *p)
|
||||
{
|
||||
struct git_pack_idx_header *hdr;
|
||||
uint32_t version, nr, i, *index;
|
||||
uint32_t version, nr = 0, i, *index;
|
||||
void *idx_map;
|
||||
size_t idx_size;
|
||||
struct stat st;
|
||||
int error;
|
||||
|
||||
/* TODO: properly open the file without access time using O_NOATIME */
|
||||
git_file fd = git_futils_open_ro(path);
|
||||
if (fd < 0)
|
||||
@ -218,8 +219,7 @@ static int pack_index_check_locked(const char *path, struct git_pack_file *p)
|
||||
|
||||
if (!S_ISREG(st.st_mode) ||
|
||||
!git__is_sizet(st.st_size) ||
|
||||
(idx_size = (size_t)st.st_size) < 4 * 256 + 20 + 20)
|
||||
{
|
||||
(idx_size = (size_t)st.st_size) < (size_t)((4 * 256) + (p->oid_size * 2))) {
|
||||
p_close(fd);
|
||||
git_error_set(GIT_ERROR_ODB, "invalid pack index '%s'", path);
|
||||
return -1;
|
||||
@ -242,10 +242,10 @@ static int pack_index_check_locked(const char *path, struct git_pack_file *p)
|
||||
return packfile_error("unsupported index version");
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
version = 1;
|
||||
}
|
||||
|
||||
nr = 0;
|
||||
index = idx_map;
|
||||
|
||||
if (version > 1)
|
||||
@ -264,11 +264,11 @@ static int pack_index_check_locked(const char *path, struct git_pack_file *p)
|
||||
/*
|
||||
* Total size:
|
||||
* - 256 index entries 4 bytes each
|
||||
* - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
|
||||
* - 20-byte SHA1 of the packfile
|
||||
* - 20-byte SHA1 file checksum
|
||||
* - 24/36-byte entries * nr (20/32 byte SHA + 4-byte offset)
|
||||
* - 20/32-byte SHA of the packfile
|
||||
* - 20/32-byte SHA file checksum
|
||||
*/
|
||||
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
|
||||
if (idx_size != (4 * 256 + ((uint64_t) nr * (p->oid_size + 4)) + (p->oid_size * 2))) {
|
||||
git_futils_mmap_free(&p->index_map);
|
||||
return packfile_error("index is corrupted");
|
||||
}
|
||||
@ -277,17 +277,17 @@ static int pack_index_check_locked(const char *path, struct git_pack_file *p)
|
||||
* Minimum size:
|
||||
* - 8 bytes of header
|
||||
* - 256 index entries 4 bytes each
|
||||
* - 20-byte sha1 entry * nr
|
||||
* - 20/32-byte SHA entry * nr
|
||||
* - 4-byte crc entry * nr
|
||||
* - 4-byte offset entry * nr
|
||||
* - 20-byte SHA1 of the packfile
|
||||
* - 20-byte SHA1 file checksum
|
||||
* - 20/32-byte SHA of the packfile
|
||||
* - 20/32-byte SHA file checksum
|
||||
* And after the 4-byte offset table might be a
|
||||
* variable sized table containing 8-byte entries
|
||||
* for offsets larger than 2^31.
|
||||
*/
|
||||
unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
|
||||
unsigned long max_size = min_size;
|
||||
uint64_t min_size = 8 + (4 * 256) + ((uint64_t)nr * (p->oid_size + 4 + 4)) + (p->oid_size * 2);
|
||||
uint64_t max_size = min_size;
|
||||
|
||||
if (nr)
|
||||
max_size += (nr - 1)*8;
|
||||
@ -365,12 +365,12 @@ static unsigned char *pack_window_open(
|
||||
* Don't allow a negative offset, as that means we've wrapped
|
||||
* around.
|
||||
*/
|
||||
if (offset > (p->mwf.size - 20))
|
||||
if (offset > (p->mwf.size - p->oid_size))
|
||||
goto cleanup;
|
||||
if (offset < 0)
|
||||
goto cleanup;
|
||||
|
||||
pack_data = git_mwindow_open(&p->mwf, w_cursor, offset, 20, left);
|
||||
pack_data = git_mwindow_open(&p->mwf, w_cursor, offset, p->oid_size, left);
|
||||
|
||||
cleanup:
|
||||
git_mutex_unlock(&p->mwf.lock);
|
||||
@ -473,13 +473,13 @@ int git_packfile_unpack_header(
|
||||
return error;
|
||||
}
|
||||
|
||||
/* pack_window_open() assures us we have [base, base + 20) available
|
||||
* as a range that we can look at at. (Its actually the hash
|
||||
* size that is assured.) With our object header encoding
|
||||
* the maximum deflated object size is 2^137, which is just
|
||||
* insane, so we know won't exceed what we have been given.
|
||||
/* pack_window_open() assures us we have [base, base + oid_size)
|
||||
* available as a range that we can look at at. (It's actually
|
||||
* the hash size that is assured.) With our object header
|
||||
* encoding the maximum deflated object size is 2^137, which is
|
||||
* just insane, so we know won't exceed what we have been given.
|
||||
*/
|
||||
base = git_mwindow_open(&p->mwf, w_curs, *curpos, 20, &left);
|
||||
base = git_mwindow_open(&p->mwf, w_curs, *curpos, p->oid_size, &left);
|
||||
git_mutex_unlock(&p->lock);
|
||||
git_mutex_unlock(&p->mwf.lock);
|
||||
if (base == NULL)
|
||||
@ -977,11 +977,12 @@ int get_delta_base(
|
||||
/* Assumption: the only reason this would fail is because the file is too small */
|
||||
if (base_info == NULL)
|
||||
return GIT_EBUFS;
|
||||
/* pack_window_open() assured us we have [base_info, base_info + 20)
|
||||
* as a range that we can look at without walking off the
|
||||
* end of the mapped window. Its actually the hash size
|
||||
* that is assured. An OFS_DELTA longer than the hash size
|
||||
* is stupid, as then a REF_DELTA would be smaller to store.
|
||||
/* pack_window_open() assured us we have
|
||||
* [base_info, base_info + oid_size) as a range that we can look
|
||||
* at without walking off the end of the mapped window. Its
|
||||
* actually the hash size that is assured. An OFS_DELTA longer
|
||||
* than the hash size is stupid, as then a REF_DELTA would be
|
||||
* smaller to store.
|
||||
*/
|
||||
if (type == GIT_OBJECT_OFS_DELTA) {
|
||||
unsigned used = 0;
|
||||
@ -1002,7 +1003,7 @@ int get_delta_base(
|
||||
*curpos += used;
|
||||
} else if (type == GIT_OBJECT_REF_DELTA) {
|
||||
git_oid base_oid;
|
||||
git_oid_fromraw(&base_oid, base_info);
|
||||
git_oid__fromraw(&base_oid, base_info, p->oid_type);
|
||||
|
||||
/* If we have the cooperative cache, search in it first */
|
||||
if (p->has_cache) {
|
||||
@ -1012,7 +1013,7 @@ int get_delta_base(
|
||||
if (entry->offset == 0)
|
||||
return packfile_error("delta offset is zero");
|
||||
|
||||
*curpos += 20;
|
||||
*curpos += p->oid_size;
|
||||
*delta_base_out = entry->offset;
|
||||
return 0;
|
||||
} else {
|
||||
@ -1025,9 +1026,9 @@ int get_delta_base(
|
||||
}
|
||||
|
||||
/* The base entry _must_ be in the same pack */
|
||||
if (pack_entry_find_offset(&base_offset, &unused, p, &base_oid, GIT_OID_HEXSZ) < 0)
|
||||
if (pack_entry_find_offset(&base_offset, &unused, p, &base_oid, p->oid_hexsize) < 0)
|
||||
return packfile_error("base entry delta is not in the same pack");
|
||||
*curpos += 20;
|
||||
*curpos += p->oid_size;
|
||||
} else
|
||||
return packfile_error("unknown object type");
|
||||
|
||||
@ -1070,7 +1071,7 @@ void git_packfile_free(struct git_pack_file *p, bool unlink_packfile)
|
||||
|
||||
pack_index_free(p);
|
||||
|
||||
git__free(p->bad_object_sha1);
|
||||
git__free(p->bad_object_ids);
|
||||
|
||||
git_mutex_free(&p->bases.lock);
|
||||
git_mutex_free(&p->mwf.lock);
|
||||
@ -1083,8 +1084,8 @@ static int packfile_open_locked(struct git_pack_file *p)
|
||||
{
|
||||
struct stat st;
|
||||
struct git_pack_header hdr;
|
||||
unsigned char sha1[GIT_OID_RAWSZ];
|
||||
unsigned char *idx_sha1;
|
||||
unsigned char checksum[GIT_OID_MAX_SIZE];
|
||||
unsigned char *idx_checksum;
|
||||
|
||||
if (pack_index_open_locked(p) < 0)
|
||||
return git_odb__error_notfound("failed to open packfile", NULL, 0);
|
||||
@ -1131,12 +1132,13 @@ static int packfile_open_locked(struct git_pack_file *p)
|
||||
|
||||
/* Verify the pack matches its index. */
|
||||
if (p->num_objects != ntohl(hdr.hdr_entries) ||
|
||||
p_pread(p->mwf.fd, sha1, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
|
||||
p_pread(p->mwf.fd, checksum, p->oid_size, p->mwf.size - p->oid_size) < 0)
|
||||
goto cleanup;
|
||||
|
||||
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
|
||||
idx_checksum = ((unsigned char *)p->index_map.data) +
|
||||
p->index_map.len - (p->oid_size * 2);
|
||||
|
||||
if (git_oid_raw_cmp(sha1, idx_sha1) != 0)
|
||||
if (git_oid_raw_cmp(checksum, idx_checksum, p->oid_size) != 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_mwindow_file_register(&p->mwf) < 0)
|
||||
@ -1171,7 +1173,10 @@ int git_packfile__name(char **out, const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
|
||||
int git_packfile_alloc(
|
||||
struct git_pack_file **pack_out,
|
||||
const char *path,
|
||||
git_oid_t oid_type)
|
||||
{
|
||||
struct stat st;
|
||||
struct git_pack_file *p;
|
||||
@ -1219,6 +1224,9 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
|
||||
p->pack_local = 1;
|
||||
p->mtime = (git_time_t)st.st_mtime;
|
||||
p->index_version = -1;
|
||||
p->oid_type = oid_type ? oid_type : GIT_OID_DEFAULT;
|
||||
p->oid_size = (unsigned int)git_oid_size(p->oid_type);
|
||||
p->oid_hexsize = (unsigned int)git_oid_hexsize(p->oid_type);
|
||||
|
||||
if (git_mutex_init(&p->lock) < 0) {
|
||||
git_error_set(GIT_ERROR_OS, "failed to initialize packfile mutex");
|
||||
@ -1260,9 +1268,9 @@ static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t
|
||||
end = index + p->index_map.len;
|
||||
index += 4 * 256;
|
||||
if (p->index_version == 1)
|
||||
return ntohl(*((uint32_t *)(index + 24 * n)));
|
||||
return ntohl(*((uint32_t *)(index + (p->oid_size + 4) * n)));
|
||||
|
||||
index += 8 + p->num_objects * (20 + 4);
|
||||
index += 8 + p->num_objects * (p->oid_size + 4);
|
||||
off32 = ntohl(*((uint32_t *)(index + 4 * n)));
|
||||
if (!(off32 & 0x80000000))
|
||||
return off32;
|
||||
@ -1273,7 +1281,7 @@ static off64_t nth_packed_object_offset_locked(struct git_pack_file *p, uint32_t
|
||||
return -1;
|
||||
|
||||
return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
|
||||
ntohl(*((uint32_t *)(index + 4)));
|
||||
ntohl(*((uint32_t *)(index + 4)));
|
||||
}
|
||||
|
||||
static int git__memcmp4(const void *a, const void *b) {
|
||||
@ -1312,7 +1320,7 @@ int git_pack_foreach_entry(
|
||||
|
||||
index += 4 * 256;
|
||||
|
||||
if (p->oids == NULL) {
|
||||
if (p->ids == NULL) {
|
||||
git_vector offsets, oids;
|
||||
|
||||
if ((error = git_vector_init(&oids, p->num_objects, NULL))) {
|
||||
@ -1326,22 +1334,25 @@ int git_pack_foreach_entry(
|
||||
}
|
||||
|
||||
if (p->index_version > 1) {
|
||||
const unsigned char *off = index + 24 * p->num_objects;
|
||||
const unsigned char *off = index +
|
||||
(p->oid_size + 4) * p->num_objects;
|
||||
|
||||
for (i = 0; i < p->num_objects; i++)
|
||||
git_vector_insert(&offsets, (void*)&off[4 * i]);
|
||||
|
||||
git_vector_sort(&offsets);
|
||||
git_vector_foreach(&offsets, i, current)
|
||||
git_vector_insert(&oids, (void*)&index[5 * (current - off)]);
|
||||
} else {
|
||||
for (i = 0; i < p->num_objects; i++)
|
||||
git_vector_insert(&offsets, (void*)&index[24 * i]);
|
||||
git_vector_insert(&offsets, (void*)&index[(p->oid_size + 4) * i]);
|
||||
git_vector_sort(&offsets);
|
||||
git_vector_foreach(&offsets, i, current)
|
||||
git_vector_insert(&oids, (void*)¤t[4]);
|
||||
}
|
||||
|
||||
git_vector_free(&offsets);
|
||||
p->oids = (unsigned char **)git_vector_detach(NULL, NULL, &oids);
|
||||
p->ids = (unsigned char **)git_vector_detach(NULL, NULL, &oids);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1362,7 +1373,7 @@ int git_pack_foreach_entry(
|
||||
git_array_clear(oids);
|
||||
GIT_ERROR_CHECK_ALLOC(oid);
|
||||
}
|
||||
git_oid_fromraw(oid, p->oids[i]);
|
||||
git_oid__fromraw(oid, p->ids[i], p->oid_type);
|
||||
}
|
||||
|
||||
git_mutex_unlock(&p->lock);
|
||||
@ -1412,10 +1423,13 @@ int git_pack_foreach_entry_offset(
|
||||
|
||||
/* all offsets should have been validated by pack_index_check_locked */
|
||||
if (p->index_version > 1) {
|
||||
const unsigned char *offsets = index + 24 * p->num_objects;
|
||||
const unsigned char *offsets = index +
|
||||
(p->oid_size + 4) * p->num_objects;
|
||||
const unsigned char *large_offset_ptr;
|
||||
const unsigned char *large_offsets = index + 28 * p->num_objects;
|
||||
const unsigned char *large_offsets_end = ((const unsigned char *)p->index_map.data) + p->index_map.len - 20;
|
||||
const unsigned char *large_offsets = index +
|
||||
(p->oid_size + 8) * p->num_objects;
|
||||
const unsigned char *large_offsets_end = ((const unsigned char *)p->index_map.data) + p->index_map.len - p->oid_size;
|
||||
|
||||
for (i = 0; i < p->num_objects; i++) {
|
||||
current_offset = ntohl(*(const uint32_t *)(offsets + 4 * i));
|
||||
if (current_offset & 0x80000000) {
|
||||
@ -1428,7 +1442,7 @@ int git_pack_foreach_entry_offset(
|
||||
ntohl(*((uint32_t *)(large_offset_ptr + 4)));
|
||||
}
|
||||
|
||||
git_oid_fromraw(¤t_oid, (index + 20 * i));
|
||||
git_oid__fromraw(¤t_oid, (index + p->oid_size * i), p->oid_type);
|
||||
if ((error = cb(¤t_oid, current_offset, data)) != 0) {
|
||||
error = git_error_set_after_callback(error);
|
||||
goto cleanup;
|
||||
@ -1436,8 +1450,8 @@ int git_pack_foreach_entry_offset(
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < p->num_objects; i++) {
|
||||
current_offset = ntohl(*(const uint32_t *)(index + 24 * i));
|
||||
git_oid_fromraw(¤t_oid, (index + 24 * i + 4));
|
||||
current_offset = ntohl(*(const uint32_t *)(index + (p->oid_size + 4) * i));
|
||||
git_oid__fromraw(¤t_oid, (index + (p->oid_size + 4) * i + 4), p->oid_type);
|
||||
if ((error = cb(¤t_oid, current_offset, data)) != 0) {
|
||||
error = git_error_set_after_callback(error);
|
||||
goto cleanup;
|
||||
@ -1450,14 +1464,20 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo,
|
||||
unsigned hi, const unsigned char *oid_prefix)
|
||||
int git_pack__lookup_id(
|
||||
const void *oid_lookup_table,
|
||||
size_t stride,
|
||||
unsigned lo,
|
||||
unsigned hi,
|
||||
const unsigned char *oid_prefix,
|
||||
const git_oid_t oid_type)
|
||||
{
|
||||
const unsigned char *base = oid_lookup_table;
|
||||
size_t oid_size = git_oid_size(oid_type);
|
||||
|
||||
while (lo < hi) {
|
||||
unsigned mi = (lo + hi) / 2;
|
||||
int cmp = git_oid_raw_cmp(base + mi * stride, oid_prefix);
|
||||
int cmp = git_oid_raw_cmp(base + mi * stride, oid_prefix, oid_size);
|
||||
|
||||
if (!cmp)
|
||||
return mi;
|
||||
@ -1512,9 +1532,9 @@ static int pack_entry_find_offset(
|
||||
lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(level1_ofs[(int)short_oid->id[0] - 1]));
|
||||
|
||||
if (p->index_version > 1) {
|
||||
stride = 20;
|
||||
stride = p->oid_size;
|
||||
} else {
|
||||
stride = 24;
|
||||
stride = p->oid_size + 4;
|
||||
index += 4;
|
||||
}
|
||||
|
||||
@ -1523,7 +1543,8 @@ static int pack_entry_find_offset(
|
||||
short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects);
|
||||
#endif
|
||||
|
||||
pos = git_pack__lookup_sha1(index, stride, lo, hi, short_oid->id);
|
||||
pos = git_pack__lookup_id(index, stride, lo, hi,
|
||||
short_oid->id, p->oid_type);
|
||||
|
||||
if (pos >= 0) {
|
||||
/* An object matching exactly the oid was found */
|
||||
@ -1541,7 +1562,9 @@ static int pack_entry_find_offset(
|
||||
}
|
||||
}
|
||||
|
||||
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)p->num_objects) {
|
||||
if (found &&
|
||||
len != p->oid_hexsize &&
|
||||
pos + 1 < (int)p->num_objects) {
|
||||
/* Check for ambiguousity */
|
||||
const unsigned char *next = current + stride;
|
||||
|
||||
@ -1566,13 +1589,13 @@ static int pack_entry_find_offset(
|
||||
}
|
||||
|
||||
*offset_out = offset;
|
||||
git_oid_fromraw(found_oid, current);
|
||||
git_oid__fromraw(found_oid, current, p->oid_type);
|
||||
|
||||
#ifdef INDEX_DEBUG_LOOKUP
|
||||
{
|
||||
unsigned char hex_sha1[GIT_OID_HEXSZ + 1];
|
||||
char hex_sha1[p->oid_hexsize + 1];
|
||||
git_oid_fmt(hex_sha1, found_oid);
|
||||
hex_sha1[GIT_OID_HEXSZ] = '\0';
|
||||
hex_sha1[p->oid_hexsize] = '\0';
|
||||
printf("found lo=%d %s\n", lo, hex_sha1);
|
||||
}
|
||||
#endif
|
||||
@ -1594,10 +1617,10 @@ int git_pack_entry_find(
|
||||
|
||||
GIT_ASSERT_ARG(p);
|
||||
|
||||
if (len == GIT_OID_HEXSZ && p->num_bad_objects) {
|
||||
if (len == p->oid_hexsize && p->num_bad_objects) {
|
||||
unsigned i;
|
||||
for (i = 0; i < p->num_bad_objects; i++)
|
||||
if (git_oid__cmp(short_oid, &p->bad_object_sha1[i]) == 0)
|
||||
if (git_oid__cmp(short_oid, &p->bad_object_ids[i]) == 0)
|
||||
return packfile_error("bad object found in packfile");
|
||||
}
|
||||
|
||||
@ -1630,6 +1653,6 @@ int git_pack_entry_find(
|
||||
e->offset = offset;
|
||||
e->p = p;
|
||||
|
||||
git_oid_cpy(&e->sha1, &found_oid);
|
||||
git_oid_cpy(&e->id, &found_oid);
|
||||
return 0;
|
||||
}
|
||||
|
@ -99,13 +99,19 @@ struct git_pack_file {
|
||||
|
||||
uint32_t num_objects;
|
||||
uint32_t num_bad_objects;
|
||||
git_oid *bad_object_sha1; /* array of git_oid */
|
||||
git_oid *bad_object_ids; /* array of git_oid */
|
||||
|
||||
git_oid_t oid_type;
|
||||
unsigned oid_hexsize:7,
|
||||
oid_size:6,
|
||||
pack_local:1,
|
||||
pack_keep:1,
|
||||
has_cache:1;
|
||||
|
||||
int index_version;
|
||||
git_time_t mtime;
|
||||
unsigned pack_local:1, pack_keep:1, has_cache:1;
|
||||
git_oidmap *idx_cache;
|
||||
unsigned char **oids;
|
||||
unsigned char **ids;
|
||||
|
||||
git_pack_cache bases; /* delta base cache */
|
||||
|
||||
@ -116,21 +122,26 @@ struct git_pack_file {
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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).
|
||||
* 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 = oid_size + 4), whereas files with version 2 store
|
||||
* them in a contiguous flat array (stride = oid_size).
|
||||
*/
|
||||
int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned lo,
|
||||
unsigned hi, const unsigned char *oid_prefix);
|
||||
int git_pack__lookup_id(
|
||||
const void *id_lookup_table,
|
||||
size_t stride,
|
||||
unsigned lo,
|
||||
unsigned hi,
|
||||
const unsigned char *id_prefix,
|
||||
const git_oid_t oid_type);
|
||||
|
||||
struct git_pack_entry {
|
||||
off64_t offset;
|
||||
git_oid sha1;
|
||||
git_oid id;
|
||||
struct git_pack_file *p;
|
||||
};
|
||||
|
||||
@ -174,12 +185,15 @@ int get_delta_base(
|
||||
off64_t delta_obj_offset);
|
||||
|
||||
void git_packfile_free(struct git_pack_file *p, bool unlink_packfile);
|
||||
int git_packfile_alloc(struct git_pack_file **pack_out, const char *path);
|
||||
int git_packfile_alloc(
|
||||
struct git_pack_file **pack_out,
|
||||
const char *path,
|
||||
git_oid_t oid_type);
|
||||
|
||||
int git_pack_entry_find(
|
||||
struct git_pack_entry *e,
|
||||
struct git_pack_file *p,
|
||||
const git_oid *short_oid,
|
||||
const git_oid *short_id,
|
||||
size_t len);
|
||||
int git_pack_foreach_entry(
|
||||
struct git_pack_file *p,
|
||||
|
@ -5,6 +5,7 @@
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#include "parse.h"
|
||||
#include "oid.h"
|
||||
|
||||
int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len)
|
||||
{
|
||||
@ -103,11 +104,11 @@ 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)
|
||||
{
|
||||
if (ctx->line_len < GIT_OID_HEXSZ)
|
||||
if (ctx->line_len < GIT_OID_SHA1_HEXSIZE)
|
||||
return -1;
|
||||
if ((git_oid_fromstrn(out, ctx->line, GIT_OID_HEXSZ)) < 0)
|
||||
if ((git_oid__fromstrn(out, ctx->line, GIT_OID_SHA1_HEXSIZE, GIT_OID_SHA1)) < 0)
|
||||
return -1;
|
||||
git_parse_advance_chars(ctx, GIT_OID_HEXSZ);
|
||||
git_parse_advance_chars(ctx, GIT_OID_SHA1_HEXSIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -168,13 +168,13 @@ static int parse_header_oid(
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; len < ctx->parse_ctx.line_len && len < GIT_OID_HEXSZ; len++) {
|
||||
for (len = 0; len < ctx->parse_ctx.line_len && len < GIT_OID_SHA1_HEXSIZE; len++) {
|
||||
if (!git__isxdigit(ctx->parse_ctx.line[len]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (len < GIT_OID_MINPREFIXLEN || len > GIT_OID_HEXSZ ||
|
||||
git_oid_fromstrn(oid, ctx->parse_ctx.line, len) < 0)
|
||||
if (len < GIT_OID_MINPREFIXLEN || len > GIT_OID_SHA1_HEXSIZE ||
|
||||
git_oid__fromstrn(oid, ctx->parse_ctx.line, len, GIT_OID_SHA1) < 0)
|
||||
return git_parse_err("invalid hex formatted object id at line %"PRIuZ,
|
||||
ctx->parse_ctx.line_num);
|
||||
|
||||
@ -1065,12 +1065,12 @@ static int check_patch(git_patch_parsed *patch)
|
||||
return git_parse_err("patch with no hunks");
|
||||
|
||||
if (delta->status == GIT_DELTA_ADDED) {
|
||||
memset(&delta->old_file.id, 0x0, sizeof(git_oid));
|
||||
git_oid_clear(&delta->old_file.id, GIT_OID_SHA1);
|
||||
delta->old_file.id_abbrev = 0;
|
||||
}
|
||||
|
||||
if (delta->status == GIT_DELTA_DELETED) {
|
||||
memset(&delta->new_file.id, 0x0, sizeof(git_oid));
|
||||
git_oid_clear(&delta->new_file.id, GIT_OID_SHA1);
|
||||
delta->new_file.id_abbrev = 0;
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,9 @@ static int parse_refspec(git_push *push, push_spec **spec, const char *str)
|
||||
s = git__calloc(1, sizeof(*s));
|
||||
GIT_ERROR_CHECK_ALLOC(s);
|
||||
|
||||
git_oid_clear(&s->loid, GIT_OID_SHA1);
|
||||
git_oid_clear(&s->roid, GIT_OID_SHA1);
|
||||
|
||||
if (git_refspec__parse(&s->refspec, str, false) < 0) {
|
||||
git_error_set(GIT_ERROR_INVALID, "invalid refspec %s", str);
|
||||
goto on_error;
|
||||
@ -382,11 +385,18 @@ static int calculate_work(git_push *push)
|
||||
git_vector_foreach(&push->specs, i, spec) {
|
||||
if (spec->refspec.src && spec->refspec.src[0]!= '\0') {
|
||||
/* This is a create or update. Local ref must exist. */
|
||||
if (git_reference_name_to_id(
|
||||
&spec->loid, push->repo, spec->refspec.src) < 0) {
|
||||
git_error_set(GIT_ERROR_REFERENCE, "no such reference '%s'", spec->refspec.src);
|
||||
|
||||
git_object *obj;
|
||||
int error = git_revparse_single(&obj, push->repo, spec->refspec.src);
|
||||
|
||||
if (error < 0) {
|
||||
git_object_free(obj);
|
||||
git_error_set(GIT_ERROR_REFERENCE, "src refspec %s does not match any", spec->refspec.src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_oid_cpy(&spec->loid, git_object_id(obj));
|
||||
git_object_free(obj);
|
||||
}
|
||||
|
||||
/* Remote ref may or may not (e.g. during create) already exist. */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user