mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-09 22:39:38 +00:00
Update upstream source from tag 'upstream/0.27.7+dfsg.1'
Update to upstream version '0.27.7+dfsg.1'
with Debian dir 3a55b6017d
This commit is contained in:
commit
7838d95547
92
.travis.yml
92
.travis.yml
@ -1,92 +0,0 @@
|
|||||||
# Travis-CI Build for libgit2
|
|
||||||
# see travis-ci.org for details
|
|
||||||
|
|
||||||
language: c
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
|
|
||||||
# Settings to try
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
|
|
||||||
- GITTEST_INVASIVE_FS_SIZE=1
|
|
||||||
matrix:
|
|
||||||
- OPTIONS="-DTHREADSAFE=ON -DENABLE_TRACE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_WERROR=ON"
|
|
||||||
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DENABLE_WERROR=ON"
|
|
||||||
|
|
||||||
dist: trusty
|
|
||||||
osx_image: xcode8.3
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- sourceline: 'deb https://dl.bintray.com/libgit2/ci-dependencies trusty libgit2deps'
|
|
||||||
key_url: 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray'
|
|
||||||
packages:
|
|
||||||
cmake
|
|
||||||
curl
|
|
||||||
libcurl3
|
|
||||||
libcurl3-gnutls
|
|
||||||
libcurl4-gnutls-dev
|
|
||||||
libssh2-1-dev
|
|
||||||
openssh-client
|
|
||||||
openssh-server
|
|
||||||
valgrind
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
exclude:
|
|
||||||
- os: osx
|
|
||||||
compiler: gcc
|
|
||||||
include:
|
|
||||||
- compiler: gcc
|
|
||||||
env: COVERITY=1
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
- compiler: gcc
|
|
||||||
env:
|
|
||||||
- VALGRIND=1
|
|
||||||
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
|
|
||||||
os: linux
|
|
||||||
dist: trusty
|
|
||||||
allow_failures:
|
|
||||||
- env: COVERITY=1
|
|
||||||
|
|
||||||
install:
|
|
||||||
- if [ -f ./script/install-deps-${TRAVIS_OS_NAME}.sh ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
|
|
||||||
|
|
||||||
# Run the Build script and tests
|
|
||||||
script:
|
|
||||||
- script/cibuild.sh
|
|
||||||
|
|
||||||
# Run Tests
|
|
||||||
after_success:
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
|
|
||||||
|
|
||||||
# Only watch the development and master branches
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- /^maint.*/
|
|
||||||
|
|
||||||
# Notify development list when needed
|
|
||||||
notifications:
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- irc.freenode.net#libgit2
|
|
||||||
on_success: change
|
|
||||||
on_failure: always
|
|
||||||
use_notice: true
|
|
||||||
skip_join: true
|
|
||||||
campfire:
|
|
||||||
on_success: always
|
|
||||||
on_failure: always
|
|
||||||
rooms:
|
|
||||||
- secure: "sH0dpPWMirbEe7AvLddZ2yOp8rzHalGmv0bYL/LIhVw3JDI589HCYckeLMSB\n3e/FeXw4bn0EqXWEXijVa4ijbilVY6d8oprdqMdWHEodng4KvY5vID3iZSGT\nxylhahO1XHmRynKQLOAvxlc93IlpVW38vQfby8giIY1nkpspb2w="
|
|
140
CHANGELOG.md
140
CHANGELOG.md
@ -1,3 +1,143 @@
|
|||||||
|
v0.27.7
|
||||||
|
-------
|
||||||
|
|
||||||
|
This is a bugfix release with the following changes or improvements:
|
||||||
|
|
||||||
|
- Our continuous integration environment has switched from Travis and
|
||||||
|
AppVeyor to Azure Pipelines CI.
|
||||||
|
|
||||||
|
- Fix adding worktrees for bare repositories.
|
||||||
|
|
||||||
|
- Fix parsed patches not computing the old respectively new line
|
||||||
|
numbers correctly.
|
||||||
|
|
||||||
|
- Fix parsing configuration variables which do not have a section.
|
||||||
|
|
||||||
|
- Fix a zero-byte allocation when trying to detect file renames and
|
||||||
|
copies of a diff without any hunks.
|
||||||
|
|
||||||
|
- Fix a zero-byte allocation when trying to resize or duplicate
|
||||||
|
vectors.
|
||||||
|
|
||||||
|
- Fix return value when trying to unlock worktrees which aren't
|
||||||
|
locked.
|
||||||
|
|
||||||
|
- Fix returning an unitialized error code when preparing a revision
|
||||||
|
walk without any pushed commits.
|
||||||
|
|
||||||
|
- Fix return value of `git_remote_lookup` when lookup of
|
||||||
|
"remote.$remote.tagopt" fails.
|
||||||
|
|
||||||
|
- Fix the revision walk always labelling commits as interesting due
|
||||||
|
to a mishandling of the commit date.
|
||||||
|
|
||||||
|
- Fix the packbuilder inserting uninteresting blobs when adding a
|
||||||
|
tree containing references to such blobs.
|
||||||
|
|
||||||
|
- Ignore unsupported authentication schemes in HTTP transport.
|
||||||
|
|
||||||
|
- Improve performane of `git_remote_prune`.
|
||||||
|
|
||||||
|
- Fix detection of whether `qsort_r` has a BSD or GNU function
|
||||||
|
signature.
|
||||||
|
|
||||||
|
- Fix detection of iconv if it is provided by libc.
|
||||||
|
|
||||||
|
v0.27.6
|
||||||
|
-------
|
||||||
|
|
||||||
|
This as a security release fixing the following list of issues:
|
||||||
|
|
||||||
|
- The function family `git__strtol` is used to parse integers
|
||||||
|
from a buffer. As the functions do not take a buffer length as
|
||||||
|
argument, they will scan either until the end of the current
|
||||||
|
number or until a NUL byte is encountered. Many callers have
|
||||||
|
been misusing the function and called it on potentially
|
||||||
|
non-NUL-terminated buffers, resulting in possible out-of-bounds
|
||||||
|
reads. Callers have been fixed to use `git__strntol` functions
|
||||||
|
instead and `git__strtol` functions were removed.
|
||||||
|
|
||||||
|
- The function `git__strntol64` relied on the undefined behavior
|
||||||
|
of signed integer overflows. While the code tried to detect
|
||||||
|
such overflows after they have happened, this is unspecified
|
||||||
|
behavior and may lead to weird behavior on uncommon platforms.
|
||||||
|
|
||||||
|
- In the case where `git__strntol32` was unable to parse an
|
||||||
|
integer because it doesn't fit into an `int32_t`, it printed an
|
||||||
|
error message containing the string that is currently being
|
||||||
|
parsed. The code didn't truncate the string though, which
|
||||||
|
caused it to print the complete string until a NUL byte is
|
||||||
|
encountered and not only the currently parsed number. In case
|
||||||
|
where the string was not NUL terminated, this could have lead
|
||||||
|
to an out-of-bounds read.
|
||||||
|
|
||||||
|
- When parsing tags, all unknown fields that appear before the
|
||||||
|
tag message are skipped. This skipping is done by using a plain
|
||||||
|
`strstr(buffer, "\n\n")` to search for the two newlines that
|
||||||
|
separate tag fields from tag message. As it is not possible to
|
||||||
|
supply a buffer length to `strstr`, this call may skip over the
|
||||||
|
buffer's end and thus result in an out of bounds read. As
|
||||||
|
`strstr` may return a pointer that is out of bounds, the
|
||||||
|
following computation of `buffer_end - buffer` will overflow
|
||||||
|
and result in an allocation of an invalid length. Note that
|
||||||
|
when reading objects from the object database, we make sure to
|
||||||
|
always NUL terminate them, making the use of `strstr` safe.
|
||||||
|
|
||||||
|
- When parsing the "encoding" field of a commit, we may perform
|
||||||
|
an out of bounds read due to using `git__prefixcmp` instead of
|
||||||
|
`git__prefixncmp`. This can result in the parsed commit object
|
||||||
|
containing uninitialized data in both its message encoding and
|
||||||
|
message fields. Note that when reading objects from the object
|
||||||
|
database, we make sure to always NUL terminate them, making the
|
||||||
|
use of `strstr` safe.
|
||||||
|
|
||||||
|
v0.27.5
|
||||||
|
-------
|
||||||
|
|
||||||
|
This is a security release fixing the following list of issues:
|
||||||
|
|
||||||
|
- Submodule URLs and paths with a leading "-" are now ignored.
|
||||||
|
This is due to the recently discovered CVE-2018-17456, which
|
||||||
|
can lead to arbitrary code execution in upstream git. While
|
||||||
|
libgit2 itself is not vulnerable, it can be used to inject
|
||||||
|
options in an implementation which performs a recursive clone
|
||||||
|
by executing an external command.
|
||||||
|
|
||||||
|
- When running repack while doing repo writes,
|
||||||
|
`packfile_load__cb()` could see some temporary files in the
|
||||||
|
directory that were bigger than the usual, and makes `memcmp`
|
||||||
|
overflow on the `p->pack_name` string. This issue was reported
|
||||||
|
and fixed by bisho.
|
||||||
|
|
||||||
|
- The configuration file parser used unbounded recursion to parse
|
||||||
|
multiline variables, which could lead to a stack overflow. The
|
||||||
|
issue was reported by the oss-fuzz project, issue 10048 and
|
||||||
|
fixed by Nelson Elhage.
|
||||||
|
|
||||||
|
- The fix to the unbounded recursion introduced a memory leak in
|
||||||
|
the config parser. While this leak was never in a public
|
||||||
|
release, the oss-fuzz project reported this as issue 10127. The
|
||||||
|
fix was implemented by Nelson Elhage and Patrick Steinhardt.
|
||||||
|
|
||||||
|
- When parsing "ok" packets received via the smart protocol, our
|
||||||
|
parsing code did not correctly verify the bounds of the
|
||||||
|
packets, which could result in a heap-buffer overflow. The
|
||||||
|
issue was reported by the oss-fuzz project, issue 9749 and
|
||||||
|
fixed by Patrick Steinhardt.
|
||||||
|
|
||||||
|
- The parsing code for the smart protocol has been tightened in
|
||||||
|
general, fixing heap-buffer overflows when parsing the packet
|
||||||
|
type as well as for "ACK" and "unpack" packets. The issue was
|
||||||
|
discovered and fixed by Patrick Steinhardt.
|
||||||
|
|
||||||
|
- Fixed potential integer overflows on platforms with 16 bit
|
||||||
|
integers when parsing packets for the smart protocol. The issue
|
||||||
|
was discovered and fixed by Patrick Steinhardt.
|
||||||
|
|
||||||
|
- Fixed potential NULL pointer dereference when parsing
|
||||||
|
configuration files which have "include.path" or
|
||||||
|
"includeIf..path" statements without a value.
|
||||||
|
|
||||||
v0.27.4
|
v0.27.4
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ INCLUDE(CheckLibraryExists)
|
|||||||
INCLUDE(CheckFunctionExists)
|
INCLUDE(CheckFunctionExists)
|
||||||
INCLUDE(CheckSymbolExists)
|
INCLUDE(CheckSymbolExists)
|
||||||
INCLUDE(CheckStructHasMember)
|
INCLUDE(CheckStructHasMember)
|
||||||
|
INCLUDE(CheckPrototypeDefinition) # Added in CMake 3.0
|
||||||
INCLUDE(AddCFlagIfSupported)
|
INCLUDE(AddCFlagIfSupported)
|
||||||
INCLUDE(FindPkgLibraries)
|
INCLUDE(FindPkgLibraries)
|
||||||
INCLUDE(FindThreads)
|
INCLUDE(FindThreads)
|
||||||
@ -224,6 +225,9 @@ ELSE ()
|
|||||||
ENABLE_WARNINGS(shift-count-overflow)
|
ENABLE_WARNINGS(shift-count-overflow)
|
||||||
DISABLE_WARNINGS(unused-const-variable)
|
DISABLE_WARNINGS(unused-const-variable)
|
||||||
DISABLE_WARNINGS(unused-function)
|
DISABLE_WARNINGS(unused-function)
|
||||||
|
ENABLE_WARNINGS(format)
|
||||||
|
ENABLE_WARNINGS(format-security)
|
||||||
|
ENABLE_WARNINGS(int-conversion)
|
||||||
|
|
||||||
IF (APPLE) # Apple deprecated OpenSSL
|
IF (APPLE) # Apple deprecated OpenSSL
|
||||||
DISABLE_WARNINGS(deprecated-declarations)
|
DISABLE_WARNINGS(deprecated-declarations)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
libgit2 - the Git linkable library
|
libgit2 - the Git linkable library
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
[](http://travis-ci.org/libgit2/libgit2)
|
[](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7)
|
||||||
[](https://ci.appveyor.com/project/libgit2/libgit2/branch/master)
|
|
||||||
[](https://scan.coverity.com/projects/639)
|
[](https://scan.coverity.com/projects/639)
|
||||||
|
|
||||||
`libgit2` is a portable, pure C implementation of the Git core methods
|
`libgit2` is a portable, pure C implementation of the Git core methods
|
||||||
@ -18,7 +17,7 @@ in your favorite language.
|
|||||||
[GitKraken](https://gitkraken.com/) and [gmaster](https://gmaster.io/)
|
[GitKraken](https://gitkraken.com/) and [gmaster](https://gmaster.io/)
|
||||||
and on Git hosting providers like [GitHub](https://github.com/),
|
and on Git hosting providers like [GitHub](https://github.com/),
|
||||||
[GitLab](https://gitlab.com/) and
|
[GitLab](https://gitlab.com/) and
|
||||||
[Visual Studio Team Services](https://visualstudio.com/team-services/).
|
[Azure DevOps](https://azure.com/devops).
|
||||||
We perform the merge every time you click "merge pull request".
|
We perform the merge every time you click "merge pull request".
|
||||||
|
|
||||||
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special
|
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special
|
||||||
@ -87,7 +86,7 @@ What It Can Do
|
|||||||
|
|
||||||
libgit2 provides you with the ability to manage Git repositories in the
|
libgit2 provides you with the ability to manage Git repositories in the
|
||||||
programming language of your choice. It's used in production to power many
|
programming language of your choice. It's used in production to power many
|
||||||
applications including GitHub.com, Plastic SCM and Visual Studio Team Services.
|
applications including GitHub.com, Plastic SCM and Azure DevOps.
|
||||||
|
|
||||||
It does not aim to replace the git tool or its user-facing commands. Some APIs
|
It does not aim to replace the git tool or its user-facing commands. Some APIs
|
||||||
resemble the plumbing commands as those align closely with the concepts of the
|
resemble the plumbing commands as those align closely with the concepts of the
|
||||||
|
60
appveyor.yml
60
appveyor.yml
@ -1,60 +0,0 @@
|
|||||||
version: '{build}'
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- appveyor
|
|
||||||
- /^maint.*/
|
|
||||||
environment:
|
|
||||||
GITTEST_INVASIVE_FS_STRUCTURE: 1
|
|
||||||
GITTEST_INVASIVE_FS_SIZE: 1
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
|
||||||
GENERATOR: "Visual Studio 10 2010"
|
|
||||||
ARCH: 32
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
|
||||||
GENERATOR: "Visual Studio 10 2010 Win64"
|
|
||||||
ARCH: 64
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
GENERATOR: "Visual Studio 14 2015"
|
|
||||||
ARCH: 32
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
GENERATOR: "Visual Studio 14 2015 Win64"
|
|
||||||
ARCH: 64
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
GENERATOR: "MSYS Makefiles"
|
|
||||||
ARCH: i686 # this is for 32-bit MinGW-w64
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
GENERATOR: "MSYS Makefiles"
|
|
||||||
ARCH: 64
|
|
||||||
cache:
|
|
||||||
- i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
|
|
||||||
- x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- ps: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
if ($env:GENERATOR -ne "MSYS Makefiles") {
|
|
||||||
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON -D MSVC_CRTDBG=ON .. -G"$env:GENERATOR"
|
|
||||||
cmake --build . --config Debug
|
|
||||||
}
|
|
||||||
- cmd: |
|
|
||||||
if "%GENERATOR%"=="MSYS Makefiles" (C:\MinGW\msys\1.0\bin\sh --login /c/projects/libgit2/script/appveyor-mingw.sh)
|
|
||||||
test_script:
|
|
||||||
- ps: |
|
|
||||||
# Disable DHE key exchange to fix intermittent build failures ("A buffer
|
|
||||||
# provided was too small") due to SChannel bug. See e.g.
|
|
||||||
# - https://github.com/aws/aws-sdk-cpp/issues/671
|
|
||||||
# - https://github.com/dotnet/corefx/issues/7812
|
|
||||||
New-Item HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman -Force | New-ItemProperty -Name Enabled -Value 0 -Force
|
|
||||||
$ErrorActionPreference="Stop"
|
|
||||||
Start-FileDownload https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -FileName poxyproxy.jar
|
|
||||||
# Run this early so we know it's ready by the time we need it
|
|
||||||
$proxyJob = Start-Job { java -jar $Env:APPVEYOR_BUILD_FOLDER\build\poxyproxy.jar -d --port 8080 --credentials foo:bar }
|
|
||||||
ctest -V -R libgit2_clar
|
|
||||||
Receive-Job -Job $proxyJob
|
|
||||||
$env:GITTEST_REMOTE_PROXY_URL = "localhost:8080"
|
|
||||||
$env:GITTEST_REMOTE_PROXY_USER = "foo"
|
|
||||||
$env:GITTEST_REMOTE_PROXY_PASS = "bar"
|
|
||||||
ctest -V -R libgit2_clar-proxy_credentials
|
|
94
azure-pipelines.yml
Normal file
94
azure-pipelines.yml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
resources:
|
||||||
|
- repo: self
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
- maint/*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: linux_trusty_gcc_openssl
|
||||||
|
displayName: 'Linux (Trusty; GCC; OpenSSL)'
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu 16.04'
|
||||||
|
steps:
|
||||||
|
- template: ci/docker.yml
|
||||||
|
parameters:
|
||||||
|
imageName: 'libgit2/trusty-openssl:latest'
|
||||||
|
environmentVariables: |
|
||||||
|
CC=gcc
|
||||||
|
LEAK_CHECK=valgrind
|
||||||
|
|
||||||
|
- job: linux_trusty_clang_openssl
|
||||||
|
displayName: 'Linux (Trusty; Clang; OpenSSL)'
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu 16.04'
|
||||||
|
steps:
|
||||||
|
- template: ci/docker.yml
|
||||||
|
parameters:
|
||||||
|
imageName: 'libgit2/trusty-openssl:latest'
|
||||||
|
environmentVariables: |
|
||||||
|
CC=clang
|
||||||
|
LEAK_CHECK=valgrind
|
||||||
|
|
||||||
|
- job: macos
|
||||||
|
displayName: 'macOS'
|
||||||
|
pool:
|
||||||
|
vmImage: 'macOS 10.13'
|
||||||
|
steps:
|
||||||
|
- bash: . '$(Build.SourcesDirectory)/ci/setup-osx.sh'
|
||||||
|
displayName: Setup
|
||||||
|
- template: ci/bash.yml
|
||||||
|
parameters:
|
||||||
|
environmentVariables:
|
||||||
|
TMPDIR: $(Agent.TempDirectory)
|
||||||
|
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
|
||||||
|
LEAK_CHECK: leaks
|
||||||
|
|
||||||
|
- job: windows_vs_amd64
|
||||||
|
displayName: 'Windows (Visual Studio; amd64)'
|
||||||
|
pool: Hosted
|
||||||
|
steps:
|
||||||
|
- template: ci/powershell.yml
|
||||||
|
parameters:
|
||||||
|
environmentVariables:
|
||||||
|
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013 Win64"
|
||||||
|
|
||||||
|
- job: windows_vs_x86
|
||||||
|
displayName: 'Windows (Visual Studio; x86)'
|
||||||
|
pool: Hosted
|
||||||
|
steps:
|
||||||
|
- template: ci/powershell.yml
|
||||||
|
parameters:
|
||||||
|
environmentVariables:
|
||||||
|
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013"
|
||||||
|
|
||||||
|
- job: windows_mingw_amd64
|
||||||
|
displayName: 'Windows (MinGW; amd64)'
|
||||||
|
pool: Hosted
|
||||||
|
steps:
|
||||||
|
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
|
||||||
|
displayName: Setup
|
||||||
|
env:
|
||||||
|
TEMP: $(Agent.TempDirectory)
|
||||||
|
ARCH: amd64
|
||||||
|
- template: ci/powershell.yml
|
||||||
|
parameters:
|
||||||
|
environmentVariables:
|
||||||
|
CMAKE_OPTIONS: -G"MinGW Makefiles"
|
||||||
|
PATH: $(Agent.TempDirectory)\mingw64\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
|
||||||
|
|
||||||
|
- job: windows_mingw_x86
|
||||||
|
displayName: 'Windows (MinGW; x86)'
|
||||||
|
pool: Hosted
|
||||||
|
steps:
|
||||||
|
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
|
||||||
|
displayName: Setup
|
||||||
|
workingDirectory: '$(Build.BinariesDirectory)'
|
||||||
|
env:
|
||||||
|
TEMP: $(Agent.TempDirectory)
|
||||||
|
ARCH: x86
|
||||||
|
- template: ci/powershell.yml
|
||||||
|
parameters:
|
||||||
|
environmentVariables:
|
||||||
|
CMAKE_OPTIONS: -G"MinGW Makefiles"
|
||||||
|
PATH: $(Agent.TempDirectory)\mingw32\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
|
17
ci/bash.yml
Normal file
17
ci/bash.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# These are the steps used for building on machines with bash.
|
||||||
|
steps:
|
||||||
|
- bash: . '$(Build.SourcesDirectory)/ci/build.sh'
|
||||||
|
displayName: Build
|
||||||
|
workingDirectory: '$(Build.BinariesDirectory)'
|
||||||
|
env: ${{ parameters.environmentVariables }}
|
||||||
|
- bash: . '$(Build.SourcesDirectory)/ci/test.sh'
|
||||||
|
displayName: Test
|
||||||
|
workingDirectory: '$(Build.BinariesDirectory)'
|
||||||
|
env: ${{ parameters.environmentVariables }}
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
displayName: Publish Test Results
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: 'results_*.xml'
|
||||||
|
searchFolder: '$(Build.BinariesDirectory)'
|
||||||
|
mergeTestResults: true
|
30
ci/build.ps1
Normal file
30
ci/build.ps1
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||||
|
|
||||||
|
if ($Env:SOURCE_DIR) { $SourceDirectory = $Env:SOURCE_DIR } else { $SourceDirectory = Split-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) -Parent }
|
||||||
|
$BuildDirectory = $(Get-Location).Path
|
||||||
|
|
||||||
|
Write-Host "Source directory: ${SourceDirectory}"
|
||||||
|
Write-Host "Build directory: ${BuildDirectory}"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operating system version:"
|
||||||
|
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, BuildNumber, OSArchitecture | Format-List
|
||||||
|
Write-Host "PATH: ${Env:PATH}"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Configuring build environment"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
Invoke-Expression "cmake ${SourceDirectory} -DBUILD_EXAMPLES=ON ${Env:CMAKE_OPTIONS}"
|
||||||
|
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Building libgit2"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
cmake --build .
|
||||||
|
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
|
39
ci/build.sh
Executable file
39
ci/build.sh
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Environment variables:
|
||||||
|
#
|
||||||
|
# SOURCE_DIR: Set to the directory of the libgit2 source (optional)
|
||||||
|
# If not set, it will be derived relative to this script.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||||
|
BUILD_DIR=$(pwd)
|
||||||
|
CC=${CC:-cc}
|
||||||
|
|
||||||
|
indent() { sed "s/^/ /"; }
|
||||||
|
|
||||||
|
echo "Source directory: ${SOURCE_DIR}"
|
||||||
|
echo "Build directory: ${BUILD_DIR}"
|
||||||
|
echo ""
|
||||||
|
echo "Operating system version:"
|
||||||
|
uname -a 2>&1 | indent
|
||||||
|
echo "CMake version:"
|
||||||
|
cmake --version 2>&1 | indent
|
||||||
|
echo "Compiler version:"
|
||||||
|
$CC --version 2>&1 | indent
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "##############################################################################"
|
||||||
|
echo "## Configuring build environment"
|
||||||
|
echo "##############################################################################"
|
||||||
|
|
||||||
|
echo cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
|
||||||
|
cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "##############################################################################"
|
||||||
|
echo "## Building libgit2"
|
||||||
|
echo "##############################################################################"
|
||||||
|
|
||||||
|
cmake --build .
|
@ -1,17 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
|
||||||
|
|
||||||
# Only run this on our branches
|
set -e
|
||||||
echo "Branch: $TRAVIS_BRANCH | Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
|
|
||||||
if [ "$TRAVIS_BRANCH" != "master" -o "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
|
|
||||||
then
|
|
||||||
echo "Only analyzing the 'master' brach of the main repository."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Environment check
|
# Environment check
|
||||||
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
|
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
|
||||||
|
|
||||||
|
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||||
|
BUILD_DIR=$(pwd)
|
||||||
|
|
||||||
case $(uname -m) in
|
case $(uname -m) in
|
||||||
i?86) BITS=32 ;;
|
i?86) BITS=32 ;;
|
||||||
amd64|x86_64) BITS=64 ;;
|
amd64|x86_64) BITS=64 ;;
|
||||||
@ -32,31 +28,29 @@ if [ ! -d "$TOOL_BASE" ]; then
|
|||||||
ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis
|
ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp script/user_nodefs.h "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
|
cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
|
||||||
|
|
||||||
COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build"
|
COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build"
|
||||||
|
|
||||||
# Configure and build
|
# Configure and build
|
||||||
rm -rf _build
|
cmake ${SOURCE_DIR}
|
||||||
mkdir _build
|
|
||||||
cd _build
|
|
||||||
cmake .. -DTHREADSAFE=ON
|
|
||||||
COVERITY_UNSUPPORTED=1 \
|
COVERITY_UNSUPPORTED=1 \
|
||||||
$COV_BUILD --dir cov-int \
|
$COV_BUILD --dir cov-int \
|
||||||
cmake --build .
|
cmake --build .
|
||||||
|
|
||||||
# Upload results
|
# Upload results
|
||||||
tar czf libgit2.tgz cov-int
|
tar czf libgit2.tgz cov-int
|
||||||
SHA=$(git rev-parse --short HEAD)
|
SHA=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD)
|
||||||
|
|
||||||
HTML="$(curl \
|
HTML="$(curl \
|
||||||
--silent \
|
--silent \
|
||||||
--write-out "\n%{http_code}" \
|
--write-out "\n%{http_code}" \
|
||||||
--form token="$COVERITY_TOKEN" \
|
--form token="$COVERITY_TOKEN" \
|
||||||
--form email=bs@github.com \
|
--form email=libgit2@gmail.com \
|
||||||
--form file=@libgit2.tgz \
|
--form file=@libgit2.tgz \
|
||||||
--form version="$SHA" \
|
--form version="$SHA" \
|
||||||
--form description="Travis build" \
|
--form description="libgit2 build" \
|
||||||
https://scan.coverity.com/builds?project=libgit2)"
|
https://scan.coverity.com/builds?project=libgit2)"
|
||||||
# Body is everything up to the last line
|
# Body is everything up to the last line
|
||||||
BODY="$(echo "$HTML" | head -n-1)"
|
BODY="$(echo "$HTML" | head -n-1)"
|
||||||
@ -65,7 +59,7 @@ STATUS_CODE="$(echo "$HTML" | tail -n1)"
|
|||||||
|
|
||||||
echo "${BODY}"
|
echo "${BODY}"
|
||||||
|
|
||||||
if [ "${STATUS_CODE}" != "201" ]; then
|
if [ "${STATUS_CODE}" != "200" -a "${STATUS_CODE}" != "201" ]; then
|
||||||
echo "Received error code ${STATUS_CODE} from Coverity"
|
echo "Received error code ${STATUS_CODE} from Coverity"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
33
ci/docker.yml
Normal file
33
ci/docker.yml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# These are the steps used in a container-based build in VSTS.
|
||||||
|
steps:
|
||||||
|
- task: docker@0
|
||||||
|
displayName: Build
|
||||||
|
inputs:
|
||||||
|
action: 'Run an image'
|
||||||
|
imageName: ${{ parameters.imageName }}
|
||||||
|
volumes: |
|
||||||
|
$(Build.SourcesDirectory):/src
|
||||||
|
$(Build.BinariesDirectory):/build
|
||||||
|
envVars: ${{ parameters.environmentVariables }}
|
||||||
|
workDir: '/build'
|
||||||
|
containerCommand: '/src/ci/build.sh'
|
||||||
|
detached: false
|
||||||
|
- task: docker@0
|
||||||
|
displayName: Test
|
||||||
|
inputs:
|
||||||
|
action: 'Run an image'
|
||||||
|
imageName: ${{ parameters.imageName }}
|
||||||
|
volumes: |
|
||||||
|
$(Build.SourcesDirectory):/src
|
||||||
|
$(Build.BinariesDirectory):/build
|
||||||
|
envVars: ${{ parameters.environmentVariables }}
|
||||||
|
workDir: '/build'
|
||||||
|
containerCommand: '/src/ci/test.sh'
|
||||||
|
detached: false
|
||||||
|
- task: publishtestresults@2
|
||||||
|
displayName: Publish Test Results
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: 'results_*.xml'
|
||||||
|
searchFolder: '$(Build.BinariesDirectory)'
|
||||||
|
mergeTestResults: true
|
22
ci/nightly.yml
Normal file
22
ci/nightly.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
resources:
|
||||||
|
- repo: self
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: coverity
|
||||||
|
displayName: 'Coverity'
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu 16.04'
|
||||||
|
steps:
|
||||||
|
- task: Docker@0
|
||||||
|
displayName: Build
|
||||||
|
inputs:
|
||||||
|
action: 'Run an image'
|
||||||
|
imageName: 'libgit2/trusty-openssl:latest'
|
||||||
|
volumes: |
|
||||||
|
$(Build.SourcesDirectory):/src
|
||||||
|
$(Build.BinariesDirectory):/build
|
||||||
|
envVars: |
|
||||||
|
COVERITY_TOKEN=$(COVERITY_TOKEN)
|
||||||
|
workDir: '/build'
|
||||||
|
containerCommand: '/src/ci/coverity.sh'
|
||||||
|
detached: false
|
17
ci/powershell.yml
Normal file
17
ci/powershell.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# These are the steps used for building on machines with PowerShell.
|
||||||
|
steps:
|
||||||
|
- powershell: . '$(Build.SourcesDirectory)\ci\build.ps1'
|
||||||
|
displayName: Build
|
||||||
|
workingDirectory: '$(Build.BinariesDirectory)'
|
||||||
|
env: ${{ parameters.environmentVariables }}
|
||||||
|
- powershell: . '$(Build.SourcesDirectory)\ci\test.ps1'
|
||||||
|
displayName: Test
|
||||||
|
workingDirectory: '$(Build.BinariesDirectory)'
|
||||||
|
env: ${{ parameters.environmentVariables }}
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
displayName: Publish Test Results
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: 'results_*.xml'
|
||||||
|
searchFolder: '$(Build.BinariesDirectory)'
|
||||||
|
mergeTestResults: true
|
13
ci/setup-linux.sh
Executable file
13
ci/setup-linux.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
TMPDIR=${TMPDIR:-/tmp}
|
||||||
|
|
||||||
|
if [ -z "$SKIP_APT" ]; then
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p /var/run/sshd
|
25
ci/setup-mingw.ps1
Normal file
25
ci/setup-mingw.ps1
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||||
|
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem");
|
||||||
|
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Downloading mingw"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
if ($env:ARCH -eq "amd64") {
|
||||||
|
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip"
|
||||||
|
$platform = "x86_64"
|
||||||
|
} else {
|
||||||
|
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip"
|
||||||
|
$platform = "x86"
|
||||||
|
}
|
||||||
|
|
||||||
|
$wc = New-Object net.webclient
|
||||||
|
$wc.Downloadfile($mingw_uri, "${Env:TEMP}/mingw-${Env:ARCH}.zip")
|
||||||
|
|
||||||
|
[System.IO.Compression.ZipFile]::ExtractToDirectory("${Env:TEMP}/mingw-${Env:ARCH}.zip", $Env:TEMP)
|
8
ci/setup-osx.sh
Executable file
8
ci/setup-osx.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
brew update
|
||||||
|
brew install pkgconfig zlib curl openssl libssh2
|
||||||
|
|
||||||
|
ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
|
72
ci/test.ps1
Normal file
72
ci/test.ps1
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||||
|
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
$SourceDir = Split-Path (Split-Path (Get-Variable MyInvocation).Value.MyCommand.Path)
|
||||||
|
$BuildDir = Get-Location
|
||||||
|
$global:Success = $true
|
||||||
|
|
||||||
|
if ($Env:SKIP_TESTS) { exit }
|
||||||
|
|
||||||
|
# Ask ctest what it would run if we were to invoke it directly. This lets
|
||||||
|
# us manage the test configuration in a single place (tests/CMakeLists.txt)
|
||||||
|
# instead of running clar here as well. But it allows us to wrap our test
|
||||||
|
# harness with a leak checker like valgrind. Append the option to write
|
||||||
|
# JUnit-style XML files.
|
||||||
|
function run_test {
|
||||||
|
$TestName = $args[0]
|
||||||
|
|
||||||
|
$TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" -replace "(?ms).*\n^[0-9]*: Test command: ","" -replace "\n.*",""
|
||||||
|
$TestCommand += " -r${BuildDir}\results_${TestName}.xml"
|
||||||
|
|
||||||
|
Write-Host $TestCommand
|
||||||
|
Invoke-Expression $TestCommand
|
||||||
|
|
||||||
|
if ($LastExitCode -ne 0) { $global:Success = $false }
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Configuring test environment"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
if (-not $Env:SKIP_PROXY_TESTS) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Starting HTTP proxy..."
|
||||||
|
Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -OutFile poxyproxy.jar
|
||||||
|
javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Running (offline) tests"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
run_test offline
|
||||||
|
|
||||||
|
if (-not $Env:SKIP_ONLINE_TESTS) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
Write-Host "## Running (online) tests"
|
||||||
|
Write-Host "##############################################################################"
|
||||||
|
|
||||||
|
run_test online
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $Env:SKIP_PROXY_TESTS) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Running proxy tests"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
$Env:GITTEST_REMOTE_PROXY_URL="localhost:8080"
|
||||||
|
$Env:GITTEST_REMOTE_PROXY_USER="foo"
|
||||||
|
$Env:GITTEST_REMOTE_PROXY_PASS="bar"
|
||||||
|
|
||||||
|
run_test proxy
|
||||||
|
|
||||||
|
taskkill /F /IM javaw.exe
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-Not $global:Success) { exit 1 }
|
198
ci/test.sh
Executable file
198
ci/test.sh
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -n "$SKIP_TESTS" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||||
|
BUILD_DIR=$(pwd)
|
||||||
|
TMPDIR=${TMPDIR:-/tmp}
|
||||||
|
USER=${USER:-$(whoami)}
|
||||||
|
|
||||||
|
SUCCESS=1
|
||||||
|
|
||||||
|
VALGRIND="valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions=\"$SOURCE_DIR/libgit2_clar.supp\""
|
||||||
|
LEAKS="MallocStackLogging=1 MallocScribble=1 leaks -quiet -atExit -- nohup"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "Cleaning up..."
|
||||||
|
|
||||||
|
if [ ! -z "$GITDAEMON_DIR" -a -f "${GITDAEMON_DIR}/pid" ]; then
|
||||||
|
echo "Stopping git daemon..."
|
||||||
|
kill $(cat "${GITDAEMON_DIR}/pid")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then
|
||||||
|
echo "Stopping SSH..."
|
||||||
|
kill $(cat "${SSHD_DIR}/pid")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Done."
|
||||||
|
}
|
||||||
|
|
||||||
|
failure() {
|
||||||
|
echo "Test exited with code: $1"
|
||||||
|
SUCCESS=0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ask ctest what it would run if we were to invoke it directly. This lets
|
||||||
|
# us manage the test configuration in a single place (tests/CMakeLists.txt)
|
||||||
|
# instead of running clar here as well. But it allows us to wrap our test
|
||||||
|
# harness with a leak checker like valgrind. Append the option to write
|
||||||
|
# JUnit-style XML files.
|
||||||
|
run_test() {
|
||||||
|
TEST_CMD=$(ctest -N -V -R "^${1}$" | sed -n 's/^[0-9]*: Test command: //p')
|
||||||
|
TEST_CMD="${TEST_CMD} -r${BUILD_DIR}/results_${1}.xml"
|
||||||
|
|
||||||
|
if [ "$LEAK_CHECK" = "valgrind" ]; then
|
||||||
|
RUNNER="$VALGRIND $TEST_CMD"
|
||||||
|
elif [ "$LEAK_CHECK" = "leaks" ]; then
|
||||||
|
RUNNER="$LEAKS $TEST_CMD"
|
||||||
|
else
|
||||||
|
RUNNER="$TEST_CMD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval $RUNNER || failure
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure the test environment; run them early so that we're certain
|
||||||
|
# that they're started by the time we need them.
|
||||||
|
|
||||||
|
echo "##############################################################################"
|
||||||
|
echo "## Configuring test environment"
|
||||||
|
echo "##############################################################################"
|
||||||
|
|
||||||
|
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
|
||||||
|
echo "Starting git daemon..."
|
||||||
|
GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX`
|
||||||
|
git init --bare "${GITDAEMON_DIR}/test.git"
|
||||||
|
git daemon --listen=localhost --export-all --enable=receive-pack --pid-file="${GITDAEMON_DIR}/pid" --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null &
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_PROXY_TESTS" ]; then
|
||||||
|
echo "Starting HTTP proxy..."
|
||||||
|
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar
|
||||||
|
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar >/dev/null 2>&1 &
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_SSH_TESTS" ]; then
|
||||||
|
echo "Starting ssh daemon..."
|
||||||
|
HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
|
||||||
|
SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
|
||||||
|
git init --bare "${SSHD_DIR}/test.git"
|
||||||
|
cat >"${SSHD_DIR}/sshd_config" <<-EOF
|
||||||
|
Port 2222
|
||||||
|
ListenAddress 0.0.0.0
|
||||||
|
Protocol 2
|
||||||
|
HostKey ${SSHD_DIR}/id_rsa
|
||||||
|
PidFile ${SSHD_DIR}/pid
|
||||||
|
AuthorizedKeysFile ${HOME}/.ssh/authorized_keys
|
||||||
|
LogLevel DEBUG
|
||||||
|
RSAAuthentication yes
|
||||||
|
PasswordAuthentication yes
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
ChallengeResponseAuthentication no
|
||||||
|
StrictModes no
|
||||||
|
# Required here as sshd will simply close connection otherwise
|
||||||
|
UsePAM no
|
||||||
|
EOF
|
||||||
|
ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q
|
||||||
|
/usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log"
|
||||||
|
|
||||||
|
# Set up keys
|
||||||
|
mkdir "${HOME}/.ssh"
|
||||||
|
ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q
|
||||||
|
cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys"
|
||||||
|
while read algorithm key comment; do
|
||||||
|
echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts"
|
||||||
|
done <"${SSHD_DIR}/id_rsa.pub"
|
||||||
|
|
||||||
|
# Get the fingerprint for localhost and remove the colons so we can
|
||||||
|
# parse it as a hex number. Older versions have a different output
|
||||||
|
# format.
|
||||||
|
if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then
|
||||||
|
SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
|
||||||
|
else
|
||||||
|
SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the tests that do not require network connectivity.
|
||||||
|
|
||||||
|
if [ -z "$SKIP_OFFLINE_TESTS" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "##############################################################################"
|
||||||
|
echo "## Running (offline) tests"
|
||||||
|
echo "##############################################################################"
|
||||||
|
|
||||||
|
run_test offline
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_ONLINE_TESTS" ]; then
|
||||||
|
# Run the various online tests. The "online" test suite only includes the
|
||||||
|
# default online tests that do not require additional configuration. The
|
||||||
|
# "proxy" and "ssh" test suites require further setup.
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "##############################################################################"
|
||||||
|
echo "## Running (online) tests"
|
||||||
|
echo "##############################################################################"
|
||||||
|
|
||||||
|
run_test online
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Running gitdaemon tests"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
export GITTEST_REMOTE_URL="git://localhost/test.git"
|
||||||
|
run_test gitdaemon
|
||||||
|
unset GITTEST_REMOTE_URL
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_PROXY_TESTS" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Running proxy tests"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
export GITTEST_REMOTE_PROXY_URL="localhost:8080"
|
||||||
|
export GITTEST_REMOTE_PROXY_USER="foo"
|
||||||
|
export GITTEST_REMOTE_PROXY_PASS="bar"
|
||||||
|
run_test proxy
|
||||||
|
unset GITTEST_REMOTE_PROXY_URL
|
||||||
|
unset GITTEST_REMOTE_PROXY_USER
|
||||||
|
unset GITTEST_REMOTE_PROXY_PASS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SKIP_SSH_TESTS" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Running ssh tests"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git"
|
||||||
|
export GITTEST_REMOTE_USER=$USER
|
||||||
|
export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa"
|
||||||
|
export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub"
|
||||||
|
export GITTEST_REMOTE_SSH_PASSPHRASE=""
|
||||||
|
export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}"
|
||||||
|
run_test ssh
|
||||||
|
unset GITTEST_REMOTE_URL
|
||||||
|
unset GITTEST_REMOTE_USER
|
||||||
|
unset GITTEST_REMOTE_SSH_KEY
|
||||||
|
unset GITTEST_REMOTE_SSH_PUBKEY
|
||||||
|
unset GITTEST_REMOTE_SSH_PASSPHRASE
|
||||||
|
unset GITTEST_REMOTE_SSH_FINGERPRINT
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
if [ "$SUCCESS" -ne "1" ]; then
|
||||||
|
echo "Some tests failed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Success."
|
||||||
|
exit 0
|
29
cmake/Modules/CheckPrototypeDefinition.c.in
Normal file
29
cmake/Modules/CheckPrototypeDefinition.c.in
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
@CHECK_PROTOTYPE_DEFINITION_HEADER@
|
||||||
|
|
||||||
|
static void cmakeRequireSymbol(int dummy, ...) {
|
||||||
|
(void) dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void checkSymbol(void) {
|
||||||
|
#ifndef @CHECK_PROTOTYPE_DEFINITION_SYMBOL@
|
||||||
|
cmakeRequireSymbol(0, &@CHECK_PROTOTYPE_DEFINITION_SYMBOL@);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@CHECK_PROTOTYPE_DEFINITION_PROTO@ {
|
||||||
|
return @CHECK_PROTOTYPE_DEFINITION_RETURN@;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __CLASSIC_C__
|
||||||
|
int main() {
|
||||||
|
int ac;
|
||||||
|
char*av[];
|
||||||
|
#else
|
||||||
|
int main(int ac, char *av[]) {
|
||||||
|
#endif
|
||||||
|
checkSymbol();
|
||||||
|
if (ac > 1000) {
|
||||||
|
return *av[0];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
96
cmake/Modules/CheckPrototypeDefinition.cmake
Normal file
96
cmake/Modules/CheckPrototypeDefinition.cmake
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# - Check if the protoype we expect is correct.
|
||||||
|
# check_prototype_definition(FUNCTION PROTOTYPE RETURN HEADER VARIABLE)
|
||||||
|
# FUNCTION - The name of the function (used to check if prototype exists)
|
||||||
|
# PROTOTYPE- The prototype to check.
|
||||||
|
# RETURN - The return value of the function.
|
||||||
|
# HEADER - The header files required.
|
||||||
|
# VARIABLE - The variable to store the result.
|
||||||
|
# Example:
|
||||||
|
# check_prototype_definition(getpwent_r
|
||||||
|
# "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
|
||||||
|
# "NULL"
|
||||||
|
# "unistd.h;pwd.h"
|
||||||
|
# SOLARIS_GETPWENT_R)
|
||||||
|
# The following variables may be set before calling this macro to
|
||||||
|
# modify the way the check is run:
|
||||||
|
#
|
||||||
|
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||||
|
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||||
|
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||||
|
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2005-2009 Kitware, Inc.
|
||||||
|
# Copyright 2010-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
#
|
||||||
|
|
||||||
|
get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||||
|
|
||||||
|
function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE)
|
||||||
|
|
||||||
|
if ("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n")
|
||||||
|
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||||
|
if (CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_LIBS
|
||||||
|
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
||||||
|
else(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_LIBS)
|
||||||
|
endif(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
if (CMAKE_REQUIRED_INCLUDES)
|
||||||
|
set(CMAKE_SYMBOL_EXISTS_INCLUDES
|
||||||
|
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
|
||||||
|
else(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
set(CMAKE_SYMBOL_EXISTS_INCLUDES)
|
||||||
|
endif(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
|
||||||
|
foreach(_FILE ${_HEADER})
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_HEADER
|
||||||
|
"${CHECK_PROTOTYPE_DEFINITION_HEADER}#include <${_FILE}>\n")
|
||||||
|
endforeach(_FILE)
|
||||||
|
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION})
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
|
||||||
|
set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
|
||||||
|
|
||||||
|
configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in"
|
||||||
|
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY)
|
||||||
|
|
||||||
|
file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE)
|
||||||
|
|
||||||
|
try_compile(${_VARIABLE}
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c
|
||||||
|
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
|
||||||
|
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS}
|
||||||
|
"${CHECK_PROTOTYPE_DEFINITION_LIBS}"
|
||||||
|
"${CMAKE_SYMBOL_EXISTS_INCLUDES}"
|
||||||
|
OUTPUT_VARIABLE OUTPUT)
|
||||||
|
|
||||||
|
if (${_VARIABLE})
|
||||||
|
set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
|
||||||
|
message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||||
|
"Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n"
|
||||||
|
"${OUTPUT}\n\n")
|
||||||
|
else (${_VARIABLE})
|
||||||
|
message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False")
|
||||||
|
set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} failed with the following output:\n"
|
||||||
|
"${OUTPUT}\n\n${_SOURCE}\n\n")
|
||||||
|
endif (${_VARIABLE})
|
||||||
|
endif("${_VARIABLE}" MATCHES "^${_VARIABLE}$")
|
||||||
|
|
||||||
|
endfunction(CHECK_PROTOTYPE_DEFINITION)
|
@ -12,14 +12,19 @@ IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
|
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
|
||||||
|
CHECK_FUNCTION_EXISTS(iconv_open libc_has_iconv)
|
||||||
FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
|
FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
|
||||||
|
|
||||||
IF(ICONV_INCLUDE_DIR AND iconv_lib)
|
IF(ICONV_INCLUDE_DIR AND libc_has_iconv)
|
||||||
SET(ICONV_FOUND TRUE)
|
SET(ICONV_FOUND TRUE)
|
||||||
ENDIF()
|
SET(ICONV_LIBRARIES "")
|
||||||
|
IF(NOT ICONV_FIND_QUIETLY)
|
||||||
IF(ICONV_FOUND)
|
MESSAGE(STATUS "Found Iconv: provided by libc")
|
||||||
# split iconv into -L and -l linker options, so we can set them for pkg-config
|
ENDIF(NOT ICONV_FIND_QUIETLY)
|
||||||
|
ELSEIF(ICONV_INCLUDE_DIR AND iconv_lib)
|
||||||
|
SET(ICONV_FOUND TRUE)
|
||||||
|
# split iconv into -L and -l linker options, so we can
|
||||||
|
# set them for pkg-config
|
||||||
GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH)
|
GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH)
|
||||||
GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE)
|
GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE)
|
||||||
STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
|
STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#ifndef INCLUDE_git_version_h__
|
#ifndef INCLUDE_git_version_h__
|
||||||
#define INCLUDE_git_version_h__
|
#define INCLUDE_git_version_h__
|
||||||
|
|
||||||
#define LIBGIT2_VERSION "0.27.4"
|
#define LIBGIT2_VERSION "0.27.7"
|
||||||
#define LIBGIT2_VER_MAJOR 0
|
#define LIBGIT2_VER_MAJOR 0
|
||||||
#define LIBGIT2_VER_MINOR 27
|
#define LIBGIT2_VER_MINOR 27
|
||||||
#define LIBGIT2_VER_REVISION 4
|
#define LIBGIT2_VER_REVISION 7
|
||||||
#define LIBGIT2_VER_PATCH 0
|
#define LIBGIT2_VER_PATCH 0
|
||||||
|
|
||||||
#define LIBGIT2_SOVERSION 27
|
#define LIBGIT2_SOVERSION 27
|
||||||
|
@ -47,3 +47,28 @@
|
|||||||
...
|
...
|
||||||
fun:__check_pf
|
fun:__check_pf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore-curl-global-init
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:curl_global_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore-libssh2-gcrypt-leak
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:gcry_control
|
||||||
|
obj:*libssh2.so*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ignore-noai6ai_cached-double-free
|
||||||
|
Memcheck:Free
|
||||||
|
fun:free
|
||||||
|
fun:__libc_freeres
|
||||||
|
...
|
||||||
|
fun:exit
|
||||||
|
...
|
||||||
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
cd `dirname "$0"`/..
|
|
||||||
if [ "$ARCH" = "i686" ]; then
|
|
||||||
f=i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
|
|
||||||
if ! [ -e $f ]; then
|
|
||||||
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/sjlj/$f
|
|
||||||
fi
|
|
||||||
7z x $f > /dev/null
|
|
||||||
export PATH=`pwd`/mingw32/bin:$PATH
|
|
||||||
else
|
|
||||||
f=x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
|
|
||||||
if ! [ -e $f ]; then
|
|
||||||
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/$f
|
|
||||||
fi
|
|
||||||
7z x $f > /dev/null
|
|
||||||
export PATH=`pwd`/mingw64/bin:$PATH
|
|
||||||
fi
|
|
||||||
cd build
|
|
||||||
gcc --version
|
|
||||||
cmake --version
|
|
||||||
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON .. -G"$GENERATOR"
|
|
||||||
cmake --build . --config RelWithDebInfo
|
|
@ -1,102 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
if [ -n "$COVERITY" ];
|
|
||||||
then
|
|
||||||
./script/coverity.sh;
|
|
||||||
exit $?;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -)
|
|
||||||
|
|
||||||
# Set up a ramdisk for us to put our test data on to speed up tests on macOS
|
|
||||||
export CLAR_TMP="$HOME"/_clar_tmp
|
|
||||||
mkdir -p $CLAR_TMP
|
|
||||||
|
|
||||||
# 5*2M sectors aka ~5GB of space
|
|
||||||
device=$(hdiutil attach -nomount ram://$((5 * 2 * 1024 * 1024)))
|
|
||||||
newfs_hfs $device
|
|
||||||
mount -t hfs $device $CLAR_TMP
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Should we ask Travis to cache this file?
|
|
||||||
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar || exit $?
|
|
||||||
# Run this early so we know it's ready by the time we need it
|
|
||||||
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar &
|
|
||||||
|
|
||||||
mkdir _build
|
|
||||||
cd _build
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
cmake .. -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
|
|
||||||
make -j2 install || exit $?
|
|
||||||
|
|
||||||
# If this platform doesn't support test execution, bail out now
|
|
||||||
if [ -n "$SKIP_TESTS" ];
|
|
||||||
then
|
|
||||||
exit $?;
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create a test repo which we can use for the online::push tests
|
|
||||||
mkdir "$HOME"/_temp
|
|
||||||
git init --bare "$HOME"/_temp/test.git
|
|
||||||
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="$HOME"/_temp "$HOME"/_temp 2>/dev/null &
|
|
||||||
export GITTEST_REMOTE_URL="git://localhost/test.git"
|
|
||||||
|
|
||||||
# Run the test suite
|
|
||||||
ctest -V -R libgit2_clar || exit $?
|
|
||||||
|
|
||||||
# Now that we've tested the raw git protocol, let's set up ssh to we
|
|
||||||
# can do the push tests over it
|
|
||||||
|
|
||||||
killall git-daemon
|
|
||||||
|
|
||||||
# Set up sshd
|
|
||||||
mkdir ~/sshd/
|
|
||||||
cat >~/sshd/sshd_config<<-EOF
|
|
||||||
Port 2222
|
|
||||||
ListenAddress 0.0.0.0
|
|
||||||
Protocol 2
|
|
||||||
HostKey ${HOME}/sshd/id_rsa
|
|
||||||
PidFile ${HOME}/sshd/pid
|
|
||||||
RSAAuthentication yes
|
|
||||||
PasswordAuthentication yes
|
|
||||||
PubkeyAuthentication yes
|
|
||||||
ChallengeResponseAuthentication no
|
|
||||||
# Required here as sshd will simply close connection otherwise
|
|
||||||
UsePAM no
|
|
||||||
EOF
|
|
||||||
ssh-keygen -t rsa -f ~/sshd/id_rsa -N "" -q
|
|
||||||
/usr/sbin/sshd -f ~/sshd/sshd_config
|
|
||||||
|
|
||||||
# Set up keys
|
|
||||||
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
|
|
||||||
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
|
|
||||||
while read algorithm key comment; do
|
|
||||||
echo "[localhost]:2222 $algorithm $key" >>~/.ssh/known_hosts
|
|
||||||
done <~/sshd/id_rsa.pub
|
|
||||||
|
|
||||||
# Get the fingerprint for localhost and remove the colons so we can parse it as
|
|
||||||
# a hex number. The Mac version is newer so it has a different output format.
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
|
|
||||||
else
|
|
||||||
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use the SSH server
|
|
||||||
export GITTEST_REMOTE_URL="ssh://localhost:2222/$HOME/_temp/test.git"
|
|
||||||
export GITTEST_REMOTE_USER=$USER
|
|
||||||
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
|
|
||||||
export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
|
|
||||||
export GITTEST_REMOTE_SSH_PASSPHRASE=""
|
|
||||||
ctest -V -R libgit2_clar-ssh || exit $?
|
|
||||||
|
|
||||||
# Use the proxy we started at the beginning
|
|
||||||
export GITTEST_REMOTE_PROXY_URL="localhost:8080"
|
|
||||||
export GITTEST_REMOTE_PROXY_USER="foo"
|
|
||||||
export GITTEST_REMOTE_PROXY_PASS="bar"
|
|
||||||
ctest -V -R libgit2_clar-proxy_credentials || exit $?
|
|
||||||
|
|
||||||
kill $(cat "$HOME/sshd/pid")
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
brew update
|
|
||||||
brew install zlib
|
|
||||||
brew install curl
|
|
||||||
brew install openssl
|
|
||||||
brew install libssh2
|
|
@ -57,10 +57,19 @@ IF (HAVE_FUTIMENS)
|
|||||||
SET(GIT_USE_FUTIMENS 1)
|
SET(GIT_USE_FUTIMENS 1)
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
CHECK_FUNCTION_EXISTS(qsort_r HAVE_QSORT_R)
|
CHECK_PROTOTYPE_DEFINITION(qsort_r
|
||||||
IF (HAVE_QSORT_R)
|
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
|
||||||
ADD_DEFINITIONS(-DHAVE_QSORT_R)
|
"" "stdlib.h" HAVE_QSORT_R_BSD)
|
||||||
ENDIF ()
|
IF (HAVE_QSORT_R_BSD)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
CHECK_PROTOTYPE_DEFINITION(qsort_r
|
||||||
|
"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
|
||||||
|
"" "stdlib.h" HAVE_QSORT_R_GNU)
|
||||||
|
IF (HAVE_QSORT_R_GNU)
|
||||||
|
ADD_DEFINITIONS(-DHAVE_QSORT_R_GNU)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
|
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
|
||||||
IF (HAVE_QSORT_S)
|
IF (HAVE_QSORT_S)
|
||||||
|
@ -443,7 +443,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
|
|||||||
while (eoln < buffer_end && *eoln != '\n')
|
while (eoln < buffer_end && *eoln != '\n')
|
||||||
++eoln;
|
++eoln;
|
||||||
|
|
||||||
if (git__prefixcmp(buffer, "encoding ") == 0) {
|
if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
|
||||||
buffer += strlen("encoding ");
|
buffer += strlen("encoding ");
|
||||||
|
|
||||||
commit->message_encoding = git__strndup(buffer, eoln - buffer);
|
commit->message_encoding = git__strndup(buffer, eoln - buffer);
|
||||||
|
@ -171,7 +171,9 @@ static int commit_quick_parse(
|
|||||||
buffer--;
|
buffer--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((buffer == committer_start) || (git__strtol64(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
|
if ((buffer == committer_start) ||
|
||||||
|
(git__strntol64(&commit_time, (char *)(buffer + 1),
|
||||||
|
buffer_end - buffer + 1, NULL, 10) < 0))
|
||||||
return commit_error(commit, "cannot parse commit time");
|
return commit_error(commit, "cannot parse commit time");
|
||||||
|
|
||||||
commit->time = commit_time;
|
commit->time = commit_time;
|
||||||
|
@ -1300,7 +1300,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
|
|||||||
const char *num_end;
|
const char *num_end;
|
||||||
int64_t num;
|
int64_t num;
|
||||||
|
|
||||||
if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
|
if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
|
||||||
goto fail_parse;
|
goto fail_parse;
|
||||||
|
|
||||||
switch (*num_end) {
|
switch (*num_end) {
|
||||||
|
@ -928,6 +928,9 @@ static int parse_include(git_config_parser *reader,
|
|||||||
char *dir;
|
char *dir;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
|
if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -1029,7 +1032,7 @@ static int parse_conditional_include(git_config_parser *reader,
|
|||||||
size_t i;
|
size_t i;
|
||||||
int error = 0, matches;
|
int error = 0, matches;
|
||||||
|
|
||||||
if (!parse_data->repo)
|
if (!parse_data->repo || !file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
condition = git__substrdup(section + strlen("includeIf."),
|
condition = git__substrdup(section + strlen("includeIf."),
|
||||||
@ -1072,8 +1075,16 @@ static int read_on_variable(
|
|||||||
GIT_UNUSED(line);
|
GIT_UNUSED(line);
|
||||||
GIT_UNUSED(line_len);
|
GIT_UNUSED(line_len);
|
||||||
|
|
||||||
|
if (current_section) {
|
||||||
|
/* TODO: Once warnings lang, we should likely warn
|
||||||
|
* here. Git appears to warn in most cases if it sees
|
||||||
|
* un-namespaced config options.
|
||||||
|
*/
|
||||||
|
git_buf_puts(&buf, current_section);
|
||||||
|
git_buf_putc(&buf, '.');
|
||||||
|
}
|
||||||
git__strtolower(var_name);
|
git__strtolower(var_name);
|
||||||
git_buf_printf(&buf, "%s.%s", current_section, var_name);
|
git_buf_puts(&buf, var_name);
|
||||||
git__free(var_name);
|
git__free(var_name);
|
||||||
|
|
||||||
if (git_buf_oom(&buf)) {
|
if (git_buf_oom(&buf)) {
|
||||||
|
@ -315,49 +315,51 @@ done:
|
|||||||
|
|
||||||
static int parse_multiline_variable(git_config_parser *reader, git_buf *value, int in_quotes)
|
static int parse_multiline_variable(git_config_parser *reader, git_buf *value, int in_quotes)
|
||||||
{
|
{
|
||||||
char *line = NULL, *proc_line = NULL;
|
|
||||||
int quote_count;
|
int quote_count;
|
||||||
bool multiline;
|
bool multiline = true;
|
||||||
|
|
||||||
|
while (multiline) {
|
||||||
|
char *line = NULL, *proc_line = NULL;
|
||||||
|
int error;
|
||||||
|
|
||||||
/* Check that the next line exists */
|
/* Check that the next line exists */
|
||||||
git_parse_advance_line(&reader->ctx);
|
git_parse_advance_line(&reader->ctx);
|
||||||
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
|
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
|
||||||
if (line == NULL)
|
GITERR_CHECK_ALLOC(line);
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* We've reached the end of the file, there is no continuation.
|
/*
|
||||||
|
* We've reached the end of the file, there is no continuation.
|
||||||
* (this is not an error).
|
* (this is not an error).
|
||||||
*/
|
*/
|
||||||
if (line[0] == '\0') {
|
if (line[0] == '\0') {
|
||||||
git__free(line);
|
error = 0;
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
quote_count = strip_comments(line, !!in_quotes);
|
|
||||||
|
|
||||||
/* If it was just a comment, pretend it didn't exist */
|
/* If it was just a comment, pretend it didn't exist */
|
||||||
if (line[0] == '\0') {
|
quote_count = strip_comments(line, !!in_quotes);
|
||||||
git__free(line);
|
if (line[0] == '\0')
|
||||||
return parse_multiline_variable(reader, value, quote_count);
|
goto next;
|
||||||
/* TODO: unbounded recursion. This **could** be exploitable */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unescape_line(&proc_line, &multiline, line, in_quotes) < 0) {
|
if ((error = unescape_line(&proc_line, &multiline,
|
||||||
git__free(line);
|
line, in_quotes)) < 0)
|
||||||
return -1;
|
goto out;
|
||||||
}
|
|
||||||
/* add this line to the multiline var */
|
|
||||||
|
|
||||||
git_buf_puts(value, proc_line);
|
/* Add this line to the multiline var */
|
||||||
|
if ((error = git_buf_puts(value, proc_line)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
next:
|
||||||
git__free(line);
|
git__free(line);
|
||||||
git__free(proc_line);
|
git__free(proc_line);
|
||||||
|
in_quotes = quote_count;
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
out:
|
||||||
* If we need to continue reading the next line, let's just
|
git__free(line);
|
||||||
* keep putting stuff in the buffer
|
git__free(proc_line);
|
||||||
*/
|
return error;
|
||||||
if (multiline)
|
}
|
||||||
return parse_multiline_variable(reader, value, quote_count);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -822,7 +822,7 @@ int git_diff_find_similar(
|
|||||||
num_deltas = diff->deltas.length;
|
num_deltas = diff->deltas.length;
|
||||||
|
|
||||||
/* TODO: maybe abort if deltas.length > rename_limit ??? */
|
/* TODO: maybe abort if deltas.length > rename_limit ??? */
|
||||||
if (!git__is_uint32(num_deltas))
|
if (!num_deltas || !git__is_uint32(num_deltas))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* No flags set; nothing to do */
|
/* No flags set; nothing to do */
|
||||||
|
@ -1774,7 +1774,8 @@ int git_index_conflict_add(git_index *index,
|
|||||||
if (entries[i] && !valid_filemode(entries[i]->mode)) {
|
if (entries[i] && !valid_filemode(entries[i]->mode)) {
|
||||||
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
|
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
|
||||||
i + 1);
|
i + 1);
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2206,7 +2207,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
|||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
int64_t tmp;
|
int64_t tmp;
|
||||||
|
|
||||||
if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
|
if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 ||
|
||||||
!endptr || endptr == buffer || *endptr ||
|
!endptr || endptr == buffer || *endptr ||
|
||||||
tmp < 0 || tmp > UINT32_MAX) {
|
tmp < 0 || tmp > UINT32_MAX) {
|
||||||
index_entry_reuc_free(lost);
|
index_entry_reuc_free(lost);
|
||||||
@ -3509,7 +3510,7 @@ int git_index_snapshot_new(git_vector *snap, git_index *index)
|
|||||||
error = git_vector_dup(snap, &index->entries, index->entries._cmp);
|
error = git_vector_dup(snap, &index->entries, index->entries._cmp);
|
||||||
|
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
git_index_free(index);
|
git_index_snapshot_release(snap, index);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -1384,8 +1384,8 @@ static int git_odb_stream__invalid_length(
|
|||||||
{
|
{
|
||||||
giterr_set(GITERR_ODB,
|
giterr_set(GITERR_ODB,
|
||||||
"cannot %s - "
|
"cannot %s - "
|
||||||
"Invalid length. %"PRIdZ" was expected. The "
|
"Invalid length. %"PRId64" was expected. The "
|
||||||
"total size of the received chunks amounts to %"PRIdZ".",
|
"total size of the received chunks amounts to %"PRId64".",
|
||||||
action, stream->declared_size, stream->received_bytes);
|
action, stream->declared_size, stream->received_bytes);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -210,7 +210,7 @@ static int packfile_load__cb(void *data, git_buf *path)
|
|||||||
for (i = 0; i < backend->packs.length; ++i) {
|
for (i = 0; i < backend->packs.length; ++i) {
|
||||||
struct git_pack_file *p = git_vector_get(&backend->packs, i);
|
struct git_pack_file *p = git_vector_get(&backend->packs, i);
|
||||||
|
|
||||||
if (memcmp(p->pack_name, path_str, cmp_len) == 0)
|
if (strncmp(p->pack_name, path_str, cmp_len) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1666,7 +1666,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case GIT_OBJ_BLOB:
|
case GIT_OBJ_BLOB:
|
||||||
if ((error = retrieve_object(&obj, pb, git_tree_id(tree))) < 0)
|
if ((error = retrieve_object(&obj, pb, entry_id)) < 0)
|
||||||
return error;
|
return error;
|
||||||
if (obj->uninteresting)
|
if (obj->uninteresting)
|
||||||
continue;
|
continue;
|
||||||
|
11
src/parse.c
11
src/parse.c
@ -8,12 +8,14 @@
|
|||||||
|
|
||||||
int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len)
|
int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len)
|
||||||
{
|
{
|
||||||
if (content_len)
|
if (content && content_len) {
|
||||||
ctx->content = content;
|
ctx->content = content;
|
||||||
else
|
|
||||||
ctx->content = NULL;
|
|
||||||
|
|
||||||
ctx->content_len = content_len;
|
ctx->content_len = content_len;
|
||||||
|
} else {
|
||||||
|
ctx->content = "";
|
||||||
|
ctx->content_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->remain = ctx->content;
|
ctx->remain = ctx->content;
|
||||||
ctx->remain_len = ctx->content_len;
|
ctx->remain_len = ctx->content_len;
|
||||||
ctx->line = ctx->remain;
|
ctx->line = ctx->remain;
|
||||||
@ -26,6 +28,7 @@ int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_l
|
|||||||
void git_parse_ctx_clear(git_parse_ctx *ctx)
|
void git_parse_ctx_clear(git_parse_ctx *ctx)
|
||||||
{
|
{
|
||||||
memset(ctx, 0, sizeof(*ctx));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
ctx->content = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_parse_advance_line(git_parse_ctx *ctx)
|
void git_parse_advance_line(git_parse_ctx *ctx)
|
||||||
|
@ -563,6 +563,8 @@ static int parse_hunk_body(
|
|||||||
char c;
|
char c;
|
||||||
int origin;
|
int origin;
|
||||||
int prefix = 1;
|
int prefix = 1;
|
||||||
|
int old_lineno = hunk->hunk.old_start + (hunk->hunk.old_lines - oldlines);
|
||||||
|
int new_lineno = hunk->hunk.new_start + (hunk->hunk.new_lines - newlines);
|
||||||
|
|
||||||
if (ctx->parse_ctx.line_len == 0 || ctx->parse_ctx.line[ctx->parse_ctx.line_len - 1] != '\n') {
|
if (ctx->parse_ctx.line_len == 0 || ctx->parse_ctx.line[ctx->parse_ctx.line_len - 1] != '\n') {
|
||||||
error = git_parse_err("invalid patch instruction at line %"PRIuZ,
|
error = git_parse_err("invalid patch instruction at line %"PRIuZ,
|
||||||
@ -586,11 +588,13 @@ static int parse_hunk_body(
|
|||||||
case '-':
|
case '-':
|
||||||
origin = GIT_DIFF_LINE_DELETION;
|
origin = GIT_DIFF_LINE_DELETION;
|
||||||
oldlines--;
|
oldlines--;
|
||||||
|
new_lineno = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
origin = GIT_DIFF_LINE_ADDITION;
|
origin = GIT_DIFF_LINE_ADDITION;
|
||||||
newlines--;
|
newlines--;
|
||||||
|
old_lineno = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -607,6 +611,9 @@ static int parse_hunk_body(
|
|||||||
line->content_len = ctx->parse_ctx.line_len - prefix;
|
line->content_len = ctx->parse_ctx.line_len - prefix;
|
||||||
line->content_offset = ctx->parse_ctx.content_len - ctx->parse_ctx.remain_len;
|
line->content_offset = ctx->parse_ctx.content_len - ctx->parse_ctx.remain_len;
|
||||||
line->origin = origin;
|
line->origin = origin;
|
||||||
|
line->num_lines = 1;
|
||||||
|
line->old_lineno = old_lineno;
|
||||||
|
line->new_lineno = new_lineno;
|
||||||
|
|
||||||
hunk->line_count++;
|
hunk->line_count++;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ GIT_INLINE(int) rebase_readint(
|
|||||||
if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
|
if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
|
if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
|
||||||
giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
|
giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +428,7 @@ static int get_optional_config(
|
|||||||
|
|
||||||
int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
|
int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
|
||||||
{
|
{
|
||||||
git_remote *remote;
|
git_remote *remote = NULL;
|
||||||
git_buf buf = GIT_BUF_INIT;
|
git_buf buf = GIT_BUF_INIT;
|
||||||
const char *val;
|
const char *val;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@ -510,7 +510,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
|
|||||||
if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
|
if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (download_tags_value(remote, config) < 0)
|
if ((error = download_tags_value(remote, config)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
|
if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
|
||||||
@ -1234,7 +1234,7 @@ int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
key.name = (char *) git_buf_cstr(&buf);
|
key.name = (char *) git_buf_cstr(&buf);
|
||||||
error = git_vector_search(&pos, &remote_refs, &key);
|
error = git_vector_bsearch(&pos, &remote_refs, &key);
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
|
|
||||||
if (error < 0 && error != GIT_ENOTFOUND)
|
if (error < 0 && error != GIT_ENOTFOUND)
|
||||||
|
@ -268,11 +268,15 @@ static int load_config_data(git_repository *repo, const git_config *config)
|
|||||||
{
|
{
|
||||||
int is_bare;
|
int is_bare;
|
||||||
|
|
||||||
|
int err = git_config_get_bool(&is_bare, config, "core.bare");
|
||||||
|
if (err < 0 && err != GIT_ENOTFOUND)
|
||||||
|
return err;
|
||||||
|
|
||||||
/* Try to figure out if it's bare, default to non-bare if it's not set */
|
/* Try to figure out if it's bare, default to non-bare if it's not set */
|
||||||
if (git_config_get_bool(&is_bare, config, "core.bare") < 0)
|
if (err != GIT_ENOTFOUND)
|
||||||
repo->is_bare = 0;
|
repo->is_bare = is_bare && !repo->is_worktree;
|
||||||
else
|
else
|
||||||
repo->is_bare = is_bare;
|
repo->is_bare = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,8 @@ static int try_parse_numeric(int *n, const char *curly_braces_content)
|
|||||||
int32_t content;
|
int32_t content;
|
||||||
const char *end_ptr;
|
const char *end_ptr;
|
||||||
|
|
||||||
if (git__strtol32(&content, curly_braces_content, &end_ptr, 10) < 0)
|
if (git__strntol32(&content, curly_braces_content, strlen(curly_braces_content),
|
||||||
|
&end_ptr, 10) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (*end_ptr != '\0')
|
if (*end_ptr != '\0')
|
||||||
@ -578,7 +579,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
|
|||||||
} while (spec[(*pos)] == kind && kind == '~');
|
} while (spec[(*pos)] == kind && kind == '~');
|
||||||
|
|
||||||
if (git__isdigit(spec[*pos])) {
|
if (git__isdigit(spec[*pos])) {
|
||||||
if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0)
|
if (git__strntol32(&parsed, spec + *pos, strlen(spec + *pos), &end_ptr, 10) < 0)
|
||||||
return GIT_EINVALIDSPEC;
|
return GIT_EINVALIDSPEC;
|
||||||
|
|
||||||
accumulated += (parsed - 1);
|
accumulated += (parsed - 1);
|
||||||
|
@ -384,10 +384,16 @@ static int still_interesting(git_commit_list *list, int64_t time, int slop)
|
|||||||
if (!list)
|
if (!list)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the destination list has commits with an earlier date than our
|
||||||
|
* source, we want to reset the slop counter as we're not done.
|
||||||
|
*/
|
||||||
|
if (time <= list->item->time)
|
||||||
|
return SLOP;
|
||||||
|
|
||||||
for (; list; list = list->next) {
|
for (; list; list = list->next) {
|
||||||
/*
|
/*
|
||||||
* If the destination list has commits with an earlier date than
|
* If the destination list still contains interesting commits we
|
||||||
* our source or if it still contains interesting commits we
|
|
||||||
* want to continue looking.
|
* want to continue looking.
|
||||||
*/
|
*/
|
||||||
if (!list->item->uninteresting || list->item->time > time)
|
if (!list->item->uninteresting || list->item->time > time)
|
||||||
@ -401,7 +407,7 @@ static int still_interesting(git_commit_list *list, int64_t time, int slop)
|
|||||||
static int limit_list(git_commit_list **out, git_revwalk *walk, git_commit_list *commits)
|
static int limit_list(git_commit_list **out, git_revwalk *walk, git_commit_list *commits)
|
||||||
{
|
{
|
||||||
int error, slop = SLOP;
|
int error, slop = SLOP;
|
||||||
int64_t time = ~0ll;
|
int64_t time = INT64_MAX;
|
||||||
git_commit_list *list = commits;
|
git_commit_list *list = commits;
|
||||||
git_commit_list *newlist = NULL;
|
git_commit_list *newlist = NULL;
|
||||||
git_commit_list **p = &newlist;
|
git_commit_list **p = &newlist;
|
||||||
@ -522,7 +528,7 @@ cleanup:
|
|||||||
|
|
||||||
static int prepare_walk(git_revwalk *walk)
|
static int prepare_walk(git_revwalk *walk)
|
||||||
{
|
{
|
||||||
int error;
|
int error = 0;
|
||||||
git_commit_list *list, *commits = NULL;
|
git_commit_list *list, *commits = NULL;
|
||||||
git_commit_list_node *next;
|
git_commit_list_node *next;
|
||||||
|
|
||||||
|
@ -231,7 +231,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
|||||||
const char *time_start = email_end + 2;
|
const char *time_start = email_end + 2;
|
||||||
const char *time_end;
|
const char *time_end;
|
||||||
|
|
||||||
if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
|
if (git__strntol64(&sig->when.time, time_start,
|
||||||
|
buffer_end - time_start, &time_end, 10) < 0) {
|
||||||
git__free(sig->name);
|
git__free(sig->name);
|
||||||
git__free(sig->email);
|
git__free(sig->email);
|
||||||
sig->name = sig->email = NULL;
|
sig->name = sig->email = NULL;
|
||||||
@ -246,8 +247,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
|||||||
tz_start = time_end + 1;
|
tz_start = time_end + 1;
|
||||||
|
|
||||||
if ((tz_start[0] != '-' && tz_start[0] != '+') ||
|
if ((tz_start[0] != '-' && tz_start[0] != '+') ||
|
||||||
git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) {
|
git__strntol32(&offset, tz_start + 1,
|
||||||
//malformed timezone, just assume it's zero
|
buffer_end - tz_start + 1, &tz_end, 10) < 0) {
|
||||||
|
/* malformed timezone, just assume it's zero */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
|
if ((error = git__strntol32(&iport, port, strlen(port), NULL, 10)) < 0) {
|
||||||
git__free(st);
|
git__free(st);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -1813,6 +1813,14 @@ static int get_value(const char **out, git_config *cfg, git_buf *buf, const char
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool looks_like_command_line_option(const char *s)
|
||||||
|
{
|
||||||
|
if (s && s[0] == '-')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int submodule_read_config(git_submodule *sm, git_config *cfg)
|
static int submodule_read_config(git_submodule *sm, git_config *cfg)
|
||||||
{
|
{
|
||||||
git_buf key = GIT_BUF_INIT;
|
git_buf key = GIT_BUF_INIT;
|
||||||
@ -1826,6 +1834,8 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
|
|||||||
|
|
||||||
if ((error = get_value(&value, cfg, &key, sm->name, "path")) == 0) {
|
if ((error = get_value(&value, cfg, &key, sm->name, "path")) == 0) {
|
||||||
in_config = 1;
|
in_config = 1;
|
||||||
|
/* We would warn here if we had that API */
|
||||||
|
if (!looks_like_command_line_option(value)) {
|
||||||
/*
|
/*
|
||||||
* TODO: if case insensitive filesystem, then the following strcmp
|
* TODO: if case insensitive filesystem, then the following strcmp
|
||||||
* should be strcasecmp
|
* should be strcasecmp
|
||||||
@ -1836,14 +1846,19 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
|
|||||||
sm->path = git__strdup(value);
|
sm->path = git__strdup(value);
|
||||||
GITERR_CHECK_ALLOC(sm->path);
|
GITERR_CHECK_ALLOC(sm->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
} else if (error != GIT_ENOTFOUND) {
|
} else if (error != GIT_ENOTFOUND) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = get_value(&value, cfg, &key, sm->name, "url")) == 0) {
|
if ((error = get_value(&value, cfg, &key, sm->name, "url")) == 0) {
|
||||||
|
/* We would warn here if we had that API */
|
||||||
|
if (!looks_like_command_line_option(value)) {
|
||||||
in_config = 1;
|
in_config = 1;
|
||||||
sm->url = git__strdup(value);
|
sm->url = git__strdup(value);
|
||||||
GITERR_CHECK_ALLOC(sm->url);
|
GITERR_CHECK_ALLOC(sm->url);
|
||||||
|
}
|
||||||
} else if (error != GIT_ENOTFOUND) {
|
} else if (error != GIT_ENOTFOUND) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
10
src/tag.c
10
src/tag.c
@ -70,10 +70,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
|||||||
static const char *tag_types[] = {
|
static const char *tag_types[] = {
|
||||||
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
|
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
size_t text_len, alloc_len;
|
size_t text_len, alloc_len;
|
||||||
char *search;
|
const char *search;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
|
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
|
||||||
return tag_error("object field invalid");
|
return tag_error("object field invalid");
|
||||||
@ -138,8 +137,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
|||||||
tag->message = NULL;
|
tag->message = NULL;
|
||||||
if (buffer < buffer_end) {
|
if (buffer < buffer_end) {
|
||||||
/* If we're not at the end of the header, search for it */
|
/* If we're not at the end of the header, search for it */
|
||||||
if( *buffer != '\n' ) {
|
if(*buffer != '\n') {
|
||||||
search = strstr(buffer, "\n\n");
|
search = git__memmem(buffer, buffer_end - buffer,
|
||||||
|
"\n\n", 2);
|
||||||
if (search)
|
if (search)
|
||||||
buffer = search + 1;
|
buffer = search + 1;
|
||||||
else
|
else
|
||||||
|
@ -188,6 +188,9 @@ static int apply_credentials(git_buf *buf, http_subtransport *t)
|
|||||||
if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
|
if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return context->next_token(buf, context, cred);
|
return context->next_token(buf, context, cred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,11 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
|
|||||||
t->current_stream = NULL;
|
t->current_stream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t->url) {
|
||||||
|
git__free(t->url);
|
||||||
|
t->url = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (close_subtransport &&
|
if (close_subtransport &&
|
||||||
t->wrapped->close(t->wrapped) < 0)
|
t->wrapped->close(t->wrapped) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -33,14 +33,14 @@
|
|||||||
|
|
||||||
extern bool git_smart__ofs_delta_enabled;
|
extern bool git_smart__ofs_delta_enabled;
|
||||||
|
|
||||||
enum git_pkt_type {
|
typedef enum {
|
||||||
GIT_PKT_CMD,
|
GIT_PKT_CMD,
|
||||||
GIT_PKT_FLUSH,
|
GIT_PKT_FLUSH,
|
||||||
GIT_PKT_REF,
|
GIT_PKT_REF,
|
||||||
GIT_PKT_HAVE,
|
GIT_PKT_HAVE,
|
||||||
GIT_PKT_ACK,
|
GIT_PKT_ACK,
|
||||||
GIT_PKT_NAK,
|
GIT_PKT_NAK,
|
||||||
GIT_PKT_PACK,
|
GIT_PKT_PACK__UNUSED,
|
||||||
GIT_PKT_COMMENT,
|
GIT_PKT_COMMENT,
|
||||||
GIT_PKT_ERR,
|
GIT_PKT_ERR,
|
||||||
GIT_PKT_DATA,
|
GIT_PKT_DATA,
|
||||||
@ -48,7 +48,7 @@ enum git_pkt_type {
|
|||||||
GIT_PKT_OK,
|
GIT_PKT_OK,
|
||||||
GIT_PKT_NG,
|
GIT_PKT_NG,
|
||||||
GIT_PKT_UNPACK,
|
GIT_PKT_UNPACK,
|
||||||
};
|
} git_pkt_type;
|
||||||
|
|
||||||
/* Used for multi_ack and mutli_ack_detailed */
|
/* Used for multi_ack and mutli_ack_detailed */
|
||||||
enum git_ack_status {
|
enum git_ack_status {
|
||||||
@ -60,11 +60,11 @@ enum git_ack_status {
|
|||||||
|
|
||||||
/* This would be a flush pkt */
|
/* This would be a flush pkt */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
} git_pkt;
|
} git_pkt;
|
||||||
|
|
||||||
struct git_pkt_cmd {
|
struct git_pkt_cmd {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char *path;
|
char *path;
|
||||||
char *host;
|
char *host;
|
||||||
@ -72,50 +72,50 @@ struct git_pkt_cmd {
|
|||||||
|
|
||||||
/* This is a pkt-line with some info in it */
|
/* This is a pkt-line with some info in it */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
git_remote_head head;
|
git_remote_head head;
|
||||||
char *capabilities;
|
char *capabilities;
|
||||||
} git_pkt_ref;
|
} git_pkt_ref;
|
||||||
|
|
||||||
/* Useful later */
|
/* Useful later */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
enum git_ack_status status;
|
enum git_ack_status status;
|
||||||
} git_pkt_ack;
|
} git_pkt_ack;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
char comment[GIT_FLEX_ARRAY];
|
char comment[GIT_FLEX_ARRAY];
|
||||||
} git_pkt_comment;
|
} git_pkt_comment;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
int len;
|
size_t len;
|
||||||
char data[GIT_FLEX_ARRAY];
|
char data[GIT_FLEX_ARRAY];
|
||||||
} git_pkt_data;
|
} git_pkt_data;
|
||||||
|
|
||||||
typedef git_pkt_data git_pkt_progress;
|
typedef git_pkt_data git_pkt_progress;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
int len;
|
size_t len;
|
||||||
char error[GIT_FLEX_ARRAY];
|
char error[GIT_FLEX_ARRAY];
|
||||||
} git_pkt_err;
|
} git_pkt_err;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
char *ref;
|
char *ref;
|
||||||
} git_pkt_ok;
|
} git_pkt_ok;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
char *ref;
|
char *ref;
|
||||||
char *msg;
|
char *msg;
|
||||||
} git_pkt_ng;
|
} git_pkt_ng;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum git_pkt_type type;
|
git_pkt_type type;
|
||||||
int unpack_ok;
|
int unpack_ok;
|
||||||
} git_pkt_unpack;
|
} git_pkt_unpack;
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
|
|||||||
int git_smart__update_heads(transport_smart *t, git_vector *symrefs);
|
int git_smart__update_heads(transport_smart *t, git_vector *symrefs);
|
||||||
|
|
||||||
/* smart_pkt.c */
|
/* smart_pkt.c */
|
||||||
int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len);
|
int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, size_t linelen);
|
||||||
int git_pkt_buffer_flush(git_buf *buf);
|
int git_pkt_buffer_flush(git_buf *buf);
|
||||||
int git_pkt_send_flush(GIT_SOCKET s);
|
int git_pkt_send_flush(GIT_SOCKET s);
|
||||||
int git_pkt_buffer_done(git_buf *buf);
|
int git_pkt_buffer_done(git_buf *buf);
|
||||||
|
@ -43,34 +43,43 @@ static int flush_pkt(git_pkt **out)
|
|||||||
static int ack_pkt(git_pkt **out, const char *line, size_t len)
|
static int ack_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
git_pkt_ack *pkt;
|
git_pkt_ack *pkt;
|
||||||
GIT_UNUSED(line);
|
|
||||||
GIT_UNUSED(len);
|
|
||||||
|
|
||||||
pkt = git__calloc(1, sizeof(git_pkt_ack));
|
pkt = git__calloc(1, sizeof(git_pkt_ack));
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_ACK;
|
pkt->type = GIT_PKT_ACK;
|
||||||
line += 3;
|
|
||||||
len -= 3;
|
|
||||||
|
|
||||||
if (len >= GIT_OID_HEXSZ) {
|
if (git__prefixncmp(line, len, "ACK "))
|
||||||
git_oid_fromstr(&pkt->oid, line + 1);
|
goto out_err;
|
||||||
line += GIT_OID_HEXSZ + 1;
|
line += 4;
|
||||||
len -= GIT_OID_HEXSZ + 1;
|
len -= 4;
|
||||||
}
|
|
||||||
|
|
||||||
if (len >= 7) {
|
if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->oid, line) < 0)
|
||||||
if (!git__prefixcmp(line + 1, "continue"))
|
goto out_err;
|
||||||
|
line += GIT_OID_HEXSZ;
|
||||||
|
len -= GIT_OID_HEXSZ;
|
||||||
|
|
||||||
|
if (len && line[0] == ' ') {
|
||||||
|
line++;
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (!git__prefixncmp(line, len, "continue"))
|
||||||
pkt->status = GIT_ACK_CONTINUE;
|
pkt->status = GIT_ACK_CONTINUE;
|
||||||
if (!git__prefixcmp(line + 1, "common"))
|
else if (!git__prefixncmp(line, len, "common"))
|
||||||
pkt->status = GIT_ACK_COMMON;
|
pkt->status = GIT_ACK_COMMON;
|
||||||
if (!git__prefixcmp(line + 1, "ready"))
|
else if (!git__prefixncmp(line, len, "ready"))
|
||||||
pkt->status = GIT_ACK_READY;
|
pkt->status = GIT_ACK_READY;
|
||||||
|
else
|
||||||
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = (git_pkt *) pkt;
|
*out = (git_pkt *) pkt;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
giterr_set(GITERR_NET, "error parsing ACK pkt-line");
|
||||||
|
git__free(pkt);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nak_pkt(git_pkt **out)
|
static int nak_pkt(git_pkt **out)
|
||||||
@ -86,19 +95,6 @@ static int nak_pkt(git_pkt **out)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pack_pkt(git_pkt **out)
|
|
||||||
{
|
|
||||||
git_pkt *pkt;
|
|
||||||
|
|
||||||
pkt = git__malloc(sizeof(git_pkt));
|
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
|
||||||
|
|
||||||
pkt->type = GIT_PKT_PACK;
|
|
||||||
*out = pkt;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int comment_pkt(git_pkt **out, const char *line, size_t len)
|
static int comment_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
git_pkt_comment *pkt;
|
git_pkt_comment *pkt;
|
||||||
@ -120,10 +116,12 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
|
|
||||||
static int err_pkt(git_pkt **out, const char *line, size_t len)
|
static int err_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
git_pkt_err *pkt;
|
git_pkt_err *pkt = NULL;
|
||||||
size_t alloclen;
|
size_t alloclen;
|
||||||
|
|
||||||
/* Remove "ERR " from the line */
|
/* Remove "ERR " from the line */
|
||||||
|
if (git__prefixncmp(line, len, "ERR "))
|
||||||
|
goto out_err;
|
||||||
line += 4;
|
line += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
@ -131,15 +129,20 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
|
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
|
||||||
pkt = git__malloc(alloclen);
|
pkt = git__malloc(alloclen);
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_ERR;
|
pkt->type = GIT_PKT_ERR;
|
||||||
pkt->len = (int)len;
|
pkt->len = len;
|
||||||
|
|
||||||
memcpy(pkt->error, line, len);
|
memcpy(pkt->error, line, len);
|
||||||
pkt->error[len] = '\0';
|
pkt->error[len] = '\0';
|
||||||
|
|
||||||
*out = (git_pkt *) pkt;
|
*out = (git_pkt *) pkt;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
giterr_set(GITERR_NET, "error parsing ERR pkt-line");
|
||||||
|
git__free(pkt);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int data_pkt(git_pkt **out, const char *line, size_t len)
|
static int data_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
@ -155,7 +158,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_DATA;
|
pkt->type = GIT_PKT_DATA;
|
||||||
pkt->len = (int) len;
|
pkt->len = len;
|
||||||
memcpy(pkt->data, line, len);
|
memcpy(pkt->data, line, len);
|
||||||
|
|
||||||
*out = (git_pkt *) pkt;
|
*out = (git_pkt *) pkt;
|
||||||
@ -176,7 +179,7 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_PROGRESS;
|
pkt->type = GIT_PKT_PROGRESS;
|
||||||
pkt->len = (int) len;
|
pkt->len = len;
|
||||||
memcpy(pkt->data, line, len);
|
memcpy(pkt->data, line, len);
|
||||||
|
|
||||||
*out = (git_pkt *) pkt;
|
*out = (git_pkt *) pkt;
|
||||||
@ -212,28 +215,25 @@ static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
*/
|
*/
|
||||||
static int ref_pkt(git_pkt **out, const char *line, size_t len)
|
static int ref_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
git_pkt_ref *pkt;
|
git_pkt_ref *pkt;
|
||||||
size_t alloclen;
|
size_t alloclen;
|
||||||
|
|
||||||
pkt = git__malloc(sizeof(git_pkt_ref));
|
pkt = git__calloc(1, sizeof(git_pkt_ref));
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
memset(pkt, 0x0, sizeof(git_pkt_ref));
|
|
||||||
pkt->type = GIT_PKT_REF;
|
pkt->type = GIT_PKT_REF;
|
||||||
if ((error = git_oid_fromstr(&pkt->head.oid, line)) < 0)
|
|
||||||
goto error_out;
|
|
||||||
|
|
||||||
/* Check for a bit of consistency */
|
if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->head.oid, line) < 0)
|
||||||
if (line[GIT_OID_HEXSZ] != ' ') {
|
goto out_err;
|
||||||
giterr_set(GITERR_NET, "error parsing pkt-line");
|
line += GIT_OID_HEXSZ;
|
||||||
error = -1;
|
len -= GIT_OID_HEXSZ;
|
||||||
goto error_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Jump from the name */
|
if (git__prefixncmp(line, len, " "))
|
||||||
line += GIT_OID_HEXSZ + 1;
|
goto out_err;
|
||||||
len -= (GIT_OID_HEXSZ + 1);
|
line++;
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
if (line[len - 1] == '\n')
|
if (line[len - 1] == '\n')
|
||||||
--len;
|
--len;
|
||||||
@ -245,36 +245,36 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
memcpy(pkt->head.name, line, len);
|
memcpy(pkt->head.name, line, len);
|
||||||
pkt->head.name[len] = '\0';
|
pkt->head.name[len] = '\0';
|
||||||
|
|
||||||
if (strlen(pkt->head.name) < len) {
|
if (strlen(pkt->head.name) < len)
|
||||||
pkt->capabilities = strchr(pkt->head.name, '\0') + 1;
|
pkt->capabilities = strchr(pkt->head.name, '\0') + 1;
|
||||||
}
|
|
||||||
|
|
||||||
*out = (git_pkt *)pkt;
|
*out = (git_pkt *)pkt;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_out:
|
out_err:
|
||||||
|
giterr_set(GITERR_NET, "error parsing REF pkt-line");
|
||||||
|
if (pkt)
|
||||||
|
git__free(pkt->head.name);
|
||||||
git__free(pkt);
|
git__free(pkt);
|
||||||
return error;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ok_pkt(git_pkt **out, const char *line, size_t len)
|
static int ok_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
git_pkt_ok *pkt;
|
git_pkt_ok *pkt;
|
||||||
const char *ptr;
|
|
||||||
size_t alloc_len;
|
size_t alloc_len;
|
||||||
|
|
||||||
pkt = git__malloc(sizeof(*pkt));
|
pkt = git__malloc(sizeof(*pkt));
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_OK;
|
pkt->type = GIT_PKT_OK;
|
||||||
|
|
||||||
line += 3; /* skip "ok " */
|
if (git__prefixncmp(line, len, "ok "))
|
||||||
if (!(ptr = strchr(line, '\n'))) {
|
goto out_err;
|
||||||
giterr_set(GITERR_NET, "invalid packet line");
|
line += 3;
|
||||||
git__free(pkt);
|
len -= 3;
|
||||||
return -1;
|
|
||||||
}
|
if (line[len - 1] == '\n')
|
||||||
len = ptr - line;
|
--len;
|
||||||
|
|
||||||
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
|
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
|
||||||
pkt->ref = git__malloc(alloc_len);
|
pkt->ref = git__malloc(alloc_len);
|
||||||
@ -285,12 +285,17 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
|
|
||||||
*out = (git_pkt *)pkt;
|
*out = (git_pkt *)pkt;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
giterr_set(GITERR_NET, "error parsing OK pkt-line");
|
||||||
|
git__free(pkt);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ng_pkt(git_pkt **out, const char *line, size_t len)
|
static int ng_pkt(git_pkt **out, const char *line, size_t len)
|
||||||
{
|
{
|
||||||
git_pkt_ng *pkt;
|
git_pkt_ng *pkt;
|
||||||
const char *ptr;
|
const char *ptr, *eol;
|
||||||
size_t alloclen;
|
size_t alloclen;
|
||||||
|
|
||||||
pkt = git__malloc(sizeof(*pkt));
|
pkt = git__malloc(sizeof(*pkt));
|
||||||
@ -299,11 +304,13 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
pkt->ref = NULL;
|
pkt->ref = NULL;
|
||||||
pkt->type = GIT_PKT_NG;
|
pkt->type = GIT_PKT_NG;
|
||||||
|
|
||||||
if (len < 3)
|
eol = line + len;
|
||||||
|
|
||||||
|
if (git__prefixncmp(line, len, "ng "))
|
||||||
goto out_err;
|
goto out_err;
|
||||||
line += 3; /* skip "ng " */
|
line += 3;
|
||||||
len -= 3;
|
|
||||||
if (!(ptr = memchr(line, ' ', len)))
|
if (!(ptr = memchr(line, ' ', eol - line)))
|
||||||
goto out_err;
|
goto out_err;
|
||||||
len = ptr - line;
|
len = ptr - line;
|
||||||
|
|
||||||
@ -314,11 +321,11 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
memcpy(pkt->ref, line, len);
|
memcpy(pkt->ref, line, len);
|
||||||
pkt->ref[len] = '\0';
|
pkt->ref[len] = '\0';
|
||||||
|
|
||||||
if (len < 1)
|
|
||||||
goto out_err;
|
|
||||||
line = ptr + 1;
|
line = ptr + 1;
|
||||||
len -= 1;
|
if (line >= eol)
|
||||||
if (!(ptr = memchr(line, '\n', len)))
|
goto out_err;
|
||||||
|
|
||||||
|
if (!(ptr = memchr(line, '\n', eol - line)))
|
||||||
goto out_err;
|
goto out_err;
|
||||||
len = ptr - line;
|
len = ptr - line;
|
||||||
|
|
||||||
@ -343,13 +350,11 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
{
|
{
|
||||||
git_pkt_unpack *pkt;
|
git_pkt_unpack *pkt;
|
||||||
|
|
||||||
GIT_UNUSED(len);
|
|
||||||
|
|
||||||
pkt = git__malloc(sizeof(*pkt));
|
pkt = git__malloc(sizeof(*pkt));
|
||||||
GITERR_CHECK_ALLOC(pkt);
|
GITERR_CHECK_ALLOC(pkt);
|
||||||
|
|
||||||
pkt->type = GIT_PKT_UNPACK;
|
pkt->type = GIT_PKT_UNPACK;
|
||||||
if (!git__prefixcmp(line, "unpack ok"))
|
|
||||||
|
if (!git__prefixncmp(line, len, "unpack ok"))
|
||||||
pkt->unpack_ok = 1;
|
pkt->unpack_ok = 1;
|
||||||
else
|
else
|
||||||
pkt->unpack_ok = 0;
|
pkt->unpack_ok = 0;
|
||||||
@ -358,13 +363,17 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t parse_len(const char *line)
|
static int parse_len(size_t *out, const char *line, size_t linelen)
|
||||||
{
|
{
|
||||||
char num[PKT_LEN_SIZE + 1];
|
char num[PKT_LEN_SIZE + 1];
|
||||||
int i, k, error;
|
int i, k, error;
|
||||||
int32_t len;
|
int32_t len;
|
||||||
const char *num_end;
|
const char *num_end;
|
||||||
|
|
||||||
|
/* Not even enough for the length */
|
||||||
|
if (linelen < PKT_LEN_SIZE)
|
||||||
|
return GIT_EBUFS;
|
||||||
|
|
||||||
memcpy(num, line, PKT_LEN_SIZE);
|
memcpy(num, line, PKT_LEN_SIZE);
|
||||||
num[PKT_LEN_SIZE] = '\0';
|
num[PKT_LEN_SIZE] = '\0';
|
||||||
|
|
||||||
@ -382,10 +391,14 @@ static int32_t parse_len(const char *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = git__strtol32(&len, num, &num_end, 16)) < 0)
|
if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
return len;
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out = (size_t) len;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -402,35 +415,32 @@ static int32_t parse_len(const char *line)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int git_pkt_parse_line(
|
int git_pkt_parse_line(
|
||||||
git_pkt **head, const char *line, const char **out, size_t bufflen)
|
git_pkt **pkt, const char **endptr, const char *line, size_t linelen)
|
||||||
{
|
{
|
||||||
int ret;
|
int error;
|
||||||
int32_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Not even enough for the length */
|
if ((error = parse_len(&len, line, linelen)) < 0) {
|
||||||
if (bufflen > 0 && bufflen < PKT_LEN_SIZE)
|
|
||||||
return GIT_EBUFS;
|
|
||||||
|
|
||||||
len = parse_len(line);
|
|
||||||
if (len < 0) {
|
|
||||||
/*
|
/*
|
||||||
* If we fail to parse the length, it might be because the
|
* If we fail to parse the length, it might be
|
||||||
* server is trying to send us the packfile already.
|
* because the server is trying to send us the
|
||||||
|
* packfile already or because we do not yet have
|
||||||
|
* enough data.
|
||||||
*/
|
*/
|
||||||
if (bufflen >= 4 && !git__prefixcmp(line, "PACK")) {
|
if (error == GIT_EBUFS)
|
||||||
giterr_clear();
|
;
|
||||||
*out = line;
|
else if (!git__prefixncmp(line, linelen, "PACK"))
|
||||||
return pack_pkt(head);
|
giterr_set(GITERR_NET, "unexpected pack file");
|
||||||
}
|
else
|
||||||
|
giterr_set(GITERR_NET, "bad packet length");
|
||||||
return (int)len;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we were given a buffer length, then make sure there is
|
* Make sure there is enough in the buffer to satisfy
|
||||||
* enough in the buffer to satisfy this line
|
* this line.
|
||||||
*/
|
*/
|
||||||
if (bufflen > 0 && bufflen < (size_t)len)
|
if (linelen < len)
|
||||||
return GIT_EBUFS;
|
return GIT_EBUFS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -453,38 +463,38 @@ int git_pkt_parse_line(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0) { /* Flush pkt */
|
if (len == 0) { /* Flush pkt */
|
||||||
*out = line;
|
*endptr = line;
|
||||||
return flush_pkt(head);
|
return flush_pkt(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
|
len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
|
||||||
|
|
||||||
if (*line == GIT_SIDE_BAND_DATA)
|
if (*line == GIT_SIDE_BAND_DATA)
|
||||||
ret = data_pkt(head, line, len);
|
error = data_pkt(pkt, line, len);
|
||||||
else if (*line == GIT_SIDE_BAND_PROGRESS)
|
else if (*line == GIT_SIDE_BAND_PROGRESS)
|
||||||
ret = sideband_progress_pkt(head, line, len);
|
error = sideband_progress_pkt(pkt, line, len);
|
||||||
else if (*line == GIT_SIDE_BAND_ERROR)
|
else if (*line == GIT_SIDE_BAND_ERROR)
|
||||||
ret = sideband_error_pkt(head, line, len);
|
error = sideband_error_pkt(pkt, line, len);
|
||||||
else if (!git__prefixcmp(line, "ACK"))
|
else if (!git__prefixncmp(line, len, "ACK"))
|
||||||
ret = ack_pkt(head, line, len);
|
error = ack_pkt(pkt, line, len);
|
||||||
else if (!git__prefixcmp(line, "NAK"))
|
else if (!git__prefixncmp(line, len, "NAK"))
|
||||||
ret = nak_pkt(head);
|
error = nak_pkt(pkt);
|
||||||
else if (!git__prefixcmp(line, "ERR "))
|
else if (!git__prefixncmp(line, len, "ERR"))
|
||||||
ret = err_pkt(head, line, len);
|
error = err_pkt(pkt, line, len);
|
||||||
else if (*line == '#')
|
else if (*line == '#')
|
||||||
ret = comment_pkt(head, line, len);
|
error = comment_pkt(pkt, line, len);
|
||||||
else if (!git__prefixcmp(line, "ok"))
|
else if (!git__prefixncmp(line, len, "ok"))
|
||||||
ret = ok_pkt(head, line, len);
|
error = ok_pkt(pkt, line, len);
|
||||||
else if (!git__prefixcmp(line, "ng"))
|
else if (!git__prefixncmp(line, len, "ng"))
|
||||||
ret = ng_pkt(head, line, len);
|
error = ng_pkt(pkt, line, len);
|
||||||
else if (!git__prefixcmp(line, "unpack"))
|
else if (!git__prefixncmp(line, len, "unpack"))
|
||||||
ret = unpack_pkt(head, line, len);
|
error = unpack_pkt(pkt, line, len);
|
||||||
else
|
else
|
||||||
ret = ref_pkt(head, line, len);
|
error = ref_pkt(pkt, line, len);
|
||||||
|
|
||||||
*out = line + len;
|
*endptr = line + len;
|
||||||
|
|
||||||
return ret;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_pkt_free(git_pkt *pkt)
|
void git_pkt_free(git_pkt *pkt)
|
||||||
|
@ -44,7 +44,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if (buf->offset > 0)
|
if (buf->offset > 0)
|
||||||
error = git_pkt_parse_line(&pkt, buf->data, &line_end, buf->offset);
|
error = git_pkt_parse_line(&pkt, &line_end, buf->data, buf->offset);
|
||||||
else
|
else
|
||||||
error = GIT_EBUFS;
|
error = GIT_EBUFS;
|
||||||
|
|
||||||
@ -209,15 +209,15 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recv_pkt(git_pkt **out, gitno_buffer *buf)
|
static int recv_pkt(git_pkt **out, git_pkt_type *pkt_type, gitno_buffer *buf)
|
||||||
{
|
{
|
||||||
const char *ptr = buf->data, *line_end = ptr;
|
const char *ptr = buf->data, *line_end = ptr;
|
||||||
git_pkt *pkt = NULL;
|
git_pkt *pkt = NULL;
|
||||||
int pkt_type, error = 0, ret;
|
int error = 0, ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (buf->offset > 0)
|
if (buf->offset > 0)
|
||||||
error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset);
|
error = git_pkt_parse_line(&pkt, &line_end, ptr, buf->offset);
|
||||||
else
|
else
|
||||||
error = GIT_EBUFS;
|
error = GIT_EBUFS;
|
||||||
|
|
||||||
@ -236,13 +236,14 @@ static int recv_pkt(git_pkt **out, gitno_buffer *buf)
|
|||||||
} while (error);
|
} while (error);
|
||||||
|
|
||||||
gitno_consume(buf, line_end);
|
gitno_consume(buf, line_end);
|
||||||
pkt_type = pkt->type;
|
if (pkt_type)
|
||||||
|
*pkt_type = pkt->type;
|
||||||
if (out != NULL)
|
if (out != NULL)
|
||||||
*out = pkt;
|
*out = pkt;
|
||||||
else
|
else
|
||||||
git__free(pkt);
|
git__free(pkt);
|
||||||
|
|
||||||
return pkt_type;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int store_common(transport_smart *t)
|
static int store_common(transport_smart *t)
|
||||||
@ -252,7 +253,7 @@ static int store_common(transport_smart *t)
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((error = recv_pkt(&pkt, buf)) < 0)
|
if ((error = recv_pkt(&pkt, NULL, buf)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (pkt->type == GIT_PKT_ACK) {
|
if (pkt->type == GIT_PKT_ACK) {
|
||||||
@ -320,7 +321,7 @@ static int wait_while_ack(gitno_buffer *buf)
|
|||||||
while (1) {
|
while (1) {
|
||||||
git__free(pkt);
|
git__free(pkt);
|
||||||
|
|
||||||
if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0)
|
if ((error = recv_pkt((git_pkt **)&pkt, NULL, buf)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (pkt->type == GIT_PKT_NAK)
|
if (pkt->type == GIT_PKT_NAK)
|
||||||
@ -345,7 +346,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
|
|||||||
gitno_buffer *buf = &t->buffer;
|
gitno_buffer *buf = &t->buffer;
|
||||||
git_buf data = GIT_BUF_INIT;
|
git_buf data = GIT_BUF_INIT;
|
||||||
git_revwalk *walk = NULL;
|
git_revwalk *walk = NULL;
|
||||||
int error = -1, pkt_type;
|
int error = -1;
|
||||||
|
git_pkt_type pkt_type;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
|
|
||||||
@ -395,16 +397,13 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
|
|||||||
if ((error = store_common(t)) < 0)
|
if ((error = store_common(t)) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
} else {
|
} else {
|
||||||
pkt_type = recv_pkt(NULL, buf);
|
error = recv_pkt(NULL, &pkt_type, buf);
|
||||||
|
if (error < 0) {
|
||||||
if (pkt_type == GIT_PKT_ACK) {
|
goto on_error;
|
||||||
|
} else if (pkt_type == GIT_PKT_ACK) {
|
||||||
break;
|
break;
|
||||||
} else if (pkt_type == GIT_PKT_NAK) {
|
} else if (pkt_type == GIT_PKT_NAK) {
|
||||||
continue;
|
continue;
|
||||||
} else if (pkt_type < 0) {
|
|
||||||
/* recv_pkt returned an error */
|
|
||||||
error = pkt_type;
|
|
||||||
goto on_error;
|
|
||||||
} else {
|
} else {
|
||||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||||
error = -1;
|
error = -1;
|
||||||
@ -470,10 +469,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
|
|||||||
|
|
||||||
/* Now let's eat up whatever the server gives us */
|
/* Now let's eat up whatever the server gives us */
|
||||||
if (!t->caps.multi_ack && !t->caps.multi_ack_detailed) {
|
if (!t->caps.multi_ack && !t->caps.multi_ack_detailed) {
|
||||||
pkt_type = recv_pkt(NULL, buf);
|
error = recv_pkt(NULL, &pkt_type, buf);
|
||||||
|
|
||||||
if (pkt_type < 0) {
|
if (error < 0) {
|
||||||
return pkt_type;
|
return error;
|
||||||
} else if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) {
|
} else if (pkt_type != GIT_PKT_ACK && pkt_type != GIT_PKT_NAK) {
|
||||||
giterr_set(GITERR_NET, "Unexpected pkt type");
|
giterr_set(GITERR_NET, "Unexpected pkt type");
|
||||||
return -1;
|
return -1;
|
||||||
@ -594,7 +593,7 @@ int git_smart__download_pack(
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = recv_pkt(&pkt, buf)) >= 0) {
|
if ((error = recv_pkt(&pkt, NULL, buf)) >= 0) {
|
||||||
/* Check cancellation after network call */
|
/* Check cancellation after network call */
|
||||||
if (t->cancelled.val) {
|
if (t->cancelled.val) {
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
@ -752,7 +751,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (line_len > 0) {
|
while (line_len > 0) {
|
||||||
error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
|
error = git_pkt_parse_line(&pkt, &line_end, line, line_len);
|
||||||
|
|
||||||
if (error == GIT_EBUFS) {
|
if (error == GIT_EBUFS) {
|
||||||
/* Buffer the data when the inner packet is split
|
/* Buffer the data when the inner packet is split
|
||||||
@ -795,8 +794,8 @@ static int parse_report(transport_smart *transport, git_push *push)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (buf->offset > 0)
|
if (buf->offset > 0)
|
||||||
error = git_pkt_parse_line(&pkt, buf->data,
|
error = git_pkt_parse_line(&pkt, &line_end,
|
||||||
&line_end, buf->offset);
|
buf->data, buf->offset);
|
||||||
else
|
else
|
||||||
error = GIT_EBUFS;
|
error = GIT_EBUFS;
|
||||||
|
|
||||||
|
@ -761,7 +761,8 @@ static int winhttp_connect(
|
|||||||
t->connection = NULL;
|
t->connection = NULL;
|
||||||
|
|
||||||
/* Prepare port */
|
/* Prepare port */
|
||||||
if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
|
if (git__strntol32(&port, t->connection_data.port,
|
||||||
|
strlen(t->connection_data.port), NULL, 10) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Prepare host */
|
/* Prepare host */
|
||||||
@ -845,23 +846,27 @@ on_error:
|
|||||||
|
|
||||||
static int do_send_request(winhttp_stream *s, size_t len, int ignore_length)
|
static int do_send_request(winhttp_stream *s, size_t len, int ignore_length)
|
||||||
{
|
{
|
||||||
|
int attempts;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
for (attempts = 0; attempts < 5; attempts++) {
|
||||||
if (ignore_length) {
|
if (ignore_length) {
|
||||||
if (!WinHttpSendRequest(s->request,
|
success = WinHttpSendRequest(s->request,
|
||||||
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
||||||
WINHTTP_NO_REQUEST_DATA, 0,
|
WINHTTP_NO_REQUEST_DATA, 0,
|
||||||
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
|
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!WinHttpSendRequest(s->request,
|
success = WinHttpSendRequest(s->request,
|
||||||
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
|
||||||
WINHTTP_NO_REQUEST_DATA, 0,
|
WINHTTP_NO_REQUEST_DATA, 0,
|
||||||
len, 0)) {
|
len, 0);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (success || GetLastError() != SEC_E_BUFFER_TOO_SMALL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_request(winhttp_stream *s, size_t len, int ignore_length)
|
static int send_request(winhttp_stream *s, size_t len, int ignore_length)
|
||||||
|
@ -91,7 +91,7 @@ static int read_tree_internal(git_tree_cache **out,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Blank-terminated ASCII decimal number of entries in this tree */
|
/* Blank-terminated ASCII decimal number of entries in this tree */
|
||||||
if (git__strtol32(&count, buffer, &buffer, 10) < 0)
|
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0)
|
||||||
goto corrupted;
|
goto corrupted;
|
||||||
|
|
||||||
tree->entry_count = count;
|
tree->entry_count = count;
|
||||||
@ -100,7 +100,7 @@ static int read_tree_internal(git_tree_cache **out,
|
|||||||
goto corrupted;
|
goto corrupted;
|
||||||
|
|
||||||
/* Number of children of the tree, newline-terminated */
|
/* Number of children of the tree, newline-terminated */
|
||||||
if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0)
|
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0 || count < 0)
|
||||||
goto corrupted;
|
goto corrupted;
|
||||||
|
|
||||||
tree->children_count = count;
|
tree->children_count = count;
|
||||||
|
14
src/tree.c
14
src/tree.c
@ -490,15 +490,16 @@ static int append_entry(
|
|||||||
git_treebuilder *bld,
|
git_treebuilder *bld,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const git_oid *id,
|
const git_oid *id,
|
||||||
git_filemode_t filemode)
|
git_filemode_t filemode,
|
||||||
|
bool validate)
|
||||||
{
|
{
|
||||||
git_tree_entry *entry;
|
git_tree_entry *entry;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!valid_entry_name(bld->repo, filename))
|
if (validate && !valid_entry_name(bld->repo, filename))
|
||||||
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
|
return tree_error("failed to insert entry: invalid name for a tree entry", filename);
|
||||||
|
|
||||||
if (git_oid_iszero(id))
|
if (validate && git_oid_iszero(id))
|
||||||
return tree_error("failed to insert entry: invalid null OID for a tree entry", filename);
|
return tree_error("failed to insert entry: invalid null OID for a tree entry", filename);
|
||||||
|
|
||||||
entry = alloc_entry(filename, strlen(filename), id);
|
entry = alloc_entry(filename, strlen(filename), id);
|
||||||
@ -596,12 +597,12 @@ static int write_tree(
|
|||||||
last_comp = subdir;
|
last_comp = subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = append_entry(bld, last_comp, &sub_oid, S_IFDIR);
|
error = append_entry(bld, last_comp, &sub_oid, S_IFDIR, true);
|
||||||
git__free(subdir);
|
git__free(subdir);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
} else {
|
} else {
|
||||||
error = append_entry(bld, filename, &entry->id, entry->mode);
|
error = append_entry(bld, filename, &entry->id, entry->mode, true);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
@ -699,7 +700,8 @@ int git_treebuilder_new(
|
|||||||
if (append_entry(
|
if (append_entry(
|
||||||
bld, entry_src->filename,
|
bld, entry_src->filename,
|
||||||
entry_src->oid,
|
entry_src->oid,
|
||||||
entry_src->attr) < 0)
|
entry_src->attr,
|
||||||
|
false) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
src/util.c
85
src/util.c
@ -68,12 +68,6 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
|
|
||||||
{
|
|
||||||
|
|
||||||
return git__strntol64(result, nptr, (size_t)-1, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
@ -132,10 +126,20 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
|
|||||||
v = c - 'A' + 10;
|
v = c - 'A' + 10;
|
||||||
if (v >= base)
|
if (v >= base)
|
||||||
break;
|
break;
|
||||||
nn = n * base + (neg ? -v : v);
|
v = neg ? -v : v;
|
||||||
if ((!neg && nn < n) || (neg && nn > n))
|
if (n > INT64_MAX / base || n < INT64_MIN / base) {
|
||||||
ovfl = 1;
|
ovfl = 1;
|
||||||
n = nn;
|
/* Keep on iterating until the end of this number */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nn = n * base;
|
||||||
|
if ((v > 0 && nn > INT64_MAX - v) ||
|
||||||
|
(v < 0 && nn < INT64_MIN - v)) {
|
||||||
|
ovfl = 1;
|
||||||
|
/* Keep on iterating until the end of this number */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n = nn + v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
@ -156,28 +160,26 @@ Return:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
|
|
||||||
{
|
|
||||||
|
|
||||||
return git__strntol32(result, nptr, (size_t)-1, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
||||||
{
|
{
|
||||||
int error;
|
const char *tmp_endptr;
|
||||||
int32_t tmp_int;
|
int32_t tmp_int;
|
||||||
int64_t tmp_long;
|
int64_t tmp_long;
|
||||||
|
int error;
|
||||||
|
|
||||||
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0)
|
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
tmp_int = tmp_long & 0xFFFFFFFF;
|
tmp_int = tmp_long & 0xFFFFFFFF;
|
||||||
if (tmp_int != tmp_long) {
|
if (tmp_int != tmp_long) {
|
||||||
giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr);
|
int len = tmp_endptr - nptr;
|
||||||
|
giterr_set(GITERR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = tmp_int;
|
*result = tmp_int;
|
||||||
|
if (endptr)
|
||||||
|
*endptr = tmp_endptr;
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -355,6 +357,47 @@ size_t git__linenlen(const char *buffer, size_t buffer_len)
|
|||||||
return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
|
return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
|
||||||
|
*/
|
||||||
|
const void * git__memmem(const void *haystack, size_t haystacklen,
|
||||||
|
const void *needle, size_t needlelen)
|
||||||
|
{
|
||||||
|
const char *h, *n;
|
||||||
|
size_t j, k, l;
|
||||||
|
|
||||||
|
if (needlelen > haystacklen || !haystacklen || !needlelen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
h = (const char *) haystack,
|
||||||
|
n = (const char *) needle;
|
||||||
|
|
||||||
|
if (needlelen == 1)
|
||||||
|
return memchr(haystack, *n, haystacklen);
|
||||||
|
|
||||||
|
if (n[0] == n[1]) {
|
||||||
|
k = 2;
|
||||||
|
l = 1;
|
||||||
|
} else {
|
||||||
|
k = 1;
|
||||||
|
l = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
while (j <= haystacklen - needlelen) {
|
||||||
|
if (n[1] != h[j + 1]) {
|
||||||
|
j += k;
|
||||||
|
} else {
|
||||||
|
if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
|
||||||
|
n[0] == h[j])
|
||||||
|
return h + j;
|
||||||
|
j += l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void git__hexdump(const char *buffer, size_t len)
|
void git__hexdump(const char *buffer, size_t len)
|
||||||
{
|
{
|
||||||
static const size_t LINE_WIDTH = 16;
|
static const size_t LINE_WIDTH = 16;
|
||||||
@ -647,7 +690,7 @@ size_t git__unescape(char *str)
|
|||||||
return (pos - str);
|
return (pos - str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_QSORT_S) || (defined(HAVE_QSORT_R) && defined(BSD))
|
#if defined(HAVE_QSORT_S) || defined(HAVE_QSORT_R_BSD)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git__sort_r_cmp cmp;
|
git__sort_r_cmp cmp;
|
||||||
void *payload;
|
void *payload;
|
||||||
@ -664,10 +707,10 @@ static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
|
|||||||
void git__qsort_r(
|
void git__qsort_r(
|
||||||
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
|
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_QSORT_R) && defined(BSD)
|
#if defined(HAVE_QSORT_R_BSD)
|
||||||
git__qsort_r_glue glue = { cmp, payload };
|
git__qsort_r_glue glue = { cmp, payload };
|
||||||
qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
|
qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
|
||||||
#elif defined(HAVE_QSORT_R) && defined(__GLIBC__)
|
#elif defined(HAVE_QSORT_R_GNU)
|
||||||
qsort_r(els, nel, elsize, cmp, payload);
|
qsort_r(els, nel, elsize, cmp, payload);
|
||||||
#elif defined(HAVE_QSORT_S)
|
#elif defined(HAVE_QSORT_S)
|
||||||
git__qsort_r_glue glue = { cmp, payload };
|
git__qsort_r_glue glue = { cmp, payload };
|
||||||
|
@ -193,9 +193,7 @@ GIT_INLINE(int) git__signum(int val)
|
|||||||
return ((val > 0) - (val < 0));
|
return ((val > 0) - (val < 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
|
|
||||||
extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
||||||
extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base);
|
|
||||||
extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
||||||
|
|
||||||
|
|
||||||
@ -248,6 +246,9 @@ GIT_INLINE(const void *) git__memrchr(const void *s, int c, size_t n)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const void * git__memmem(const void *haystack, size_t haystacklen,
|
||||||
|
const void *needle, size_t needlelen);
|
||||||
|
|
||||||
typedef int (*git__tsort_cmp)(const void *a, const void *b);
|
typedef int (*git__tsort_cmp)(const void *a, const void *b);
|
||||||
|
|
||||||
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
|
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
|
||||||
|
17
src/vector.c
17
src/vector.c
@ -32,6 +32,9 @@ GIT_INLINE(int) resize_vector(git_vector *v, size_t new_size)
|
|||||||
{
|
{
|
||||||
void *new_contents;
|
void *new_contents;
|
||||||
|
|
||||||
|
if (new_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
new_contents = git__reallocarray(v->contents, new_size, sizeof(void *));
|
new_contents = git__reallocarray(v->contents, new_size, sizeof(void *));
|
||||||
GITERR_CHECK_ALLOC(new_contents);
|
GITERR_CHECK_ALLOC(new_contents);
|
||||||
|
|
||||||
@ -50,22 +53,24 @@ int git_vector_size_hint(git_vector *v, size_t size_hint)
|
|||||||
|
|
||||||
int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
|
int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
|
||||||
{
|
{
|
||||||
size_t bytes;
|
|
||||||
|
|
||||||
assert(v && src);
|
assert(v && src);
|
||||||
|
|
||||||
GITERR_CHECK_ALLOC_MULTIPLY(&bytes, src->length, sizeof(void *));
|
v->_alloc_size = 0;
|
||||||
|
v->contents = NULL;
|
||||||
v->_alloc_size = src->length;
|
|
||||||
v->_cmp = cmp ? cmp : src->_cmp;
|
v->_cmp = cmp ? cmp : src->_cmp;
|
||||||
v->length = src->length;
|
v->length = src->length;
|
||||||
v->flags = src->flags;
|
v->flags = src->flags;
|
||||||
if (cmp != src->_cmp)
|
if (cmp != src->_cmp)
|
||||||
git_vector_set_sorted(v, 0);
|
git_vector_set_sorted(v, 0);
|
||||||
|
|
||||||
|
if (src->length) {
|
||||||
|
size_t bytes;
|
||||||
|
GITERR_CHECK_ALLOC_MULTIPLY(&bytes, src->length, sizeof(void *));
|
||||||
v->contents = git__malloc(bytes);
|
v->contents = git__malloc(bytes);
|
||||||
GITERR_CHECK_ALLOC(v->contents);
|
GITERR_CHECK_ALLOC(v->contents);
|
||||||
|
v->_alloc_size = src->length;
|
||||||
memcpy(v->contents, src->contents, bytes);
|
memcpy(v->contents, src->contents, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
|
|||||||
if ((wt->name = git__strdup(name)) == NULL
|
if ((wt->name = git__strdup(name)) == NULL
|
||||||
|| (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL
|
|| (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL
|
||||||
|| (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL
|
|| (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL
|
||||||
|| (wt->parent_path = git__strdup(parent)) == NULL) {
|
|| (parent && (wt->parent_path = git__strdup(parent)) == NULL)) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -417,7 +417,7 @@ int git_worktree_unlock(git_worktree *wt)
|
|||||||
assert(wt);
|
assert(wt);
|
||||||
|
|
||||||
if (!git_worktree_is_locked(NULL, wt))
|
if (!git_worktree_is_locked(NULL, wt))
|
||||||
return 0;
|
return 1;
|
||||||
|
|
||||||
if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
|
if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -52,12 +52,8 @@ IF (MSVC_IDE)
|
|||||||
SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
|
SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
IF (USE_HTTPS)
|
ADD_TEST(offline "${libgit2_BINARY_DIR}/libgit2_clar" -v -xonline)
|
||||||
ADD_TEST(libgit2_clar "${libgit2_BINARY_DIR}/libgit2_clar" -ionline -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
|
ADD_TEST(online "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline)
|
||||||
ELSE ()
|
ADD_TEST(gitdaemon "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push)
|
||||||
ADD_TEST(libgit2_clar "${libgit2_BINARY_DIR}/libgit2_clar" -v -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
|
ADD_TEST(ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths)
|
||||||
ENDIF ()
|
ADD_TEST(proxy "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request)
|
||||||
|
|
||||||
# Add additional test targets that require special setup
|
|
||||||
ADD_TEST(libgit2_clar-proxy_credentials "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request)
|
|
||||||
ADD_TEST(libgit2_clar-ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths)
|
|
||||||
|
@ -1,10 +1,22 @@
|
|||||||
#include "clar_libgit2.h"
|
#include "clar_libgit2.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
#if defined(GIT_ARCH_64)
|
/*
|
||||||
#define TOOBIG 0xffffffffffffff00
|
* We want to use some ridiculous size that `malloc` will fail with
|
||||||
|
* but that does not otherwise interfere with testing. On Linux, choose
|
||||||
|
* a number that is large enough to fail immediately but small enough
|
||||||
|
* that valgrind doesn't believe it to erroneously be a negative number.
|
||||||
|
* On macOS, choose a number that is large enough to fail immediately
|
||||||
|
* without having libc print warnings to stderr.
|
||||||
|
*/
|
||||||
|
#if defined(GIT_ARCH_64) && defined(__linux__)
|
||||||
|
# define TOOBIG 0x0fffffffffffffff
|
||||||
|
#elif defined(__linux__)
|
||||||
|
# define TOOBIG 0x0fffffff
|
||||||
|
#elif defined(GIT_ARCH_64)
|
||||||
|
# define TOOBIG 0xffffffffffffff00
|
||||||
#else
|
#else
|
||||||
#define TOOBIG 0xffffff00
|
# define TOOBIG 0xffffff00
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
205
tests/clar.c
205
tests/clar.c
@ -95,9 +95,6 @@ static const char *
|
|||||||
fixture_path(const char *base, const char *fixture_name);
|
fixture_path(const char *base, const char *fixture_name);
|
||||||
|
|
||||||
struct clar_error {
|
struct clar_error {
|
||||||
const char *test;
|
|
||||||
int test_number;
|
|
||||||
const char *suite;
|
|
||||||
const char *file;
|
const char *file;
|
||||||
int line_number;
|
int line_number;
|
||||||
const char *error_msg;
|
const char *error_msg;
|
||||||
@ -106,11 +103,34 @@ struct clar_error {
|
|||||||
struct clar_error *next;
|
struct clar_error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
struct clar_explicit {
|
||||||
int argc;
|
size_t suite_idx;
|
||||||
char **argv;
|
const char *filter;
|
||||||
|
|
||||||
|
struct clar_explicit *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clar_report {
|
||||||
|
const char *test;
|
||||||
|
int test_number;
|
||||||
|
const char *suite;
|
||||||
|
|
||||||
|
enum cl_test_status status;
|
||||||
|
|
||||||
|
struct clar_error *errors;
|
||||||
|
struct clar_error *last_error;
|
||||||
|
|
||||||
|
struct clar_report *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clar_summary {
|
||||||
|
const char *filename;
|
||||||
|
FILE *fp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
enum cl_test_status test_status;
|
enum cl_test_status test_status;
|
||||||
|
|
||||||
const char *active_test;
|
const char *active_test;
|
||||||
const char *active_suite;
|
const char *active_suite;
|
||||||
|
|
||||||
@ -124,8 +144,15 @@ static struct {
|
|||||||
int exit_on_error;
|
int exit_on_error;
|
||||||
int report_suite_names;
|
int report_suite_names;
|
||||||
|
|
||||||
struct clar_error *errors;
|
int write_summary;
|
||||||
struct clar_error *last_error;
|
const char *summary_filename;
|
||||||
|
struct clar_summary *summary;
|
||||||
|
|
||||||
|
struct clar_explicit *explicit;
|
||||||
|
struct clar_explicit *last_explicit;
|
||||||
|
|
||||||
|
struct clar_report *reports;
|
||||||
|
struct clar_report *last_report;
|
||||||
|
|
||||||
void (*local_cleanup)(void *);
|
void (*local_cleanup)(void *);
|
||||||
void *local_cleanup_payload;
|
void *local_cleanup_payload;
|
||||||
@ -155,7 +182,7 @@ struct clar_suite {
|
|||||||
/* From clar_print_*.c */
|
/* From clar_print_*.c */
|
||||||
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
|
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
|
||||||
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
|
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
|
||||||
static void clar_print_error(int num, const struct clar_error *error);
|
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
|
||||||
static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
|
static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
|
||||||
static void clar_print_onsuite(const char *suite_name, int suite_index);
|
static void clar_print_onsuite(const char *suite_name, int suite_index);
|
||||||
static void clar_print_onabort(const char *msg, ...);
|
static void clar_print_onabort(const char *msg, ...);
|
||||||
@ -164,6 +191,10 @@ static void clar_print_onabort(const char *msg, ...);
|
|||||||
static void clar_unsandbox(void);
|
static void clar_unsandbox(void);
|
||||||
static int clar_sandbox(void);
|
static int clar_sandbox(void);
|
||||||
|
|
||||||
|
/* From summary.h */
|
||||||
|
static struct clar_summary *clar_summary_init(const char *filename);
|
||||||
|
static int clar_summary_shutdown(struct clar_summary *fp);
|
||||||
|
|
||||||
/* Load the declarations for the test suite */
|
/* Load the declarations for the test suite */
|
||||||
#include "clar.suite"
|
#include "clar.suite"
|
||||||
|
|
||||||
@ -186,21 +217,29 @@ void cl_trace_register(cl_trace_cb *cb, void *payload)
|
|||||||
|
|
||||||
/* Core test functions */
|
/* Core test functions */
|
||||||
static void
|
static void
|
||||||
clar_report_errors(void)
|
clar_report_errors(struct clar_report *report)
|
||||||
{
|
{
|
||||||
|
struct clar_error *error;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
struct clar_error *error, *next;
|
|
||||||
|
|
||||||
error = _clar.errors;
|
for (error = report->errors; error; error = error->next)
|
||||||
while (error != NULL) {
|
clar_print_error(i++, _clar.last_report, error);
|
||||||
next = error->next;
|
}
|
||||||
clar_print_error(i++, error);
|
|
||||||
free(error->description);
|
static void
|
||||||
free(error);
|
clar_report_all(void)
|
||||||
error = next;
|
{
|
||||||
|
struct clar_report *report;
|
||||||
|
struct clar_error *error;
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
for (report = _clar.reports; report; report = report->next) {
|
||||||
|
if (report->status != CL_TEST_FAILURE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (error = report->errors; error; error = error->next)
|
||||||
|
clar_print_error(i++, report, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
_clar.errors = _clar.last_error = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -209,7 +248,6 @@ clar_run_test(
|
|||||||
const struct clar_func *initialize,
|
const struct clar_func *initialize,
|
||||||
const struct clar_func *cleanup)
|
const struct clar_func *cleanup)
|
||||||
{
|
{
|
||||||
_clar.test_status = CL_TEST_OK;
|
|
||||||
_clar.trampoline_enabled = 1;
|
_clar.trampoline_enabled = 1;
|
||||||
|
|
||||||
CL_TRACE(CL_TRACE__TEST__BEGIN);
|
CL_TRACE(CL_TRACE__TEST__BEGIN);
|
||||||
@ -225,6 +263,9 @@ clar_run_test(
|
|||||||
|
|
||||||
_clar.trampoline_enabled = 0;
|
_clar.trampoline_enabled = 0;
|
||||||
|
|
||||||
|
if (_clar.last_report->status == CL_TEST_NOTRUN)
|
||||||
|
_clar.last_report->status = CL_TEST_OK;
|
||||||
|
|
||||||
if (_clar.local_cleanup != NULL)
|
if (_clar.local_cleanup != NULL)
|
||||||
_clar.local_cleanup(_clar.local_cleanup_payload);
|
_clar.local_cleanup(_clar.local_cleanup_payload);
|
||||||
|
|
||||||
@ -240,9 +281,9 @@ clar_run_test(
|
|||||||
_clar.local_cleanup_payload = NULL;
|
_clar.local_cleanup_payload = NULL;
|
||||||
|
|
||||||
if (_clar.report_errors_only) {
|
if (_clar.report_errors_only) {
|
||||||
clar_report_errors();
|
clar_report_errors(_clar.last_report);
|
||||||
} else {
|
} else {
|
||||||
clar_print_ontest(test->name, _clar.tests_ran, _clar.test_status);
|
clar_print_ontest(test->name, _clar.tests_ran, _clar.last_report->status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +292,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
|
|||||||
{
|
{
|
||||||
const struct clar_func *test = suite->tests;
|
const struct clar_func *test = suite->tests;
|
||||||
size_t i, matchlen;
|
size_t i, matchlen;
|
||||||
|
struct clar_report *report;
|
||||||
|
|
||||||
if (!suite->enabled)
|
if (!suite->enabled)
|
||||||
return;
|
return;
|
||||||
@ -283,6 +325,21 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
_clar.active_test = test[i].name;
|
_clar.active_test = test[i].name;
|
||||||
|
|
||||||
|
report = calloc(1, sizeof(struct clar_report));
|
||||||
|
report->suite = _clar.active_suite;
|
||||||
|
report->test = _clar.active_test;
|
||||||
|
report->test_number = _clar.tests_ran;
|
||||||
|
report->status = CL_TEST_NOTRUN;
|
||||||
|
|
||||||
|
if (_clar.reports == NULL)
|
||||||
|
_clar.reports = report;
|
||||||
|
|
||||||
|
if (_clar.last_report != NULL)
|
||||||
|
_clar.last_report->next = report;
|
||||||
|
|
||||||
|
_clar.last_report = report;
|
||||||
|
|
||||||
clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
|
clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
|
||||||
|
|
||||||
if (_clar.exit_on_error && _clar.total_errors)
|
if (_clar.exit_on_error && _clar.total_errors)
|
||||||
@ -298,13 +355,14 @@ clar_usage(const char *arg)
|
|||||||
{
|
{
|
||||||
printf("Usage: %s [options]\n\n", arg);
|
printf("Usage: %s [options]\n\n", arg);
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n");
|
printf(" -sname Run only the suite with `name` (can go to individual test name)\n");
|
||||||
printf(" -iname\tInclude the suite with `name`\n");
|
printf(" -iname Include the suite with `name`\n");
|
||||||
printf(" -xname\tExclude the suite with `name`\n");
|
printf(" -xname Exclude the suite with `name`\n");
|
||||||
printf(" -v \tIncrease verbosity (show suite names)\n");
|
printf(" -v Increase verbosity (show suite names)\n");
|
||||||
printf(" -q \tOnly report tests that had an error\n");
|
printf(" -q Only report tests that had an error\n");
|
||||||
printf(" -Q \tQuit as soon as a test fails\n");
|
printf(" -Q Quit as soon as a test fails\n");
|
||||||
printf(" -l \tPrint suite names\n");
|
printf(" -l Print suite names\n");
|
||||||
|
printf(" -r[filename] Write summary file (to the optional filename)\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +376,7 @@ clar_parse_args(int argc, char **argv)
|
|||||||
char *argument = argv[i];
|
char *argument = argv[i];
|
||||||
|
|
||||||
if (argument[0] != '-' || argument[1] == '\0'
|
if (argument[0] != '-' || argument[1] == '\0'
|
||||||
|| strchr("sixvqQl", argument[1]) == NULL) {
|
|| strchr("sixvqQlr", argument[1]) == NULL) {
|
||||||
clar_usage(argv[0]);
|
clar_usage(argv[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +417,24 @@ clar_parse_args(int argc, char **argv)
|
|||||||
_clar.report_suite_names = 1;
|
_clar.report_suite_names = 1;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 's': _clar_suites[j].enabled = 1; clar_run_suite(&_clar_suites[j], argument); break;
|
case 's': {
|
||||||
|
struct clar_explicit *explicit =
|
||||||
|
calloc(1, sizeof(struct clar_explicit));
|
||||||
|
assert(explicit);
|
||||||
|
|
||||||
|
explicit->suite_idx = j;
|
||||||
|
explicit->filter = argument;
|
||||||
|
|
||||||
|
if (_clar.explicit == NULL)
|
||||||
|
_clar.explicit = explicit;
|
||||||
|
|
||||||
|
if (_clar.last_explicit != NULL)
|
||||||
|
_clar.last_explicit->next = explicit;
|
||||||
|
|
||||||
|
_clar_suites[j].enabled = 1;
|
||||||
|
_clar.last_explicit = explicit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'i': _clar_suites[j].enabled = 1; break;
|
case 'i': _clar_suites[j].enabled = 1; break;
|
||||||
case 'x': _clar_suites[j].enabled = 0; break;
|
case 'x': _clar_suites[j].enabled = 0; break;
|
||||||
}
|
}
|
||||||
@ -397,6 +472,12 @@ clar_parse_args(int argc, char **argv)
|
|||||||
_clar.report_suite_names = 1;
|
_clar.report_suite_names = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
_clar.write_summary = 1;
|
||||||
|
_clar.summary_filename = *(argument + 2) ? (argument + 2) :
|
||||||
|
"summary.xml";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(!"Unexpected commandline argument!");
|
assert(!"Unexpected commandline argument!");
|
||||||
}
|
}
|
||||||
@ -412,23 +493,31 @@ clar_test_init(int argc, char **argv)
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
clar_parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (_clar.write_summary &&
|
||||||
|
!(_clar.summary = clar_summary_init(_clar.summary_filename))) {
|
||||||
|
clar_print_onabort("Failed to open the summary file\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (clar_sandbox() < 0) {
|
if (clar_sandbox() < 0) {
|
||||||
clar_print_onabort("Failed to sandbox the test runner.\n");
|
clar_print_onabort("Failed to sandbox the test runner.\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_clar.argc = argc;
|
|
||||||
_clar.argv = argv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
clar_test_run(void)
|
clar_test_run(void)
|
||||||
{
|
{
|
||||||
if (_clar.argc > 1)
|
|
||||||
clar_parse_args(_clar.argc, _clar.argv);
|
|
||||||
|
|
||||||
if (!_clar.suites_ran) {
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
struct clar_explicit *explicit;
|
||||||
|
|
||||||
|
if (_clar.explicit) {
|
||||||
|
for (explicit = _clar.explicit; explicit; explicit = explicit->next)
|
||||||
|
clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter);
|
||||||
|
} else {
|
||||||
for (i = 0; i < _clar_suite_count; ++i)
|
for (i = 0; i < _clar_suite_count; ++i)
|
||||||
clar_run_suite(&_clar_suites[i], NULL);
|
clar_run_suite(&_clar_suites[i], NULL);
|
||||||
}
|
}
|
||||||
@ -439,6 +528,9 @@ clar_test_run(void)
|
|||||||
void
|
void
|
||||||
clar_test_shutdown(void)
|
clar_test_shutdown(void)
|
||||||
{
|
{
|
||||||
|
struct clar_explicit *explicit, *explicit_next;
|
||||||
|
struct clar_report *report, *report_next;
|
||||||
|
|
||||||
clar_print_shutdown(
|
clar_print_shutdown(
|
||||||
_clar.tests_ran,
|
_clar.tests_ran,
|
||||||
(int)_clar_suite_count,
|
(int)_clar_suite_count,
|
||||||
@ -446,6 +538,21 @@ clar_test_shutdown(void)
|
|||||||
);
|
);
|
||||||
|
|
||||||
clar_unsandbox();
|
clar_unsandbox();
|
||||||
|
|
||||||
|
if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) {
|
||||||
|
clar_print_onabort("Failed to write the summary file\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (explicit = _clar.explicit; explicit; explicit = explicit_next) {
|
||||||
|
explicit_next = explicit->next;
|
||||||
|
free(explicit);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (report = _clar.reports; report; report = report_next) {
|
||||||
|
report_next = report->next;
|
||||||
|
free(report);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -465,7 +572,7 @@ static void abort_test(void)
|
|||||||
if (!_clar.trampoline_enabled) {
|
if (!_clar.trampoline_enabled) {
|
||||||
clar_print_onabort(
|
clar_print_onabort(
|
||||||
"Fatal error: a cleanup method raised an exception.");
|
"Fatal error: a cleanup method raised an exception.");
|
||||||
clar_report_errors();
|
clar_report_errors(_clar.last_report);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +582,7 @@ static void abort_test(void)
|
|||||||
|
|
||||||
void clar__skip(void)
|
void clar__skip(void)
|
||||||
{
|
{
|
||||||
_clar.test_status = CL_TEST_SKIP;
|
_clar.last_report->status = CL_TEST_SKIP;
|
||||||
_clar.total_skipped++;
|
_clar.total_skipped++;
|
||||||
abort_test();
|
abort_test();
|
||||||
}
|
}
|
||||||
@ -489,17 +596,14 @@ void clar__fail(
|
|||||||
{
|
{
|
||||||
struct clar_error *error = calloc(1, sizeof(struct clar_error));
|
struct clar_error *error = calloc(1, sizeof(struct clar_error));
|
||||||
|
|
||||||
if (_clar.errors == NULL)
|
if (_clar.last_report->errors == NULL)
|
||||||
_clar.errors = error;
|
_clar.last_report->errors = error;
|
||||||
|
|
||||||
if (_clar.last_error != NULL)
|
if (_clar.last_report->last_error != NULL)
|
||||||
_clar.last_error->next = error;
|
_clar.last_report->last_error->next = error;
|
||||||
|
|
||||||
_clar.last_error = error;
|
_clar.last_report->last_error = error;
|
||||||
|
|
||||||
error->test = _clar.active_test;
|
|
||||||
error->test_number = _clar.tests_ran;
|
|
||||||
error->suite = _clar.active_suite;
|
|
||||||
error->file = file;
|
error->file = file;
|
||||||
error->line_number = line;
|
error->line_number = line;
|
||||||
error->error_msg = error_msg;
|
error->error_msg = error_msg;
|
||||||
@ -508,7 +612,7 @@ void clar__fail(
|
|||||||
error->description = strdup(description);
|
error->description = strdup(description);
|
||||||
|
|
||||||
_clar.total_errors++;
|
_clar.total_errors++;
|
||||||
_clar.test_status = CL_TEST_FAILURE;
|
_clar.last_report->status = CL_TEST_FAILURE;
|
||||||
|
|
||||||
if (should_abort)
|
if (should_abort)
|
||||||
abort_test();
|
abort_test();
|
||||||
@ -653,3 +757,4 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
|
|||||||
#include "clar/fixtures.h"
|
#include "clar/fixtures.h"
|
||||||
#include "clar/fs.h"
|
#include "clar/fs.h"
|
||||||
#include "clar/print.h"
|
#include "clar/print.h"
|
||||||
|
#include "clar/summary.h"
|
||||||
|
@ -12,13 +12,16 @@
|
|||||||
enum cl_test_status {
|
enum cl_test_status {
|
||||||
CL_TEST_OK,
|
CL_TEST_OK,
|
||||||
CL_TEST_FAILURE,
|
CL_TEST_FAILURE,
|
||||||
CL_TEST_SKIP
|
CL_TEST_SKIP,
|
||||||
|
CL_TEST_NOTRUN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Setup clar environment */
|
||||||
void clar_test_init(int argc, char *argv[]);
|
void clar_test_init(int argc, char *argv[]);
|
||||||
int clar_test_run(void);
|
int clar_test_run(void);
|
||||||
void clar_test_shutdown(void);
|
void clar_test_shutdown(void);
|
||||||
|
|
||||||
|
/** One shot setup & run */
|
||||||
int clar_test(int argc, char *argv[]);
|
int clar_test(int argc, char *argv[]);
|
||||||
|
|
||||||
const char *clar_sandbox_path(void);
|
const char *clar_sandbox_path(void);
|
||||||
|
@ -13,16 +13,16 @@ static void clar_print_shutdown(int test_count, int suite_count, int error_count
|
|||||||
(void)error_count;
|
(void)error_count;
|
||||||
|
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
clar_report_errors();
|
clar_report_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clar_print_error(int num, const struct clar_error *error)
|
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error)
|
||||||
{
|
{
|
||||||
printf(" %d) Failure:\n", num);
|
printf(" %d) Failure:\n", num);
|
||||||
|
|
||||||
printf("%s::%s [%s:%d]\n",
|
printf("%s::%s [%s:%d]\n",
|
||||||
error->suite,
|
report->suite,
|
||||||
error->test,
|
report->test,
|
||||||
error->file,
|
error->file,
|
||||||
error->line_number);
|
error->line_number);
|
||||||
|
|
||||||
@ -44,6 +44,7 @@ static void clar_print_ontest(const char *test_name, int test_number, enum cl_te
|
|||||||
case CL_TEST_OK: printf("."); break;
|
case CL_TEST_OK: printf("."); break;
|
||||||
case CL_TEST_FAILURE: printf("F"); break;
|
case CL_TEST_FAILURE: printf("F"); break;
|
||||||
case CL_TEST_SKIP: printf("S"); break;
|
case CL_TEST_SKIP: printf("S"); break;
|
||||||
|
case CL_TEST_NOTRUN: printf("N"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
134
tests/clar/summary.h
Normal file
134
tests/clar/summary.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int clar_summary_close_tag(
|
||||||
|
struct clar_summary *summary, const char *tag, int indent)
|
||||||
|
{
|
||||||
|
const char *indt;
|
||||||
|
|
||||||
|
if (indent == 0) indt = "";
|
||||||
|
else if (indent == 1) indt = "\t";
|
||||||
|
else indt = "\t\t";
|
||||||
|
|
||||||
|
return fprintf(summary->fp, "%s</%s>\n", indt, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clar_summary_testsuites(struct clar_summary *summary)
|
||||||
|
{
|
||||||
|
return fprintf(summary->fp, "<testsuites>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int clar_summary_testsuite(struct clar_summary *summary,
|
||||||
|
int idn, const char *name, const char *pkg, time_t timestamp,
|
||||||
|
double elapsed, int test_count, int fail_count, int error_count)
|
||||||
|
{
|
||||||
|
struct tm *tm = localtime(×tamp);
|
||||||
|
char iso_dt[20];
|
||||||
|
|
||||||
|
if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return fprintf(summary->fp, "\t<testsuite "
|
||||||
|
" id=\"%d\""
|
||||||
|
" name=\"%s\""
|
||||||
|
" package=\"%s\""
|
||||||
|
" hostname=\"localhost\""
|
||||||
|
" timestamp=\"%s\""
|
||||||
|
" time=\"%.2f\""
|
||||||
|
" tests=\"%d\""
|
||||||
|
" failures=\"%d\""
|
||||||
|
" errors=\"%d\">\n",
|
||||||
|
idn, name, pkg, iso_dt, elapsed, test_count, fail_count, error_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clar_summary_testcase(struct clar_summary *summary,
|
||||||
|
const char *name, const char *classname, double elapsed)
|
||||||
|
{
|
||||||
|
return fprintf(summary->fp,
|
||||||
|
"\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n",
|
||||||
|
name, classname, elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clar_summary_failure(struct clar_summary *summary,
|
||||||
|
const char *type, const char *message, const char *desc)
|
||||||
|
{
|
||||||
|
return fprintf(summary->fp,
|
||||||
|
"\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n",
|
||||||
|
type, message, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clar_summary *clar_summary_init(const char *filename)
|
||||||
|
{
|
||||||
|
struct clar_summary *summary;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if ((fp = fopen(filename, "w")) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((summary = malloc(sizeof(struct clar_summary))) == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary->filename = filename;
|
||||||
|
summary->fp = fp;
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clar_summary_shutdown(struct clar_summary *summary)
|
||||||
|
{
|
||||||
|
struct clar_report *report;
|
||||||
|
const char *last_suite = NULL;
|
||||||
|
|
||||||
|
if (clar_summary_testsuites(summary) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
report = _clar.reports;
|
||||||
|
while (report != NULL) {
|
||||||
|
struct clar_error *error = report->errors;
|
||||||
|
|
||||||
|
if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) {
|
||||||
|
if (clar_summary_testsuite(summary, 0, report->suite, "",
|
||||||
|
time(NULL), 0, _clar.tests_ran, _clar.total_errors, 0) < 0)
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_suite = report->suite;
|
||||||
|
|
||||||
|
clar_summary_testcase(summary, report->test, "what", 0);
|
||||||
|
|
||||||
|
while (error != NULL) {
|
||||||
|
if (clar_summary_failure(summary, "assert",
|
||||||
|
error->error_msg, error->description) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
error = error->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clar_summary_close_tag(summary, "testcase", 2) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
report = report->next;
|
||||||
|
|
||||||
|
if (!report || strcmp(last_suite, report->suite) != 0) {
|
||||||
|
if (clar_summary_close_tag(summary, "testsuite", 1) < 0)
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clar_summary_close_tag(summary, "testsuites", 0) < 0 ||
|
||||||
|
fclose(summary->fp) != 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
printf("written summary file to %s\n", summary->filename);
|
||||||
|
|
||||||
|
free(summary);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
fclose(summary->fp);
|
||||||
|
free(summary);
|
||||||
|
return -1;
|
||||||
|
}
|
@ -35,6 +35,8 @@ void test_config_include__absolute(void)
|
|||||||
|
|
||||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
|
||||||
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("config-include-absolute"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__homedir(void)
|
void test_config_include__homedir(void)
|
||||||
@ -48,6 +50,8 @@ void test_config_include__homedir(void)
|
|||||||
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
||||||
|
|
||||||
cl_sandbox_set_search_path_defaults();
|
cl_sandbox_set_search_path_defaults();
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("config-include-homedir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to pretend that the variables were defined where the file was included */
|
/* We need to pretend that the variables were defined where the file was included */
|
||||||
@ -66,6 +70,9 @@ void test_config_include__ordering(void)
|
|||||||
git_buf_clear(&buf);
|
git_buf_clear(&buf);
|
||||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
|
||||||
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("included"));
|
||||||
|
cl_git_pass(p_unlink("including"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to pretend that the variables were defined where the file was included */
|
/* We need to pretend that the variables were defined where the file was included */
|
||||||
@ -76,8 +83,18 @@ void test_config_include__depth(void)
|
|||||||
|
|
||||||
cl_git_fail(git_config_open_ondisk(&cfg, "a"));
|
cl_git_fail(git_config_open_ondisk(&cfg, "a"));
|
||||||
|
|
||||||
p_unlink("a");
|
cl_git_pass(p_unlink("a"));
|
||||||
p_unlink("b");
|
cl_git_pass(p_unlink("b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_config_include__empty_path_sanely_handled(void)
|
||||||
|
{
|
||||||
|
cl_git_mkfile("a", "[include]\npath");
|
||||||
|
cl_git_pass(git_config_open_ondisk(&cfg, "a"));
|
||||||
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "include.path"));
|
||||||
|
cl_assert_equal_s("", git_buf_cstr(&buf));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__missing(void)
|
void test_config_include__missing(void)
|
||||||
@ -89,6 +106,8 @@ void test_config_include__missing(void)
|
|||||||
cl_assert(giterr_last() == NULL);
|
cl_assert(giterr_last() == NULL);
|
||||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
||||||
cl_assert_equal_s("baz", git_buf_cstr(&buf));
|
cl_assert_equal_s("baz", git_buf_cstr(&buf));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("including"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__missing_homedir(void)
|
void test_config_include__missing_homedir(void)
|
||||||
@ -103,6 +122,7 @@ void test_config_include__missing_homedir(void)
|
|||||||
cl_assert_equal_s("baz", git_buf_cstr(&buf));
|
cl_assert_equal_s("baz", git_buf_cstr(&buf));
|
||||||
|
|
||||||
cl_sandbox_set_search_path_defaults();
|
cl_sandbox_set_search_path_defaults();
|
||||||
|
cl_git_pass(p_unlink("including"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define replicate10(s) s s s s s s s s s s
|
#define replicate10(s) s s s s s s s s s s
|
||||||
@ -122,6 +142,10 @@ void test_config_include__depth2(void)
|
|||||||
git_buf_clear(&buf);
|
git_buf_clear(&buf);
|
||||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar2"));
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar2"));
|
||||||
cl_assert_equal_s("baz2", git_buf_cstr(&buf));
|
cl_assert_equal_s("baz2", git_buf_cstr(&buf));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("top-level"));
|
||||||
|
cl_git_pass(p_unlink("middle"));
|
||||||
|
cl_git_pass(p_unlink("bottom"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__removing_include_removes_values(void)
|
void test_config_include__removing_include_removes_values(void)
|
||||||
@ -132,6 +156,9 @@ void test_config_include__removing_include_removes_values(void)
|
|||||||
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
||||||
cl_git_mkfile("top-level", "");
|
cl_git_mkfile("top-level", "");
|
||||||
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("top-level"));
|
||||||
|
cl_git_pass(p_unlink("included"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__rewriting_include_refreshes_values(void)
|
void test_config_include__rewriting_include_refreshes_values(void)
|
||||||
@ -145,6 +172,10 @@ void test_config_include__rewriting_include_refreshes_values(void)
|
|||||||
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
|
||||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "first.other"));
|
cl_git_pass(git_config_get_string_buf(&buf, cfg, "first.other"));
|
||||||
cl_assert_equal_s(buf.ptr, "value");
|
cl_assert_equal_s(buf.ptr, "value");
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("top-level"));
|
||||||
|
cl_git_pass(p_unlink("first"));
|
||||||
|
cl_git_pass(p_unlink("second"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__included_variables_cannot_be_deleted(void)
|
void test_config_include__included_variables_cannot_be_deleted(void)
|
||||||
@ -154,13 +185,20 @@ void test_config_include__included_variables_cannot_be_deleted(void)
|
|||||||
|
|
||||||
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
||||||
cl_git_fail(git_config_delete_entry(cfg, "foo.bar"));
|
cl_git_fail(git_config_delete_entry(cfg, "foo.bar"));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("top-level"));
|
||||||
|
cl_git_pass(p_unlink("included"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_config_include__included_variables_cannot_be_modified(void)
|
void test_config_include__included_variables_cannot_be_modified(void)
|
||||||
{
|
{
|
||||||
cl_git_mkfile("top-level", "[include]\npath = included\n");
|
cl_git_mkfile("top-level", "[include]\npath = included\n");
|
||||||
|
|
||||||
cl_git_mkfile("included", "[foo]\nbar = value");
|
cl_git_mkfile("included", "[foo]\nbar = value");
|
||||||
|
|
||||||
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
|
||||||
cl_git_fail(git_config_set_string(cfg, "foo.bar", "other-value"));
|
cl_git_fail(git_config_set_string(cfg, "foo.bar", "other-value"));
|
||||||
|
|
||||||
|
cl_git_pass(p_unlink("top-level"));
|
||||||
|
cl_git_pass(p_unlink("included"));
|
||||||
}
|
}
|
||||||
|
@ -748,3 +748,36 @@ void test_config_read__bom(void)
|
|||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_nosection_cb(const git_config_entry *entry, void *payload) {
|
||||||
|
int *seen = (int*)payload;
|
||||||
|
if (strcmp(entry->name, "key") == 0) {
|
||||||
|
(*seen)++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This would ideally issue a warning, if we had a way to do so. */
|
||||||
|
void test_config_read__nosection(void)
|
||||||
|
{
|
||||||
|
git_config *cfg;
|
||||||
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
int seen = 0;
|
||||||
|
|
||||||
|
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-nosection")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a key with no section, we do not allow reading it,
|
||||||
|
* but we do include it in an iteration over the config
|
||||||
|
* store. This appears to match how git's own APIs (and
|
||||||
|
* git-config(1)) behave.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cl_git_fail_with(git_config_get_string_buf(&buf, cfg, "key"), GIT_EINVALIDSPEC);
|
||||||
|
|
||||||
|
cl_git_pass(git_config_foreach(cfg, read_nosection_cb, &seen));
|
||||||
|
cl_assert_equal_i(seen, 1);
|
||||||
|
|
||||||
|
git_buf_free(&buf);
|
||||||
|
git_config_free(cfg);
|
||||||
|
}
|
||||||
|
46
tests/core/memmem.c
Normal file
46
tests/core/memmem.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
|
||||||
|
static void assert_found(const char *haystack, const char *needle, size_t expected_pos)
|
||||||
|
{
|
||||||
|
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
|
||||||
|
needle, needle ? strlen(needle) : 0),
|
||||||
|
haystack + expected_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_absent(const char *haystack, const char *needle)
|
||||||
|
{
|
||||||
|
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
|
||||||
|
needle, needle ? strlen(needle) : 0),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_memmem__found(void)
|
||||||
|
{
|
||||||
|
assert_found("a", "a", 0);
|
||||||
|
assert_found("ab", "a", 0);
|
||||||
|
assert_found("ba", "a", 1);
|
||||||
|
assert_found("aa", "a", 0);
|
||||||
|
assert_found("aab", "aa", 0);
|
||||||
|
assert_found("baa", "aa", 1);
|
||||||
|
assert_found("dabc", "abc", 1);
|
||||||
|
assert_found("abababc", "abc", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_memmem__absent(void)
|
||||||
|
{
|
||||||
|
assert_absent("a", "b");
|
||||||
|
assert_absent("a", "aa");
|
||||||
|
assert_absent("ba", "ab");
|
||||||
|
assert_absent("ba", "ab");
|
||||||
|
assert_absent("abc", "abcd");
|
||||||
|
assert_absent("abcabcabc", "bcac");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_memmem__edgecases(void)
|
||||||
|
{
|
||||||
|
assert_absent(NULL, NULL);
|
||||||
|
assert_absent("a", NULL);
|
||||||
|
assert_absent(NULL, "a");
|
||||||
|
assert_absent("", "a");
|
||||||
|
assert_absent("a", "");
|
||||||
|
}
|
@ -1,45 +1,84 @@
|
|||||||
#include "clar_libgit2.h"
|
#include "clar_libgit2.h"
|
||||||
|
|
||||||
|
static void assert_l32_parses(const char *string, int32_t expected, int base)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
cl_git_pass(git__strntol32(&i, string, strlen(string), NULL, base));
|
||||||
|
cl_assert_equal_i(i, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_l32_fails(const char *string, int base)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
cl_git_fail(git__strntol32(&i, string, strlen(string), NULL, base));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_l64_parses(const char *string, int64_t expected, int base)
|
||||||
|
{
|
||||||
|
int64_t i;
|
||||||
|
cl_git_pass(git__strntol64(&i, string, strlen(string), NULL, base));
|
||||||
|
cl_assert_equal_i(i, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_l64_fails(const char *string, int base)
|
||||||
|
{
|
||||||
|
int64_t i;
|
||||||
|
cl_git_fail(git__strntol64(&i, string, strlen(string), NULL, base));
|
||||||
|
}
|
||||||
|
|
||||||
void test_core_strtol__int32(void)
|
void test_core_strtol__int32(void)
|
||||||
{
|
{
|
||||||
int32_t i;
|
assert_l32_parses("123", 123, 10);
|
||||||
|
assert_l32_parses(" +123 ", 123, 10);
|
||||||
|
assert_l32_parses(" +2147483647 ", 2147483647, 10);
|
||||||
|
assert_l32_parses(" -2147483648 ", -2147483648LL, 10);
|
||||||
|
assert_l32_parses("A", 10, 16);
|
||||||
|
assert_l32_parses("1x1", 1, 10);
|
||||||
|
|
||||||
cl_git_pass(git__strtol32(&i, "123", NULL, 10));
|
assert_l32_fails("", 10);
|
||||||
cl_assert(i == 123);
|
assert_l32_fails("a", 10);
|
||||||
cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10));
|
assert_l32_fails("x10x", 10);
|
||||||
cl_assert(i == 123);
|
assert_l32_fails(" 2147483657 ", 10);
|
||||||
cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10));
|
assert_l32_fails(" -2147483657 ", 10);
|
||||||
cl_assert(i == 2147483647);
|
|
||||||
cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10));
|
|
||||||
cl_assert(i == -2147483648LL);
|
|
||||||
|
|
||||||
cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10));
|
|
||||||
cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_core_strtol__int64(void)
|
void test_core_strtol__int64(void)
|
||||||
{
|
{
|
||||||
int64_t i;
|
assert_l64_parses("123", 123, 10);
|
||||||
|
assert_l64_parses(" +123 ", 123, 10);
|
||||||
|
assert_l64_parses(" +2147483647 ", 2147483647, 10);
|
||||||
|
assert_l64_parses(" -2147483648 ", -2147483648LL, 10);
|
||||||
|
assert_l64_parses(" 2147483657 ", 2147483657LL, 10);
|
||||||
|
assert_l64_parses(" -2147483657 ", -2147483657LL, 10);
|
||||||
|
assert_l64_parses(" 9223372036854775807 ", INT64_MAX, 10);
|
||||||
|
assert_l64_parses(" -9223372036854775808 ", INT64_MIN, 10);
|
||||||
|
assert_l64_parses(" 0x7fffffffffffffff ", INT64_MAX, 16);
|
||||||
|
assert_l64_parses(" -0x8000000000000000 ", INT64_MIN, 16);
|
||||||
|
assert_l64_parses("1a", 26, 16);
|
||||||
|
assert_l64_parses("1A", 26, 16);
|
||||||
|
|
||||||
cl_git_pass(git__strtol64(&i, "123", NULL, 10));
|
assert_l64_fails("", 10);
|
||||||
cl_assert(i == 123);
|
assert_l64_fails("a", 10);
|
||||||
cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10));
|
assert_l64_fails("x10x", 10);
|
||||||
cl_assert(i == 123);
|
assert_l64_fails("0x8000000000000000", 16);
|
||||||
cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10));
|
assert_l64_fails("-0x8000000000000001", 16);
|
||||||
cl_assert(i == 2147483647);
|
|
||||||
cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10));
|
|
||||||
cl_assert(i == -2147483648LL);
|
|
||||||
cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10));
|
|
||||||
cl_assert(i == 2147483657LL);
|
|
||||||
cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10));
|
|
||||||
cl_assert(i == -2147483657LL);
|
|
||||||
cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10));
|
|
||||||
cl_assert(i == INT64_MAX);
|
|
||||||
cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10));
|
|
||||||
cl_assert(i == INT64_MIN);
|
|
||||||
cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16));
|
|
||||||
cl_assert(i == INT64_MAX);
|
|
||||||
cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16));
|
|
||||||
cl_assert(i == INT64_MIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_core_strtol__buffer_length_truncates(void)
|
||||||
|
{
|
||||||
|
int32_t i32;
|
||||||
|
int64_t i64;
|
||||||
|
|
||||||
|
cl_git_pass(git__strntol32(&i32, "11", 1, NULL, 10));
|
||||||
|
cl_assert_equal_i(i32, 1);
|
||||||
|
|
||||||
|
cl_git_pass(git__strntol64(&i64, "11", 1, NULL, 10));
|
||||||
|
cl_assert_equal_i(i64, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_core_strtol__error_message_cuts_off(void)
|
||||||
|
{
|
||||||
|
assert_l32_fails("2147483657foobar", 10);
|
||||||
|
cl_assert(strstr(giterr_last()->message, "2147483657") != NULL);
|
||||||
|
cl_assert(strstr(giterr_last()->message, "foobar") == NULL);
|
||||||
|
}
|
||||||
|
@ -407,3 +407,22 @@ void test_core_vector__reverse(void)
|
|||||||
|
|
||||||
git_vector_free(&v);
|
git_vector_free(&v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_core_vector__dup_empty_vector(void)
|
||||||
|
{
|
||||||
|
git_vector v = GIT_VECTOR_INIT;
|
||||||
|
git_vector dup = GIT_VECTOR_INIT;
|
||||||
|
int dummy;
|
||||||
|
|
||||||
|
cl_assert_equal_i(0, v.length);
|
||||||
|
|
||||||
|
cl_git_pass(git_vector_dup(&dup, &v, v._cmp));
|
||||||
|
cl_assert_equal_i(0, dup._alloc_size);
|
||||||
|
cl_assert_equal_i(0, dup.length);
|
||||||
|
|
||||||
|
cl_git_pass(git_vector_insert(&dup, &dummy));
|
||||||
|
cl_assert_equal_i(8, dup._alloc_size);
|
||||||
|
cl_assert_equal_i(1, dup.length);
|
||||||
|
|
||||||
|
git_vector_free(&dup);
|
||||||
|
}
|
||||||
|
@ -288,3 +288,74 @@ void test_diff_parse__patch_roundtrip_succeeds(void)
|
|||||||
git_buf_free(&patchbuf);
|
git_buf_free(&patchbuf);
|
||||||
git_buf_free(&diffbuf);
|
git_buf_free(&diffbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define cl_assert_equal_i_src(i1,i2,file,line) clar__assert_equal(file,line,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2))
|
||||||
|
|
||||||
|
static void cl_git_assert_lineinfo_(int old_lineno, int new_lineno, int num_lines, git_patch *patch, size_t hunk_idx, size_t line_idx, const char *file, int lineno)
|
||||||
|
{
|
||||||
|
const git_diff_line *line;
|
||||||
|
|
||||||
|
cl_git_expect(git_patch_get_line_in_hunk(&line, patch, hunk_idx, line_idx), 0, file, lineno);
|
||||||
|
cl_assert_equal_i_src(old_lineno, line->old_lineno, file, lineno);
|
||||||
|
cl_assert_equal_i_src(new_lineno, line->new_lineno, file, lineno);
|
||||||
|
cl_assert_equal_i_src(num_lines, line->num_lines, file, lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define cl_git_assert_lineinfo(old, new, num, p, h, l) \
|
||||||
|
cl_git_assert_lineinfo_(old,new,num,p,h,l,__FILE__,__LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
void test_diff_parse__issue4672(void)
|
||||||
|
{
|
||||||
|
const char *text = "diff --git a/a b/a\n"
|
||||||
|
"index 7f129fd..af431f2 100644\n"
|
||||||
|
"--- a/a\n"
|
||||||
|
"+++ b/a\n"
|
||||||
|
"@@ -3 +3 @@\n"
|
||||||
|
"-a contents 2\n"
|
||||||
|
"+a contents\n";
|
||||||
|
|
||||||
|
git_diff *diff;
|
||||||
|
git_patch *patch;
|
||||||
|
const git_diff_hunk *hunk;
|
||||||
|
size_t n, l = 0;
|
||||||
|
|
||||||
|
cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text)));
|
||||||
|
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
|
||||||
|
cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0));
|
||||||
|
|
||||||
|
cl_git_assert_lineinfo(3, -1, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(-1, 3, 1, patch, 0, l++);
|
||||||
|
|
||||||
|
cl_assert_equal_i(n, l);
|
||||||
|
|
||||||
|
git_patch_free(patch);
|
||||||
|
git_diff_free(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_diff_parse__lineinfo(void)
|
||||||
|
{
|
||||||
|
const char *text = PATCH_ORIGINAL_TO_CHANGE_MIDDLE;
|
||||||
|
git_diff *diff;
|
||||||
|
git_patch *patch;
|
||||||
|
const git_diff_hunk *hunk;
|
||||||
|
size_t n, l = 0;
|
||||||
|
|
||||||
|
cl_git_pass(git_diff_from_buffer(&diff, text, strlen(text)));
|
||||||
|
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
|
||||||
|
cl_git_pass(git_patch_get_hunk(&hunk, &n, patch, 0));
|
||||||
|
|
||||||
|
cl_git_assert_lineinfo(3, 3, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(4, 4, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(5, 5, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(6, -1, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(-1, 6, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(7, 7, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(8, 8, 1, patch, 0, l++);
|
||||||
|
cl_git_assert_lineinfo(9, 9, 1, patch, 0, l++);
|
||||||
|
|
||||||
|
cl_assert_equal_i(n, l);
|
||||||
|
|
||||||
|
git_patch_free(patch);
|
||||||
|
git_diff_free(diff);
|
||||||
|
}
|
||||||
|
@ -284,3 +284,19 @@ void test_object_tree_update__add_conflict2(void)
|
|||||||
|
|
||||||
cl_git_fail(git_tree_create_updated(&tree_updater_id, g_repo, NULL, 2, updates));
|
cl_git_fail(git_tree_create_updated(&tree_updater_id, g_repo, NULL, 2, updates));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_object_tree_update__remove_invalid_submodule(void)
|
||||||
|
{
|
||||||
|
git_tree *baseline;
|
||||||
|
git_oid updated_tree_id, baseline_id;
|
||||||
|
git_tree_update updates[] = {
|
||||||
|
{GIT_TREE_UPDATE_REMOVE, {{0}}, GIT_FILEMODE_BLOB, "submodule"},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This tree contains a submodule with an all-zero commit for a submodule named 'submodule' */
|
||||||
|
cl_git_pass(git_oid_fromstr(&baseline_id, "396c7f1adb7925f51ba13a75f48252f44c5a14a2"));
|
||||||
|
cl_git_pass(git_tree_lookup(&baseline, g_repo, &baseline_id));
|
||||||
|
cl_git_pass(git_tree_create_updated(&updated_tree_id, g_repo, baseline, 1, updates));
|
||||||
|
|
||||||
|
git_tree_free(baseline);
|
||||||
|
}
|
||||||
|
@ -263,6 +263,9 @@ static int cred_failure_cb(
|
|||||||
|
|
||||||
void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void)
|
void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void)
|
||||||
{
|
{
|
||||||
|
git__free(_remote_url);
|
||||||
|
git__free(_remote_user);
|
||||||
|
|
||||||
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
||||||
_remote_user = git__strdup("libgit2test");
|
_remote_user = git__strdup("libgit2test");
|
||||||
|
|
||||||
@ -293,6 +296,9 @@ void test_online_clone__cred_callback_called_again_on_auth_failure(void)
|
|||||||
{
|
{
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
|
|
||||||
|
git__free(_remote_url);
|
||||||
|
git__free(_remote_user);
|
||||||
|
|
||||||
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
||||||
_remote_user = git__strdup("libgit2test");
|
_remote_user = git__strdup("libgit2test");
|
||||||
|
|
||||||
|
@ -152,8 +152,12 @@ static void do_verify_push_status(record_callbacks_data *data, const push_status
|
|||||||
git_buf_free(&msg);
|
git_buf_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
git_vector_foreach(actual, i, iter)
|
git_vector_foreach(actual, i, iter) {
|
||||||
git__free(iter);
|
push_status *s = (push_status *)iter;
|
||||||
|
git__free(s->ref);
|
||||||
|
git__free(s->msg);
|
||||||
|
git__free(s);
|
||||||
|
}
|
||||||
|
|
||||||
git_vector_free(actual);
|
git_vector_free(actual);
|
||||||
}
|
}
|
||||||
@ -393,7 +397,7 @@ void test_online_push__initialize(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
git_remote_disconnect(_remote);
|
git_remote_disconnect(_remote);
|
||||||
git_vector_free(&delete_specs);
|
git_vector_free_deep(&delete_specs);
|
||||||
|
|
||||||
/* Now that we've deleted everything, fetch from the remote */
|
/* Now that we've deleted everything, fetch from the remote */
|
||||||
memcpy(&fetch_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks));
|
memcpy(&fetch_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks));
|
||||||
|
BIN
tests/resources/config/config-nosection
Normal file
BIN
tests/resources/config/config-nosection
Normal file
Binary file not shown.
Binary file not shown.
80
tests/submodule/inject_option.c
Normal file
80
tests/submodule/inject_option.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
#include "posix.h"
|
||||||
|
#include "path.h"
|
||||||
|
#include "submodule_helpers.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "repository.h"
|
||||||
|
|
||||||
|
static git_repository *g_repo = NULL;
|
||||||
|
|
||||||
|
void test_submodule_inject_option__initialize(void)
|
||||||
|
{
|
||||||
|
g_repo = setup_fixture_submodule_simple();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_submodule_inject_option__cleanup(void)
|
||||||
|
{
|
||||||
|
cl_git_sandbox_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_naughty(git_submodule *sm, const char *name, void *payload)
|
||||||
|
{
|
||||||
|
int *foundit = (int *) payload;
|
||||||
|
|
||||||
|
GIT_UNUSED(sm);
|
||||||
|
|
||||||
|
if (!git__strcmp("naughty", name))
|
||||||
|
*foundit = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_submodule_inject_option__url(void)
|
||||||
|
{
|
||||||
|
int foundit;
|
||||||
|
git_submodule *sm;
|
||||||
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
|
cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
|
||||||
|
cl_git_rewritefile(buf.ptr,
|
||||||
|
"[submodule \"naughty\"]\n"
|
||||||
|
" path = testrepo\n"
|
||||||
|
" url = -u./payload\n");
|
||||||
|
git_buf_free(&buf);
|
||||||
|
|
||||||
|
/* We do want to find it, but with the appropriate field empty */
|
||||||
|
foundit = 0;
|
||||||
|
cl_git_pass(git_submodule_foreach(g_repo, find_naughty, &foundit));
|
||||||
|
cl_assert_equal_i(1, foundit);
|
||||||
|
|
||||||
|
cl_git_pass(git_submodule_lookup(&sm, g_repo, "naughty"));
|
||||||
|
cl_assert_equal_s("testrepo", git_submodule_path(sm));
|
||||||
|
cl_assert_equal_p(NULL, git_submodule_url(sm));
|
||||||
|
|
||||||
|
git_submodule_free(sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_submodule_inject_option__path(void)
|
||||||
|
{
|
||||||
|
int foundit;
|
||||||
|
git_submodule *sm;
|
||||||
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
|
cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
|
||||||
|
cl_git_rewritefile(buf.ptr,
|
||||||
|
"[submodule \"naughty\"]\n"
|
||||||
|
" path = --something\n"
|
||||||
|
" url = blah.git\n");
|
||||||
|
git_buf_free(&buf);
|
||||||
|
|
||||||
|
/* We do want to find it, but with the appropriate field empty */
|
||||||
|
foundit = 0;
|
||||||
|
cl_git_pass(git_submodule_foreach(g_repo, find_naughty, &foundit));
|
||||||
|
cl_assert_equal_i(1, foundit);
|
||||||
|
|
||||||
|
cl_git_pass(git_submodule_lookup(&sm, g_repo, "naughty"));
|
||||||
|
cl_assert_equal_s("naughty", git_submodule_path(sm));
|
||||||
|
cl_assert_equal_s("blah.git", git_submodule_url(sm));
|
||||||
|
|
||||||
|
git_submodule_free(sm);
|
||||||
|
}
|
340
tests/transports/smart/packet.c
Normal file
340
tests/transports/smart/packet.c
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
#include "clar_libgit2.h"
|
||||||
|
#include "transports/smart.h"
|
||||||
|
|
||||||
|
enum expected_status {
|
||||||
|
PARSE_SUCCESS,
|
||||||
|
PARSE_FAILURE
|
||||||
|
};
|
||||||
|
|
||||||
|
static void assert_flush_parses(const char *line)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_FLUSH);
|
||||||
|
cl_assert_equal_strn(endptr, line + 4, linelen - 4);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_data_pkt_parses(const char *line, const char *expected_data, size_t expected_len)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_data *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_DATA);
|
||||||
|
cl_assert_equal_i(pkt->len, expected_len);
|
||||||
|
cl_assert_equal_strn(pkt->data, expected_data, expected_len);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_sideband_progress_parses(const char *line, const char *expected_data, size_t expected_len)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_progress *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_PROGRESS);
|
||||||
|
cl_assert_equal_i(pkt->len, expected_len);
|
||||||
|
cl_assert_equal_strn(pkt->data, expected_data, expected_len);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_error_parses(const char *line, const char *expected_error, size_t expected_len)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_err *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_ERR);
|
||||||
|
cl_assert_equal_i(pkt->len, expected_len);
|
||||||
|
cl_assert_equal_strn(pkt->error, expected_error, expected_len);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_ack_parses(const char *line, const char *expected_oid, enum git_ack_status expected_status)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_ack *pkt;
|
||||||
|
git_oid oid;
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&oid, expected_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_ACK);
|
||||||
|
cl_assert_equal_oid(&pkt->oid, &oid);
|
||||||
|
cl_assert_equal_i(pkt->status, expected_status);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_nak_parses(const char *line)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_NAK);
|
||||||
|
cl_assert_equal_strn(endptr, line + 7, linelen - 7);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_comment_parses(const char *line, const char *expected_comment)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_comment *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_COMMENT);
|
||||||
|
cl_assert_equal_strn(pkt->comment, expected_comment, strlen(expected_comment));
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_ok_parses(const char *line, const char *expected_ref)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_ok *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_OK);
|
||||||
|
cl_assert_equal_strn(pkt->ref, expected_ref, strlen(expected_ref));
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_unpack_parses(const char *line, bool ok)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_unpack *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_UNPACK);
|
||||||
|
cl_assert_equal_i(pkt->unpack_ok, ok);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_ng_parses(const char *line, const char *expected_ref, const char *expected_msg)
|
||||||
|
{
|
||||||
|
size_t linelen = strlen(line) + 1;
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_ng *pkt;
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_NG);
|
||||||
|
cl_assert_equal_strn(pkt->ref, expected_ref, strlen(expected_ref));
|
||||||
|
cl_assert_equal_strn(pkt->msg, expected_msg, strlen(expected_msg));
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define assert_ref_parses(line, expected_oid, expected_ref, expected_capabilities) \
|
||||||
|
assert_ref_parses_(line, sizeof(line), expected_oid, expected_ref, expected_capabilities)
|
||||||
|
|
||||||
|
static void assert_ref_parses_(const char *line, size_t linelen, const char *expected_oid,
|
||||||
|
const char *expected_ref, const char *expected_capabilities)
|
||||||
|
{
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt_ref *pkt;
|
||||||
|
git_oid oid;
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&oid, expected_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
|
||||||
|
cl_assert_equal_i(pkt->type, GIT_PKT_REF);
|
||||||
|
cl_assert_equal_oid(&pkt->head.oid, &oid);
|
||||||
|
cl_assert_equal_strn(pkt->head.name, expected_ref, strlen(expected_ref));
|
||||||
|
if (expected_capabilities)
|
||||||
|
cl_assert_equal_strn(pkt->capabilities, expected_capabilities, strlen(expected_capabilities));
|
||||||
|
else
|
||||||
|
cl_assert_equal_p(NULL, pkt->capabilities);
|
||||||
|
|
||||||
|
git_pkt_free((git_pkt *) pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assert_pkt_fails(const char *line)
|
||||||
|
{
|
||||||
|
const char *endptr;
|
||||||
|
git_pkt *pkt;
|
||||||
|
cl_git_fail(git_pkt_parse_line(&pkt, &endptr, line, strlen(line) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__parsing_garbage_fails(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("0foobar");
|
||||||
|
assert_pkt_fails("00foobar");
|
||||||
|
assert_pkt_fails("000foobar");
|
||||||
|
assert_pkt_fails("0001");
|
||||||
|
assert_pkt_fails("");
|
||||||
|
assert_pkt_fails("0");
|
||||||
|
assert_pkt_fails("0i00");
|
||||||
|
assert_pkt_fails("f");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__flush_parses(void)
|
||||||
|
{
|
||||||
|
assert_flush_parses("0000");
|
||||||
|
assert_flush_parses("0000foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__data_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("000foobar");
|
||||||
|
assert_pkt_fails("0001o");
|
||||||
|
assert_pkt_fails("0001\1");
|
||||||
|
assert_data_pkt_parses("0005\1", "", 0);
|
||||||
|
assert_pkt_fails("0009\1o");
|
||||||
|
assert_data_pkt_parses("0009\1data", "data", 4);
|
||||||
|
assert_data_pkt_parses("000a\1data", "data", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__sideband_progress_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("0001\2");
|
||||||
|
assert_sideband_progress_parses("0005\2", "", 0);
|
||||||
|
assert_pkt_fails("0009\2o");
|
||||||
|
assert_sideband_progress_parses("0009\2data", "data", 4);
|
||||||
|
assert_sideband_progress_parses("000a\2data", "data", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__sideband_err_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("0001\3");
|
||||||
|
assert_error_parses("0005\3", "", 0);
|
||||||
|
assert_pkt_fails("0009\3o");
|
||||||
|
assert_error_parses("0009\3data", "data", 4);
|
||||||
|
assert_error_parses("000a\3data", "data", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__ack_pkt(void)
|
||||||
|
{
|
||||||
|
assert_ack_parses("0030ACK 0000000000000000000000000000000000000000",
|
||||||
|
"0000000000000000000000000000000000000000", 0);
|
||||||
|
assert_ack_parses("0039ACK 0000000000000000000000000000000000000000 continue",
|
||||||
|
"0000000000000000000000000000000000000000",
|
||||||
|
GIT_ACK_CONTINUE);
|
||||||
|
assert_ack_parses("0037ACK 0000000000000000000000000000000000000000 common",
|
||||||
|
"0000000000000000000000000000000000000000",
|
||||||
|
GIT_ACK_COMMON);
|
||||||
|
assert_ack_parses("0037ACK 0000000000000000000000000000000000000000 ready",
|
||||||
|
"0000000000000000000000000000000000000000",
|
||||||
|
GIT_ACK_READY);
|
||||||
|
|
||||||
|
/* these should fail as they don't have OIDs */
|
||||||
|
assert_pkt_fails("0007ACK");
|
||||||
|
assert_pkt_fails("0008ACK ");
|
||||||
|
|
||||||
|
/* this one is missing a space and should thus fail */
|
||||||
|
assert_pkt_fails("0036ACK00000000000000000x0000000000000000000000 ready");
|
||||||
|
|
||||||
|
/* the following ones have invalid OIDs and should thus fail */
|
||||||
|
assert_pkt_fails("0037ACK 00000000000000000x0000000000000000000000 ready");
|
||||||
|
assert_pkt_fails("0036ACK 000000000000000000000000000000000000000 ready");
|
||||||
|
assert_pkt_fails("0036ACK 00000000000000000x0000000000000000000000ready");
|
||||||
|
|
||||||
|
/* this one has an invalid status and should thus fail */
|
||||||
|
assert_pkt_fails("0036ACK 0000000000000000000000000000000000000000 read");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__nak_pkt(void)
|
||||||
|
{
|
||||||
|
assert_nak_parses("0007NAK");
|
||||||
|
assert_pkt_fails("0007NaK");
|
||||||
|
assert_pkt_fails("0007nak");
|
||||||
|
assert_nak_parses("0007NAKfoobar");
|
||||||
|
assert_pkt_fails("0007nakfoobar");
|
||||||
|
assert_pkt_fails("0007 NAK");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__error_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("0007ERR");
|
||||||
|
assert_pkt_fails("0008ERRx");
|
||||||
|
assert_error_parses("0008ERR ", "", 0);
|
||||||
|
assert_error_parses("000EERR ERRMSG", "ERRMSG", 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__comment_pkt(void)
|
||||||
|
{
|
||||||
|
assert_comment_parses("0005#", "");
|
||||||
|
assert_comment_parses("000B#foobar", "#fooba");
|
||||||
|
assert_comment_parses("000C#foobar", "#foobar");
|
||||||
|
assert_comment_parses("001A#this is a comment\nfoo", "#this is a comment\nfoo");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__ok_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("0007ok\n");
|
||||||
|
assert_ok_parses("0007ok ", "");
|
||||||
|
assert_ok_parses("0008ok \n", "");
|
||||||
|
assert_ok_parses("0008ok x", "x");
|
||||||
|
assert_ok_parses("0009ok x\n", "x");
|
||||||
|
assert_pkt_fails("001OK ref/foo/bar");
|
||||||
|
assert_ok_parses("0012ok ref/foo/bar", "ref/foo/bar");
|
||||||
|
assert_pkt_fails("0013OK ref/foo/bar\n");
|
||||||
|
assert_ok_parses("0013ok ref/foo/bar\n", "ref/foo/bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__ng_pkt(void)
|
||||||
|
{
|
||||||
|
/* TODO: same as for ok pkt */
|
||||||
|
assert_pkt_fails("0007ng\n");
|
||||||
|
assert_pkt_fails("0008ng \n");
|
||||||
|
assert_pkt_fails("000Bng ref\n");
|
||||||
|
assert_pkt_fails("000Bng ref\n");
|
||||||
|
/* TODO: is this a valid packet line? Probably not. */
|
||||||
|
assert_ng_parses("000Ang x\n", "", "x");
|
||||||
|
assert_ng_parses("000Fng ref msg\n", "ref", "msg");
|
||||||
|
assert_ng_parses("000Fng ref msg\n", "ref", "msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__unpack_pkt(void)
|
||||||
|
{
|
||||||
|
assert_unpack_parses("000Dunpack ok", 1);
|
||||||
|
assert_unpack_parses("000Dunpack ng error-msg", 0);
|
||||||
|
/* TODO: the following tests should fail */
|
||||||
|
assert_unpack_parses("000Aunpack", 0);
|
||||||
|
assert_unpack_parses("0011unpack foobar", 0);
|
||||||
|
assert_unpack_parses("0010unpack ng ok", 0);
|
||||||
|
assert_unpack_parses("0010unpack okfoo", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_transports_smart_packet__ref_pkt(void)
|
||||||
|
{
|
||||||
|
assert_pkt_fails("002C0000000000000000000000000000000000000000");
|
||||||
|
assert_pkt_fails("002D0000000000000000000000000000000000000000\n");
|
||||||
|
assert_pkt_fails("00300000000000000000000000000000000000000000HEAD");
|
||||||
|
assert_pkt_fails("004800000000x0000000000000000000000000000000 refs/heads/master\0multi_ack");
|
||||||
|
assert_ref_parses(
|
||||||
|
"003F0000000000000000000000000000000000000000 refs/heads/master\0",
|
||||||
|
"0000000000000000000000000000000000000000", "refs/heads/master", "");
|
||||||
|
assert_ref_parses(
|
||||||
|
"00480000000000000000000000000000000000000000 refs/heads/master\0multi_ack",
|
||||||
|
"0000000000000000000000000000000000000000", "refs/heads/master", "multi_ack");
|
||||||
|
assert_ref_parses(
|
||||||
|
"00460000000000000000000000000000000000000000 refs/heads/master\0one two",
|
||||||
|
"0000000000000000000000000000000000000000", "refs/heads/master", "one two");
|
||||||
|
assert_ref_parses(
|
||||||
|
"00310000000000000000000000000000000000000000 HEAD",
|
||||||
|
"0000000000000000000000000000000000000000", "HEAD", NULL);
|
||||||
|
assert_pkt_fails("0031000000000000000000000000000000000000000 HEAD");
|
||||||
|
assert_ref_parses(
|
||||||
|
"00360000000000000000000000000000000000000000 HEAD HEAD",
|
||||||
|
"0000000000000000000000000000000000000000", "HEAD HEAD", NULL);
|
||||||
|
}
|
@ -228,6 +228,26 @@ void test_worktree_worktree__init(void)
|
|||||||
git_repository_free(repo);
|
git_repository_free(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_worktree_worktree__add_from_bare(void)
|
||||||
|
{
|
||||||
|
git_worktree *wt;
|
||||||
|
git_repository *repo, *wtrepo;
|
||||||
|
|
||||||
|
repo = cl_git_sandbox_init("short_tag.git");
|
||||||
|
|
||||||
|
cl_assert_equal_i(1, git_repository_is_bare(repo));
|
||||||
|
cl_assert_equal_i(0, git_repository_is_worktree(repo));
|
||||||
|
|
||||||
|
cl_git_pass(git_worktree_add(&wt, repo, "worktree-frombare", "worktree-frombare", NULL));
|
||||||
|
cl_git_pass(git_repository_open(&wtrepo, "worktree-frombare"));
|
||||||
|
cl_assert_equal_i(0, git_repository_is_bare(wtrepo));
|
||||||
|
cl_assert_equal_i(1, git_repository_is_worktree(wtrepo));
|
||||||
|
|
||||||
|
git_worktree_free(wt);
|
||||||
|
git_repository_free(repo);
|
||||||
|
git_repository_free(wtrepo);
|
||||||
|
}
|
||||||
|
|
||||||
void test_worktree_worktree__add_locked(void)
|
void test_worktree_worktree__add_locked(void)
|
||||||
{
|
{
|
||||||
git_worktree *wt;
|
git_worktree *wt;
|
||||||
@ -435,7 +455,7 @@ void test_worktree_worktree__unlock_unlocked_worktree(void)
|
|||||||
|
|
||||||
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
cl_assert(!git_worktree_is_locked(NULL, wt));
|
cl_assert(!git_worktree_is_locked(NULL, wt));
|
||||||
cl_assert(git_worktree_unlock(wt) == 0);
|
cl_assert_equal_i(1, git_worktree_unlock(wt));
|
||||||
cl_assert(!wt->locked);
|
cl_assert(!wt->locked);
|
||||||
|
|
||||||
git_worktree_free(wt);
|
git_worktree_free(wt);
|
||||||
@ -448,7 +468,7 @@ void test_worktree_worktree__unlock_locked_worktree(void)
|
|||||||
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
cl_git_pass(git_worktree_lock(wt, NULL));
|
cl_git_pass(git_worktree_lock(wt, NULL));
|
||||||
cl_assert(git_worktree_is_locked(NULL, wt));
|
cl_assert(git_worktree_is_locked(NULL, wt));
|
||||||
cl_git_pass(git_worktree_unlock(wt));
|
cl_assert_equal_i(0, git_worktree_unlock(wt));
|
||||||
cl_assert(!wt->locked);
|
cl_assert(!wt->locked);
|
||||||
|
|
||||||
git_worktree_free(wt);
|
git_worktree_free(wt);
|
||||||
|
Loading…
Reference in New Issue
Block a user