Merge remote-tracking branch 'upstream/master' into cmn/describe

This commit is contained in:
Carlos Martín Nieto 2014-09-30 04:38:05 +02:00
commit af6cc38fc0
337 changed files with 11834 additions and 4247 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
; Check http://editorconfig.org/ for more informations
; Top-most EditorConfig file
root = true
; tab indentation
[*]
indent_style = tab
trim_trailing_whitespace = true
insert_final_newline = true
; 4-column space indentation
[*.md]
indent_style = space
indent_size = 4

View File

@ -3,6 +3,10 @@
language: c
os:
- linux
- osx
compiler:
- gcc
- clang
@ -17,17 +21,27 @@ env:
matrix:
fast_finish: true
exclude:
- os: osx
compiler: gcc
include:
- compiler: i586-mingw32msvc-gcc
env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON"
env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON -DUSE_SSH=OFF"
os: linux
- compiler: gcc
env: COVERITY=1
os: linux
- compiler: gcc
env:
- VALGRIND=1
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Debug"
os: linux
allow_failures:
- env: COVERITY=1
- env: VALGRIND=1
install:
- sudo apt-get -qq update
- sudo apt-get -qq install cmake libssh2-1-dev openssh-client openssh-server
- ./script/install-deps-${TRAVIS_OS_NAME}.sh
# Run the Build script and tests
script:
@ -35,13 +49,14 @@ script:
# Run Tests
after_success:
- sudo apt-get -qq install valgrind
- valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline
- if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then sudo apt-get -qq install valgrind; fi
- 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 branch
# Only watch the development and master branches
branches:
only:
- development
- master
# Notify development list when needed
notifications:

View File

@ -6,6 +6,7 @@ Alexei Sholik
Andreas Ericsson
Anton "antong" Gyllenberg
Ankur Sethi
Arthur Schreiber
Ben Noordhuis
Ben Straub
Benjamin C Meyer

60
CHANGELOG.md Normal file
View File

@ -0,0 +1,60 @@
v0.21 + 1
------
* File unlocks are atomic again via rename. Read-only files on Windows are
made read-write if necessary.
* Share open packfiles across repositories to share descriptors and mmaps.
* Use a map for the treebuilder, making insertion O(1)
* LF -> CRLF filter refuses to handle mixed-EOL files
* LF -> CRLF filter now runs when * text = auto (with Git for Windows 1.9.4)
* The git_transport structure definition has moved into the sys/transport.h
file.
* The ssh transport supports asking the remote host for accepted
credential types as well as multiple challeges using a single
connection. This requires to know which username you want to connect
as, so this introduces the USERNAME credential type which the ssh
transport will use to ask for the username.
* The git_transport_register function no longer takes a priority and takes
a URL scheme name (eg "http") instead of a prefix like "http://"
* The git_remote_set_transport function now sets a transport factory function,
rather than a pre-existing transport instance.
* A factory function for ssh has been added which allows to change the
path of the programs to execute for receive-pack and upload-pack on
the server, git_transport_ssh_with_paths.
* The git_clone_options struct no longer provides the ignore_cert_errors or
remote_name members for remote customization.
Instead, the git_clone_options struct has two new members, remote_cb and
remote_cb_payload, which allow the caller to completely override the remote
creation process. If needed, the caller can use this callback to give their
remote a name other than the default (origin) or disable cert checking.
The remote_callbacks member has been preserved for convenience, although it
is not used when a remote creation callback is supplied.
* The git_clone_options struct now provides repository_cb and
repository_cb_payload to allow the user to create a repository with
custom options.
* The option to ignore certificate errors via git_remote_cert_check()
is no longer present. Instead, git_remote_callbacks has gained a new
entry which lets the user perform their own certificate checks.
* git_clone_into and git_clone_local_into have been removed from the
public API in favour of git_clone callbacks
* Add support for refspecs with the asterisk in the middle of a
pattern.
* Introduce git_merge_bases() and the git_oidarray type to expose all
merge bases between two commits.

View File

@ -36,6 +36,7 @@ OPTION( ANDROID "Build for android NDK" OFF )
OPTION( USE_ICONV "Link with and use iconv library" OFF )
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF )
OPTION( VALGRIND "Configure build for valgrind" OFF )
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@ -127,6 +128,9 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_V
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
FILE(STRINGS "include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$")
STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
# Find required dependencies
INCLUDE_DIRECTORIES(src include)
@ -139,7 +143,7 @@ ELSE ()
FIND_PACKAGE(OpenSSL)
ENDIF ()
FIND_PACKAGE(HTTP_Parser QUIET)
FIND_PACKAGE(HTTP_Parser)
IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS})
LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES})
@ -157,7 +161,11 @@ IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin")
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin")
ADD_DEFINITIONS(-DOPENSSL_SHA1)
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl")
IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lssl")
ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl")
ENDIF ()
ELSE()
FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
ENDIF()
@ -168,25 +176,21 @@ IF (ENABLE_TRACE STREQUAL "ON")
ENDIF()
# Include POSIX regex when it is required
IF(WIN32 OR AMIGA OR ANDROID)
IF(WIN32 OR AMIGA OR ANDROID OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
INCLUDE_DIRECTORIES(deps/regex)
SET(SRC_REGEX deps/regex/regex.c)
ENDIF()
# Optional external dependency: zlib
# It's optional, but FIND_PACKAGE gives a warning that looks more like an
# error.
FIND_PACKAGE(ZLIB QUIET)
FIND_PACKAGE(ZLIB)
IF (ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
LINK_LIBRARIES(${ZLIB_LIBRARIES})
IF(APPLE)
IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lz")
ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib")
ENDIF()
# Fake the message CMake would have shown
MESSAGE(STATUS "Found zlib: ${ZLIB_LIBRARY}")
ELSE()
MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
INCLUDE_DIRECTORIES(deps/zlib)
@ -195,8 +199,8 @@ ELSE()
ENDIF()
# Optional external dependency: libssh2
IF (USE_SSH AND NOT MINGW)
FIND_PACKAGE(LIBSSH2 QUIET)
IF (USE_SSH)
FIND_PACKAGE(LIBSSH2)
ENDIF()
IF (LIBSSH2_FOUND)
ADD_DEFINITIONS(-DGIT_SSH)
@ -205,9 +209,17 @@ IF (LIBSSH2_FOUND)
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
ENDIF()
# Optional external dependency: libgssapi
IF (USE_GSSAPI)
FIND_PACKAGE(GSSAPI)
ENDIF()
IF (GSSAPI_FOUND)
ADD_DEFINITIONS(-DGIT_GSSAPI)
ENDIF()
# Optional external dependency: iconv
IF (USE_ICONV)
FIND_PACKAGE(ICONV QUIET)
FIND_PACKAGE(Iconv)
ENDIF()
IF (ICONV_FOUND)
ADD_DEFINITIONS(-DGIT_USE_ICONV)
@ -290,6 +302,10 @@ IF (MSVC)
ELSE ()
SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra ${CMAKE_C_FLAGS}")
IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}")
ENDIF()
IF (WIN32 AND NOT CYGWIN)
SET(CMAKE_C_FLAGS_DEBUG "-D_DEBUG")
ENDIF ()
@ -380,6 +396,7 @@ ENDIF()
ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${GSSAPI_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${ICONV_LIBRARIES})
TARGET_OS_LIBRARIES(git2)
@ -393,7 +410,7 @@ MSVC_SPLIT_SOURCES(git2)
IF (SONAME)
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
@ -446,6 +463,7 @@ IF (BUILD_CLAR)
TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${GSSAPI_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${ICONV_LIBRARIES})
TARGET_OS_LIBRARIES(libgit2_clar)
MSVC_SPLIT_SOURCES(libgit2_clar)

View File

@ -22,17 +22,25 @@ Also, feel free to open an
about any concerns you have. We like to use Issues for that so there is an
easily accessible permanent record of the conversation.
## Libgit2 Versions
The `master` branch is the main branch where development happens.
Releases are tagged
(e.g. [v0.21.0](https://github.com/libgit2/libgit2/releases/tag/v0.21.0) )
and when a critical bug fix needs to be backported, it will be done on a
`<tag>-maint` maintenance branch.
## Reporting Bugs
First, know which version of libgit2 your problem is in and include it in
your bug report. This can either be a tag (e.g.
[v0.17.0](https://github.com/libgit2/libgit2/tree/v0.17.0) ) or a commit
SHA (e.g.
[v0.17.0](https://github.com/libgit2/libgit2/releases/tag/v0.17.0) ) or a
commit SHA (e.g.
[01be7863](https://github.com/libgit2/libgit2/commit/01be786319238fd6507a08316d1c265c1a89407f)
). Using [`git describe`](http://git-scm.com/docs/git-describe) is a great
way to tell us what version you're working with.
). Using [`git describe`](http://git-scm.com/docs/git-describe) is a
great way to tell us what version you're working with.
If you're not running against the latest `development` branch version,
If you're not running against the latest `master` branch version,
please compile and test against that to avoid re-reporting an issue that's
already been fixed.
@ -44,25 +52,33 @@ out a way to help you.
## Pull Requests
Our work flow is a typical GitHub flow, where contributors fork the
[libgit2 repository](https://github.com/libgit2/libgit2), make their changes
on branch, and submit a
[Pull Request](https://help.github.com/articles/using-pull-requests)
(a.k.a. "PR").
Our work flow is a [typical GitHub flow](https://guides.github.com/introduction/flow/index.html),
where contributors fork the [libgit2 repository](https://github.com/libgit2/libgit2),
make their changes on branch, and submit a
[Pull Request](https://help.github.com/articles/using-pull-requests) (a.k.a. "PR").
Pull requests should usually be targeted at the `master` branch.
Life will be a lot easier for you (and us) if you follow this pattern
(i.e. fork, named branch, submit PR). If you use your fork's `development`
branch, things can get messy.
(i.e. fork, named branch, submit PR). If you use your fork's `master`
branch directly, things can get messy.
Please include a nice description of your changes with your PR; if we have
to read the whole diff to figure out why you're contributing in the first
place, you're less likely to get feedback and have your change merged in.
Please include a nice description of your changes when you submit your PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your change
merged in.
If you are working on a particular area then feel free to submit a PR that
highlights your work in progress (and flag in the PR title that it's not
ready to merge). This will help in getting visibility for your fix, allow
others to comment early on the changes and also let others know that you
are currently working on something.
If you are starting to work on a particular area, feel free to submit a PR
that highlights your work in progress (and note in the PR title that it's
not ready to merge). These early PRs are welcome and will help in getting
visibility for your fix, allow others to comment early on the changes and
also let others know that you are currently working on something.
Before wrapping up a PR, you should be sure to:
* Write tests to cover any functional changes (ideally tests that would
have failed before the PR and now pass)
* Update documentation for any changed public APIs
* Add to the [`CHANGELOG.md`](CHANGELOG.md) file describing any major changes
## Porting Code From Other Open-Source Projects
@ -80,10 +96,10 @@ you're porting code *from* to see what you need to do. As a general rule,
MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0
license typically doesn't work due to GPL incompatibility.
If you are pulling in code from core Git, another project or code you've
pulled from a forum / Stack Overflow then please flag this in your PR and
also make sure you've given proper credit to the original author in the
code snippet.
If your pull request uses code from core Git, another project, or code
from a forum / Stack Overflow, then *please* flag this in your PR and make
sure you've given proper credit to the original author in the code
snippet.
## Style Guide

View File

@ -10,10 +10,11 @@ ideas that no one is actively working on.
## Before You Start
Please start by reading the README.md, CONTRIBUTING.md, and CONVENTIONS.md
files before diving into one of these projects. Those will explain our
work flow and coding conventions to help ensure that your work will be
easily integrated into libgit2.
Please start by reading the [README.md](README.md),
[CONTRIBUTING.md](CONTRIBUTING.md), and [CONVENTIONS.md](CONVENTIONS.md)
files before diving into one of these projects. Those explain our work
flow and coding conventions to help ensure that your work will be easily
integrated into libgit2.
Next, work through the build instructions and make sure you can clone the
repository, compile it, and run the tests successfully. That will make
@ -27,7 +28,7 @@ These are good small projects to get started with libgit2.
* Look at the `examples/` programs, find an existing one that mirrors a
core Git command and add a missing command-line option. There are many
gaps right now and this helps demonstrate how to use the library. Here
are some specific ideas:
are some specific ideas (though there are many more):
* Fix the `examples/diff.c` implementation of the `-B`
(a.k.a. `--break-rewrites`) command line option to actually look for
the optional `[<n>][/<m>]` configuration values. There is an
@ -39,12 +40,6 @@ These are good small projects to get started with libgit2.
the data is available, you would just need to add the code into the
`print_commit()` routine (along with a way of passing the option
into that function).
* For `examples/log.c`, implement any one of `--author=<...>`,
`--committer=<...>`, or `--grep=<...>` but just use simple string
match with `strstr()` instead of full regular expression
matching. (I.e. I'm suggesting implementing this as if
`--fixed-strings` was always turned on, because it will be a simpler
project.)
* As an extension to the matching idea for `examples/log.c`, add the
`-i` option to use `strcasestr()` for matches.
* For `examples/log.c`, implement the `--first-parent` option now that
@ -58,9 +53,6 @@ These are good small projects to get started with libgit2.
* Submit a PR to clarify documentation! While we do try to document all of
the APIs, your fresh eyes on the documentation will find areas that are
confusing much more easily.
* Add support for the symref protocol extension, so we don't guess
what the remote's default branch is
[#2006](https://github.com/libgit2/libgit2/issues/2006)
If none of these appeal to you, take a look at our issues list to see if
there are any unresolved issues you'd like to jump in on.
@ -73,19 +65,44 @@ into one of these as a first project for libgit2 - we'd rather get to
know you first by successfully shipping your work on one of the smaller
projects above.
Some of these projects are broken down into subprojects and/or have
some incremental steps listed towards the larger goal. Those steps
might make good smaller projects by themselves.
* Port part of the Git test suite to run against the command line emulation
in examples/
* Pick a Git command that is emulated in our examples/ area
* Extract the Git tests that exercise that command
* Convert the tests to call our emulation
* These tests could go in examples/tests/...
* Fix symlink support for files in the .git directory (i.e. don't overwrite
the symlinks when writing the file contents back out)
* Implement a 'git describe' like API
* Add hooks API to enumerate and manage hooks (not run them at this point)
* Enumeration of available hooks
* Lookup API to see which hooks have a script and get the script
* Read/write API to load a hook script and write a hook script
* Eventually, callback API to invoke a hook callback when libgit2
executes the action in question
* Isolate logic of ignore evaluation into a standalone API
* Upgrade internal libxdiff code to latest from core Git
* Add a hashtable lookup for files in the index instead of binary search
every time
* Improve index internals with hashtable lookup for files instead of
using binary search every time
* Make the index write the cache out to disk (with tests to gain
confidence that the caching invalidation works correctly)
* Have the tree builder use a hash table when building instead of a
list.
* Tree builder improvements:
* Use a hash table when building instead of a list
* Extend to allow building a tree hierarchy
* Move the tagopt mechanism to the newer git 1.9 interpretation of
--tags [#2120](https://github.com/libgit2/libgit2/issues/2120)
* Apply-patch API
* Add a patch editing API to enable "git add -p" type operations
* Textconv API to filter binary data before generating diffs (something
like the current Filter API, probably).
* Performance profiling and improvement
* Build in handling of "empty tree" and "empty blob" SHAs
* Support "git replace" ref replacements
* Include conflicts in diff results and in status
* GIT_DELTA_CONFLICT for items in conflict (with multiple files)
* Appropriate flags for status
* Support sparse checkout (i.e. "core.sparsecheckout" and ".git/info/sparse-checkout")

View File

@ -55,7 +55,7 @@ dependencies, it can make use of a few libraries to add to it:
- pthreads (non-Windows) to enable threadsafe access as well as multi-threaded pack generation
- OpenSSL (non-Windows) to talk over HTTPS and provide the SHA-1 functions
- LibSSH2 to enable the ssh transport
- LibSSH2 to enable the SSH transport
- iconv (OSX) to handle the HFS+ path encoding peculiarities
Building libgit2 - Using CMake
@ -119,8 +119,7 @@ You need to run the CMake commands from the Visual Studio command
prompt, not the regular or Windows SDK one. Select the right generator
for your version with the `-G "Visual Studio X" option.
See [the wiki]
(https://github.com/libgit2/libgit2/wiki/Building-libgit2-on-Windows)
See [the website](https://libgit2.github.com/docs/guides/build-and-link)
for more detailed instructions.
Android
@ -168,6 +167,8 @@ Here are the bindings to libgit2 that are currently available:
* hgit2 <https://github.com/fpco/gitlib>
* Java
* Jagged <https://github.com/ethomson/jagged>
* Julia
* LibGit2.jl <https://github.com/jakebolewski/LibGit2.jl>
* Lua
* luagit2 <https://github.com/libgit2/luagit2>
* .NET
@ -182,15 +183,19 @@ Here are the bindings to libgit2 that are currently available:
* Parrot Virtual Machine
* parrot-libgit2 <https://github.com/letolabs/parrot-libgit2>
* Perl
* Git-Raw <https://github.com/ghedo/p5-Git-Raw>
* Git-Raw <https://github.com/jacquesg/p5-Git-Raw>
* PHP
* php-git <https://github.com/libgit2/php-git>
* PowerShell
* GitPowerShell <https://github.com/ethomson/gitpowershell>
* Python
* pygit2 <https://github.com/libgit2/pygit2>
* R
* git2r <https://github.com/ropensci/git2r>
* Ruby
* Rugged <https://github.com/libgit2/rugged>
* Rust
* git2-rs <https://github.com/alexcrichton/git2-rs>
* Vala
* libgit2.vapi <https://github.com/apmasell/vapis/blob/master/libgit2.vapi>

View File

@ -0,0 +1,324 @@
# - Try to find GSSAPI
# Once done this will define
#
# KRB5_CONFIG - Path to krb5-config
# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
#
# Read-Only variables:
# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found
# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found
# GSSAPI_FOUND - system has GSSAPI
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
# GSSAPI_LIBRARIES - Link these to use GSSAPI
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
#
#=============================================================================
# Copyright (c) 2013 Andreas Schneider <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.
#=============================================================================
#
find_path(GSSAPI_ROOT_DIR
NAMES
include/gssapi.h
include/gssapi/gssapi.h
HINTS
${_GSSAPI_ROOT_HINTS}
PATHS
${_GSSAPI_ROOT_PATHS}
)
mark_as_advanced(GSSAPI_ROOT_DIR)
if (UNIX)
find_program(KRB5_CONFIG
NAMES
krb5-config
PATHS
${GSSAPI_ROOT_DIR}/bin
/opt/local/bin)
mark_as_advanced(KRB5_CONFIG)
if (KRB5_CONFIG)
# Check if we have MIT KRB5
execute_process(
COMMAND
${KRB5_CONFIG} --vendor
RESULT_VARIABLE
_GSSAPI_VENDOR_RESULT
OUTPUT_VARIABLE
_GSSAPI_VENDOR_STRING)
if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
set(GSSAPI_FLAVOR_MIT TRUE)
else()
execute_process(
COMMAND
${KRB5_CONFIG} --libs gssapi
RESULT_VARIABLE
_GSSAPI_LIBS_RESULT
OUTPUT_VARIABLE
_GSSAPI_LIBS_STRING)
if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
endif()
endif()
# Get the include dir
execute_process(
COMMAND
${KRB5_CONFIG} --cflags gssapi
RESULT_VARIABLE
_GSSAPI_INCLUDE_RESULT
OUTPUT_VARIABLE
_GSSAPI_INCLUDE_STRING)
string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
endif()
if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
# Check for HEIMDAL
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_GSSAPI heimdal-gssapi)
endif (PKG_CONFIG_FOUND)
if (_GSSAPI_FOUND)
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
else()
find_path(_GSSAPI_ROKEN
NAMES
roken.h
PATHS
${GSSAPI_ROOT_DIR}/include
${_GSSAPI_INCLUDEDIR})
if (_GSSAPI_ROKEN)
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
endif()
endif ()
endif()
endif (UNIX)
find_path(GSSAPI_INCLUDE_DIR
NAMES
gssapi.h
gssapi/gssapi.h
PATHS
${GSSAPI_ROOT_DIR}/include
${_GSSAPI_INCLUDEDIR}
)
if (GSSAPI_FLAVOR_MIT)
find_library(GSSAPI_LIBRARY
NAMES
gssapi_krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(KRB5_LIBRARY
NAMES
krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(K5CRYPTO_LIBRARY
NAMES
k5crypto
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(COM_ERR_LIBRARY
NAMES
com_err
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
if (GSSAPI_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${GSSAPI_LIBRARY}
)
endif (GSSAPI_LIBRARY)
if (KRB5_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${KRB5_LIBRARY}
)
endif (KRB5_LIBRARY)
if (K5CRYPTO_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${K5CRYPTO_LIBRARY}
)
endif (K5CRYPTO_LIBRARY)
if (COM_ERR_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${COM_ERR_LIBRARY}
)
endif (COM_ERR_LIBRARY)
endif (GSSAPI_FLAVOR_MIT)
if (GSSAPI_FLAVOR_HEIMDAL)
find_library(GSSAPI_LIBRARY
NAMES
gssapi
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(KRB5_LIBRARY
NAMES
krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HCRYPTO_LIBRARY
NAMES
hcrypto
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(COM_ERR_LIBRARY
NAMES
com_err
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HEIMNTLM_LIBRARY
NAMES
heimntlm
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HX509_LIBRARY
NAMES
hx509
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(ASN1_LIBRARY
NAMES
asn1
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(WIND_LIBRARY
NAMES
wind
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(ROKEN_LIBRARY
NAMES
roken
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
if (GSSAPI_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${GSSAPI_LIBRARY}
)
endif (GSSAPI_LIBRARY)
if (KRB5_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${KRB5_LIBRARY}
)
endif (KRB5_LIBRARY)
if (HCRYPTO_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HCRYPTO_LIBRARY}
)
endif (HCRYPTO_LIBRARY)
if (COM_ERR_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${COM_ERR_LIBRARY}
)
endif (COM_ERR_LIBRARY)
if (HEIMNTLM_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HEIMNTLM_LIBRARY}
)
endif (HEIMNTLM_LIBRARY)
if (HX509_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HX509_LIBRARY}
)
endif (HX509_LIBRARY)
if (ASN1_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${ASN1_LIBRARY}
)
endif (ASN1_LIBRARY)
if (WIND_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${WIND_LIBRARY}
)
endif (WIND_LIBRARY)
if (ROKEN_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${WIND_LIBRARY}
)
endif (ROKEN_LIBRARY)
endif (GSSAPI_FLAVOR_HEIMDAL)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
set(GSSAPI_FOUND TRUE)
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)

View File

@ -40,6 +40,8 @@ typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef SIZE_T size_t;
typedef SSIZE_T ssize_t;
#elif defined(__sun) || defined(__sun__)
#include <sys/inttypes.h>
#else
#include <stdint.h>
#endif

68
deps/zlib/adler32.c vendored
View File

@ -1,5 +1,5 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2007 Mark Adler
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -9,9 +9,9 @@
#define local static
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
#define BASE 65521UL /* largest prime smaller than 65536 */
#define BASE 65521 /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
@ -21,39 +21,44 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
/* use NO_DIVIDE if your processor does not do division in hardware --
try it both ways to see which is faster */
#ifdef NO_DIVIDE
# define MOD(a) \
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
(thank you to John Reiser for pointing this out) */
# define CHOP(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
unsigned long tmp = a >> 16; \
a &= 0xffffUL; \
a += (tmp << 4) - tmp; \
} while (0)
# define MOD28(a) \
do { \
CHOP(a); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
# define MOD(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
CHOP(a); \
MOD28(a); \
} while (0)
# define MOD63(a) \
do { /* this assumes a is not negative */ \
z_off64_t tmp = a >> 32; \
a &= 0xffffffffL; \
a += (tmp << 8) - (tmp << 5) + tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
# define MOD28(a) a %= BASE
# define MOD63(a) a %= BASE
#endif
/* ========================================================================= */
@ -92,7 +97,7 @@ uLong ZEXPORT adler32(adler, buf, len)
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
MOD28(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
@ -137,8 +142,13 @@ local uLong adler32_combine_(adler1, adler2, len2)
unsigned long sum2;
unsigned rem;
/* for negative len, return invalid adler32 as a clue for debugging */
if (len2 < 0)
return 0xffffffffUL;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
MOD63(len2); /* assumes len2 >= 0 */
rem = (unsigned)len2;
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);

83
deps/zlib/crc32.c vendored
View File

@ -1,5 +1,5 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2006, 2010 Mark Adler
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
@ -17,6 +17,8 @@
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
*/
#ifdef MAKECRCH
@ -30,31 +32,11 @@
#define local static
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
#ifndef NOBYFOUR
# ifdef STDC /* need ANSI C limits.h to determine sizes */
# include <limits.h>
# define BYFOUR
# if (UINT_MAX == 0xffffffffUL)
typedef unsigned int u4;
# else
# if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long u4;
# else
# if (USHRT_MAX == 0xffffffffUL)
typedef unsigned short u4;
# else
# undef BYFOUR /* can't find a four-byte integer type! */
# endif
# endif
# endif
# endif /* STDC */
#endif /* !NOBYFOUR */
/* Definitions for doing the crc four data bytes at a time. */
#if !defined(NOBYFOUR) && defined(Z_U4)
# define BYFOUR
#endif
#ifdef BYFOUR
# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
local unsigned long crc32_big OF((unsigned long,
@ -68,16 +50,16 @@
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256];
local z_crc_t FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *));
local void write_table OF((FILE *, const z_crc_t FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
@ -107,9 +89,9 @@ local void make_crc_table OF((void));
*/
local void make_crc_table()
{
unsigned long c;
z_crc_t c;
int n, k;
unsigned long poly; /* polynomial exclusive-or pattern */
z_crc_t poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
@ -121,13 +103,13 @@ local void make_crc_table()
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL;
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
poly |= 1UL << (31 - p[n]);
poly = 0;
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
poly |= (z_crc_t)1 << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (unsigned long)n;
c = (z_crc_t)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
@ -138,11 +120,11 @@ local void make_crc_table()
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = REV(c);
crc_table[4][n] = ZSWAP32(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = REV(c);
crc_table[k + 4][n] = ZSWAP32(c);
}
}
#endif /* BYFOUR */
@ -164,7 +146,7 @@ local void make_crc_table()
if (out == NULL) return;
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const unsigned long FAR ");
fprintf(out, "local const z_crc_t FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
# ifdef BYFOUR
@ -184,12 +166,13 @@ local void make_crc_table()
#ifdef MAKECRCH
local void write_table(out, table)
FILE *out;
const unsigned long FAR *table;
const z_crc_t FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
(unsigned long)(table[n]),
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
@ -204,13 +187,13 @@ local void write_table(out, table)
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const unsigned long FAR * ZEXPORT get_crc_table()
const z_crc_t FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const unsigned long FAR *)crc_table;
return (const z_crc_t FAR *)crc_table;
}
/* ========================================================================= */
@ -232,7 +215,7 @@ unsigned long ZEXPORT crc32(crc, buf, len)
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
u4 endian;
z_crc_t endian;
endian = 1;
if (*((unsigned char *)(&endian)))
@ -266,17 +249,17 @@ local unsigned long crc32_little(crc, buf, len)
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = (u4)crc;
c = (z_crc_t)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
@ -306,17 +289,17 @@ local unsigned long crc32_big(crc, buf, len)
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = REV((u4)crc);
c = ZSWAP32((z_crc_t)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
@ -333,7 +316,7 @@ local unsigned long crc32_big(crc, buf, len)
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(REV(c));
return (unsigned long)(ZSWAP32(c));
}
#endif /* BYFOUR */

2
deps/zlib/crc32.h vendored
View File

@ -2,7 +2,7 @@
* Generated automatically by crc32.c
*/
local const unsigned long FAR crc_table[TBLS][256] =
local const z_crc_t FAR crc_table[TBLS][256] =
{
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,

261
deps/zlib/deflate.c vendored
View File

@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -37,7 +37,7 @@
* REFERENCES
*
* Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
* Available in http://www.ietf.org/rfc/rfc1951.txt
* Available in http://tools.ietf.org/html/rfc1951
*
* A description of the Rabin and Karp algorithm is given in the book
* "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
" deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
" deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -155,6 +155,9 @@ local const config configuration_table[10] = {
struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
#endif
/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0))
/* ===========================================================================
* Update a hash value with the given input byte
* IN assertion: all calls to to UPDATE_HASH are made with consecutive
@ -235,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
strm->msg = Z_NULL;
if (strm->zalloc == (alloc_func)0) {
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
#endif
}
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
if (strm->zfree == (free_func)0)
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zfree = zcfree;
#endif
#ifdef FASTEST
if (level != 0) level = 1;
@ -293,7 +305,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
s->pending_buf == Z_NULL) {
s->status = FINISH_STATE;
strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
strm->msg = ERR_MSG(Z_MEM_ERROR);
deflateEnd (strm);
return Z_MEM_ERROR;
}
@ -314,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
uInt dictLength;
{
deflate_state *s;
uInt length = dictLength;
uInt n;
IPos hash_head = 0;
uInt str, n;
int wrap;
unsigned avail;
z_const unsigned char *next;
if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
strm->state->wrap == 2 ||
(strm->state->wrap == 1 && strm->state->status != INIT_STATE))
if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
return Z_STREAM_ERROR;
s = strm->state;
wrap = s->wrap;
if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
return Z_STREAM_ERROR;
s = strm->state;
if (s->wrap)
/* when using zlib wrappers, compute Adler-32 for provided dictionary */
if (wrap == 1)
strm->adler = adler32(strm->adler, dictionary, dictLength);
s->wrap = 0; /* avoid computing Adler-32 in read_buf */
if (length < MIN_MATCH) return Z_OK;
if (length > s->w_size) {
length = s->w_size;
dictionary += dictLength - length; /* use the tail of the dictionary */
/* if dictionary would fill window, just replace the history */
if (dictLength >= s->w_size) {
if (wrap == 0) { /* already empty otherwise */
CLEAR_HASH(s);
s->strstart = 0;
s->block_start = 0L;
s->insert = 0;
}
dictionary += dictLength - s->w_size; /* use the tail */
dictLength = s->w_size;
}
zmemcpy(s->window, dictionary, length);
s->strstart = length;
s->block_start = (long)length;
/* Insert all strings in the hash table (except for the last two bytes).
* s->lookahead stays null, so s->ins_h will be recomputed at the next
* call of fill_window.
*/
s->ins_h = s->window[0];
UPDATE_HASH(s, s->ins_h, s->window[1]);
for (n = 0; n <= length - MIN_MATCH; n++) {
INSERT_STRING(s, n, hash_head);
/* insert dictionary into window and hash */
avail = strm->avail_in;
next = strm->next_in;
strm->avail_in = dictLength;
strm->next_in = (z_const Bytef *)dictionary;
fill_window(s);
while (s->lookahead >= MIN_MATCH) {
str = s->strstart;
n = s->lookahead - (MIN_MATCH-1);
do {
UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
#ifndef FASTEST
s->prev[str & s->w_mask] = s->head[s->ins_h];
#endif
s->head[s->ins_h] = (Pos)str;
str++;
} while (--n);
s->strstart = str;
s->lookahead = MIN_MATCH-1;
fill_window(s);
}
if (hash_head) hash_head = 0; /* to make compiler happy */
s->strstart += s->lookahead;
s->block_start = (long)s->strstart;
s->insert = s->lookahead;
s->lookahead = 0;
s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0;
strm->next_in = next;
strm->avail_in = avail;
s->wrap = wrap;
return Z_OK;
}
/* ========================================================================= */
int ZEXPORT deflateReset (strm)
int ZEXPORT deflateResetKeep (strm)
z_streamp strm;
{
deflate_state *s;
@ -380,11 +419,22 @@ int ZEXPORT deflateReset (strm)
s->last_flush = Z_NO_FLUSH;
_tr_init(s);
lm_init(s);
return Z_OK;
}
/* ========================================================================= */
int ZEXPORT deflateReset (strm)
z_streamp strm;
{
int ret;
ret = deflateResetKeep(strm);
if (ret == Z_OK)
lm_init(strm->state);
return ret;
}
/* ========================================================================= */
int ZEXPORT deflateSetHeader (strm, head)
z_streamp strm;
@ -396,15 +446,43 @@ int ZEXPORT deflateSetHeader (strm, head)
return Z_OK;
}
/* ========================================================================= */
int ZEXPORT deflatePending (strm, pending, bits)
unsigned *pending;
int *bits;
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
if (pending != Z_NULL)
*pending = strm->state->pending;
if (bits != Z_NULL)
*bits = strm->state->bi_valid;
return Z_OK;
}
/* ========================================================================= */
int ZEXPORT deflatePrime (strm, bits, value)
z_streamp strm;
int bits;
int value;
{
deflate_state *s;
int put;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
strm->state->bi_valid = bits;
strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
s = strm->state;
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
do {
put = Buf_size - s->bi_valid;
if (put > bits)
put = bits;
s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
s->bi_valid += put;
_tr_flush_bits(s);
value >>= put;
bits -= put;
} while (bits);
return Z_OK;
}
@ -435,6 +513,8 @@ int ZEXPORT deflateParams(strm, level, strategy)
strm->total_in != 0) {
/* Flush the last buffer: */
err = deflate(strm, Z_BLOCK);
if (err == Z_BUF_ERROR && s->pending == 0)
err = Z_OK;
}
if (s->level != level) {
s->level = level;
@ -562,19 +642,22 @@ local void putShortMSB (s, b)
local void flush_pending(strm)
z_streamp strm;
{
unsigned len = strm->state->pending;
unsigned len;
deflate_state *s = strm->state;
_tr_flush_bits(s);
len = s->pending;
if (len > strm->avail_out) len = strm->avail_out;
if (len == 0) return;
zmemcpy(strm->next_out, strm->state->pending_out, len);
zmemcpy(strm->next_out, s->pending_out, len);
strm->next_out += len;
strm->state->pending_out += len;
s->pending_out += len;
strm->total_out += len;
strm->avail_out -= len;
strm->state->pending -= len;
if (strm->state->pending == 0) {
strm->state->pending_out = strm->state->pending_buf;
s->pending -= len;
if (s->pending == 0) {
s->pending_out = s->pending_buf;
}
}
@ -801,7 +884,7 @@ int ZEXPORT deflate (strm, flush)
* flushes. For repeated and useless calls with Z_FINISH, we keep
* returning Z_STREAM_END instead of Z_BUF_ERROR.
*/
} else if (strm->avail_in == 0 && flush <= old_flush &&
} else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
flush != Z_FINISH) {
ERR_RETURN(strm, Z_BUF_ERROR);
}
@ -850,6 +933,7 @@ int ZEXPORT deflate (strm, flush)
if (s->lookahead == 0) {
s->strstart = 0;
s->block_start = 0L;
s->insert = 0;
}
}
}
@ -945,12 +1029,12 @@ int ZEXPORT deflateCopy (dest, source)
ss = source->state;
zmemcpy(dest, source, sizeof(z_stream));
zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
if (ds == Z_NULL) return Z_MEM_ERROR;
dest->state = (struct internal_state FAR *) ds;
zmemcpy(ds, ss, sizeof(deflate_state));
zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
ds->strm = dest;
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@ -966,8 +1050,8 @@ int ZEXPORT deflateCopy (dest, source)
}
/* following zmemcpy do not work for 16-bit MSDOS */
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
@ -1001,15 +1085,15 @@ local int read_buf(strm, buf, size)
strm->avail_in -= len;
zmemcpy(buf, strm->next_in, len);
if (strm->state->wrap == 1) {
strm->adler = adler32(strm->adler, strm->next_in, len);
strm->adler = adler32(strm->adler, buf, len);
}
#ifdef GZIP
else if (strm->state->wrap == 2) {
strm->adler = crc32(strm->adler, strm->next_in, len);
strm->adler = crc32(strm->adler, buf, len);
}
#endif
zmemcpy(buf, strm->next_in, len);
strm->next_in += len;
strm->total_in += len;
@ -1036,6 +1120,7 @@ local void lm_init (s)
s->strstart = 0;
s->block_start = 0L;
s->lookahead = 0;
s->insert = 0;
s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0;
s->ins_h = 0;
@ -1310,6 +1395,8 @@ local void fill_window(s)
unsigned more; /* Amount of free space at the end of the window. */
uInt wsize = s->w_size;
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
do {
more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
@ -1362,7 +1449,7 @@ local void fill_window(s)
#endif
more += wsize;
}
if (s->strm->avail_in == 0) return;
if (s->strm->avail_in == 0) break;
/* If there was no sliding:
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
@ -1381,12 +1468,24 @@ local void fill_window(s)
s->lookahead += n;
/* Initialize the hash value now that we have some input: */
if (s->lookahead >= MIN_MATCH) {
s->ins_h = s->window[s->strstart];
UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
if (s->lookahead + s->insert >= MIN_MATCH) {
uInt str = s->strstart - s->insert;
s->ins_h = s->window[str];
UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
#if MIN_MATCH != 3
Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
while (s->insert) {
UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
#ifndef FASTEST
s->prev[str & s->w_mask] = s->head[s->ins_h];
#endif
s->head[s->ins_h] = (Pos)str;
str++;
s->insert--;
if (s->lookahead + s->insert < MIN_MATCH)
break;
}
}
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
* but this is not important since only literal bytes will be emitted.
@ -1427,6 +1526,9 @@ local void fill_window(s)
s->high_water += init;
}
}
Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
"not enough room for search");
}
/* ===========================================================================
@ -1506,8 +1608,14 @@ local block_state deflate_stored(s, flush)
FLUSH_BLOCK(s, 0);
}
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
s->insert = 0;
if (flush == Z_FINISH) {
FLUSH_BLOCK(s, 1);
return finish_done;
}
if ((long)s->strstart > s->block_start)
FLUSH_BLOCK(s, 0);
return block_done;
}
/* ===========================================================================
@ -1603,8 +1711,14 @@ local block_state deflate_fast(s, flush)
}
if (bflush) FLUSH_BLOCK(s, 0);
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
if (flush == Z_FINISH) {
FLUSH_BLOCK(s, 1);
return finish_done;
}
if (s->last_lit)
FLUSH_BLOCK(s, 0);
return block_done;
}
#ifndef FASTEST
@ -1728,8 +1842,14 @@ local block_state deflate_slow(s, flush)
_tr_tally_lit(s, s->window[s->strstart-1], bflush);
s->match_available = 0;
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
if (flush == Z_FINISH) {
FLUSH_BLOCK(s, 1);
return finish_done;
}
if (s->last_lit)
FLUSH_BLOCK(s, 0);
return block_done;
}
#endif /* FASTEST */
@ -1749,11 +1869,11 @@ local block_state deflate_rle(s, flush)
for (;;) {
/* Make sure that we always have enough lookahead, except
* at the end of the input file. We need MAX_MATCH bytes
* for the longest encodable run.
* for the longest run, plus one for the unrolled loop.
*/
if (s->lookahead < MAX_MATCH) {
if (s->lookahead <= MAX_MATCH) {
fill_window(s);
if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
return need_more;
}
if (s->lookahead == 0) break; /* flush the current block */
@ -1776,6 +1896,7 @@ local block_state deflate_rle(s, flush)
if (s->match_length > s->lookahead)
s->match_length = s->lookahead;
}
Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
}
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
@ -1796,8 +1917,14 @@ local block_state deflate_rle(s, flush)
}
if (bflush) FLUSH_BLOCK(s, 0);
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
s->insert = 0;
if (flush == Z_FINISH) {
FLUSH_BLOCK(s, 1);
return finish_done;
}
if (s->last_lit)
FLUSH_BLOCK(s, 0);
return block_done;
}
/* ===========================================================================
@ -1829,6 +1956,12 @@ local block_state deflate_huff(s, flush)
s->strstart++;
if (bflush) FLUSH_BLOCK(s, 0);
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
s->insert = 0;
if (flush == Z_FINISH) {
FLUSH_BLOCK(s, 1);
return finish_done;
}
if (s->last_lit)
FLUSH_BLOCK(s, 0);
return block_done;
}

12
deps/zlib/deflate.h vendored
View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2010 Jean-loup Gailly
* Copyright (C) 1995-2012 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -48,6 +48,9 @@
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define Buf_size 16
/* size of bit buffer in bi_buf */
#define INIT_STATE 42
#define EXTRA_STATE 69
#define NAME_STATE 73
@ -101,7 +104,7 @@ typedef struct internal_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
gz_headerp gzhead; /* gzip header information to write */
uInt gzindex; /* where in extra, name, or comment */
Byte method; /* STORED (for zip only) or DEFLATED */
Byte method; /* can only be DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
@ -188,7 +191,7 @@ typedef struct internal_state {
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to supress compiler warning */
/* Didn't use ct_data typedef below to suppress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
@ -244,7 +247,7 @@ typedef struct internal_state {
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
uInt insert; /* bytes at end of window left to insert */
#ifdef DEBUG
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
@ -294,6 +297,7 @@ void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
ulg stored_len, int last));
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
ulg stored_len, int last));

640
deps/zlib/infback.c vendored Normal file
View File

@ -0,0 +1,640 @@
/* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/*
This code is largely copied from inflate.c. Normally either infback.o or
inflate.o would be linked into an application--not both. The interface
with inffast.c is retained so that optimized assembler-coded versions of
inflate_fast() can be used with either inflate.c or infback.c.
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.
windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
int stream_size;
{
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (int)(sizeof(z_stream)))
return Z_VERSION_ERROR;
if (strm == Z_NULL || window == Z_NULL ||
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
#endif
}
if (strm->zfree == (free_func)0)
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zfree = zcfree;
#endif
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
state->wnext = 0;
state->whave = 0;
return Z_OK;
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
static int virgin = 1;
static code *lenfix, *distfix;
static code fixed[544];
/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
unsigned sym, bits;
static code *next;
/* literal/length table */
sym = 0;
while (sym < 144) state->lens[sym++] = 8;
while (sym < 256) state->lens[sym++] = 9;
while (sym < 280) state->lens[sym++] = 7;
while (sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
/* distance table */
sym = 0;
while (sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
/* do this just once */
virgin = 0;
}
#else /* !BUILDFIXED */
# include "inffixed.h"
#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}
/* Macros for inflateBack(): */
/* Load returned state from inflate_fast() */
#define LOAD() \
do { \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
} while (0)
/* Set state from registers for inflate_fast() */
#define RESTORE() \
do { \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
} while (0)
/* Clear the input bit accumulator */
#define INITBITS() \
do { \
hold = 0; \
bits = 0; \
} while (0)
/* Assure that some input is available. If input is requested, but denied,
then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
do { \
if (have == 0) { \
have = in(in_desc, &next); \
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/* Get a byte of input into the bit accumulator, or return from inflateBack()
with an error if there is no input available. */
#define PULLBYTE() \
do { \
PULL(); \
have--; \
hold += (unsigned long)(*next++) << bits; \
bits += 8; \
} while (0)
/* Assure that there are at least n bits in the bit accumulator. If there is
not enough available input to do that, then return from inflateBack() with
an error. */
#define NEEDBITS(n) \
do { \
while (bits < (unsigned)(n)) \
PULLBYTE(); \
} while (0)
/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))
/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
do { \
hold >>= (n); \
bits -= (unsigned)(n); \
} while (0)
/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
do { \
hold >>= bits & 7; \
bits -= bits & 7; \
} while (0)
/* Assure that some output space is available, by writing out the window
if it's full. If the write fails, return from inflateBack() with a
Z_BUF_ERROR. */
#define ROOM() \
do { \
if (left == 0) { \
put = state->window; \
left = state->wsize; \
state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/*
strm provides the memory allocation functions and window buffer on input,
and provides information on the unused input on return. For Z_DATA_ERROR
returns, strm will also provide an error message.
in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.
in() and out() are called with a descriptor parameter provided in the
inflateBack() call. This parameter can be a structure that provides the
information required to do the read or write, as well as accumulated
information on the input and output such as totals and check values.
in() should return zero on failure. out() should return non-zero on
failure. If either in() or out() fails, than inflateBack() returns a
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
was in() or out() that caused in the error. Otherwise, inflateBack()
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
error, or Z_MEM_ERROR if it could not allocate memory for the state.
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */
code here; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
static const unsigned short order[19] = /* permutation of code lengths */
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/* Check that the strm exists and that the state was initialized */
if (strm == Z_NULL || strm->state == Z_NULL)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
/* Reset the state */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
bits = 0;
put = state->window;
left = state->wsize;
/* Inflate until end of block marked as last */
for (;;)
switch (state->mode) {
case TYPE:
/* determine and dispatch block type */
if (state->last) {
BYTEBITS();
state->mode = DONE;
break;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch (BITS(2)) {
case 0: /* stored block */
Tracev((stderr, "inflate: stored block%s\n",
state->last ? " (last)" : ""));
state->mode = STORED;
break;
case 1: /* fixed block */
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
case 3:
strm->msg = (char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
break;
case STORED:
/* get and verify stored block length */
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();
/* copy stored block from input to output */
while (state->length != 0) {
copy = state->length;
PULL();
ROOM();
if (copy > have) copy = have;
if (copy > left) copy = left;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
}
Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;
case TABLE:
/* get dynamic table entries descriptor */
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));
/* get code length code lengths (not a typo) */
state->have = 0;
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
/* get length and distance code code lengths */
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if (here.val < 16) {
DROPBITS(here.bits);
state->lens[state->have++] = here.val;
}
else {
if (here.val == 16) {
NEEDBITS(here.bits + 2);
DROPBITS(here.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = (unsigned)(state->lens[state->have - 1]);
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (here.val == 17) {
NEEDBITS(here.bits + 3);
DROPBITS(here.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(here.bits + 7);
DROPBITS(here.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}
/* handle error breaks in while */
if (state->mode == BAD) break;
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
if (state->whave < state->wsize)
state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
}
/* get a literal, length, or end-of-block code */
for (;;) {
here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if (here.op && (here.op & 0xf0) == 0) {
last = here;
for (;;) {
here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(here.bits);
state->length = (unsigned)here.val;
/* process literal */
if (here.op == 0) {
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", here.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
}
/* process end of block */
if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
/* invalid code */
if (here.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
/* length code -- get extra bits, if any */
state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));
/* get distance code */
for (;;) {
here = state->distcode[BITS(state->distbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if ((here.op & 0xf0) == 0) {
last = here;
for (;;) {
here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(here.bits);
if (here.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)here.val;
/* get distance extra bits, if any */
state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));
/* copy match from window to output */
do {
ROOM();
copy = state->wsize - state->offset;
if (copy < left) {
from = put + copy;
copy = left - copy;
}
else {
from = put - state->offset;
copy = left;
}
if (copy > state->length) copy = state->length;
state->length -= copy;
left -= copy;
do {
*put++ = *from++;
} while (--copy);
} while (state->length != 0);
break;
case DONE:
/* inflate stream terminated properly -- write leftover output */
ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
/* Return unused input */
inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}
int ZEXPORT inflateBackEnd(strm)
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}

6
deps/zlib/inffast.c vendored
View File

@ -1,5 +1,5 @@
/* inffast.c -- fast decoding
* Copyright (C) 1995-2008, 2010 Mark Adler
* Copyright (C) 1995-2008, 2010, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -69,8 +69,8 @@ z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
unsigned char FAR *in; /* local strm->next_in */
unsigned char FAR *last; /* while in < last, enough input available */
z_const unsigned char FAR *in; /* local strm->next_in */
z_const unsigned char FAR *last; /* have enough input while in < last */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */

View File

@ -2,9 +2,9 @@
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications. It
is part of the implementation of the compression library and
is subject to change. Applications should only use zlib.h.
/* WARNING: this file should *not* be used by applications.
It is part of the implementation of this library and is
subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {

136
deps/zlib/inflate.c vendored
View File

@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
* Copyright (C) 1995-2010 Mark Adler
* Copyright (C) 1995-2012 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -93,14 +93,15 @@
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
local int updatewindow OF((z_streamp strm, unsigned out));
local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
unsigned copy));
#ifdef BUILDFIXED
void makefixed OF((void));
#endif
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
unsigned len));
int ZEXPORT inflateReset(strm)
int ZEXPORT inflateResetKeep(strm)
z_streamp strm;
{
struct inflate_state FAR *state;
@ -109,15 +110,13 @@ z_streamp strm;
state = (struct inflate_state FAR *)strm->state;
strm->total_in = strm->total_out = state->total = 0;
strm->msg = Z_NULL;
strm->adler = 1; /* to support ill-conceived Java test suite */
if (state->wrap) /* to support ill-conceived Java test suite */
strm->adler = state->wrap & 1;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
state->dmax = 32768U;
state->head = Z_NULL;
state->wsize = 0;
state->whave = 0;
state->wnext = 0;
state->hold = 0;
state->bits = 0;
state->lencode = state->distcode = state->next = state->codes;
@ -127,6 +126,19 @@ z_streamp strm;
return Z_OK;
}
int ZEXPORT inflateReset(strm)
z_streamp strm;
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
state->wsize = 0;
state->whave = 0;
state->wnext = 0;
return inflateResetKeep(strm);
}
int ZEXPORT inflateReset2(strm, windowBits)
z_streamp strm;
int windowBits;
@ -180,10 +192,19 @@ int stream_size;
if (strm == Z_NULL) return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
#endif
}
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
if (strm->zfree == (free_func)0)
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zfree = zcfree;
#endif
state = (struct inflate_state FAR *)
ZALLOC(strm, 1, sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
@ -321,8 +342,8 @@ void makefixed()
low = 0;
for (;;) {
if ((low % 7) == 0) printf("\n ");
printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
state.lencode[low].val);
printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
state.lencode[low].bits, state.lencode[low].val);
if (++low == size) break;
putchar(',');
}
@ -355,12 +376,13 @@ void makefixed()
output will fall in the output data, making match copies simpler and faster.
The advantage may be dependent on the size of the processor's data caches.
*/
local int updatewindow(strm, out)
local int updatewindow(strm, end, copy)
z_streamp strm;
unsigned out;
const Bytef *end;
unsigned copy;
{
struct inflate_state FAR *state;
unsigned copy, dist;
unsigned dist;
state = (struct inflate_state FAR *)strm->state;
@ -380,19 +402,18 @@ unsigned out;
}
/* copy state->wsize or less output bytes into the circular window */
copy = out - strm->avail_out;
if (copy >= state->wsize) {
zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
zmemcpy(state->window, end - state->wsize, state->wsize);
state->wnext = 0;
state->whave = state->wsize;
}
else {
dist = state->wsize - state->wnext;
if (dist > copy) dist = copy;
zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
zmemcpy(state->window + state->wnext, end - copy, dist);
copy -= dist;
if (copy) {
zmemcpy(state->window, strm->next_out - copy, copy);
zmemcpy(state->window, end - copy, copy);
state->wnext = copy;
state->whave = state->wsize;
}
@ -499,11 +520,6 @@ unsigned out;
bits -= bits & 7; \
} while (0)
/* Reverse the bytes in a 32-bit value */
#define REVERSE(q) \
((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
/*
inflate() uses a state machine to process as much input data and generate as
much output data as possible before returning. The state machine is
@ -591,7 +607,7 @@ z_streamp strm;
int flush;
{
struct inflate_state FAR *state;
unsigned char FAR *next; /* next input */
z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
@ -797,7 +813,7 @@ int flush;
#endif
case DICTID:
NEEDBITS(32);
strm->adler = state->check = REVERSE(hold);
strm->adler = state->check = ZSWAP32(hold);
INITBITS();
state->mode = DICT;
case DICT:
@ -905,7 +921,7 @@ int flush;
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lencode = (const code FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
@ -925,7 +941,6 @@ int flush;
PULLBYTE();
}
if (here.val < 16) {
NEEDBITS(here.bits);
DROPBITS(here.bits);
state->lens[state->have++] = here.val;
}
@ -980,7 +995,7 @@ int flush;
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lencode = (const code FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
@ -989,7 +1004,7 @@ int flush;
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distcode = (const code FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
@ -1170,7 +1185,7 @@ int flush;
#ifdef GUNZIP
state->flags ? hold :
#endif
REVERSE(hold)) != state->check) {
ZSWAP32(hold)) != state->check) {
strm->msg = (char *)"incorrect data check";
state->mode = BAD;
break;
@ -1214,8 +1229,9 @@ int flush;
*/
inf_leave:
RESTORE();
if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
if (updatewindow(strm, out)) {
if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
(state->mode < CHECK || flush != Z_FINISH)))
if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
state->mode = MEM;
return Z_MEM_ERROR;
}
@ -1249,13 +1265,37 @@ z_streamp strm;
return Z_OK;
}
int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
z_streamp strm;
Bytef *dictionary;
uInt *dictLength;
{
struct inflate_state FAR *state;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
/* copy dictionary */
if (state->whave && dictionary != Z_NULL) {
zmemcpy(dictionary, state->window + state->wnext,
state->whave - state->wnext);
zmemcpy(dictionary + state->whave - state->wnext,
state->window, state->wnext);
}
if (dictLength != Z_NULL)
*dictLength = state->whave;
return Z_OK;
}
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
z_streamp strm;
const Bytef *dictionary;
uInt dictLength;
{
struct inflate_state FAR *state;
unsigned long id;
unsigned long dictid;
int ret;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
@ -1263,29 +1303,21 @@ uInt dictLength;
if (state->wrap != 0 && state->mode != DICT)
return Z_STREAM_ERROR;
/* check for correct dictionary id */
/* check for correct dictionary identifier */
if (state->mode == DICT) {
id = adler32(0L, Z_NULL, 0);
id = adler32(id, dictionary, dictLength);
if (id != state->check)
dictid = adler32(0L, Z_NULL, 0);
dictid = adler32(dictid, dictionary, dictLength);
if (dictid != state->check)
return Z_DATA_ERROR;
}
/* copy dictionary to window */
if (updatewindow(strm, strm->avail_out)) {
/* copy dictionary to window using updatewindow(), which will amend the
existing dictionary if appropriate */
ret = updatewindow(strm, dictionary + dictLength, dictLength);
if (ret) {
state->mode = MEM;
return Z_MEM_ERROR;
}
if (dictLength > state->wsize) {
zmemcpy(state->window, dictionary + dictLength - state->wsize,
state->wsize);
state->whave = state->wsize;
}
else {
zmemcpy(state->window + state->wsize - dictLength, dictionary,
dictLength);
state->whave = dictLength;
}
state->havedict = 1;
Tracev((stderr, "inflate: dictionary set\n"));
return Z_OK;
@ -1321,7 +1353,7 @@ gz_headerp head;
*/
local unsigned syncsearch(have, buf, len)
unsigned FAR *have;
unsigned char FAR *buf;
const unsigned char FAR *buf;
unsigned len;
{
unsigned got;
@ -1433,8 +1465,8 @@ z_streamp source;
}
/* copy state */
zmemcpy(dest, source, sizeof(z_stream));
zmemcpy(copy, state, sizeof(struct inflate_state));
zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
if (state->lencode >= state->codes &&
state->lencode <= state->codes + ENOUGH - 1) {
copy->lencode = copy->codes + (state->lencode - state->codes);

54
deps/zlib/inftrees.c vendored
View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2010 Mark Adler
* Copyright (C) 1995-2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
" inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@ -208,8 +208,8 @@ unsigned short FAR *work;
mask = used - 1; /* mask for comparing low */
/* check available table space */
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
@ -277,8 +277,8 @@ unsigned short FAR *work;
/* check for enough space */
used += 1U << curr;
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */
@ -289,38 +289,14 @@ unsigned short FAR *work;
}
}
/*
Fill in rest of table for incomplete codes. This loop is similar to the
loop above in incrementing huff for table indices. It is assumed that
len is equal to curr + drop, so there is no loop needed to increment
through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there.
*/
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
while (huff != 0) {
/* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) {
drop = 0;
len = root;
next = *table;
here.bits = (unsigned char)len;
}
/* put invalid code marker in table */
next[huff >> drop] = here;
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* fill in remaining table entry if code is incomplete (guaranteed to have
at most one remaining entry, since if the code is incomplete, the
maximum code length that was allowed to get this far is one bit) */
if (huff != 0) {
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
next[huff] = here;
}
/* set return parameters */

54
deps/zlib/trees.c vendored
View File

@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2010 Jean-loup Gailly
* Copyright (C) 1995-2012 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -74,11 +74,6 @@ local const uch bl_order[BL_CODES]
* probability, to avoid transmitting the lengths for unused bit length codes.
*/
#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
/* ===========================================================================
* Local data. These are initialized only once.
*/
@ -151,8 +146,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
local int build_bl_tree OF((deflate_state *s));
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
int blcodes));
local void compress_block OF((deflate_state *s, ct_data *ltree,
ct_data *dtree));
local void compress_block OF((deflate_state *s, const ct_data *ltree,
const ct_data *dtree));
local int detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length));
local void bi_windup OF((deflate_state *s));
@ -399,7 +394,6 @@ void ZLIB_INTERNAL _tr_init(s)
s->bi_buf = 0;
s->bi_valid = 0;
s->last_eob_len = 8; /* enough lookahead for inflate */
#ifdef DEBUG
s->compressed_len = 0L;
s->bits_sent = 0L;
@ -882,16 +876,18 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
}
/* ===========================================================================
* Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
*/
void ZLIB_INTERNAL _tr_flush_bits(s)
deflate_state *s;
{
bi_flush(s);
}
/* ===========================================================================
* Send one empty static block to give enough lookahead for inflate.
* This takes 10 bits, of which 7 may remain in the bit buffer.
* The current inflate code requires 9 bits of lookahead. If the
* last two codes for the previous block (real code plus EOB) were coded
* on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
* the last real code. In this case we send two empty static blocks instead
* of one. (There are no problems if the previous block is stored or fixed.)
* To simplify the code, we assume the worst case of last real code encoded
* on one bit only.
*/
void ZLIB_INTERNAL _tr_align(s)
deflate_state *s;
@ -902,20 +898,6 @@ void ZLIB_INTERNAL _tr_align(s)
s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
#endif
bi_flush(s);
/* Of the 10 bits for the empty block, we have already sent
* (10 - bi_valid) bits. The lookahead for the last real code (before
* the EOB of the previous block) was thus at least one plus the length
* of the EOB plus what we have just sent of the empty static block.
*/
if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
send_bits(s, STATIC_TREES<<1, 3);
send_code(s, END_BLOCK, static_ltree);
#ifdef DEBUG
s->compressed_len += 10L;
#endif
bi_flush(s);
}
s->last_eob_len = 7;
}
/* ===========================================================================
@ -990,7 +972,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
send_bits(s, (STATIC_TREES<<1)+last, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
compress_block(s, (const ct_data *)static_ltree,
(const ct_data *)static_dtree);
#ifdef DEBUG
s->compressed_len += 3 + s->static_len;
#endif
@ -998,7 +981,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
send_bits(s, (DYN_TREES<<1)+last, 3);
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
max_blindex+1);
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
compress_block(s, (const ct_data *)s->dyn_ltree,
(const ct_data *)s->dyn_dtree);
#ifdef DEBUG
s->compressed_len += 3 + s->opt_len;
#endif
@ -1075,8 +1059,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
*/
local void compress_block(s, ltree, dtree)
deflate_state *s;
ct_data *ltree; /* literal tree */
ct_data *dtree; /* distance tree */
const ct_data *ltree; /* literal tree */
const ct_data *dtree; /* distance tree */
{
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
@ -1118,7 +1102,6 @@ local void compress_block(s, ltree, dtree)
} while (lx < s->last_lit);
send_code(s, END_BLOCK, ltree);
s->last_eob_len = ltree[END_BLOCK].Len;
}
/* ===========================================================================
@ -1226,7 +1209,6 @@ local void copy_block(s, buf, len, header)
int header; /* true if block header must be written */
{
bi_windup(s); /* align on byte boundary */
s->last_eob_len = 8; /* enough lookahead for inflate */
if (header) {
put_short(s, (ush)len);

4
deps/zlib/zconf.h vendored
View File

@ -14,6 +14,7 @@
* forms, we didn't write zlib */
#if defined(_MSC_VER)
# pragma warning( disable : 4131 )
# pragma warning( disable : 4142 ) /* benign redefinition of type */
#endif
/* Maximum value for memLevel in deflateInit2 */
@ -33,10 +34,12 @@
# define FAR
#endif
#define OF(args) args
#define Z_ARG(args) args
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
typedef unsigned long z_crc_t;
typedef Byte FAR Bytef;
typedef char FAR charf;
@ -50,5 +53,6 @@ typedef void *voidp;
#define z_off_t git_off_t
#define z_off64_t z_off_t
#define z_const const
#endif /* ZCONF_H */

343
deps/zlib/zlib.h vendored
View File

@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.5, April 19th, 2010
version 1.2.8, April 28th, 2013
Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -24,8 +24,8 @@
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
*/
#ifndef ZLIB_H
@ -37,11 +37,11 @@
extern "C" {
#endif
#define ZLIB_VERSION "1.2.5"
#define ZLIB_VERNUM 0x1250
#define ZLIB_VERSION "1.2.8"
#define ZLIB_VERNUM 0x1280
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 5
#define ZLIB_VER_REVISION 8
#define ZLIB_VER_SUBREVISION 0
/*
@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address));
struct internal_state;
typedef struct z_stream_s {
Bytef *next_in; /* next input byte */
z_const Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
uLong total_in; /* total number of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
uLong total_out; /* total number of bytes output so far */
char *msg; /* last error message, NULL if no error */
z_const char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
@ -327,8 +327,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
Z_FINISH can be used immediately after deflateInit if all the compression
is to be done in a single step. In this case, avail_out must be at least the
value returned by deflateBound (see below). If deflate does not return
Z_STREAM_END, then it must be called again as described above.
value returned by deflateBound (see below). Then deflate is guaranteed to
return Z_STREAM_END. If not enough output space is provided, deflate will
not return Z_STREAM_END, and it must be called again as described above.
deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes).
@ -451,23 +452,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
error. However if all decompression is to be performed in a single step (a
single call of inflate), the parameter flush should be set to Z_FINISH. In
this case all pending input is processed and all pending output is flushed;
avail_out must be large enough to hold all the uncompressed data. (The size
of the uncompressed data may have been saved by the compressor for this
purpose.) The next operation on this stream must be inflateEnd to deallocate
the decompression state. The use of Z_FINISH is never required, but can be
used to inform inflate that a faster approach may be used for the single
inflate() call.
avail_out must be large enough to hold all of the uncompressed data for the
operation to complete. (The size of the uncompressed data may have been
saved by the compressor for this purpose.) The use of Z_FINISH is not
required to perform an inflation in one step. However it may be used to
inform inflate that a faster approach can be used for the single inflate()
call. Z_FINISH also informs inflate to not maintain a sliding window if the
stream completes, which reduces inflate's memory footprint. If the stream
does not complete, either because not all of the stream is provided or not
enough output space is provided, then a sliding window will be allocated and
inflate() can be called again to continue the operation as if Z_NO_FLUSH had
been used.
In this implementation, inflate() always flushes as much output as
possible to the output buffer, and always uses the faster approach on the
first call. So the only effect of the flush parameter in this implementation
is on the return value of inflate(), as noted below, or when it returns early
because Z_BLOCK or Z_TREES is used.
first call. So the effects of the flush parameter in this implementation are
on the return value of inflate() as noted below, when inflate() returns early
when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
memory for a sliding window when Z_FINISH is used.
If a preset dictionary is needed after this call (see inflateSetDictionary
below), inflate sets strm->adler to the adler32 checksum of the dictionary
below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
strm->adler to the adler32 checksum of all output produced so far (that is,
strm->adler to the Adler-32 checksum of all output produced so far (that is,
total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
below. At the end of the stream, inflate() checks that its computed adler32
checksum is equal to that saved by the compressor and returns Z_STREAM_END
@ -478,7 +485,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
initializing with inflateInit2(). Any information contained in the gzip
header is not retained, so applications that need that information should
instead use raw inflate, see inflateInit2() below, or inflateBack() and
perform their own processing of the gzip header and trailer.
perform their own processing of the gzip header and trailer. When processing
gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
producted so far. The CRC-32 is checked against the gzip trailer.
inflate() returns Z_OK if some progress has been made (more input processed
or more output produced), Z_STREAM_END if the end of the compressed data has
@ -580,10 +589,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
uInt dictLength));
/*
Initializes the compression dictionary from the given byte sequence
without producing any compressed output. This function must be called
immediately after deflateInit, deflateInit2 or deflateReset, before any call
of deflate. The compressor and decompressor must use exactly the same
dictionary (see inflateSetDictionary).
without producing any compressed output. When using the zlib format, this
function must be called immediately after deflateInit, deflateInit2 or
deflateReset, and before any call of deflate. When doing raw deflate, this
function must be called either before any call of deflate, or immediately
after the completion of a deflate block, i.e. after all input has been
consumed and all output has been delivered when using any of the flush
options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
compressor and decompressor must use exactly the same dictionary (see
inflateSetDictionary).
The dictionary should consist of strings (byte sequences) that are likely
to be encountered later in the data to be compressed, with the most commonly
@ -610,8 +624,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent (for example if deflate has already been called for this stream
or if the compression method is bsort). deflateSetDictionary does not
perform any compression: this will be done by deflate().
or if not at a block boundary for raw deflate). deflateSetDictionary does
not perform any compression: this will be done by deflate().
*/
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
@ -688,9 +702,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
deflation of sourceLen bytes. It must be called after deflateInit() or
deflateInit2(), and after deflateSetHeader(), if used. This would be used
to allocate an output buffer for deflation in a single pass, and so would be
called before deflate().
called before deflate(). If that first deflate() call is provided the
sourceLen input bytes, an output buffer allocated to the size returned by
deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
to return Z_STREAM_END. Note that it is possible for the compressed size to
be larger than the value returned by deflateBound() if flush options other
than Z_FINISH or Z_NO_FLUSH are used.
*/
ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
unsigned *pending,
int *bits));
/*
deflatePending() returns the number of bytes and bits of output that have
been generated, but not yet provided in the available output. The bytes not
provided would be due to the available output space having being consumed.
The number of bits of output not provided are between 0 and 7, where they
await more bits to join them in order to fill out a full byte. If pending
or bits are Z_NULL, then those values are not set.
deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
int bits,
int value));
@ -703,8 +737,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
than or equal to 16, and that many of the least significant bits of value
will be inserted in the output.
deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
source stream state was inconsistent.
*/
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
@ -790,10 +825,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
can be determined from the adler32 value returned by that call of inflate.
The compressor and decompressor must use exactly the same dictionary (see
deflateSetDictionary). For raw inflate, this function can be called
immediately after inflateInit2() or inflateReset() and before any call of
inflate() to set the dictionary. The application must insure that the
dictionary that was used for compression is provided.
deflateSetDictionary). For raw inflate, this function can be called at any
time to set the dictionary. If the provided dictionary is smaller than the
window and there is already data in the window, then the provided dictionary
will amend what's there. The application must insure that the dictionary
that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
@ -803,19 +839,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
inflate().
*/
ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
Bytef *dictionary,
uInt *dictLength));
/*
Returns the sliding dictionary being maintained by inflate. dictLength is
set to the number of bytes in the dictionary, and that many bytes are copied
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If inflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
Similary, if dictLength is Z_NULL, then it is not set.
inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
stream state is inconsistent.
*/
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
/*
Skips invalid compressed data until a full flush point (see above the
description of deflate with Z_FULL_FLUSH) can be found, or until all
Skips invalid compressed data until a possible full flush point (see above
for the description of deflate with Z_FULL_FLUSH) can be found, or until all
available input is skipped. No output is provided.
inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
if no more input was provided, Z_DATA_ERROR if no flush point has been
found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the
success case, the application may save the current current value of total_in
which indicates where valid compressed data was found. In the error case,
the application may repeatedly call inflateSync, providing more input each
time, until success or end of the input data.
inflateSync searches for a 00 00 FF FF pattern in the compressed data.
All full flush points have this pattern, but not all occurrences of this
pattern are full flush points.
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
In the success case, the application may save the current current value of
total_in which indicates where valid compressed data was found. In the
error case, the application may repeatedly call inflateSync, providing more
input each time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
@ -962,12 +1017,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
See inflateBack() for the usage of these routines.
inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
the parameters are invalid, Z_MEM_ERROR if the internal state could not be
allocated, or Z_VERSION_ERROR if the version of the library does not match
the version of the header file.
*/
typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
typedef unsigned (*in_func) OF((void FAR *,
z_const unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
@ -975,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
out_func out, void FAR *out_desc));
/*
inflateBack() does a raw inflate with a single call using a call-back
interface for input and output. This is more efficient than inflate() for
file i/o applications in that it avoids copying between the output and the
sliding window by simply making the window itself the output buffer. This
function trusts the application to not change the output buffer passed by
the output function, at least until inflateBack() returns.
interface for input and output. This is potentially more efficient than
inflate() for file i/o applications, in that it avoids copying between the
output and the sliding window by simply making the window itself the output
buffer. inflate() can be faster on modern CPUs when used with large
buffers. inflateBack() trusts the application to not change the output
buffer passed by the output function, at least until inflateBack() returns.
inflateBackInit() must be called first to allocate the internal state
and to initialize the state with the user-provided window buffer.
@ -1088,6 +1145,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
27-31: 0 (reserved)
*/
#ifndef Z_SOLO
/* utility functions */
@ -1149,10 +1207,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
the case where there is not enough room, uncompress() will fill the output
buffer with the uncompressed data up to that point.
*/
/* gzip file access functions */
/*
@ -1162,7 +1221,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
wrapper, documented in RFC 1952, wrapped around a deflate stream.
*/
typedef voidp gzFile; /* opaque gzip file descriptor */
typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
@ -1172,13 +1231,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
for fixed code compression as in "wb9F". (See the description of
deflateInit2 for more information about the strategy parameter.) Also "a"
can be used instead of "w" to request that the gzip stream that will be
written be appended to the file. "+" will result in an error, since reading
and writing to the same gzip file is not supported.
deflateInit2 for more information about the strategy parameter.) 'T' will
request transparent writing or appending with no compression and not using
the gzip format.
"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
reading and writing to the same gzip file is not supported. The addition of
"x" when writing will create the file exclusively, which fails if the file
already exists. On systems that support it, the addition of "e" when
reading or writing will set the flag to close the file on an execve() call.
These functions, as well as gzip, will read and decode a sequence of gzip
streams in a file. The append function of gzopen() can be used to create
such a file. (Also see gzflush() for another way to do this.) When
appending, gzopen does not test whether the file begins with a gzip stream,
nor does it look for the end of the gzip streams to begin appending. gzopen
will simply append a gzip stream to the existing file.
gzopen can be used to read a file which is not in gzip format; in this
case gzread will directly read from the file without decompression.
case gzread will directly read from the file without decompression. When
reading, this will be detected automatically by looking for the magic two-
byte gzip header.
gzopen returns NULL if the file could not be opened, if there was
insufficient memory to allocate the gzFile state, or if an invalid mode was
@ -1197,7 +1271,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
mode);. The duplicated descriptor should be saved to avoid a leak, since
gzdopen does not close fd if it fails.
gzdopen does not close fd if it fails. If you are using fileno() to get the
file descriptor from a FILE *, then you will have to use dup() to avoid
double-close()ing the file descriptor. Both gzclose() and fclose() will
close the associated file descriptor, so they need to have different file
descriptors.
gzdopen returns NULL if there was insufficient memory to allocate the
gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
@ -1235,14 +1313,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
Reads the given number of uncompressed bytes from the compressed file. If
the input file was not in gzip format, gzread copies the given number of
bytes into the buffer.
the input file is not in gzip format, gzread copies the given number of
bytes into the buffer directly from the file.
After reaching the end of a gzip stream in the input, gzread will continue
to read, looking for another gzip stream, or failing that, reading the rest
of the input file directly without decompression. The entire input file
will be read if gzread is called until it returns less than the requested
len.
to read, looking for another gzip stream. Any number of gzip streams may be
concatenated in the input file, and will all be decompressed by gzread().
If something other than a gzip stream is encountered after a gzip stream,
that remaining trailing garbage is ignored (and no error is returned).
gzread can be used to read a gzip file that is being concurrently written.
Upon reaching the end of the input, gzread will return with the available
data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
gzclearerr can be used to clear the end of file indicator in order to permit
gzread to be tried again. Z_OK indicates that a gzip stream was completed
on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
middle of a gzip stream. Note that gzread does not return -1 in the event
of an incomplete gzip stream. This error is deferred until gzclose(), which
will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
stream. Alternatively, gzerror can be used before gzclose to detect this
case.
gzread returns the number of uncompressed bytes actually read, less than
len for end of file, or -1 for error.
@ -1256,7 +1346,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
error.
*/
ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
/*
Converts, formats, and writes the arguments to the compressed file under
control of the format string, as in fprintf. gzprintf returns the number of
@ -1301,7 +1391,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
Reads one byte from the compressed file. gzgetc returns this byte or -1
in case of end of file or error.
in case of end of file or error. This is implemented as a macro for speed.
As such, it does not do all of the checking the other functions do. I.e.
it does not check to see if file is NULL, nor whether the structure file
points to has been clobbered or not.
*/
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
@ -1397,9 +1490,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
Returns true (1) if file is being copied directly while reading, or false
(0) if file is a gzip stream being decompressed. This state can change from
false to true while reading the input file if the end of a gzip stream is
reached, but is followed by data that is not another gzip stream.
(0) if file is a gzip stream being decompressed.
If the input file is empty, gzdirect() will return true, since the input
does not contain a gzip stream.
@ -1408,6 +1499,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
cause buffers to be allocated to allow reading the file to determine if it
is a gzip file. Therefore if gzbuffer() is used, it should be called before
gzdirect().
When writing, gzdirect() returns true (1) if transparent writing was
requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
gzdirect() is not needed when writing. Transparent writing must be
explicitly requested, so the application already knows the answer. When
linking statically, using gzdirect() will include all of the zlib code for
gzip file reading and decompression, which may not be desired.)
*/
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
@ -1419,7 +1517,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file));
must not be called more than once on the same allocation.
gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
file operation error, or Z_OK on success.
file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
last read ended in the middle of a gzip stream, or Z_OK on success.
*/
ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
@ -1457,6 +1556,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
file that is being written concurrently.
*/
#endif /* !Z_SOLO */
/* checksum functions */
@ -1492,16 +1592,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
that the z_off_t type (like off_t) is a signed integer. If len2 is
negative, the result has no meaning or utility.
*/
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running CRC-32 with the bytes buf[0..len-1] and return the
updated CRC-32. If buf is Z_NULL, this function returns the required
initial value for the for the crc. Pre- and post-conditioning (one's
complement) is performed within this function so it shouldn't be done by the
application.
initial value for the crc. Pre- and post-conditioning (one's complement) is
performed within this function so it shouldn't be done by the application.
Usage example:
@ -1544,17 +1645,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
const char *version,
int stream_size));
#define deflateInit(strm, level) \
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
#define inflateInit(strm) \
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
(strategy), ZLIB_VERSION, sizeof(z_stream))
(strategy), ZLIB_VERSION, (int)sizeof(z_stream))
#define inflateInit2(strm, windowBits) \
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
(int)sizeof(z_stream))
#define inflateBackInit(strm, windowBits, window) \
inflateBackInit_((strm), (windowBits), (window), \
ZLIB_VERSION, sizeof(z_stream))
ZLIB_VERSION, (int)sizeof(z_stream))
#ifndef Z_SOLO
/* gzgetc() macro and its supporting function and exposed data structure. Note
* that the real internal state is much larger than the exposed structure.
* This abbreviated structure exposes just enough for the gzgetc() macro. The
* user should not mess with these exposed elements, since their names or
* behavior could change in the future, perhaps even capriciously. They can
* only be used by the gzgetc() macro. You have been warned.
*/
struct gzFile_s {
unsigned have;
unsigned char *next;
z_off64_t pos;
};
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
#ifdef Z_PREFIX_SET
# undef z_gzgetc
# define z_gzgetc(g) \
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
#else
# define gzgetc(g) \
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
#endif
/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
* change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
@ -1562,7 +1688,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
* functions are changed to 64 bits) -- in case these are set on systems
* without large file support, _LFS64_LARGEFILE must also be true
*/
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
#ifdef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
@ -1571,14 +1697,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
#endif
#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
# define gzopen gzopen64
# define gzseek gzseek64
# define gztell gztell64
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
# ifdef _LARGEFILE64_SOURCE
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
# ifdef Z_PREFIX_SET
# define z_gzopen z_gzopen64
# define z_gzseek z_gzseek64
# define z_gztell z_gztell64
# define z_gzoffset z_gzoffset64
# define z_adler32_combine z_adler32_combine64
# define z_crc32_combine z_crc32_combine64
# else
# define gzopen gzopen64
# define gzseek gzseek64
# define gztell gztell64
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
# endif
# ifndef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
@ -1595,6 +1730,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
#endif
#else /* Z_SOLO */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
#endif /* !Z_SOLO */
/* hack for buggy compilers */
#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
struct internal_state {int dummy;};
@ -1603,8 +1745,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
/* undocumented functions */
ZEXTERN const char * ZEXPORT zError OF((int));
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
#if defined(_WIN32) && !defined(Z_SOLO)
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
const char *mode));
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
const char *format,
va_list va));
# endif
#endif
#ifdef __cplusplus
}

23
deps/zlib/zutil.c vendored
View File

@ -1,5 +1,5 @@
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
* Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -11,7 +11,7 @@
struct internal_state {int dummy;}; /* for buggy compilers */
#endif
const char * const z_errmsg[10] = {
z_const char * const z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
"", /* Z_OK 0 */
@ -85,27 +85,27 @@ uLong ZEXPORT zlibCompileFlags()
#ifdef FASTEST
flags += 1L << 21;
#endif
#ifdef STDC
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifdef NO_vsnprintf
flags += 1L << 25;
flags += 1L << 25;
# ifdef HAS_vsprintf_void
flags += 1L << 26;
flags += 1L << 26;
# endif
# else
# ifdef HAS_vsnprintf_void
flags += 1L << 26;
flags += 1L << 26;
# endif
# endif
#else
flags += 1L << 24;
flags += 1L << 24;
# ifdef NO_snprintf
flags += 1L << 25;
flags += 1L << 25;
# ifdef HAS_sprintf_void
flags += 1L << 26;
flags += 1L << 26;
# endif
# else
# ifdef HAS_snprintf_void
flags += 1L << 26;
flags += 1L << 26;
# endif
# endif
#endif
@ -181,6 +181,7 @@ void ZLIB_INTERNAL zmemzero(dest, len)
}
#endif
#ifndef Z_SOLO
#ifdef SYS16BIT
@ -316,3 +317,5 @@ void ZLIB_INTERNAL zcfree (opaque, ptr)
}
#endif /* MY_ZCALLOC */
#endif /* !Z_SOLO */

103
deps/zlib/zutil.h vendored
View File

@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2010 Jean-loup Gailly.
* Copyright (C) 1995-2013 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -13,7 +13,7 @@
#ifndef ZUTIL_H
#define ZUTIL_H
#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
#ifdef HAVE_HIDDEN
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
@ -21,7 +21,7 @@
#include "zlib.h"
#ifdef STDC
#if defined(STDC) && !defined(Z_SOLO)
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
# include <stddef.h>
# endif
@ -29,6 +29,10 @@
# include <stdlib.h>
#endif
#ifdef Z_SOLO
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
#endif
#ifndef local
# define local static
#endif
@ -40,13 +44,13 @@ typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
@ -78,16 +82,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# ifndef Z_SOLO
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
#endif
@ -107,18 +113,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#ifdef OS2
# define OS_CODE 0x06
# ifdef M_I86
# if defined(M_I86) && !defined(Z_SOLO)
# include <malloc.h>
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef Z_SOLO
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
# endif
#endif
@ -153,14 +161,15 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif
#endif
#if defined(__BORLANDC__)
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008
#pragma warn -8066
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
#if !defined(_WIN32) && \
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
#endif
@ -177,42 +186,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* functions */
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(__CYGWIN__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#ifndef HAVE_VSNPRINTF
# ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
# ifdef __TURBOC__
# define NO_vsnprintf
# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
# define vsnprintf _vsnprintf
# endif
# endif
# endif
# ifdef __SASC
# define NO_vsnprintf
# endif
#endif
#ifdef VMS
# define NO_vsnprintf
#endif
#if defined(pyr)
#if defined(pyr) || defined(Z_SOLO)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
@ -261,14 +235,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define Tracecv(c,x)
#endif
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
unsigned size));
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
#ifndef Z_SOLO
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
unsigned size));
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
#endif
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
/* Reverse the bytes in a 32-bit value */
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
#endif /* ZUTIL_H */

1
examples/.gitignore vendored
View File

@ -9,4 +9,5 @@ log
rev-parse
status
tag
for-each-ref
*.dSYM

View File

@ -4,6 +4,7 @@ CC = gcc
CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers
LFLAGS = -L../build -lgit2 -lz
APPS = general showindex diff rev-list cat-file status log rev-parse init blame tag
APPS += for-each-ref
all: $(APPS)

46
examples/for-each-ref.c Normal file
View File

@ -0,0 +1,46 @@
#include <git2.h>
#include <stdio.h>
#include "common.h"
static int show_ref(git_reference *ref, void *data)
{
git_repository *repo = data;
git_reference *resolved = NULL;
char hex[GIT_OID_HEXSZ+1];
const git_oid *oid;
git_object *obj;
if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
check_lg2(git_reference_resolve(&resolved, ref),
"Unable to resolve symbolic reference",
git_reference_name(ref));
oid = git_reference_target(resolved ? resolved : ref);
git_oid_fmt(hex, oid);
hex[GIT_OID_HEXSZ] = 0;
check_lg2(git_object_lookup(&obj, repo, oid, GIT_OBJ_ANY),
"Unable to lookup object", hex);
printf("%s %-6s\t%s\n",
hex,
git_object_type2string(git_object_type(obj)),
git_reference_name(ref));
if (resolved)
git_reference_free(resolved);
return 0;
}
int main(int argc, char **argv)
{
git_repository *repo;
if (argc != 1 || argv[1] /* silence -Wunused-parameter */)
fatal("Sorry, no for-each-ref options supported yet", NULL);
check_lg2(git_repository_open(&repo, "."),
"Could not open repository", NULL);
check_lg2(git_reference_foreach(repo, show_ref, repo),
"Could not iterate over references", NULL);
return 0;
}

View File

@ -94,8 +94,8 @@ int main (int argc, char** argv)
// Next we will convert the 20 byte raw SHA1 value to a human readable 40
// char hex value.
printf("\n*Raw to Hex*\n");
char out[41];
out[40] = '\0';
char out[GIT_OID_HEXSZ+1];
out[GIT_OID_HEXSZ] = '\0';
// If you have a oid, you can easily get the hex value of the SHA as well.
git_oid_fmt(out, &oid);

View File

@ -54,8 +54,9 @@ struct log_options {
int min_parents, max_parents;
git_time_t before;
git_time_t after;
char *author;
char *committer;
const char *author;
const char *committer;
const char *grep;
};
/** utility functions that parse options and help with log output */
@ -65,6 +66,9 @@ static void print_time(const git_time *intime, const char *prefix);
static void print_commit(git_commit *commit);
static int match_with_parent(git_commit *commit, int i, git_diff_options *);
/** utility functions for filtering */
static int signature_matches(const git_signature *sig, const char *filter);
static int log_message_matches(const git_commit *commit, const char *filter);
int main(int argc, char *argv[])
{
@ -128,6 +132,15 @@ int main(int argc, char *argv[])
continue;
}
if (!signature_matches(git_commit_author(commit), opt.author))
continue;
if (!signature_matches(git_commit_committer(commit), opt.committer))
continue;
if (!log_message_matches(commit, opt.grep))
continue;
if (count++ < opt.skip)
continue;
if (opt.limit != -1 && printed++ >= opt.limit) {
@ -172,6 +185,32 @@ int main(int argc, char *argv[])
return 0;
}
/** Determine if the given git_signature does not contain the filter text. */
static int signature_matches(const git_signature *sig, const char *filter) {
if (filter == NULL)
return 1;
if (sig != NULL &&
(strstr(sig->name, filter) != NULL ||
strstr(sig->email, filter) != NULL))
return 1;
return 0;
}
static int log_message_matches(const git_commit *commit, const char *filter) {
const char *message = NULL;
if (filter == NULL)
return 1;
if ((message = git_commit_message(commit)) != NULL &&
strstr(message, filter) != NULL)
return 1;
return 0;
}
/** Push object (for hide or show) onto revwalker. */
static void push_rev(struct log_state *s, git_object *obj, int hide)
{
@ -401,6 +440,12 @@ static int parse_options(
set_sorting(s, GIT_SORT_TOPOLOGICAL);
else if (!strcmp(a, "--reverse"))
set_sorting(s, GIT_SORT_REVERSE);
else if (match_str_arg(&opt->author, &args, "--author"))
/** Found valid --author */;
else if (match_str_arg(&opt->committer, &args, "--committer"))
/** Found valid --committer */;
else if (match_str_arg(&opt->grep, &args, "--grep"))
/** Found valid --grep */;
else if (match_str_arg(&s->repodir, &args, "--git-dir"))
/** Found git-dir. */;
else if (match_int_arg(&opt->skip, &args, "--skip", 0))

View File

@ -155,7 +155,7 @@ int fetch(git_repository *repo, int argc, char **argv)
// Update the references in the remote's namespace to point to the
// right commits. This may be needed even if there was no packfile
// to download, which can happen e.g. when the branches have been
// changed but all the neede objects are available locally.
// changed but all the needed objects are available locally.
if (git_remote_update_tips(remote, NULL, NULL) < 0)
return -1;

View File

@ -22,7 +22,7 @@ int main (int argc, char **argv)
git_repository *repo;
git_revwalk *walk;
git_oid oid;
char buf[41];
char buf[GIT_OID_HEXSZ+1];
git_threads_init();
@ -32,7 +32,7 @@ int main (int argc, char **argv)
while (!git_revwalk_next(&oid, walk)) {
git_oid_fmt(buf, &oid);
buf[40] = '\0';
buf[GIT_OID_HEXSZ] = '\0';
printf("%s\n", buf);
}

View File

@ -20,8 +20,8 @@ int main (int argc, char** argv)
unsigned int i, ecount;
char *dir = ".";
size_t dirlen;
char out[41];
out[40] = '\0';
char out[GIT_OID_HEXSZ+1];
out[GIT_OID_HEXSZ] = '\0';
git_threads_init();

View File

@ -13,7 +13,12 @@
*/
#include "common.h"
#include <unistd.h>
#ifdef _WIN32
# include <Windows.h>
# define sleep(a) Sleep(a * 1000)
#else
# include <unistd.h>
#endif
/**
* This example demonstrates the use of the libgit2 status APIs,

View File

@ -236,7 +236,7 @@ static void action_create_tag(tag_state *state)
git_signature_free(tagger);
}
static void print_usage()
static void print_usage(void)
{
fprintf(stderr, "usage: see `git help tag`\n");
exit(1);

View File

@ -76,25 +76,28 @@ GIT_BEGIN_DECL
*/
#define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_T)
/**
* Possible states for an attribute
*/
typedef enum {
GIT_ATTR_UNSPECIFIED_T = 0,
GIT_ATTR_TRUE_T,
GIT_ATTR_FALSE_T,
GIT_ATTR_VALUE_T,
GIT_ATTR_UNSPECIFIED_T = 0, /**< The attribute has been left unspecified */
GIT_ATTR_TRUE_T, /**< The attribute has been set */
GIT_ATTR_FALSE_T, /**< The attribute has been unset */
GIT_ATTR_VALUE_T, /**< This attribute has a value */
} git_attr_t;
/*
* Return the value type for a given attribute.
/**
* Return the value type for a given attribute.
*
* This can be either `TRUE`, `FALSE`, `UNSPECIFIED` (if the attribute
* was not set at all), or `VALUE`, if the attribute was set to
* an actual string.
* This can be either `TRUE`, `FALSE`, `UNSPECIFIED` (if the attribute
* was not set at all), or `VALUE`, if the attribute was set to an
* actual string.
*
* If the attribute has a `VALUE` string, it can be accessed normally
* as a NULL-terminated C string.
* If the attribute has a `VALUE` string, it can be accessed normally
* as a NULL-terminated C string.
*
* @param attr The attribute
* @return the value type for the attribute
* @param attr The attribute
* @return the value type for the attribute
*/
GIT_EXTERN(git_attr_t) git_attr_value(const char *attr);

View File

@ -83,17 +83,16 @@ typedef struct git_blame_options {
#define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION}
/**
* Initializes a `git_blame_options` with default values. Equivalent to
* creating an instance with GIT_BLAME_OPTIONS_INIT.
*
* @param opts the `git_blame_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_BLAME_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
* Initializes a `git_blame_options` with default values. Equivalent to
* creating an instance with GIT_BLAME_OPTIONS_INIT.
*
* @param opts The `git_blame_options` struct to initialize
* @param version Version of struct; pass `GIT_BLAME_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_blame_init_options(
git_blame_options* opts,
int version);
git_blame_options *opts,
unsigned int version);
/**
* Structure that represents a blame hunk.

View File

@ -210,7 +210,7 @@ GIT_EXTERN(int) git_blob_create_frombuffer(
*
* The heuristic used to guess if a file is binary is taken from core git:
* Searching for NUL bytes and looking for a reasonable ratio of printable
* to non-printable characters among the first 4000 bytes.
* to non-printable characters among the first 8000 bytes.
*
* @param blob The blob which content should be analyzed
* @return 1 if the content of the blob is detected

View File

@ -105,6 +105,22 @@ GIT_EXTERN(int) git_buf_grow(git_buf *buffer, size_t target_size);
GIT_EXTERN(int) git_buf_set(
git_buf *buffer, const void *data, size_t datalen);
/**
* Check quickly if buffer looks like it contains binary data
*
* @param buf Buffer to check
* @return 1 if buffer looks like non-text data
*/
GIT_EXTERN(int) git_buf_is_binary(const git_buf *buf);
/**
* Check quickly if buffer contains a NUL byte
*
* @param buf Buffer to check
* @return 1 if buffer contains a NUL byte
*/
GIT_EXTERN(int) git_buf_contains_nul(const git_buf *buf);
GIT_END_DECL
/** @} */

View File

@ -43,17 +43,17 @@ GIT_BEGIN_DECL
* In between those are `GIT_CHECKOUT_SAFE` and `GIT_CHECKOUT_SAFE_CREATE`
* both of which only make modifications that will not lose changes.
*
* | target == baseline | target != baseline |
* ---------------------|-----------------------|----------------------|
* workdir == baseline | no action | create, update, or |
* | | delete file |
* ---------------------|-----------------------|----------------------|
* workdir exists and | no action | conflict (notify |
* is != baseline | notify dirty MODIFIED | and cancel checkout) |
* ---------------------|-----------------------|----------------------|
* workdir missing, | create if SAFE_CREATE | create file |
* baseline present | notify dirty DELETED | |
* ---------------------|-----------------------|----------------------|
* | target == baseline | target != baseline |
* ---------------------|-----------------------|----------------------|
* workdir == baseline | no action | create, update, or |
* | | delete file |
* ---------------------|-----------------------|----------------------|
* workdir exists and | no action | conflict (notify |
* is != baseline | notify dirty MODIFIED | and cancel checkout) |
* ---------------------|-----------------------|----------------------|
* workdir missing, | create if SAFE_CREATE | create file |
* baseline present | notify dirty DELETED | |
* ---------------------|-----------------------|----------------------|
*
* The only difference between SAFE and SAFE_CREATE is that SAFE_CREATE
* will cause a file to be checked out if it is missing from the working
@ -106,7 +106,7 @@ GIT_BEGIN_DECL
* target contains that file.
*/
typedef enum {
GIT_CHECKOUT_NONE = 0, /** default is a dry run, no actual updates */
GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */
/** Allow safe updates that cannot overwrite uncommitted data */
GIT_CHECKOUT_SAFE = (1u << 0),
@ -233,18 +233,18 @@ typedef void (*git_checkout_progress_cb)(
typedef struct git_checkout_options {
unsigned int version;
unsigned int checkout_strategy; /** default will be a dry run */
unsigned int checkout_strategy; /**< default will be a dry run */
int disable_filters; /** don't apply filters like CRLF conversion */
unsigned int dir_mode; /** default is 0755 */
unsigned int file_mode; /** default is 0644 or 0755 as dictated by blob */
int file_open_flags; /** default is O_CREAT | O_TRUNC | O_WRONLY */
int disable_filters; /**< don't apply filters like CRLF conversion */
unsigned int dir_mode; /**< default is 0755 */
unsigned int file_mode; /**< default is 0644 or 0755 as dictated by blob */
int file_open_flags; /**< default is O_CREAT | O_TRUNC | O_WRONLY */
unsigned int notify_flags; /** see `git_checkout_notify_t` above */
unsigned int notify_flags; /**< see `git_checkout_notify_t` above */
git_checkout_notify_cb notify_cb;
void *notify_payload;
/* Optional callback to notify the consumer of checkout progress. */
/** Optional callback to notify the consumer of checkout progress. */
git_checkout_progress_cb progress_cb;
void *progress_payload;
@ -254,13 +254,13 @@ typedef struct git_checkout_options {
*/
git_strarray paths;
git_tree *baseline; /** expected content of workdir, defaults to HEAD */
git_tree *baseline; /**< expected content of workdir, defaults to HEAD */
const char *target_directory; /** alternative checkout path to workdir */
const char *target_directory; /**< alternative checkout path to workdir */
const char *ancestor_label; /** the name of the common ancestor side of conflicts */
const char *our_label; /** the name of the "our" side of conflicts */
const char *their_label; /** the name of the "their" side of conflicts */
const char *ancestor_label; /**< the name of the common ancestor side of conflicts */
const char *our_label; /**< the name of the "our" side of conflicts */
const char *their_label; /**< the name of the "their" side of conflicts */
} git_checkout_options;
#define GIT_CHECKOUT_OPTIONS_VERSION 1
@ -270,14 +270,13 @@ typedef struct git_checkout_options {
* Initializes a `git_checkout_options` with default values. Equivalent to
* creating an instance with GIT_CHECKOUT_OPTIONS_INIT.
*
* @param opts the `git_checkout_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_CHECKOUT_OPTIONS_VERSION` here.
* @param opts the `git_checkout_options` struct to initialize.
* @param version Version of struct; pass `GIT_CHECKOUT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_checkout_init_opts(
git_checkout_options* opts,
int version);
GIT_EXTERN(int) git_checkout_init_options(
git_checkout_options *opts,
unsigned int version);
/**
* Updates files in the index and the working tree to match the content of

View File

@ -28,23 +28,22 @@ typedef struct {
git_merge_options merge_opts;
git_checkout_options checkout_opts;
} git_cherry_pick_options;
} git_cherrypick_options;
#define GIT_CHERRY_PICK_OPTIONS_VERSION 1
#define GIT_CHERRY_PICK_OPTIONS_INIT {GIT_CHERRY_PICK_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
#define GIT_CHERRYPICK_OPTIONS_VERSION 1
#define GIT_CHERRYPICK_OPTIONS_INIT {GIT_CHERRYPICK_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
/**
* Initializes a `git_cherry_pick_options` with default values. Equivalent to
* creating an instance with GIT_CHERRY_PICK_OPTIONS_INIT.
* Initializes a `git_cherrypick_options` with default values. Equivalent to
* creating an instance with GIT_CHERRYPICK_OPTIONS_INIT.
*
* @param opts the `git_cherry_pick_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_CHERRY_PICK_OPTIONS_VERSION` here.
* @param opts the `git_cherrypick_options` struct to initialize
* @param version Version of struct; pass `GIT_CHERRYPICK_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick_init_opts(
git_cherry_pick_options* opts,
int version);
GIT_EXTERN(int) git_cherrypick_init_options(
git_cherrypick_options *opts,
unsigned int version);
/**
* Cherry-picks the given commit against the given "our" commit, producing an
@ -54,16 +53,16 @@ GIT_EXTERN(int) git_cherry_pick_init_opts(
*
* @param out pointer to store the index result in
* @param repo the repository that contains the given commits
* @param cherry_pick_commit the commit to cherry-pick
* @param cherrypick_commit the commit to cherry-pick
* @param our_commit the commit to revert against (eg, HEAD)
* @param mainline the parent of the revert commit, if it is a merge
* @param merge_tree_opts the merge tree options (or null for defaults)
* @param merge_options the merge options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick_commit(
GIT_EXTERN(int) git_cherrypick_commit(
git_index **out,
git_repository *repo,
git_commit *cherry_pick_commit,
git_commit *cherrypick_commit,
git_commit *our_commit,
unsigned int mainline,
const git_merge_options *merge_options);
@ -73,13 +72,13 @@ GIT_EXTERN(int) git_cherry_pick_commit(
*
* @param repo the repository to cherry-pick
* @param commit the commit to cherry-pick
* @param cherry_pick_options the cherry-pick options (or null for defaults)
* @param cherrypick_options the cherry-pick options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick(
GIT_EXTERN(int) git_cherrypick(
git_repository *repo,
git_commit *commit,
const git_cherry_pick_options *cherry_pick_options);
const git_cherrypick_options *cherrypick_options);
/** @} */
GIT_END_DECL

View File

@ -12,6 +12,7 @@
#include "indexer.h"
#include "checkout.h"
#include "remote.h"
#include "transport.h"
/**
@ -23,67 +24,176 @@
*/
GIT_BEGIN_DECL
/**
* Options for bypassing the git-aware transport on clone. Bypassing
* it means that instead of a fetch, libgit2 will copy the object
* database directory instead of figuring out what it needs, which is
* faster. If possible, it will hardlink the files to save space.
*/
typedef enum {
/**
* Auto-detect (default), libgit2 will bypass the git-aware
* transport for local paths, but use a normal fetch for
* `file://` urls.
*/
GIT_CLONE_LOCAL_AUTO,
/**
* Bypass the git-aware transport even for a `file://` url.
*/
GIT_CLONE_LOCAL,
/**
* Do no bypass the git-aware transport
*/
GIT_CLONE_NO_LOCAL,
/**
* Bypass the git-aware transport, but do not try to use
* hardlinks.
*/
GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t;
/**
* The signature of a function matching git_remote_create, with an additional
* void* as a callback payload.
*
* Callers of git_clone may provide a function matching this signature to override
* the remote creation and customization process during a clone operation.
*
* @param out the resulting remote
* @param repo the repository in which to create the remote
* @param name the remote's name
* @param url the remote's url
* @param payload an opaque payload
* @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*/
typedef int (*git_remote_create_cb)(
git_remote **out,
git_repository *repo,
const char *name,
const char *url,
void *payload);
/**
* The signature of a function matchin git_repository_init, with an
* aditional void * as callback payload.
*
* Callers of git_clone my provide a function matching this signature
* to override the repository creation and customization process
* during a clone operation.
*
* @param out the resulting repository
* @param path path in which to create the repository
* @param bare whether the repository is bare. This is the value from the clone options
* @param payload payload specified by the options
* @return 0, or a negative value to indicate error
*/
typedef int (*git_repository_create_cb)(
git_repository **out,
const char *path,
int bare,
void *payload);
/**
* Clone options structure
*
* Use the GIT_CLONE_OPTIONS_INIT to get the default settings, like this:
*
* git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
*
* - `checkout_opts` are option passed to the checkout step. To disable
* checkout, set the `checkout_strategy` to GIT_CHECKOUT_NONE.
* Generally you will want the use GIT_CHECKOUT_SAFE_CREATE to create
* all files in the working directory for the newly cloned repository.
* - `bare` should be set to zero (false) to create a standard repo,
* or non-zero for a bare repo
* - `ignore_cert_errors` should be set to 1 if errors validating the
* remote host's certificate should be ignored.
*
* ** "origin" remote options: **
*
* - `remote_name` is the name to be given to the "origin" remote. The
* default is "origin".
* - `checkout_branch` gives the name of the branch to checkout. NULL
* means use the remote's HEAD.
* - `signature` is the identity used when updating the reflog. NULL means to
* use the default signature using the config.
*/
typedef struct git_clone_options {
unsigned int version;
/**
* These options are passed to the checkout step. To disable
* checkout, set the `checkout_strategy` to
* `GIT_CHECKOUT_NONE`. Generally you will want the use
* GIT_CHECKOUT_SAFE_CREATE to create all files in the working
* directory for the newly cloned repository.
*/
git_checkout_options checkout_opts;
/**
* Callbacks to use for reporting fetch progress, and for acquiring
* credentials in the event they are needed. This parameter is ignored if
* the remote_cb parameter is set; if you provide a remote creation
* callback, then you have the opportunity to configure remote callbacks in
* provided function.
*/
git_remote_callbacks remote_callbacks;
/**
* Set to zero (false) to create a standard repo, or non-zero
* for a bare repo
*/
int bare;
int ignore_cert_errors;
const char *remote_name;
/**
* Whether to use a fetch or copy the object database.
*/
git_clone_local_t local;
/**
* The name of the branch to checkout. NULL means use the
* remote's default branch.
*/
const char* checkout_branch;
/**
* The identity used when updating the reflog. NULL means to
* use the default signature using the config.
*/
git_signature *signature;
/**
* A callback used to create the new repository into which to
* clone. If NULL, the 'bare' field will be used to determine
* whether to create a bare repository.
*/
git_repository_create_cb repository_cb;
/**
* An opaque payload to pass to the git_repository creation callback.
* This parameter is ignored unless repository_cb is non-NULL.
*/
void *repository_cb_payload;
/**
* A callback used to create the git_remote, prior to its being
* used to perform the clone operation. See the documentation for
* git_remote_create_cb for details. This parameter may be NULL,
* indicating that git_clone should provide default behavior.
*/
git_remote_create_cb remote_cb;
/**
* An opaque payload to pass to the git_remote creation callback.
* This parameter is ignored unless remote_cb is non-NULL.
*/
void *remote_cb_payload;
} git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1
#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT}
/**
* Initializes a `git_clone_options` with default values. Equivalent to
* creating an instance with GIT_CLONE_OPTIONS_INIT.
*
* @param opts the `git_clone_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_CLONE_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
* Initializes a `git_clone_options` with default values. Equivalent to
* creating an instance with GIT_CLONE_OPTIONS_INIT.
*
* @param opts The `git_clone_options` struct to initialize
* @param version Version of struct; pass `GIT_CLONE_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_clone_init_options(
git_clone_options* opts,
int version);
git_clone_options *opts,
unsigned int version);
/**
* Clone a remote repository.
*
* This version handles the simple case. If you'd like to create the
* repository or remote with non-default settings, you can create and
* configure them and then use `git_clone_into()`.
* By default this creates its repository and initial remote to match
* git's defaults. You can use the options in the callback to
* customize how these are created.
*
* @param out pointer that will receive the resulting repository object
* @param url the remote repository to clone
@ -100,30 +210,6 @@ GIT_EXTERN(int) git_clone(
const char *local_path,
const git_clone_options *options);
/**
* Clone into a repository
*
* After creating the repository and remote and configuring them for
* paths and callbacks respectively, you can call this function to
* perform the clone operation and optionally checkout files.
*
* @param repo the repository to use
* @param remote the remote repository to clone from
* @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the
* remote's default branch
* @param signature The identity used when updating the reflog.
* @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
*/
GIT_EXTERN(int) git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_options *co_opts,
const char *branch,
const git_signature *signature);
/** @} */
GIT_END_DECL
#endif

View File

@ -254,7 +254,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
* is not direct, it will be resolved to a direct reference.
* Use "HEAD" to update the HEAD of the current branch and
* make it point to this commit. If the reference doesn't
* exist yet, it will be created.
* exist yet, it will be created. If it does exist, the first
* parent must be the tip of this branch.
*
* @param author Signature with author and author time of commit
*
@ -329,7 +330,7 @@ GIT_EXTERN(int) git_commit_create_v(
*
* The `update_ref` value works as in the regular `git_commit_create()`,
* updating the ref to point to the newly rewritten commit. If you want
* to amend a commit that is not currently the HEAD of the branch and then
* to amend a commit that is not currently the tip of the branch and then
* rewrite the following commits to reach a ref, pass this as NULL and
* update the rest of the commit chain and ref separately.
*

View File

@ -226,6 +226,22 @@ GIT_EXTERN(int) git_config_open_level(
*/
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
/**
* Create a snapshot of the configuration
*
* Create a snapshot of the current state of a configuration, which
* allows you to look into a consistent view of the configuration for
* looking up complex values (e.g. a remote, submodule).
*
* The string returned when querying such a config object is valid
* until it is freed.
*
* @param out pointer in which to store the snapshot config object
* @param config configuration to snapshot
* @return 0 or an error code
*/
GIT_EXTERN(int) git_config_snapshot(git_config **out, git_config *config);
/**
* Reload changed config files
@ -312,7 +328,8 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char
* Get the value of a string config variable.
*
* The string is owned by the variable and should not be freed by the
* user.
* user. The pointer will be valid until the next operation on this
* config object.
*
* All config files will be looked into, in the order of their
* defined level. A higher level means a higher priority. The
@ -353,6 +370,9 @@ GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, cons
/**
* Return the current entry and advance the iterator
*
* The pointers returned by this function are valid until the iterator
* is freed.
*
* @param entry pointer to store the entry
* @param iter the iterator
* @return 0 or an error code. GIT_ITEROVER if the iteration has completed
@ -451,6 +471,9 @@ GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, co
* If the callback returns a non-zero value, the function stops iterating
* and returns that value to the caller.
*
* The pointers passed to the callback are only valid as long as the
* iteration is ongoing.
*
* @param cfg where to get the variables from
* @param callback the function to call on each variable
* @param payload the data to pass to the callback
@ -491,6 +514,9 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi
* regular expression that filters which config keys are passed to the
* callback.
*
* The pointers passed to the callback are only valid as long as the
* iteration is ongoing.
*
* @param cfg where to get the variables from
* @param regexp regular expression to match against config names
* @param callback the function to call on each variable

View File

@ -145,6 +145,19 @@ typedef enum {
*/
GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1u << 14),
/** When diff finds a file in the working directory with stat
* information different from the index, but the OID ends up being the
* same, write the correct stat information into the index. Note:
* without this flag, diff will always leave the index untouched.
*/
GIT_DIFF_UPDATE_INDEX = (1u << 15),
/** Include unreadable files in the diff */
GIT_DIFF_INCLUDE_UNREADABLE = (1u << 16),
/** Include unreadable files in the diff */
GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 17),
/*
* Options controlling how output will be generated
*/
@ -205,9 +218,9 @@ typedef struct git_diff git_diff;
* considered reserved for internal or future use.
*/
typedef enum {
GIT_DIFF_FLAG_BINARY = (1u << 0), /** file(s) treated as binary data */
GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /** file(s) treated as text data */
GIT_DIFF_FLAG_VALID_ID = (1u << 2), /** `id` value is known correct */
GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */
GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */
GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */
} git_diff_flag_t;
/**
@ -221,15 +234,16 @@ typedef enum {
* DELETED pairs).
*/
typedef enum {
GIT_DELTA_UNMODIFIED = 0, /** no changes */
GIT_DELTA_ADDED = 1, /** entry does not exist in old version */
GIT_DELTA_DELETED = 2, /** entry does not exist in new version */
GIT_DELTA_MODIFIED = 3, /** entry content changed between old and new */
GIT_DELTA_RENAMED = 4, /** entry was renamed between old and new */
GIT_DELTA_COPIED = 5, /** entry was copied from another old entry */
GIT_DELTA_IGNORED = 6, /** entry is ignored item in workdir */
GIT_DELTA_UNTRACKED = 7, /** entry is untracked item in workdir */
GIT_DELTA_TYPECHANGE = 8, /** type of entry changed between old and new */
GIT_DELTA_UNMODIFIED = 0, /**< no changes */
GIT_DELTA_ADDED = 1, /**< entry does not exist in old version */
GIT_DELTA_DELETED = 2, /**< entry does not exist in new version */
GIT_DELTA_MODIFIED = 3, /**< entry content changed between old and new */
GIT_DELTA_RENAMED = 4, /**< entry was renamed between old and new */
GIT_DELTA_COPIED = 5, /**< entry was copied from another old entry */
GIT_DELTA_IGNORED = 6, /**< entry is ignored item in workdir */
GIT_DELTA_UNTRACKED = 7, /**< entry is untracked item in workdir */
GIT_DELTA_TYPECHANGE = 8, /**< type of entry changed between old and new */
GIT_DELTA_UNREADABLE = 9, /**< entry is unreadable */
} git_delta_t;
/**
@ -381,17 +395,16 @@ typedef struct {
{GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_DEFAULT, {NULL,0}, NULL, NULL, 3}
/**
* Initializes a `git_diff_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_OPTIONS_INIT.
*
* @param opts the `git_diff_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_DIFF_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
* Initializes a `git_diff_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_OPTIONS_INIT.
*
* @param opts The `git_diff_options` struct to initialize
* @param version Version of struct; pass `GIT_DIFF_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_diff_init_options(
git_diff_options* opts,
int version);
git_diff_options *opts,
unsigned int version);
/**
* When iterating over a diff, callback that will be made per file.
@ -410,12 +423,12 @@ typedef int (*git_diff_file_cb)(
*/
typedef struct git_diff_hunk git_diff_hunk;
struct git_diff_hunk {
int old_start; /** Starting line number in old_file */
int old_lines; /** Number of lines in old_file */
int new_start; /** Starting line number in new_file */
int new_lines; /** Number of lines in new_file */
size_t header_len; /** Number of bytes in header text */
char header[128]; /** Header text, NUL-byte terminated */
int old_start; /**< Starting line number in old_file */
int old_lines; /**< Number of lines in old_file */
int new_start; /**< Starting line number in new_file */
int new_lines; /**< Number of lines in new_file */
size_t header_len; /**< Number of bytes in header text */
char header[128]; /**< Header text, NUL-byte terminated */
};
/**
@ -458,13 +471,13 @@ typedef enum {
*/
typedef struct git_diff_line git_diff_line;
struct git_diff_line {
char origin; /** A git_diff_line_t value */
int old_lineno; /** Line number in old file or -1 for added line */
int new_lineno; /** Line number in new file or -1 for deleted line */
int num_lines; /** Number of newline characters in content */
size_t content_len; /** Number of bytes of data */
git_off_t content_offset; /** Offset in the original file to the content */
const char *content; /** Pointer to diff text, not NUL-byte terminated */
char origin; /**< A git_diff_line_t value */
int old_lineno; /**< Line number in old file or -1 for added line */
int new_lineno; /**< Line number in new file or -1 for deleted line */
int num_lines; /**< Number of newline characters in content */
size_t content_len; /**< Number of bytes of data */
git_off_t content_offset; /**< Offset in the original file to the content */
const char *content; /**< Pointer to diff text, not NUL-byte terminated */
};
/**
@ -476,10 +489,10 @@ struct git_diff_line {
* of lines of file and hunk headers.
*/
typedef int (*git_diff_line_cb)(
const git_diff_delta *delta, /** delta that contains this data */
const git_diff_hunk *hunk, /** hunk containing this data */
const git_diff_line *line, /** line data */
void *payload); /** user reference data */
const git_diff_delta *delta, /**< delta that contains this data */
const git_diff_hunk *hunk, /**< hunk containing this data */
const git_diff_line *line, /**< line data */
void *payload); /**< user reference data */
/**
* Flags to control the behavior of diff rename/copy detection.
@ -622,17 +635,16 @@ typedef struct {
#define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION}
/**
* Initializes a `git_diff_find_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_FIND_OPTIONS_INIT.
*
* @param opts the `git_diff_find_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_DIFF_FIND_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
* Initializes a `git_diff_find_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_FIND_OPTIONS_INIT.
*
* @param opts The `git_diff_find_options` struct to initialize
* @param version Version of struct; pass `GIT_DIFF_FIND_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_diff_find_init_options(
git_diff_find_options* opts,
int version);
git_diff_find_options *opts,
unsigned int version);
/** @name Diff Generator Functions
*
@ -804,23 +816,6 @@ GIT_EXTERN(int) git_diff_find_similar(
git_diff *diff,
const git_diff_find_options *options);
/**
* Initialize diff options structure
*
* In most cases, you can probably just use `GIT_DIFF_OPTIONS_INIT` to
* initialize the diff options structure, but in some cases that is not
* going to work. You can call this function instead. Note that you
* must pass both a pointer to the structure to be initialized and the
* `GIT_DIFF_OPTIONS_VERSION` value from the header you compiled with.
*
* @param options Pointer to git_diff_options memory to be initialized
* @param version Should be `GIT_DIFF_OPTIONS_VERSION`
* @return 0 on success, negative on failure (such as unsupported version)
*/
GIT_EXTERN(int) git_diff_options_init(
git_diff_options *options,
unsigned int version);
/**@}*/
@ -1233,17 +1228,17 @@ GIT_EXTERN(int) git_diff_commit_as_email(
const git_diff_options *diff_opts);
/**
* Initializes a `git_diff_format_email_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
*
* @param opts the `git_diff_format_email_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
* Initializes a `git_diff_format_email_options` with default values.
*
* Equivalent to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
*
* @param opts The `git_diff_format_email_options` struct to initialize
* @param version Version of struct; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_diff_format_email_init_options(
git_diff_format_email_options *opts,
int version);
unsigned int version);
GIT_END_DECL

View File

@ -19,13 +19,13 @@ GIT_BEGIN_DECL
/** Generic return codes */
typedef enum {
GIT_OK = 0, /*< No error */
GIT_OK = 0, /**< No error */
GIT_ERROR = -1, /*< Generic error */
GIT_ENOTFOUND = -3, /*< Requested object could not be found */
GIT_EEXISTS = -4, /*< Object exists preventing operation */
GIT_EAMBIGUOUS = -5, /*< More than one object matches */
GIT_EBUFS = -6, /*< Output buffer too short to hold data */
GIT_ERROR = -1, /**< Generic error */
GIT_ENOTFOUND = -3, /**< Requested object could not be found */
GIT_EEXISTS = -4, /**< Object exists preventing operation */
GIT_EAMBIGUOUS = -5, /**< More than one object matches */
GIT_EBUFS = -6, /**< Output buffer too short to hold data */
/* GIT_EUSER is a special error that is never generated by libgit2
* code. You can return it from a callback (e.g to stop an iteration)
@ -33,17 +33,19 @@ typedef enum {
*/
GIT_EUSER = -7,
GIT_EBAREREPO = -8, /*< Operation not allowed on bare repository */
GIT_EUNBORNBRANCH = -9, /*< HEAD refers to branch with no commits */
GIT_EUNMERGED = -10, /*< Merge in progress prevented operation */
GIT_ENONFASTFORWARD = -11, /*< Reference was not fast-forwardable */
GIT_EINVALIDSPEC = -12, /*< Name/ref spec was not in a valid format */
GIT_EMERGECONFLICT = -13, /*< Merge conflicts prevented operation */
GIT_ELOCKED = -14, /*< Lock file prevented operation */
GIT_EMODIFIED = -15, /*< Reference value does not match expected */
GIT_EBAREREPO = -8, /**< Operation not allowed on bare repository */
GIT_EUNBORNBRANCH = -9, /**< HEAD refers to branch with no commits */
GIT_EUNMERGED = -10, /**< Merge in progress prevented operation */
GIT_ENONFASTFORWARD = -11, /**< Reference was not fast-forwardable */
GIT_EINVALIDSPEC = -12, /**< Name/ref spec was not in a valid format */
GIT_EMERGECONFLICT = -13, /**< Merge conflicts prevented operation */
GIT_ELOCKED = -14, /**< Lock file prevented operation */
GIT_EMODIFIED = -15, /**< Reference value does not match expected */
GIT_EAUTH = -16, /**< Authentication error */
GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
GIT_PASSTHROUGH = -30, /*< Internal only */
GIT_ITEROVER = -31, /*< Signals end of iteration with iterator */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
} git_error_code;
/**

View File

@ -35,6 +35,11 @@ typedef enum {
GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB,
} git_filter_mode_t;
typedef enum {
GIT_FILTER_OPT_DEFAULT = 0u,
GIT_FILTER_OPT_ALLOW_UNSAFE = (1u << 0),
} git_filter_opt_t;
/**
* A filter that can transform file data
*
@ -75,6 +80,7 @@ typedef struct git_filter_list git_filter_list;
* @param blob The blob to which the filter will be applied (if known)
* @param path Relative path of the file to be filtered
* @param mode Filtering direction (WT->ODB or ODB->WT)
* @param options Combination of `git_filter_opt_t` flags
* @return 0 on success (which could still return NULL if no filters are
* needed for the requested file), <0 on error
*/
@ -83,7 +89,8 @@ GIT_EXTERN(int) git_filter_list_load(
git_repository *repo,
git_blob *blob, /* can be NULL */
const char *path,
git_filter_mode_t mode);
git_filter_mode_t mode,
uint32_t options);
/**
* Apply filter list to a data buffer.

View File

@ -61,7 +61,7 @@ typedef struct git_index_entry {
unsigned short flags;
unsigned short flags_extended;
char *path;
const char *path;
} git_index_entry;
/**
@ -73,10 +73,13 @@ typedef struct git_index_entry {
*/
#define GIT_IDXENTRY_NAMEMASK (0x0fff)
#define GIT_IDXENTRY_STAGEMASK (0x3000)
#define GIT_IDXENTRY_EXTENDED (0x4000)
#define GIT_IDXENTRY_VALID (0x8000)
#define GIT_IDXENTRY_STAGESHIFT 12
typedef enum {
GIT_IDXENTRY_EXTENDED = (0x4000),
GIT_IDXENTRY_VALID = (0x8000),
} git_indxentry_flag_t;
#define GIT_IDXENTRY_STAGE(E) \
(((E)->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT)
@ -92,36 +95,36 @@ typedef struct git_index_entry {
* in-memory only and used by libgit2. Only the flags in
* `GIT_IDXENTRY_EXTENDED_FLAGS` will get saved on-disk.
*
* These bitmasks match the three fields in the `git_index_entry`
* `flags_extended` value that belong on disk. You can use them to
* interpret the data in the `flags_extended`.
*/
#define GIT_IDXENTRY_INTENT_TO_ADD (1 << 13)
#define GIT_IDXENTRY_SKIP_WORKTREE (1 << 14)
/* GIT_IDXENTRY_EXTENDED2 is reserved for future extension */
#define GIT_IDXENTRY_EXTENDED2 (1 << 15)
#define GIT_IDXENTRY_EXTENDED_FLAGS (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE)
/**
* Bitmasks for in-memory only fields of `git_index_entry`'s `flags_extended`
*
* These bitmasks match the other fields in the `git_index_entry`
* `flags_extended` value that are only used in-memory by libgit2. You
* Thee first three bitmasks match the three fields in the
* `git_index_entry` `flags_extended` value that belong on disk. You
* can use them to interpret the data in the `flags_extended`.
*
* The rest of the bitmasks match the other fields in the `git_index_entry`
* `flags_extended` value that are only used in-memory by libgit2.
* You can use them to interpret the data in the `flags_extended`.
*
*/
#define GIT_IDXENTRY_UPDATE (1 << 0)
#define GIT_IDXENTRY_REMOVE (1 << 1)
#define GIT_IDXENTRY_UPTODATE (1 << 2)
#define GIT_IDXENTRY_ADDED (1 << 3)
typedef enum {
#define GIT_IDXENTRY_HASHED (1 << 4)
#define GIT_IDXENTRY_UNHASHED (1 << 5)
#define GIT_IDXENTRY_WT_REMOVE (1 << 6) /* remove in work directory */
#define GIT_IDXENTRY_CONFLICTED (1 << 7)
GIT_IDXENTRY_INTENT_TO_ADD = (1 << 13),
GIT_IDXENTRY_SKIP_WORKTREE = (1 << 14),
/** Reserved for future extension */
GIT_IDXENTRY_EXTENDED2 = (1 << 15),
#define GIT_IDXENTRY_UNPACKED (1 << 8)
#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 9)
GIT_IDXENTRY_EXTENDED_FLAGS = (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE),
GIT_IDXENTRY_UPDATE = (1 << 0),
GIT_IDXENTRY_REMOVE = (1 << 1),
GIT_IDXENTRY_UPTODATE = (1 << 2),
GIT_IDXENTRY_ADDED = (1 << 3),
GIT_IDXENTRY_HASHED = (1 << 4),
GIT_IDXENTRY_UNHASHED = (1 << 5),
GIT_IDXENTRY_WT_REMOVE = (1 << 6), /**< remove in work directory */
GIT_IDXENTRY_CONFLICTED = (1 << 7),
GIT_IDXENTRY_UNPACKED = (1 << 8),
GIT_IDXENTRY_NEW_SKIP_WORKTREE = (1 << 9),
} git_idxentry_extended_flag_t;
/** Capabilities of system that affect index actions. */
typedef enum {
@ -412,10 +415,10 @@ GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_en
*
* This entry is calculated from the entry's flag attribute like this:
*
* (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT
* (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT
*
* @param entry The entry
* @returns the stage number
* @return the stage number
*/
GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry);

View File

@ -10,6 +10,7 @@
#include "common.h"
#include "types.h"
#include "oid.h"
#include "oidarray.h"
#include "checkout.h"
#include "index.h"
@ -57,11 +58,11 @@ typedef struct {
*/
GIT_EXTERN(int) git_merge_file_init_input(
git_merge_file_input *opts,
int version);
unsigned int version);
/**
* Flags for `git_merge_tree` options. A combination of these flags can be
* passed in via the `flags` value in the `git_merge_tree_opts`.
* passed in via the `flags` value in the `git_merge_options`.
*/
typedef enum {
/**
@ -73,7 +74,7 @@ typedef enum {
} git_merge_tree_flag_t;
/**
* Merge file favor options for `git_merge_trees_opts` instruct the file-level
* Merge file favor options for `git_merge_options` instruct the file-level
* merging functionality how to deal with conflicting regions of the files.
*/
typedef enum {
@ -164,7 +165,7 @@ typedef struct {
*/
GIT_EXTERN(int) git_merge_file_init_options(
git_merge_file_options *opts,
int version);
unsigned int version);
typedef struct {
/**
@ -232,7 +233,7 @@ typedef struct {
*/
GIT_EXTERN(int) git_merge_init_options(
git_merge_options *opts,
int version);
unsigned int version);
/**
* The results of `git_merge_analysis` indicate the merge opportunities.
@ -268,6 +269,26 @@ typedef enum {
GIT_MERGE_ANALYSIS_UNBORN = (1 << 3),
} git_merge_analysis_t;
typedef enum {
/*
* No configuration was found that suggests a preferred behavior for
* merge.
*/
GIT_MERGE_PREFERENCE_NONE = 0,
/**
* There is a `merge.ff=false` configuration setting, suggesting that
* the user does not want to allow a fast-forward merge.
*/
GIT_MERGE_PREFERENCE_NO_FASTFORWARD = (1 << 0),
/**
* There is a `merge.ff=only` configuration setting, suggesting that
* the user only wants fast-forward merges.
*/
GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1),
} git_merge_preference_t;
/**
* Analyzes the given branch(es) and determines the opportunities for
* merging them into the HEAD of the repository.
@ -280,6 +301,7 @@ typedef enum {
*/
GIT_EXTERN(int) git_merge_analysis(
git_merge_analysis_t *analysis_out,
git_merge_preference_t *preference_out,
git_repository *repo,
const git_merge_head **their_heads,
size_t their_heads_len);
@ -299,6 +321,21 @@ GIT_EXTERN(int) git_merge_base(
const git_oid *one,
const git_oid *two);
/**
* Find merge bases between two commits
*
* @param out array in which to store the resulting ids
* @param repo the repository where the commits exist
* @param one one of the commits
* @param two the other commit
* @return 0 on success, GIT_ENOTFOUND if not found or error code
*/
GIT_EXTERN(int) git_merge_bases(
git_oidarray *out,
git_repository *repo,
const git_oid *one,
const git_oid *two);
/**
* Find a merge base given a list of commits
*
@ -378,8 +415,8 @@ GIT_EXTERN(int) git_merge_head_from_id(
/**
* Gets the commit ID that the given `git_merge_head` refers to.
*
* @param id pointer to commit id to be filled in
* @param head the given merge head
* @return commit id
*/
GIT_EXTERN(const git_oid *) git_merge_head_id(
const git_merge_head *head);
@ -424,8 +461,8 @@ GIT_EXTERN(int) git_merge_file(
* @param out The git_merge_file_result to be filled in
* @param repo The repository
* @param ancestor The index entry for the ancestor file (stage level 1)
* @param our_path The index entry for our file (stage level 2)
* @param their_path The index entry for their file (stage level 3)
* @param ours The index entry for our file (stage level 2)
* @param theirs The index entry for their file (stage level 3)
* @param opts The merge file options or NULL
* @return 0 on success or error code
*/
@ -497,8 +534,8 @@ GIT_EXTERN(int) git_merge_commits(
* completes, resolve any conflicts and prepare a commit.
*
* @param repo the repository to merge
* @param merge_heads the heads to merge into
* @param merge_heads_len the number of heads to merge
* @param their_heads the heads to merge into
* @param their_heads_len the number of heads to merge
* @param merge_opts merge options
* @param checkout_opts checkout options
* @return 0 on success or error code

View File

@ -29,12 +29,14 @@ GIT_BEGIN_DECL
*
* @param message The message to be prettified.
*
* @param strip_comments Non-zero to remove lines starting with "#", 0 to
* leave them in.
* @param strip_comments Non-zero to remove comment lines, 0 to leave them in.
*
* @param comment_char Comment character. Lines starting with this character
* are considered to be comments and removed if `strip_comments` is non-zero.
*
* @return 0 or an error code.
*/
GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments);
GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char);
/** @} */
GIT_END_DECL

View File

@ -41,6 +41,11 @@ struct git_remote_head {
git_oid oid;
git_oid loid;
char *name;
/**
* If the server send a symref mapping for this ref, this will
* point to the target.
*/
char *symref_target;
};
/**

View File

@ -107,6 +107,11 @@ GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj);
/**
* Get a short abbreviated OID string for the object
*
* This starts at the "core.abbrev" length (default 7 characters) and
* iteratively extends to a longer string if that length is ambiguous.
* The result will be unambiguous (at least until new objects are added to
* the repository).
*
* @param out Buffer to write string into
* @param obj The object to get an ID for
* @return 0 on success, <0 for error

View File

@ -116,13 +116,17 @@ GIT_EXTERN(void) git_oid_nfmt(char *out, size_t n, const git_oid *id);
GIT_EXTERN(void) git_oid_pathfmt(char *out, const git_oid *id);
/**
* Format a git_oid into a newly allocated c-string.
* Format a git_oid into a statically allocated c-string.
*
* The c-string is owned by the library and should not be freed
* by the user. If libgit2 is built with thread support, the string
* will be stored in TLS (i.e. one buffer per thread) to allow for
* concurrent calls of the function.
*
* @param id the oid structure to format
* @return the c-string; NULL if memory is exhausted. Caller must
* deallocate the string with git__free().
* @return the c-string
*/
GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *id);
GIT_EXTERN(char *) git_oid_tostr_s(const git_oid *oid);
/**
* Format a git_oid into a buffer as a hex format c-string.

40
include/git2/oidarray.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_oidarray_h__
#define INCLUDE_git_oidarray_h__
#include "common.h"
#include "oid.h"
GIT_BEGIN_DECL
/** Array of object ids */
typedef struct git_oidarray {
git_oid *ids;
size_t count;
} git_oidarray;
/**
* Free the OID array
*
* This method must (and must only) be called on `git_oidarray`
* objects where the array is allocated by the library. Not doing so,
* will result in a memory leak.
*
* This does not free the `git_oidarray` itself, since the library will
* never allocate that object directly itself (it is more commonly embedded
* inside another struct or created on the stack).
*
* @param array git_oidarray from which to free oid data
*/
GIT_EXTERN(void) git_oidarray_free(git_oidarray *array);
/** @} */
GIT_END_DECL
#endif

View File

@ -12,6 +12,8 @@
#include "strarray.h"
#include "diff.h"
GIT_BEGIN_DECL
/**
* Compiled pathspec
*/
@ -257,4 +259,5 @@ GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount(
GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry(
const git_pathspec_match_list *m, size_t pos);
GIT_END_DECL
#endif

View File

@ -49,8 +49,8 @@ typedef struct {
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_push_init_options(
git_push_options* opts,
int version);
git_push_options *opts,
unsigned int version);
/** Push network progress notification function */
typedef int (*git_push_transfer_progress)(

View File

@ -69,7 +69,7 @@ GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const g
*
* @param repo the repository
* @param old_name the old name of the reference
* @param new_name the new name of the reference
* @param name the new name of the reference
* @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_reflog_rename(git_repository *repo, const char *old_name, const char *name);

View File

@ -178,7 +178,6 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor
* @param name The name of the reference
* @param id The object id pointed to by the reference.
* @param force Overwrite existing references
* @param force Overwrite existing references
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code
@ -221,7 +220,6 @@ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo,
* @param name The name of the reference
* @param id The object id pointed to by the reference.
* @param force Overwrite existing references
* @param force Overwrite existing references
* @param current_id The expected value of the reference at the time of update
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
@ -415,7 +413,7 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
* This method removes the named reference from the repository without
* looking at its old value.
*
* @param ref The reference to remove
* @param name The reference to remove
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reference_remove(git_repository *repo, const char *name);
@ -525,6 +523,17 @@ GIT_EXTERN(int) git_reference_iterator_glob_new(
*/
GIT_EXTERN(int) git_reference_next(git_reference **out, git_reference_iterator *iter);
/**
* Get the next reference's name
*
* This function is provided for convenience in case only the names
* are interesting as it avoids the allocation of the `git_reference`
* object which `git_reference_next()` needs.
*
* @param out pointer in which to store the string
* @param iter the iterator
* @return 0, GIT_ITEROVER if there are no more; or an error code
*/
GIT_EXTERN(int) git_reference_next_name(const char **out, git_reference_iterator *iter);
/**

View File

@ -384,15 +384,12 @@ GIT_EXTERN(int) git_remote_fetch(
const char *reflog_message);
/**
* Return whether a string is a valid remote URL
*
* @param url the url to check
* @return 1 if the url is valid, 0 otherwise
*/
GIT_EXTERN(int) git_remote_valid_url(const char *url);
/**
* Return whether the passed URL is supported by this version of the library.
* Return whether the library supports a particular URL scheme
*
* Both the built-in and externally-registered transport lists are
* searched for a transport which supports the scheme of the given
* URL.
*
* @param url the url to check
* @return 1 if the url is supported, 0 otherwise
@ -410,30 +407,6 @@ GIT_EXTERN(int) git_remote_supported_url(const char* url);
*/
GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
/**
* Choose whether to check the server's certificate (applies to HTTPS only)
*
* @param remote the remote to configure
* @param check whether to check the server's certificate (defaults to yes)
*/
GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
/**
* Sets a custom transport for the remote. The caller can use this function
* to bypass the automatic discovery of a transport by URL scheme (i.e.
* http://, https://, git://) and supply their own transport to be used
* instead. After providing the transport to a remote using this function,
* the transport object belongs exclusively to that remote, and the remote will
* free it when it is freed with git_remote_free.
*
* @param remote the remote to configure
* @param transport the transport object for the remote to use
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_set_transport(
git_remote *remote,
git_transport *transport);
/**
* Argument to the completion callback which tells it which operation
* finished.
@ -474,6 +447,14 @@ struct git_remote_callbacks {
*/
git_cred_acquire_cb credentials;
/**
* If cert verification fails, this will be called to let the
* user make the final decision of whether to allow the
* connection to proceed. Returns 1 to allow the connection, 0
* to disallow it or a negative value to indicate an error.
*/
git_transport_certificate_check_cb certificate_check;
/**
* During the download of new data, this will be regularly
* called with the current count of progress done by the
@ -501,14 +482,13 @@ struct git_remote_callbacks {
* Initializes a `git_remote_callbacks` with default values. Equivalent to
* creating an instance with GIT_REMOTE_CALLBACKS_INIT.
*
* @param opts the `git_remote_callbacks` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_REMOTE_CALLBACKS_VERSION` here.
* @param opts the `git_remote_callbacks` struct to initialize
* @param version Version of struct; pass `GIT_REMOTE_CALLBACKS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_remote_init_callbacks(
git_remote_callbacks* opts,
int version);
git_remote_callbacks *opts,
unsigned int version);
/**
* Set the callbacks for a remote
@ -573,18 +553,17 @@ GIT_EXTERN(void) git_remote_set_autotag(
*
* A temporary in-memory remote cannot be given a name with this method.
*
* @param problems non-default refspecs cannot be renamed and will be
* stored here for further processing by the caller. Always free this
* strarray on succesful return.
* @param remote the remote to rename
* @param new_name the new name the remote should bear
* @param callback Optional callback to notify the consumer of fetch refspecs
* that haven't been automatically updated and need potential manual tweaking.
* @param payload Additional data to pass to the callback
* @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*/
GIT_EXTERN(int) git_remote_rename(
git_strarray *problems,
git_remote *remote,
const char *new_name,
git_remote_rename_problem_cb callback,
void *payload);
const char *new_name);
/**
* Retrieve the update FETCH_HEAD setting.
@ -611,6 +590,35 @@ GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value);
*/
GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
/**
* Delete an existing persisted remote.
*
* All remote-tracking branches and configuration settings
* for the remote will be removed.
*
* @param remote A valid remote
* @return 0 on success, or an error code.
*/
GIT_EXTERN(int) git_remote_delete(git_remote *remote);
/**
* Retrieve the name of the remote's default branch
*
* The default branch of a repository is the branch which HEAD points
* to. If the remote does not support reporting this information
* directly, it performs the guess as git does; that is, if there are
* multiple branches which point to the same commit, the first one is
* chosen. If the master branch is a candidate, it wins.
*
* This function must only be called after connecting.
*
* @param out the buffern in which to store the reference name
* @param remote the remote
* @return 0, GIT_ENOTFOUND if the remote does not have any references
* or none of them point to HEAD's commit, or an error message.
*/
GIT_EXTERN(int) git_remote_default_branch(git_buf *out, git_remote *remote);
/** @} */
GIT_END_DECL
#endif

View File

@ -196,6 +196,8 @@ GIT_EXTERN(int) git_repository_init(
* looking the "template_path" from the options if set, or the
* `init.templatedir` global config if not, or falling back on
* "/usr/share/git-core/templates" if it exists.
* * GIT_REPOSITORY_INIT_RELATIVE_GITLINK - If an alternate workdir is
* specified, use relative paths for the gitdir and core.worktree.
*/
typedef enum {
GIT_REPOSITORY_INIT_BARE = (1u << 0),
@ -204,6 +206,7 @@ typedef enum {
GIT_REPOSITORY_INIT_MKDIR = (1u << 3),
GIT_REPOSITORY_INIT_MKPATH = (1u << 4),
GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1u << 5),
GIT_REPOSITORY_INIT_RELATIVE_GITLINK = (1u << 6),
} git_repository_init_flag_t;
/**
@ -271,14 +274,13 @@ typedef struct {
* Initializes a `git_repository_init_options` with default values. Equivalent
* to creating an instance with GIT_REPOSITORY_INIT_OPTIONS_INIT.
*
* @param opts the `git_repository_init_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_REPOSITORY_INIT_OPTIONS_VERSION` here.
* @param opts the `git_repository_init_options` struct to initialize
* @param version Version of struct; pass `GIT_REPOSITORY_INIT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_repository_init_init_options(
git_repository_init_options* opts,
int version);
git_repository_init_options *opts,
unsigned int version);
/**
* Create a new Git repository in the given folder with extended controls.
@ -409,12 +411,28 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
* The configuration file must be freed once it's no longer
* being used by the user.
*
* @param out Pointer to store the loaded config file
* @param out Pointer to store the loaded configuration
* @param repo A repository object
* @return 0, or an error code
*/
GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo);
/**
* Get a snapshot of the repository's configuration
*
* Convenience function to take a snapshot from the repository's
* configuration. The contents of this snapshot will not change,
* even if the underlying config files are modified.
*
* The configuration file must be freed once it's no longer
* being used by the user.
*
* @param out Pointer to store the loaded configuration
* @param repo the repository
* @return 0, or an error code
*/
GIT_EXTERN(int) git_repository_config_snapshot(git_config **out, git_repository *repo);
/**
* Get the Object Database for this repository.
*
@ -547,6 +565,10 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(
* hash a file in the repository and you want to apply filtering rules (e.g.
* crlf filters) before generating the SHA, then use this function.
*
* Note: if the repository has `core.safecrlf` set to fail and the
* filtering triggers that failure, then this function will return an
* error and not calculate the hash of the file.
*
* @param out Output value of calculated SHA
* @param repo Repository pointer
* @param path Path to file on disk whose contents should be hashed. If the
@ -556,6 +578,7 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(
* NULL, then the `path` parameter will be used instead. If
* this is passed as the empty string, then no filters will be
* applied when calculating the hash.
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_hashfile(
git_oid *out,
@ -629,7 +652,7 @@ GIT_EXTERN(int) git_repository_set_head_detached(
*
* @param repo Repository pointer
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @param reflog_message The one line long message to be appended to the reflog
* @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing
* branch or an error code
*/
@ -642,7 +665,7 @@ typedef enum {
GIT_REPOSITORY_STATE_NONE,
GIT_REPOSITORY_STATE_MERGE,
GIT_REPOSITORY_STATE_REVERT,
GIT_REPOSITORY_STATE_CHERRY_PICK,
GIT_REPOSITORY_STATE_CHERRYPICK,
GIT_REPOSITORY_STATE_BISECT,
GIT_REPOSITORY_STATE_REBASE,
GIT_REPOSITORY_STATE_REBASE_INTERACTIVE,

View File

@ -7,6 +7,10 @@
#ifndef INCLUDE_git_reset_h__
#define INCLUDE_git_reset_h__
#include "common.h"
#include "types.h"
#include "strarray.h"
/**
* @file git2/reset.h
* @brief Git reset management routines
@ -19,9 +23,9 @@ GIT_BEGIN_DECL
* Kinds of reset operation
*/
typedef enum {
GIT_RESET_SOFT = 1, /** Move the head to the given commit */
GIT_RESET_MIXED = 2, /** SOFT plus reset index to the commit */
GIT_RESET_HARD = 3, /** MIXED plus changes in working tree discarded */
GIT_RESET_SOFT = 1, /**< Move the head to the given commit */
GIT_RESET_MIXED = 2, /**< SOFT plus reset index to the commit */
GIT_RESET_HARD = 3, /**< MIXED plus changes in working tree discarded */
} git_reset_t;
/**

View File

@ -37,14 +37,13 @@ typedef struct {
* Initializes a `git_revert_options` with default values. Equivalent to
* creating an instance with GIT_REVERT_OPTIONS_INIT.
*
* @param opts the `git_revert_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_REVERT_OPTIONS_VERSION` here.
* @param opts the `git_revert_options` struct to initialize
* @param version Version of struct; pass `GIT_REVERT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_revert_init_opts(
git_revert_options* opts,
int version);
GIT_EXTERN(int) git_revert_init_options(
git_revert_options *opts,
unsigned int version);
/**
* Reverts the given commit against the given "our" commit, producing an
@ -57,10 +56,10 @@ GIT_EXTERN(int) git_revert_init_opts(
* @param revert_commit the commit to revert
* @param our_commit the commit to revert against (eg, HEAD)
* @param mainline the parent of the revert commit, if it is a merge
* @param merge_tree_opts the merge tree options (or null for defaults)
* @param merge_options the merge options (or null for defaults)
* @return zero on success, -1 on failure.
*/
int git_revert_commit(
GIT_EXTERN(int) git_revert_commit(
git_index **out,
git_repository *repo,
git_commit *revert_commit,
@ -72,9 +71,8 @@ int git_revert_commit(
* Reverts the given commit, producing changes in the working directory.
*
* @param repo the repository to revert
* @param commits the commits to revert
* @param commits_len the number of commits to revert
* @param flags merge flags
* @param commit the commit to revert
* @param given_opts merge flags
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_revert(

View File

@ -69,7 +69,7 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo)
* Call `git_signature_free()` to free the data.
*
* @param dest pointer where to store the copy
* @param entry signature to duplicate
* @param sig signature to duplicate
* @return 0 or an error code
*/
GIT_EXTERN(int) git_signature_dup(git_signature **dest, const git_signature *sig);

View File

@ -43,6 +43,7 @@ typedef enum {
GIT_STATUS_WT_DELETED = (1u << 9),
GIT_STATUS_WT_TYPECHANGE = (1u << 10),
GIT_STATUS_WT_RENAMED = (1u << 11),
GIT_STATUS_WT_UNREADABLE = (1u << 12),
GIT_STATUS_IGNORED = (1u << 14),
} git_status_t;
@ -121,6 +122,11 @@ typedef enum {
* - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of
* doing a "soft" index reload (i.e. reloading the index data if the
* file on disk has been modified outside libgit2).
* - GIT_STATUS_OPT_UPDATE_INDEX tells libgit2 to refresh the stat cache
* in the index for files that are unchanged but have out of date stat
* information in the index. It will result in less work being done on
* subsequent calls to get status. This is mutually exclusive with the
* NO_REFRESH option.
*
* Calling `git_status_foreach()` is like calling the extended version
* with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED,
@ -128,19 +134,22 @@ typedef enum {
* together as `GIT_STATUS_OPT_DEFAULTS` if you want them as a baseline.
*/
typedef enum {
GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1u << 0),
GIT_STATUS_OPT_INCLUDE_IGNORED = (1u << 1),
GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1u << 2),
GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1u << 3),
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1u << 4),
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1u << 5),
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = (1u << 6),
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = (1u << 7),
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1u << 8),
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9),
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10),
GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11),
GIT_STATUS_OPT_NO_REFRESH = (1u << 12),
GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1u << 0),
GIT_STATUS_OPT_INCLUDE_IGNORED = (1u << 1),
GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1u << 2),
GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1u << 3),
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1u << 4),
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1u << 5),
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = (1u << 6),
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = (1u << 7),
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1u << 8),
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9),
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10),
GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11),
GIT_STATUS_OPT_NO_REFRESH = (1u << 12),
GIT_STATUS_OPT_UPDATE_INDEX = (1u << 13),
GIT_STATUS_OPT_INCLUDE_UNREADABLE = (1u << 14),
GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 15),
} git_status_opt_t;
#define GIT_STATUS_OPT_DEFAULTS \
@ -178,14 +187,13 @@ typedef struct {
* Initializes a `git_status_options` with default values. Equivalent to
* creating an instance with GIT_STATUS_OPTIONS_INIT.
*
* @param opts the `git_status_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_STATUS_OPTIONS_VERSION` here.
* @param opts The `git_status_options` instance to initialize.
* @param version Version of struct; pass `GIT_STATUS_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_status_init_options(
git_status_options* opts,
int version);
git_status_options *opts,
unsigned int version);
/**
* A status entry, providing the differences between the file as it exists

View File

@ -283,7 +283,7 @@ GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule);
* Resolve a submodule url relative to the given repository.
*
* @param out buffer to store the absolute submodule url in
* @param repository Pointer to repository object
* @param repo Pointer to repository object
* @param url Relative url
* @return 0 or an error code
*/
@ -470,6 +470,24 @@ GIT_EXTERN(git_submodule_recurse_t) git_submodule_set_fetch_recurse_submodules(
*/
GIT_EXTERN(int) git_submodule_init(git_submodule *submodule, int overwrite);
/**
* Set up the subrepository for a submodule in preparation for clone.
*
* This function can be called to init and set up a submodule
* repository from a submodule in preparation to clone it from
* its remote.
*
* @param out Output pointer to the created git repository.
* @param sm The submodule to create a new subrepository from.
* @param use_gitlink Should the workdir contain a gitlink to
* the repo in .git/modules vs. repo directly in workdir.
* @return 0 on success, <0 on failure.
*/
GIT_EXTERN(int) git_submodule_repo_init(
git_repository **out,
const git_submodule *sm,
int use_gitlink);
/**
* Copy submodule remote info into submodule repo.
*

View File

@ -57,13 +57,15 @@ struct git_config_backend {
/* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *, git_config_level_t level);
int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);
int (*get)(struct git_config_backend *, const char *key, const git_config_entry **entry);
int (*set)(struct git_config_backend *, const char *key, const char *value);
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
int (*del)(struct git_config_backend *, const char *key);
int (*del_multivar)(struct git_config_backend *, const char *key, const char *regexp);
int (*iterator)(git_config_iterator **, struct git_config_backend *);
int (*refresh)(struct git_config_backend *);
/** Produce a read-only version of this backend */
int (*snapshot)(struct git_config_backend **, struct git_config_backend *);
void (*free)(struct git_config_backend *);
};
#define GIT_CONFIG_BACKEND_VERSION 1
@ -73,14 +75,13 @@ struct git_config_backend {
* Initializes a `git_config_backend` with default values. Equivalent to
* creating an instance with GIT_CONFIG_BACKEND_INIT.
*
* @param opts the `git_config_backend` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_CONFIG_BACKEND_VERSION` here.
* @param opts the `git_config_backend` struct to initialize.
* @param version Version of struct; pass `GIT_CONFIG_BACKEND_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_config_init_backend(
git_config_backend* backend,
int version);
git_config_backend *backend,
unsigned int version);
/**
* Add a generic config file instance to an existing config

View File

@ -10,6 +10,8 @@
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
#include "git2/diff.h"
#include "git2/status.h"
/**
* @file git2/sys/diff.h
@ -58,6 +60,32 @@ GIT_EXTERN(int) git_diff_print_callback__to_file_handle(
const git_diff_line *line,
void *payload); /*< payload must be a `FILE *` */
typedef struct {
unsigned int version;
size_t stat_calls;
size_t oid_calculations;
} git_diff_perfdata;
#define GIT_DIFF_PERFDATA_VERSION 1
#define GIT_DIFF_PERFDATA_INIT {GIT_DIFF_PERFDATA_VERSION,0,0}
/**
* Get performance data for a diff object.
*
* @param out Structure to be filled with diff performance data
* @param diff Diff to read performance data from
* @return 0 for success, <0 for error
*/
GIT_EXTERN(int) git_diff_get_perfdata(
git_diff_perfdata *out, const git_diff *diff);
/**
* Get performance data for diffs from a git_status_list
*/
GIT_EXTERN(int) git_status_list_get_perfdata(
git_diff_perfdata *out, const git_status_list *status);
/** @} */
GIT_END_DECL
#endif

View File

@ -55,7 +55,10 @@ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name);
* your own chains of filters.
*/
GIT_EXTERN(int) git_filter_list_new(
git_filter_list **out, git_repository *repo, git_filter_mode_t mode);
git_filter_list **out,
git_repository *repo,
git_filter_mode_t mode,
uint32_t options);
/**
* Add a filter to a filter list with the given payload.
@ -115,10 +118,15 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src);
GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src);
/**
* Get the git_filter_mode_t to be applied
* Get the git_filter_mode_t to be used
*/
GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *src);
/**
* Get the combination git_filter_opt_t options to be applied
*/
GIT_EXTERN(uint32_t) git_filter_source_options(const git_filter_source *src);
/*
* struct git_filter
*

View File

@ -93,14 +93,13 @@ struct git_odb_backend {
* Initializes a `git_odb_backend` with default values. Equivalent to
* creating an instance with GIT_ODB_BACKEND_INIT.
*
* @param opts the `git_odb_backend` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_ODB_BACKEND_VERSION` here.
* @param opts the `git_odb_backend` struct to initialize.
* @param version Version the struct; pass `GIT_ODB_BACKEND_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_odb_init_backend(
git_odb_backend* backend,
int version);
git_odb_backend *backend,
unsigned int version);
GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);

View File

@ -162,14 +162,13 @@ struct git_refdb_backend {
* Initializes a `git_refdb_backend` with default values. Equivalent to
* creating an instance with GIT_REFDB_BACKEND_INIT.
*
* @param opts the `git_refdb_backend` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_REFDB_BACKEND_VERSION` here.
* @param opts the `git_refdb_backend` struct to initialize
* @param version Version of struct; pass `GIT_REFDB_BACKEND_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_refdb_init_backend(
git_refdb_backend* backend,
int version);
git_refdb_backend *backend,
unsigned int version);
/**
* Constructors for default filesystem-based refdb backend

View File

@ -119,6 +119,19 @@ GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb
*/
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
/**
* Set a repository to be bare.
*
* Clear the working directory and set core.bare to true. You may also
* want to call `git_repository_set_index(repo, NULL)` since a bare repo
* typically does not have an index, but this function will not do that
* for you.
*
* @param repo Repo to make bare
* @return 0 on success, <0 on failure
*/
GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
/** @} */
GIT_END_DECL
#endif

View File

@ -0,0 +1,352 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_transport_h
#define INCLUDE_sys_git_transport_h
#include "git2/net.h"
#include "git2/types.h"
/**
* @file git2/sys/transport.h
* @brief Git custom transport registration interfaces and functions
* @defgroup git_transport Git custom transport registration
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
typedef enum {
GIT_TRANSPORTFLAGS_NONE = 0,
} git_transport_flags_t;
typedef struct git_transport git_transport;
struct git_transport {
unsigned int version;
/* Set progress and error callbacks */
int (*set_callbacks)(
git_transport *transport,
git_transport_message_cb progress_cb,
git_transport_message_cb error_cb,
git_transport_certificate_check_cb certificate_check_cb,
void *payload);
/* Connect the transport to the remote repository, using the given
* direction. */
int (*connect)(
git_transport *transport,
const char *url,
git_cred_acquire_cb cred_acquire_cb,
void *cred_acquire_payload,
int direction,
int flags);
/* This function may be called after a successful call to
* connect(). The array returned is owned by the transport and
* is guranteed until the next call of a transport function. */
int (*ls)(
const git_remote_head ***out,
size_t *size,
git_transport *transport);
/* Executes the push whose context is in the git_push object. */
int (*push)(git_transport *transport, git_push *push);
/* This function may be called after a successful call to connect(), when
* the direction is FETCH. The function performs a negotiation to calculate
* the wants list for the fetch. */
int (*negotiate_fetch)(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count);
/* This function may be called after a successful call to negotiate_fetch(),
* when the direction is FETCH. This function retrieves the pack file for
* the fetch from the remote end. */
int (*download_pack)(
git_transport *transport,
git_repository *repo,
git_transfer_progress *stats,
git_transfer_progress_cb progress_cb,
void *progress_payload);
/* Checks to see if the transport is connected */
int (*is_connected)(git_transport *transport);
/* Reads the flags value previously passed into connect() */
int (*read_flags)(git_transport *transport, int *flags);
/* Cancels any outstanding transport operation */
void (*cancel)(git_transport *transport);
/* This function is the reverse of connect() -- it terminates the
* connection to the remote end. */
int (*close)(git_transport *transport);
/* Frees/destructs the git_transport object. */
void (*free)(git_transport *transport);
};
#define GIT_TRANSPORT_VERSION 1
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
/**
* Initializes a `git_transport` with default values. Equivalent to
* creating an instance with GIT_TRANSPORT_INIT.
*
* @param opts the `git_transport` struct to initialize
* @param version Version of struct; pass `GIT_TRANSPORT_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_transport_init(
git_transport *opts,
unsigned int version);
/**
* Function to use to create a transport from a URL. The transport database
* is scanned to find a transport that implements the scheme of the URI (i.e.
* git:// or http://) and a transport object is returned to the caller.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param url The URL to connect to
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const char *url);
/**
* Create an ssh transport with custom git command paths
*
* This is a factory function suitable for setting as the transport
* callback in a remote (or for a clone in the options).
*
* The payload argument must be a strarray pointer with the paths for
* the `git-upload-pack` and `git-receive-pack` at index 0 and 1.
*
* @param out the resulting transport
* @param owner the owning remote
* @param payload a strarray with the paths
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload);
/* Signature of a function which creates a transport */
typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
/**
* Add a custom transport definition, to be used in addition to the built-in
* set of transports that come with libgit2.
*
* The caller is responsible for synchronizing calls to git_transport_register
* and git_transport_unregister with other calls to the library that
* instantiate transports.
*
* @param prefix The scheme (ending in "://") to match, i.e. "git://"
* @param cb The callback used to create an instance of the transport
* @param param A fixed parameter to pass to cb at creation time
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_register(
const char *prefix,
git_transport_cb cb,
void *param);
/**
*
* Unregister a custom transport definition which was previously registered
* with git_transport_register.
*
* @param prefix From the previous call to git_transport_register
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_unregister(
const char *prefix);
/* Transports which come with libgit2 (match git_transport_cb). The expected
* value for "param" is listed in-line below. */
/**
* Create an instance of the dummy transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload You must pass NULL for this parameter.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_dummy(
git_transport **out,
git_remote *owner,
/* NULL */ void *payload);
/**
* Create an instance of the local transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload You must pass NULL for this parameter.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_local(
git_transport **out,
git_remote *owner,
/* NULL */ void *payload);
/**
* Create an instance of the smart transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload A pointer to a git_smart_subtransport_definition
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_smart(
git_transport **out,
git_remote *owner,
/* (git_smart_subtransport_definition *) */ void *payload);
/*
*** End of base transport interface ***
*** Begin interface for subtransports for the smart transport ***
*/
/* The smart transport knows how to speak the git protocol, but it has no
* knowledge of how to establish a connection between it and another endpoint,
* or how to move data back and forth. For this, a subtransport interface is
* declared, and the smart transport delegates this work to the subtransports.
* Three subtransports are implemented: git, http, and winhttp. (The http and
* winhttp transports each implement both http and https.) */
/* Subtransports can either be RPC = 0 (persistent connection) or RPC = 1
* (request/response). The smart transport handles the differences in its own
* logic. The git subtransport is RPC = 0, while http and winhttp are both
* RPC = 1. */
/* Actions that the smart transport can ask
* a subtransport to perform */
typedef enum {
GIT_SERVICE_UPLOADPACK_LS = 1,
GIT_SERVICE_UPLOADPACK = 2,
GIT_SERVICE_RECEIVEPACK_LS = 3,
GIT_SERVICE_RECEIVEPACK = 4,
} git_smart_service_t;
typedef struct git_smart_subtransport git_smart_subtransport;
typedef struct git_smart_subtransport_stream git_smart_subtransport_stream;
/* A stream used by the smart transport to read and write data
* from a subtransport */
struct git_smart_subtransport_stream {
/* The owning subtransport */
git_smart_subtransport *subtransport;
int (*read)(
git_smart_subtransport_stream *stream,
char *buffer,
size_t buf_size,
size_t *bytes_read);
int (*write)(
git_smart_subtransport_stream *stream,
const char *buffer,
size_t len);
void (*free)(
git_smart_subtransport_stream *stream);
};
/* An implementation of a subtransport which carries data for the
* smart transport */
struct git_smart_subtransport {
int (* action)(
git_smart_subtransport_stream **out,
git_smart_subtransport *transport,
const char *url,
git_smart_service_t action);
/* Subtransports are guaranteed a call to close() between
* calls to action(), except for the following two "natural" progressions
* of actions against a constant URL.
*
* 1. UPLOADPACK_LS -> UPLOADPACK
* 2. RECEIVEPACK_LS -> RECEIVEPACK */
int (*close)(git_smart_subtransport *transport);
void (*free)(git_smart_subtransport *transport);
};
/* A function which creates a new subtransport for the smart transport */
typedef int (*git_smart_subtransport_cb)(
git_smart_subtransport **out,
git_transport* owner);
typedef struct git_smart_subtransport_definition {
/* The function to use to create the git_smart_subtransport */
git_smart_subtransport_cb callback;
/* True if the protocol is stateless; false otherwise. For example,
* http:// is stateless, but git:// is not. */
unsigned rpc;
} git_smart_subtransport_definition;
/* Smart transport subtransports that come with libgit2 */
/**
* Create an instance of the http subtransport. This subtransport
* also supports https. On Win32, this subtransport may be implemented
* using the WinHTTP library.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_http(
git_smart_subtransport **out,
git_transport* owner);
/**
* Create an instance of the git subtransport.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_git(
git_smart_subtransport **out,
git_transport* owner);
/**
* Create an instance of the ssh subtransport.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_ssh(
git_smart_subtransport **out,
git_transport* owner);
/**
* Sets a custom transport factory for the remote. The caller can use this
* function to override the transport used for this remote when performing
* network operations.
*
* @param remote the remote to configure
* @param transport_cb the function to use to create a transport
* @param payload opaque parameter passed to transport_cb
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_set_transport(
git_remote *remote,
git_transport_cb transport_cb,
void *payload);
/** @} */
GIT_END_DECL
#endif

View File

@ -11,10 +11,6 @@
#include "net.h"
#include "types.h"
#ifdef GIT_SSH
#include <libssh2.h>
#endif
/**
* @file git2/transport.h
* @brief Git transport interfaces and functions
@ -24,6 +20,63 @@
*/
GIT_BEGIN_DECL
/**
* Type of SSH host fingerprint
*/
typedef enum {
/** MD5 is available */
GIT_CERT_SSH_MD5 = (1 << 0),
/** SHA-1 is available */
GIT_CERT_SSH_SHA1 = (1 << 1),
} git_cert_ssh_t;
/**
* Hostkey information taken from libssh2
*/
typedef struct {
/**
* Type of certificate. Here to share the header with
* `git_cert`.
*/
git_cert_t cert_type;
/**
* A hostkey type from libssh2, either
* `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1`
*/
git_cert_ssh_t type;
/**
* Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will
* have the MD5 hash of the hostkey.
*/
unsigned char hash_md5[16];
/**
* Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will
* have the SHA-1 hash of the hostkey.
*/
unsigned char hash_sha1[20];
} git_cert_hostkey;
/**
* X.509 certificate information
*/
typedef struct {
/**
* Type of certificate. Here to share the header with
* `git_cert`.
*/
git_cert_t cert_type;
/**
* Pointer to the X.509 certificate data
*/
void *data;
/**
* Length of the memory block pointed to by `data`.
*/
size_t len;
} git_cert_x509;
/*
*** Begin interface for credentials acquisition ***
*/
@ -44,6 +97,14 @@ typedef enum {
/* git_cred_ssh_interactive */
GIT_CREDTYPE_SSH_INTERACTIVE = (1u << 4),
/**
* Username-only information
*
* If the SSH transport does not know which username to use,
* it will ask via this credential type.
*/
GIT_CREDTYPE_USERNAME = (1u << 5),
} git_credtype_t;
/* The base structure for all credential types */
@ -61,14 +122,20 @@ typedef struct {
char *password;
} git_cred_userpass_plaintext;
#ifdef GIT_SSH
typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback));
typedef LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*git_cred_ssh_interactive_callback));
#else
typedef int (*git_cred_sign_callback)(void *, ...);
typedef int (*git_cred_ssh_interactive_callback)(void *, ...);
/*
* If the user hasn't included libssh2.h before git2.h, we need to
* define a few types for the callback signatures.
*/
#ifndef LIBSSH2_VERSION
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT;
typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE;
#endif
typedef int (*git_cred_sign_callback)(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract);
typedef void (*git_cred_ssh_interactive_callback)(const char* name, int name_len, const char* instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract);
/**
* A ssh key from disk
*/
@ -105,6 +172,12 @@ typedef struct git_cred_ssh_custom {
/** A key for NTLM/Kerberos "default" credentials */
typedef struct git_cred git_cred_default;
/** Username-only credential information */
typedef struct git_cred_username {
git_cred parent;
char username[1];
} git_cred_username;
/**
* Check whether a credential object contains username information.
*
@ -206,6 +279,14 @@ GIT_EXTERN(int) git_cred_ssh_custom_new(
*/
GIT_EXTERN(int) git_cred_default_new(git_cred **out);
/**
* Create a credential to specify a username.
*
* This is used with ssh authentication to query for the username if
* none is specified in the url.
*/
GIT_EXTERN(int) git_cred_username_new(git_cred **cred, const char *username);
/**
* Signature of a function which acquires a credential object.
*
@ -225,320 +306,6 @@ typedef int (*git_cred_acquire_cb)(
unsigned int allowed_types,
void *payload);
/*
*** End interface for credentials acquisition ***
*** Begin base transport interface ***
*/
typedef enum {
GIT_TRANSPORTFLAGS_NONE = 0,
/* If the connection is secured with SSL/TLS, the authenticity
* of the server certificate should not be verified. */
GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1
} git_transport_flags_t;
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
typedef struct git_transport git_transport;
struct git_transport {
unsigned int version;
/* Set progress and error callbacks */
int (*set_callbacks)(
git_transport *transport,
git_transport_message_cb progress_cb,
git_transport_message_cb error_cb,
void *payload);
/* Connect the transport to the remote repository, using the given
* direction. */
int (*connect)(
git_transport *transport,
const char *url,
git_cred_acquire_cb cred_acquire_cb,
void *cred_acquire_payload,
int direction,
int flags);
/* This function may be called after a successful call to
* connect(). The array returned is owned by the transport and
* is guranteed until the next call of a transport function. */
int (*ls)(
const git_remote_head ***out,
size_t *size,
git_transport *transport);
/* Executes the push whose context is in the git_push object. */
int (*push)(git_transport *transport, git_push *push);
/* This function may be called after a successful call to connect(), when
* the direction is FETCH. The function performs a negotiation to calculate
* the wants list for the fetch. */
int (*negotiate_fetch)(
git_transport *transport,
git_repository *repo,
const git_remote_head * const *refs,
size_t count);
/* This function may be called after a successful call to negotiate_fetch(),
* when the direction is FETCH. This function retrieves the pack file for
* the fetch from the remote end. */
int (*download_pack)(
git_transport *transport,
git_repository *repo,
git_transfer_progress *stats,
git_transfer_progress_cb progress_cb,
void *progress_payload);
/* Checks to see if the transport is connected */
int (*is_connected)(git_transport *transport);
/* Reads the flags value previously passed into connect() */
int (*read_flags)(git_transport *transport, int *flags);
/* Cancels any outstanding transport operation */
void (*cancel)(git_transport *transport);
/* This function is the reverse of connect() -- it terminates the
* connection to the remote end. */
int (*close)(git_transport *transport);
/* Frees/destructs the git_transport object. */
void (*free)(git_transport *transport);
};
#define GIT_TRANSPORT_VERSION 1
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
/**
* Initializes a `git_transport` with default values. Equivalent to
* creating an instance with GIT_TRANSPORT_INIT.
*
* @param opts the `git_transport` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_TRANSPORT_VERSION` here.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_transport_init(
git_transport* opts,
int version);
/**
* Function to use to create a transport from a URL. The transport database
* is scanned to find a transport that implements the scheme of the URI (i.e.
* git:// or http://) and a transport object is returned to the caller.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param url The URL to connect to
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const char *url);
/* Signature of a function which creates a transport */
typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
/**
* Add a custom transport definition, to be used in addition to the built-in
* set of transports that come with libgit2.
*
* The caller is responsible for synchronizing calls to git_transport_register
* and git_transport_unregister with other calls to the library that
* instantiate transports.
*
* @param prefix The scheme (ending in "://") to match, i.e. "git://"
* @param priority The priority of this transport relative to others with
* the same prefix. Built-in transports have a priority of 1.
* @param cb The callback used to create an instance of the transport
* @param param A fixed parameter to pass to cb at creation time
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_register(
const char *prefix,
unsigned priority,
git_transport_cb cb,
void *param);
/**
*
* Unregister a custom transport definition which was previously registered
* with git_transport_register.
*
* @param prefix From the previous call to git_transport_register
* @param priority From the previous call to git_transport_register
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_unregister(
const char *prefix,
unsigned priority);
/* Transports which come with libgit2 (match git_transport_cb). The expected
* value for "param" is listed in-line below. */
/**
* Create an instance of the dummy transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload You must pass NULL for this parameter.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_dummy(
git_transport **out,
git_remote *owner,
/* NULL */ void *payload);
/**
* Create an instance of the local transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload You must pass NULL for this parameter.
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_local(
git_transport **out,
git_remote *owner,
/* NULL */ void *payload);
/**
* Create an instance of the smart transport.
*
* @param out The newly created transport (out)
* @param owner The git_remote which will own this transport
* @param payload A pointer to a git_smart_subtransport_definition
* @return 0 or an error code
*/
GIT_EXTERN(int) git_transport_smart(
git_transport **out,
git_remote *owner,
/* (git_smart_subtransport_definition *) */ void *payload);
/*
*** End of base transport interface ***
*** Begin interface for subtransports for the smart transport ***
*/
/* The smart transport knows how to speak the git protocol, but it has no
* knowledge of how to establish a connection between it and another endpoint,
* or how to move data back and forth. For this, a subtransport interface is
* declared, and the smart transport delegates this work to the subtransports.
* Three subtransports are implemented: git, http, and winhttp. (The http and
* winhttp transports each implement both http and https.) */
/* Subtransports can either be RPC = 0 (persistent connection) or RPC = 1
* (request/response). The smart transport handles the differences in its own
* logic. The git subtransport is RPC = 0, while http and winhttp are both
* RPC = 1. */
/* Actions that the smart transport can ask
* a subtransport to perform */
typedef enum {
GIT_SERVICE_UPLOADPACK_LS = 1,
GIT_SERVICE_UPLOADPACK = 2,
GIT_SERVICE_RECEIVEPACK_LS = 3,
GIT_SERVICE_RECEIVEPACK = 4,
} git_smart_service_t;
typedef struct git_smart_subtransport git_smart_subtransport;
typedef struct git_smart_subtransport_stream git_smart_subtransport_stream;
/* A stream used by the smart transport to read and write data
* from a subtransport */
struct git_smart_subtransport_stream {
/* The owning subtransport */
git_smart_subtransport *subtransport;
int (*read)(
git_smart_subtransport_stream *stream,
char *buffer,
size_t buf_size,
size_t *bytes_read);
int (*write)(
git_smart_subtransport_stream *stream,
const char *buffer,
size_t len);
void (*free)(
git_smart_subtransport_stream *stream);
};
/* An implementation of a subtransport which carries data for the
* smart transport */
struct git_smart_subtransport {
int (* action)(
git_smart_subtransport_stream **out,
git_smart_subtransport *transport,
const char *url,
git_smart_service_t action);
/* Subtransports are guaranteed a call to close() between
* calls to action(), except for the following two "natural" progressions
* of actions against a constant URL.
*
* 1. UPLOADPACK_LS -> UPLOADPACK
* 2. RECEIVEPACK_LS -> RECEIVEPACK */
int (*close)(git_smart_subtransport *transport);
void (*free)(git_smart_subtransport *transport);
};
/* A function which creates a new subtransport for the smart transport */
typedef int (*git_smart_subtransport_cb)(
git_smart_subtransport **out,
git_transport* owner);
typedef struct git_smart_subtransport_definition {
/* The function to use to create the git_smart_subtransport */
git_smart_subtransport_cb callback;
/* True if the protocol is stateless; false otherwise. For example,
* http:// is stateless, but git:// is not. */
unsigned rpc;
} git_smart_subtransport_definition;
/* Smart transport subtransports that come with libgit2 */
/**
* Create an instance of the http subtransport. This subtransport
* also supports https. On Win32, this subtransport may be implemented
* using the WinHTTP library.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_http(
git_smart_subtransport **out,
git_transport* owner);
/**
* Create an instance of the git subtransport.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_git(
git_smart_subtransport **out,
git_transport* owner);
/**
* Create an instance of the ssh subtransport.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_ssh(
git_smart_subtransport **out,
git_transport* owner);
/*
*** End interface for subtransports for the smart transport ***
*/
/** @} */
GIT_END_DECL
#endif

View File

@ -151,7 +151,7 @@ GIT_EXTERN(int) git_tree_entry_bypath(
* and must be freed explicitly with `git_tree_entry_free()`.
*
* @param dest pointer where to store the copy
* @param entry tree entry to duplicate
* @param source tree entry to duplicate
* @return 0 or an error code
*/
GIT_EXTERN(int) git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source);
@ -301,8 +301,10 @@ GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(
* If an entry named `filename` already exists, its attributes
* will be updated with the given ones.
*
* The optional pointer `out` can be used to retrieve a pointer to
* the newly created/updated entry. Pass NULL if you do not need it.
* The optional pointer `out` can be used to retrieve a pointer to the
* newly created/updated entry. Pass NULL if you do not need it. The
* pointer may not be valid past the next operation in this
* builder. Duplicate the entry if you want to keep it.
*
* No attempt is being made to ensure that the provided oid points
* to an existing git object in the object database, nor that the

View File

@ -154,15 +154,15 @@ typedef struct git_packbuilder git_packbuilder;
/** Time in a signature */
typedef struct git_time {
git_time_t time; /** time in seconds from epoch */
int offset; /** timezone offset, in minutes */
git_time_t time; /**< time in seconds from epoch */
int offset; /**< timezone offset, in minutes */
} git_time;
/** An action signature (e.g. for committers, taggers, etc) */
typedef struct git_signature {
char *name; /** full name of the author */
char *email; /** email of the author */
git_time when; /** time when the action happened */
char *name; /**< full name of the author */
char *email; /**< email of the author */
git_time when; /**< time when the action happened */
} git_signature;
/** In-memory representation of a reference. */
@ -183,9 +183,9 @@ typedef struct git_status_list git_status_list;
/** Basic type of any Git reference. */
typedef enum {
GIT_REF_INVALID = 0, /** Invalid reference */
GIT_REF_OID = 1, /** A reference which points at an object id */
GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */
GIT_REF_INVALID = 0, /**< Invalid reference */
GIT_REF_OID = 1, /**< A reference which points at an object id */
GIT_REF_SYMBOLIC = 2, /**< A reference which points at another reference */
GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC,
} git_ref_t;
@ -198,12 +198,12 @@ typedef enum {
/** Valid modes for index and tree entries. */
typedef enum {
GIT_FILEMODE_NEW = 0000000,
GIT_FILEMODE_TREE = 0040000,
GIT_FILEMODE_BLOB = 0100644,
GIT_FILEMODE_BLOB_EXECUTABLE = 0100755,
GIT_FILEMODE_LINK = 0120000,
GIT_FILEMODE_COMMIT = 0160000,
GIT_FILEMODE_UNREADABLE = 0000000,
GIT_FILEMODE_TREE = 0040000,
GIT_FILEMODE_BLOB = 0100644,
GIT_FILEMODE_BLOB_EXECUTABLE = 0100755,
GIT_FILEMODE_LINK = 0120000,
GIT_FILEMODE_COMMIT = 0160000,
} git_filemode_t;
typedef struct git_refspec git_refspec;
@ -243,6 +243,54 @@ typedef struct git_transfer_progress {
*/
typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload);
/**
* Type for messages delivered by the transport. Return a negative value
* to cancel the network operation.
*
* @param str The message from the transport
* @param len The length of the message
* @param payload Payload provided by the caller
*/
typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
/**
* Type of host certificate structure that is passed to the check callback
*/
typedef enum git_cert_t {
/**
* The `data` argument to the callback will be a pointer to
* the DER-encoded data.
*/
GIT_CERT_X509,
/**
* The `data` argument to the callback will be a pointer to a
* `git_cert_hostkey` structure.
*/
GIT_CERT_HOSTKEY_LIBSSH2,
} git_cert_t;
/**
* Parent type for `git_cert_hostkey` and `git_cert_x509`.
*/
typedef struct {
/**
* Type of certificate. A `GIT_CERT_` value.
*/
git_cert_t cert_type;
} git_cert;
/**
* Callback for the user's custom certificate checks.
*
* @param type The type of certificate or host info, SSH or X.509
* @param data The data for the certificate or host info
* @param len The size of the certificate or host info
* @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think
* this certificate is valid
* @param payload Payload provided by the caller
*/
typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, void *payload);
/**
* Opaque structure representing a submodule.
*/
@ -314,12 +362,12 @@ typedef enum {
* when we don't want any particular ignore rule to be specified.
*/
typedef enum {
GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */
GIT_SUBMODULE_IGNORE_RESET = -1, /**< reset to on-disk value */
GIT_SUBMODULE_IGNORE_NONE = 1, /* any change or untracked == dirty */
GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */
GIT_SUBMODULE_IGNORE_DIRTY = 3, /* only dirty if HEAD moved */
GIT_SUBMODULE_IGNORE_ALL = 4, /* never dirty */
GIT_SUBMODULE_IGNORE_NONE = 1, /**< any change or untracked == dirty */
GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /**< dirty if tracked files change */
GIT_SUBMODULE_IGNORE_DIRTY = 3, /**< only dirty if HEAD moved */
GIT_SUBMODULE_IGNORE_ALL = 4, /**< never dirty */
GIT_SUBMODULE_IGNORE_DEFAULT = 0
} git_submodule_ignore_t;

View File

@ -7,9 +7,11 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.20.0"
#define LIBGIT2_VERSION "0.21.0"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 20
#define LIBGIT2_VER_MINOR 21
#define LIBGIT2_VER_REVISION 0
#define LIBGIT2_SOVERSION 21
#endif

View File

@ -1,6 +1,6 @@
#!/bin/sh
if [ "$COVERITY" -eq 1 ];
if [ -n "$COVERITY" ];
then
./script/coverity.sh;
exit $?;
@ -15,18 +15,27 @@ export GITTEST_REMOTE_URL="git://localhost/test.git"
mkdir _build
cd _build
cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
cmake --build . --target install || exit $?
make -j2 install || exit $?
ctest -V . || 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
sudo start ssh
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
echo 'PasswordAuthentication yes' | sudo tee -a /etc/sshd_config
else
sudo start ssh
fi
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts
# Get the fingerprint for localhost and remove the colons so we can parse it as a hex number
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F localhost -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git"
export GITTEST_REMOTE_USER=$USER
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
@ -34,5 +43,6 @@ export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE=""
if [ -e ./libgit2_clar ]; then
./libgit2_clar -sonline::push -sonline::clone::cred_callback_failure
./libgit2_clar -sonline::push -sonline::clone::cred_callback -sonline::clone::ssh_cert &&
./libgit2_clar -sonline::clone::ssh_with_paths
fi

6
script/install-deps-linux.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
set -x
sudo apt-get -qq update &&
sudo apt-get -qq install cmake libssh2-1-dev openssh-client openssh-server

5
script/install-deps-osx.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
set -x
brew install libssh2 cmake

View File

@ -44,7 +44,7 @@ typedef git_array_t(char) git_array_generic_t;
/* use a generic array for growth so this can return the new item */
GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
{
git_array_generic_t *a = _a;
volatile git_array_generic_t *a = _a;
uint32_t new_size = (a->size < 8) ? 8 : a->asize * 3 / 2;
char *new_array = git__realloc(a->ptr, new_size * item_size);
if (!new_array) {

View File

@ -377,7 +377,7 @@ static int push_attr_file(
return error;
}
static int push_one_attr(void *ref, git_buf *path)
static int push_one_attr(void *ref, const char *path)
{
int error = 0, n_src, i;
attr_walk_up_info *info = (attr_walk_up_info *)ref;
@ -388,7 +388,7 @@ static int push_one_attr(void *ref, git_buf *path)
for (i = 0; !error && i < n_src; ++i)
error = push_attr_file(
info->repo, info->files, src[i], path->ptr, GIT_ATTR_FILE);
info->repo, info->files, src[i], path, GIT_ATTR_FILE);
return error;
}
@ -411,7 +411,7 @@ static int collect_attr_files(
const char *path,
git_vector *files)
{
int error;
int error = 0;
git_buf dir = GIT_BUF_INIT;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
@ -447,7 +447,11 @@ static int collect_attr_files(
giterr_clear(); /* no error even if there is no index */
info.files = files;
error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
if (!strcmp(dir.ptr, "."))
error = push_one_attr(&info, "");
else
error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
if (error < 0)
goto cleanup;

View File

@ -281,7 +281,7 @@ uint32_t git_attr_file__name_hash(const char *name)
int git_attr_file__lookup_one(
git_attr_file *file,
const git_attr_path *path,
git_attr_path *path,
const char *attr,
const char **value)
{
@ -342,14 +342,11 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path)
bool git_attr_fnmatch__match(
git_attr_fnmatch *match,
const git_attr_path *path)
git_attr_path *path)
{
const char *filename;
int flags = 0;
if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir)
return false;
if (match->flags & GIT_ATTR_FNMATCH_ICASE)
flags |= FNM_CASEFOLD;
if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR)
@ -365,12 +362,40 @@ bool git_attr_fnmatch__match(
flags |= FNM_LEADING_DIR;
}
if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) {
int matchval;
/* for attribute checks or root ignore checks, fail match */
if (!(match->flags & GIT_ATTR_FNMATCH_IGNORE) ||
path->basename == path->path)
return false;
/* for ignore checks, use container of current item for check */
path->basename[-1] = '\0';
flags |= FNM_LEADING_DIR;
matchval = p_fnmatch(match->pattern, path->path, flags);
path->basename[-1] = '/';
return (matchval != FNM_NOMATCH);
}
/* if path is a directory prefix of a negated pattern, then match */
if ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) && path->is_dir) {
size_t pathlen = strlen(path->path);
bool prefixed = (pathlen <= match->length) &&
((match->flags & GIT_ATTR_FNMATCH_ICASE) ?
!strncasecmp(match->pattern, path->path, pathlen) :
!strncmp(match->pattern, path->path, pathlen));
if (prefixed && git_path_at_end_of_segment(&match->pattern[pathlen]))
return true;
}
return (p_fnmatch(match->pattern, filename, flags) != FNM_NOMATCH);
}
bool git_attr_rule__match(
git_attr_rule *rule,
const git_attr_path *path)
git_attr_path *path)
{
bool matched = git_attr_fnmatch__match(&rule->match, path);
@ -509,7 +534,8 @@ int git_attr_fnmatch__parse(
}
if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) {
spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE;
spec->flags = spec->flags |
GIT_ATTR_FNMATCH_NEGATIVE | GIT_ATTR_FNMATCH_LEADINGDIR;
pattern++;
}

View File

@ -138,7 +138,7 @@ int git_attr_file__clear_rules(
int git_attr_file__lookup_one(
git_attr_file *file,
const git_attr_path *path,
git_attr_path *path,
const char *attr,
const char **value);
@ -162,13 +162,13 @@ extern int git_attr_fnmatch__parse(
extern bool git_attr_fnmatch__match(
git_attr_fnmatch *rule,
const git_attr_path *path);
git_attr_path *path);
extern void git_attr_rule__free(git_attr_rule *rule);
extern bool git_attr_rule__match(
git_attr_rule *rule,
const git_attr_path *path);
git_attr_path *path);
extern git_attr_assignment *git_attr_rule__lookup_assignment(
git_attr_rule *rule, const char *name);

View File

@ -53,7 +53,7 @@ int git_attr_cache__alloc_file_entry(
cachesize++;
}
ce = git_pool_mallocz(pool, cachesize);
ce = git_pool_mallocz(pool, (uint32_t)cachesize);
GITERR_CHECK_ALLOC(ce);
if (baselen) {
@ -349,14 +349,11 @@ int git_attr_cache__do_init(git_repository *repo)
{
int ret = 0;
git_attr_cache *cache = git_repository_attr_cache(repo);
git_config *cfg;
git_config *cfg = NULL;
if (cache)
return 0;
if ((ret = git_repository_config__weakptr(&cfg, repo)) < 0)
return ret;
cache = git__calloc(1, sizeof(git_attr_cache));
GITERR_CHECK_ALLOC(cache);
@ -367,6 +364,9 @@ int git_attr_cache__do_init(git_repository *repo)
return -1;
}
if ((ret = git_repository_config_snapshot(&cfg, repo)) < 0)
goto cancel;
/* cache config settings for attributes and ignores */
ret = attr_cache__lookup_path(
&cache->cfg_attr_file, cfg, GIT_ATTR_CONFIG, GIT_ATTR_FILE_XDG);
@ -390,11 +390,14 @@ int git_attr_cache__do_init(git_repository *repo)
if (cache)
goto cancel; /* raced with another thread, free this but no error */
git_config_free(cfg);
/* insert default macros */
return git_attr_add_macro(repo, "binary", "-diff -crlf -text");
cancel:
attr_cache__free(cache);
git_config_free(cfg);
return ret;
}

View File

@ -316,7 +316,6 @@ static int blame_internal(git_blame *blame)
ent->suspect = o;
blame->ent = ent;
blame->path = blame->path;
git_blame__like_git(blame, blame->options.flags);
@ -480,14 +479,9 @@ int git_blame_buffer(
return 0;
}
int git_blame_init_options(git_blame_options* opts, int version)
int git_blame_init_options(git_blame_options *opts, unsigned int version)
{
if (version != GIT_BLAME_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_blame_options", version);
return -1;
} else {
git_blame_options o = GIT_BLAME_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o));
return 0;
}
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
opts, version, git_blame_options, GIT_BLAME_OPTIONS_INIT);
return 0;
}

View File

@ -198,7 +198,8 @@ int git_blob__create_from_paths(
if (try_load_filters)
/* Load the filters for writing this file to the ODB */
error = git_filter_list_load(
&fl, repo, NULL, hint_path, GIT_FILTER_TO_ODB);
&fl, repo, NULL, hint_path,
GIT_FILTER_TO_ODB, GIT_FILTER_OPT_DEFAULT);
if (error < 0)
/* well, that didn't work */;
@ -333,7 +334,8 @@ int git_blob_is_binary(const git_blob *blob)
assert(blob);
content.ptr = blob->odb_object->buffer;
content.size = min(blob->odb_object->cached.size, 4000);
content.size =
min(blob->odb_object->cached.size, GIT_FILTER_BYTES_TO_CHECK_NUL);
content.asize = 0;
return git_buf_text_is_binary(&content);
@ -356,7 +358,8 @@ int git_blob_filtered_content(
return 0;
if (!(error = git_filter_list_load(
&fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE))) {
&fl, git_blob_owner(blob), blob, path,
GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT))) {
error = git_filter_list_apply_to_blob(out, fl, blob);

View File

@ -306,17 +306,13 @@ int git_branch_name(
static int retrieve_upstream_configuration(
const char **out,
git_repository *repo,
const git_config *config,
const char *canonical_branch_name,
const char *format)
{
git_config *config;
git_buf buf = GIT_BUF_INIT;
int error;
if (git_repository_config__weakptr(&config, repo) < 0)
return -1;
if (git_buf_printf(&buf, format,
canonical_branch_name + strlen(GIT_REFS_HEADS_DIR)) < 0)
return -1;
@ -336,6 +332,7 @@ int git_branch_upstream_name(
int error = -1;
git_remote *remote = NULL;
const git_refspec *refspec;
git_config *config;
assert(out && refname);
@ -344,12 +341,15 @@ int git_branch_upstream_name(
if (!git_reference__is_branch(refname))
return not_a_local_branch(refname);
if ((error = git_repository_config_snapshot(&config, repo)) < 0)
return error;
if ((error = retrieve_upstream_configuration(
&remote_name, repo, refname, "branch.%s.remote")) < 0)
&remote_name, config, refname, "branch.%s.remote")) < 0)
goto cleanup;
if ((error = retrieve_upstream_configuration(
&merge_name, repo, refname, "branch.%s.merge")) < 0)
&merge_name, config, refname, "branch.%s.merge")) < 0)
goto cleanup;
if (!*remote_name || !*merge_name) {
@ -378,6 +378,7 @@ int git_branch_upstream_name(
error = git_buf_set(out, git_buf_cstr(&buf), git_buf_len(&buf));
cleanup:
git_config_free(config);
git_remote_free(remote);
git_buf_free(&buf);
return error;

View File

@ -123,9 +123,13 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
size_t copylen = next - scan;
/* don't convert existing \r\n to \r\r\n */
size_t extralen = (next > start && next[-1] == '\r') ? 1 : 2;
size_t needsize = tgt->size + copylen + extralen + 1;
size_t needsize = tgt->size + copylen + 2 + 1;
/* if we find mixed line endings, bail */
if (next > start && next[-1] == '\r') {
git_buf_free(tgt);
return GIT_PASSTHROUGH;
}
if (tgt->asize < needsize && git_buf_grow(tgt, needsize) < 0)
return -1;
@ -134,8 +138,8 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
memcpy(tgt->ptr + tgt->size, scan, copylen);
tgt->size += copylen;
}
if (extralen == 2)
tgt->ptr[tgt->size++] = '\r';
tgt->ptr[tgt->size++] = '\r';
tgt->ptr[tgt->size++] = '\n';
}

View File

@ -56,9 +56,10 @@ GIT_INLINE(int) git_buf_text_puts_escape_regex(git_buf *buf, const char *string)
extern void git_buf_text_unescape(git_buf *buf);
/**
* Replace all \r\n with \n. Does not modify \r without trailing \n.
* Replace all \r\n with \n.
*
* @return 0 on success, -1 on memory error
* @return 0 on success, -1 on memory error, GIT_PASSTHROUGH if the
* source buffer has mixed line endings.
*/
extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src);

View File

@ -7,6 +7,7 @@
#include "buffer.h"
#include "posix.h"
#include "git2/buffer.h"
#include "buf_text.h"
#include <ctype.h>
/* Used as default value for git_buf->ptr so that people can always
@ -104,17 +105,20 @@ void git_buf_free(git_buf *buf)
void git_buf_sanitize(git_buf *buf)
{
if (buf->ptr == NULL) {
assert (buf->size == 0 && buf->asize == 0);
assert(buf->size == 0 && buf->asize == 0);
buf->ptr = git_buf__initbuf;
}
} else if (buf->asize > buf->size)
buf->ptr[buf->size] = '\0';
}
void git_buf_clear(git_buf *buf)
{
buf->size = 0;
if (!buf->ptr)
if (!buf->ptr) {
buf->ptr = git_buf__initbuf;
buf->asize = 0;
}
if (buf->asize > 0)
buf->ptr[0] = '\0';
@ -129,12 +133,25 @@ int git_buf_set(git_buf *buf, const void *data, size_t len)
ENSURE_SIZE(buf, len + 1);
memmove(buf->ptr, data, len);
}
buf->size = len;
buf->ptr[buf->size] = '\0';
if (buf->asize > buf->size)
buf->ptr[buf->size] = '\0';
}
return 0;
}
int git_buf_is_binary(const git_buf *buf)
{
return git_buf_text_is_binary(buf);
}
int git_buf_contains_nul(const git_buf *buf)
{
return git_buf_text_contains_nul(buf);
}
int git_buf_sets(git_buf *buf, const char *string)
{
return git_buf_set(buf, string, string ? strlen(string) : 0);
@ -172,10 +189,10 @@ int git_buf_puts(git_buf *buf, const char *string)
return git_buf_put(buf, string, strlen(string));
}
static const char b64str[] =
static const char base64_encode[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int git_buf_put_base64(git_buf *buf, const char *data, size_t len)
int git_buf_encode_base64(git_buf *buf, const char *data, size_t len)
{
size_t extra = len % 3;
uint8_t *write, a, b, c;
@ -190,19 +207,19 @@ int git_buf_put_base64(git_buf *buf, const char *data, size_t len)
b = *read++;
c = *read++;
*write++ = b64str[a >> 2];
*write++ = b64str[(a & 0x03) << 4 | b >> 4];
*write++ = b64str[(b & 0x0f) << 2 | c >> 6];
*write++ = b64str[c & 0x3f];
*write++ = base64_encode[a >> 2];
*write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
*write++ = base64_encode[(b & 0x0f) << 2 | c >> 6];
*write++ = base64_encode[c & 0x3f];
}
if (extra > 0) {
a = *read++;
b = (extra > 1) ? *read++ : 0;
*write++ = b64str[a >> 2];
*write++ = b64str[(a & 0x03) << 4 | b >> 4];
*write++ = (extra > 1) ? b64str[(b & 0x0f) << 2] : '=';
*write++ = base64_encode[a >> 2];
*write++ = base64_encode[(a & 0x03) << 4 | b >> 4];
*write++ = (extra > 1) ? base64_encode[(b & 0x0f) << 2] : '=';
*write++ = '=';
}
@ -212,10 +229,56 @@ int git_buf_put_base64(git_buf *buf, const char *data, size_t len)
return 0;
}
/* The inverse of base64_encode, offset by '+' == 43. */
static const int8_t base64_decode[] = {
62,
-1, -1, -1,
63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-1, -1, -1, 0, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-1, -1, -1, -1, -1, -1,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
#define BASE64_DECODE_VALUE(c) (((c) < 43 || (c) > 122) ? -1 : base64_decode[c - 43])
int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len)
{
size_t i;
int8_t a, b, c, d;
size_t orig_size = buf->size;
assert(len % 4 == 0);
ENSURE_SIZE(buf, buf->size + (len / 4 * 3) + 1);
for (i = 0; i < len; i += 4) {
if ((a = BASE64_DECODE_VALUE(base64[i])) < 0 ||
(b = BASE64_DECODE_VALUE(base64[i+1])) < 0 ||
(c = BASE64_DECODE_VALUE(base64[i+2])) < 0 ||
(d = BASE64_DECODE_VALUE(base64[i+3])) < 0) {
buf->size = orig_size;
buf->ptr[buf->size] = '\0';
giterr_set(GITERR_INVALID, "Invalid base64 input");
return -1;
}
buf->ptr[buf->size++] = ((a << 2) | (b & 0x30) >> 4);
buf->ptr[buf->size++] = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
buf->ptr[buf->size++] = (c & 0x03) << 6 | (d & 0x3f);
}
buf->ptr[buf->size] = '\0';
return 0;
}
static const char b85str[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
int git_buf_put_base85(git_buf *buf, const char *data, size_t len)
int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
{
ENSURE_SIZE(buf, buf->size + (5 * ((len / 4) + !!(len % 4))) + 1);
@ -326,19 +389,20 @@ void git_buf_consume(git_buf *buf, const char *end)
void git_buf_truncate(git_buf *buf, size_t len)
{
if (len < buf->size) {
buf->size = len;
if (len >= buf->size)
return;
buf->size = len;
if (buf->size < buf->asize)
buf->ptr[buf->size] = '\0';
}
}
void git_buf_shorten(git_buf *buf, size_t amount)
{
if (amount > buf->size)
amount = buf->size;
buf->size = buf->size - amount;
buf->ptr[buf->size] = '\0';
if (buf->size > amount)
git_buf_truncate(buf, buf->size - amount);
else
git_buf_clear(buf);
}
void git_buf_rtruncate_at_char(git_buf *buf, char separator)
@ -574,7 +638,8 @@ void git_buf_rtrim(git_buf *buf)
buf->size--;
}
buf->ptr[buf->size] = '\0';
if (buf->asize > buf->size)
buf->ptr[buf->size] = '\0';
}
int git_buf_cmp(const git_buf *a, const git_buf *b)
@ -598,8 +663,7 @@ int git_buf_splice(
/* Ported from git.git
* https://github.com/git/git/blob/16eed7c/strbuf.c#L159-176
*/
if (git_buf_grow(buf, git_buf_len(buf) + nb_to_insert - nb_to_remove) < 0)
return -1;
ENSURE_SIZE(buf, buf->size + nb_to_insert - nb_to_insert + 1);
memmove(buf->ptr + where + nb_to_insert,
buf->ptr + where + nb_to_remove,

View File

@ -156,10 +156,12 @@ void git_buf_rtrim(git_buf *buf);
int git_buf_cmp(const git_buf *a, const git_buf *b);
/* Write data as base64 encoded in buffer */
int git_buf_put_base64(git_buf *buf, const char *data, size_t len);
int git_buf_encode_base64(git_buf *buf, const char *data, size_t len);
/* Decode the given bas64 and write the result to the buffer */
int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len);
/* Write data as "base85" encoded in buffer */
int git_buf_put_base85(git_buf *buf, const char *data, size_t len);
int git_buf_encode_base85(git_buf *buf, const char *data, size_t len);
/*
* Insert, remove or replace a portion of the buffer.

View File

@ -68,8 +68,8 @@ int git_cache_init(git_cache *cache)
{
memset(cache, 0, sizeof(*cache));
cache->map = git_oidmap_alloc();
if (git_mutex_init(&cache->lock)) {
giterr_set(GITERR_OS, "Failed to initialize cache mutex");
if (git_rwlock_init(&cache->lock)) {
giterr_set(GITERR_OS, "Failed to initialize cache rwlock");
return -1;
}
return 0;
@ -94,19 +94,19 @@ static void clear_cache(git_cache *cache)
void git_cache_clear(git_cache *cache)
{
if (git_mutex_lock(&cache->lock) < 0)
if (git_rwlock_wrlock(&cache->lock) < 0)
return;
clear_cache(cache);
git_mutex_unlock(&cache->lock);
git_rwlock_wrunlock(&cache->lock);
}
void git_cache_free(git_cache *cache)
{
git_cache_clear(cache);
git_oidmap_free(cache->map);
git_mutex_free(&cache->lock);
git_rwlock_free(&cache->lock);
git__memzero(cache, sizeof(*cache));
}
@ -152,7 +152,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
khiter_t pos;
git_cached_obj *entry = NULL;
if (!git_cache__enabled || git_mutex_lock(&cache->lock) < 0)
if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0)
return NULL;
pos = kh_get(oid, cache->map, oid);
@ -166,7 +166,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
}
}
git_mutex_unlock(&cache->lock);
git_rwlock_rdunlock(&cache->lock);
return entry;
}
@ -185,7 +185,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
if (!cache_should_store(entry->type, entry->size))
return entry;
if (git_mutex_lock(&cache->lock) < 0)
if (git_rwlock_wrlock(&cache->lock) < 0)
return entry;
/* soften the load on the cache */
@ -227,7 +227,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
}
}
git_mutex_unlock(&cache->lock);
git_rwlock_wrunlock(&cache->lock);
return entry;
}

View File

@ -30,7 +30,7 @@ typedef struct {
typedef struct {
git_oidmap *map;
git_mutex lock;
git_rwlock lock;
ssize_t used_memory;
} git_cache;

View File

@ -35,6 +35,14 @@
# define GIT_TYPEOF(x)
#endif
#if defined(__GNUC__)
# define GIT_ALIGN(x,size) x __attribute__ ((aligned(size)))
#elif defined(_MSC_VER)
# define GIT_ALIGN(x,size) __declspec(align(size)) x
#else
# define GIT_ALIGN(x,size) x
#endif
#define GIT_UNUSED(x) ((void)(x))
/* Define the printf format specifer to use for size_t output */

View File

@ -46,6 +46,7 @@ enum {
typedef struct {
git_repository *repo;
git_iterator *target;
git_diff *diff;
git_checkout_options opts;
bool opts_free_baseline;
@ -54,6 +55,8 @@ typedef struct {
git_pool pool;
git_vector removes;
git_vector conflicts;
git_vector *reuc;
git_vector *names;
git_buf path;
size_t workdir_len;
git_buf tmp;
@ -116,6 +119,7 @@ static int checkout_notify(
case GIT_DELTA_ADDED:
case GIT_DELTA_IGNORED:
case GIT_DELTA_UNTRACKED:
case GIT_DELTA_UNREADABLE:
target = &delta->new_file;
break;
case GIT_DELTA_DELETED:
@ -138,6 +142,7 @@ static int checkout_notify(
static bool checkout_is_workdir_modified(
checkout_data *data,
const git_diff_file *baseitem,
const git_diff_file *newitem,
const git_index_entry *wditem)
{
git_oid oid;
@ -169,13 +174,16 @@ static bool checkout_is_workdir_modified(
/* Look at the cache to decide if the workdir is modified. If not,
* we can simply compare the oid in the cache to the baseitem instead
* of hashing the file.
* of hashing the file. If so, we allow the checkout to proceed if the
* oid is identical (ie, the staged item is what we're trying to check
* out.)
*/
if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
if (wditem->mtime.seconds == ie->mtime.seconds &&
wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
wditem->file_size == ie->file_size)
return (git_oid__cmp(&baseitem->id, &ie->id) != 0);
return (git_oid__cmp(&baseitem->id, &ie->id) != 0 &&
git_oid_cmp(&newitem->id, &ie->id) != 0);
}
/* depending on where base is coming from, we may or may not know
@ -184,9 +192,7 @@ static bool checkout_is_workdir_modified(
if (baseitem->size && wditem->file_size != baseitem->size)
return true;
if (git_diff__oid_for_file(
data->repo, wditem->path, wditem->mode,
wditem->file_size, &oid) < 0)
if (git_diff__oid_for_entry(&oid, data->diff, wditem, NULL) < 0)
return false;
return (git_oid__cmp(&baseitem->id, &oid) != 0);
@ -403,7 +409,7 @@ static int checkout_action_with_wd(
switch (delta->status) {
case GIT_DELTA_UNMODIFIED: /* case 14/15 or 33 */
if (checkout_is_workdir_modified(data, &delta->old_file, wd)) {
if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) {
GITERR_CHECK_ERROR(
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) );
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE);
@ -416,13 +422,13 @@ static int checkout_action_with_wd(
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
break;
case GIT_DELTA_DELETED: /* case 9 or 10 (or 26 but not really) */
if (checkout_is_workdir_modified(data, &delta->old_file, wd))
if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
else
*action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
break;
case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */
if (checkout_is_workdir_modified(data, &delta->old_file, wd))
if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
else
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
@ -445,7 +451,7 @@ static int checkout_action_with_wd(
} else
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
}
else if (checkout_is_workdir_modified(data, &delta->old_file, wd))
else if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd))
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
else
*action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE);
@ -790,11 +796,16 @@ done:
static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec)
{
git_index_conflict_iterator *iterator = NULL;
git_index *index;
const git_index_entry *ancestor, *ours, *theirs;
checkout_conflictdata *conflict;
int error = 0;
if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0)
/* Only write conficts from sources that have them: indexes. */
if ((index = git_iterator_get_index(data->target)) == NULL)
return 0;
if ((error = git_index_conflict_iterator_new(&iterator, index)) < 0)
goto done;
data->conflicts._cmp = checkout_conflictdata_cmp;
@ -821,6 +832,10 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
git_vector_insert(&data->conflicts, conflict);
}
/* Collect the REUC and NAME entries */
data->reuc = &index->reuc;
data->names = &index->names;
if (error == GIT_ITEROVER)
error = 0;
@ -959,16 +974,20 @@ done:
static int checkout_conflicts_coalesce_renames(
checkout_data *data)
{
git_index *index;
const git_index_name_entry *name_entry;
checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict;
size_t i, names;
int error = 0;
if ((index = git_iterator_get_index(data->target)) == NULL)
return 0;
/* Juggle entries based on renames */
names = git_index_name_entrycount(data->index);
names = git_index_name_entrycount(index);
for (i = 0; i < names; i++) {
name_entry = git_index_name_get_byindex(data->index, i);
name_entry = git_index_name_get_byindex(index, i);
if ((error = checkout_conflicts_load_byname_entry(
&ancestor_conflict, &our_conflict, &their_conflict,
@ -1012,13 +1031,17 @@ done:
static int checkout_conflicts_mark_directoryfile(
checkout_data *data)
{
git_index *index;
checkout_conflictdata *conflict;
const git_index_entry *entry;
size_t i, j, len;
const char *path;
int prefixed, error = 0;
len = git_index_entrycount(data->index);
if ((index = git_iterator_get_index(data->target)) == NULL)
return 0;
len = git_index_entrycount(index);
/* Find d/f conflicts */
git_vector_foreach(&data->conflicts, i, conflict) {
@ -1029,7 +1052,7 @@ static int checkout_conflicts_mark_directoryfile(
path = conflict->ours ?
conflict->ours->path : conflict->theirs->path;
if ((error = git_index_find(&j, data->index, path)) < 0) {
if ((error = git_index_find(&j, index, path)) < 0) {
if (error == GIT_ENOTFOUND)
giterr_set(GITERR_INDEX,
"Index inconsistency, could not find entry for expected conflict '%s'", path);
@ -1038,7 +1061,7 @@ static int checkout_conflicts_mark_directoryfile(
}
for (; j < len; j++) {
if ((entry = git_index_get_byindex(data->index, j)) == NULL) {
if ((entry = git_index_get_byindex(index, j)) == NULL) {
giterr_set(GITERR_INDEX,
"Index inconsistency, truncated index while loading expected conflict '%s'", path);
error = -1;
@ -1214,7 +1237,8 @@ static int blob_content_to_file(
if (!opts->disable_filters)
error = git_filter_list_load(
&fl, git_blob_owner(blob), blob, hint_path, GIT_FILTER_TO_WORKTREE);
&fl, git_blob_owner(blob), blob, hint_path,
GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT);
if (!error)
error = git_filter_list_apply_to_blob(&out, fl, blob);
@ -1803,6 +1827,24 @@ done:
return error;
}
static int checkout_conflict_update_index(
checkout_data *data,
checkout_conflictdata *conflict)
{
int error = 0;
if (conflict->ancestor)
error = git_index_add(data->index, conflict->ancestor);
if (!error && conflict->ours)
error = git_index_add(data->index, conflict->ours);
if (!error && conflict->theirs)
error = git_index_add(data->index, conflict->theirs);
return error;
}
static int checkout_create_conflicts(checkout_data *data)
{
checkout_conflictdata *conflict;
@ -1865,6 +1907,12 @@ static int checkout_create_conflicts(checkout_data *data)
else if (!error)
error = checkout_write_merge(data, conflict);
/* Update the index extensions (REUC and NAME) if we're checking
* out a different index. (Otherwise just leave them there.)
*/
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
error = checkout_conflict_update_index(data, conflict);
if (error)
break;
@ -1877,6 +1925,37 @@ static int checkout_create_conflicts(checkout_data *data)
return error;
}
static int checkout_extensions_update_index(checkout_data *data)
{
const git_index_reuc_entry *reuc_entry;
const git_index_name_entry *name_entry;
size_t i;
int error = 0;
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
return 0;
if (data->reuc) {
git_vector_foreach(data->reuc, i, reuc_entry) {
if ((error = git_index_reuc_add(data->index, reuc_entry->path,
reuc_entry->mode[0], &reuc_entry->oid[0],
reuc_entry->mode[1], &reuc_entry->oid[1],
reuc_entry->mode[2], &reuc_entry->oid[2])) < 0)
goto done;
}
}
if (data->names) {
git_vector_foreach(data->names, i, name_entry) {
if ((error = git_index_name_add(data->index, name_entry->ancestor,
name_entry->ours, name_entry->theirs)) < 0)
goto done;
}
}
done:
return error;
}
static void checkout_data_clear(checkout_data *data)
{
@ -1920,6 +1999,7 @@ static int checkout_data_init(
return error;
data->repo = repo;
data->target = target;
GITERR_CHECK_VERSION(
proposed, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options");
@ -1944,15 +2024,15 @@ static int checkout_data_init(
(error = git_config_refresh(cfg)) < 0)
goto cleanup;
/* if we are checking out the index, don't reload,
* otherwise get index and force reload
/* Get the repository index and reload it (unless we're checking
* out the index; then it has the changes we're trying to check
* out and those should not be overwritten.)
*/
if ((data->index = git_iterator_get_index(target)) != NULL) {
GIT_REFCOUNT_INC(data->index);
} else {
/* otherwise, grab and reload the index */
if ((error = git_repository_index(&data->index, data->repo)) < 0 ||
(error = git_index_read(data->index, true)) < 0)
if ((error = git_repository_index(&data->index, data->repo)) < 0)
goto cleanup;
if (data->index != git_iterator_get_index(target)) {
if ((error = git_index_read(data->index, true)) < 0)
goto cleanup;
/* cannot checkout if unresolved conflicts exist */
@ -1964,7 +2044,7 @@ static int checkout_data_init(
goto cleanup;
}
/* clean conflict data when doing a tree or commit checkout */
/* clean conflict data in the current index */
git_index_name_clear(data->index);
git_index_reuc_clear(data->index);
}
@ -2064,6 +2144,7 @@ int git_checkout_iterator(
diff_opts.flags =
GIT_DIFF_INCLUDE_UNMODIFIED |
GIT_DIFF_INCLUDE_UNREADABLE |
GIT_DIFF_INCLUDE_UNTRACKED |
GIT_DIFF_RECURSE_UNTRACKED_DIRS | /* needed to match baseline */
GIT_DIFF_INCLUDE_IGNORED |
@ -2133,6 +2214,10 @@ int git_checkout_iterator(
(error = checkout_create_conflicts(&data)) < 0)
goto cleanup;
if (data.index != git_iterator_get_index(target) &&
(error = checkout_extensions_update_index(&data)) < 0)
goto cleanup;
assert(data.completed_steps == data.total_steps);
cleanup:
@ -2155,7 +2240,7 @@ int git_checkout_index(
git_index *index,
const git_checkout_options *opts)
{
int error;
int error, owned = 0;
git_iterator *index_i;
if (!index && !repo) {
@ -2163,10 +2248,16 @@ int git_checkout_index(
"Must provide either repository or index to checkout");
return -1;
}
if (index && repo && git_index_owner(index) != repo) {
if (index && repo &&
git_index_owner(index) &&
git_index_owner(index) != repo) {
giterr_set(GITERR_CHECKOUT,
"Index to checkout does not match repository");
return -1;
} else if(index && repo && !git_index_owner(index)) {
GIT_REFCOUNT_OWN(index, repo);
owned = 1;
}
if (!repo)
@ -2179,6 +2270,9 @@ int git_checkout_index(
if (!(error = git_iterator_for_index(&index_i, index, 0, NULL, NULL)))
error = git_checkout_iterator(index_i, opts);
if (owned)
GIT_REFCOUNT_OWN(index, NULL);
git_iterator_free(index_i);
git_index_free(index);
@ -2242,14 +2336,9 @@ int git_checkout_head(
return git_checkout_tree(repo, NULL, opts);
}
int git_checkout_init_opts(git_checkout_options* opts, int version)
int git_checkout_init_options(git_checkout_options *opts, unsigned int version)
{
if (version != GIT_CHECKOUT_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_checkout_options", version);
return -1;
} else {
git_checkout_options o = GIT_CHECKOUT_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o));
return 0;
}
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
opts, version, git_checkout_options, GIT_CHECKOUT_OPTIONS_INIT);
return 0;
}

View File

@ -17,9 +17,9 @@
#include "git2/commit.h"
#include "git2/sys/commit.h"
#define GIT_CHERRY_PICK_FILE_MODE 0666
#define GIT_CHERRYPICK_FILE_MODE 0666
static int write_cherry_pick_head(
static int write_cherrypick_head(
git_repository *repo,
const char *commit_oidstr)
{
@ -27,8 +27,8 @@ static int write_cherry_pick_head(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRY_PICK_HEAD_FILE)) >= 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRY_PICK_FILE_MODE)) >= 0 &&
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) >= 0 &&
(error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
error = git_filebuf_commit(&file);
@ -49,7 +49,7 @@ static int write_merge_msg(
int error = 0;
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRY_PICK_FILE_MODE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) < 0 ||
(error = git_filebuf_printf(&file, "%s", commit_msg)) < 0)
goto cleanup;
@ -64,10 +64,10 @@ cleanup:
return error;
}
static int cherry_pick_normalize_opts(
static int cherrypick_normalize_opts(
git_repository *repo,
git_cherry_pick_options *opts,
const git_cherry_pick_options *given,
git_cherrypick_options *opts,
const git_cherrypick_options *given,
const char *their_label)
{
int error = 0;
@ -77,10 +77,10 @@ static int cherry_pick_normalize_opts(
GIT_UNUSED(repo);
if (given != NULL)
memcpy(opts, given, sizeof(git_cherry_pick_options));
memcpy(opts, given, sizeof(git_cherrypick_options));
else {
git_cherry_pick_options default_opts = GIT_CHERRY_PICK_OPTIONS_INIT;
memcpy(opts, &default_opts, sizeof(git_cherry_pick_options));
git_cherrypick_options default_opts = GIT_CHERRYPICK_OPTIONS_INIT;
memcpy(opts, &default_opts, sizeof(git_cherrypick_options));
}
if (!opts->checkout_opts.checkout_strategy)
@ -95,14 +95,14 @@ static int cherry_pick_normalize_opts(
return error;
}
static int cherry_pick_state_cleanup(git_repository *repo)
static int cherrypick_state_cleanup(git_repository *repo)
{
const char *state_files[] = { GIT_CHERRY_PICK_HEAD_FILE, GIT_MERGE_MSG_FILE };
const char *state_files[] = { GIT_CHERRYPICK_HEAD_FILE, GIT_MERGE_MSG_FILE };
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
}
static int cherry_pick_seterr(git_commit *commit, const char *fmt)
static int cherrypick_seterr(git_commit *commit, const char *fmt)
{
char commit_oidstr[GIT_OID_HEXSZ + 1];
@ -112,71 +112,71 @@ static int cherry_pick_seterr(git_commit *commit, const char *fmt)
return -1;
}
int git_cherry_pick_commit(
int git_cherrypick_commit(
git_index **out,
git_repository *repo,
git_commit *cherry_pick_commit,
git_commit *cherrypick_commit,
git_commit *our_commit,
unsigned int mainline,
const git_merge_options *merge_opts)
{
git_commit *parent_commit = NULL;
git_tree *parent_tree = NULL, *our_tree = NULL, *cherry_pick_tree = NULL;
git_tree *parent_tree = NULL, *our_tree = NULL, *cherrypick_tree = NULL;
int parent = 0, error = 0;
assert(out && repo && cherry_pick_commit && our_commit);
assert(out && repo && cherrypick_commit && our_commit);
if (git_commit_parentcount(cherry_pick_commit) > 1) {
if (git_commit_parentcount(cherrypick_commit) > 1) {
if (!mainline)
return cherry_pick_seterr(cherry_pick_commit,
return cherrypick_seterr(cherrypick_commit,
"Mainline branch is not specified but %s is a merge commit");
parent = mainline;
} else {
if (mainline)
return cherry_pick_seterr(cherry_pick_commit,
return cherrypick_seterr(cherrypick_commit,
"Mainline branch specified but %s is not a merge commit");
parent = git_commit_parentcount(cherry_pick_commit);
parent = git_commit_parentcount(cherrypick_commit);
}
if (parent &&
((error = git_commit_parent(&parent_commit, cherry_pick_commit, (parent - 1))) < 0 ||
((error = git_commit_parent(&parent_commit, cherrypick_commit, (parent - 1))) < 0 ||
(error = git_commit_tree(&parent_tree, parent_commit)) < 0))
goto done;
if ((error = git_commit_tree(&cherry_pick_tree, cherry_pick_commit)) < 0 ||
if ((error = git_commit_tree(&cherrypick_tree, cherrypick_commit)) < 0 ||
(error = git_commit_tree(&our_tree, our_commit)) < 0)
goto done;
error = git_merge_trees(out, repo, parent_tree, our_tree, cherry_pick_tree, merge_opts);
error = git_merge_trees(out, repo, parent_tree, our_tree, cherrypick_tree, merge_opts);
done:
git_tree_free(parent_tree);
git_tree_free(our_tree);
git_tree_free(cherry_pick_tree);
git_tree_free(cherrypick_tree);
git_commit_free(parent_commit);
return error;
}
int git_cherry_pick(
int git_cherrypick(
git_repository *repo,
git_commit *commit,
const git_cherry_pick_options *given_opts)
const git_cherrypick_options *given_opts)
{
git_cherry_pick_options opts;
git_cherrypick_options opts;
git_reference *our_ref = NULL;
git_commit *our_commit = NULL;
char commit_oidstr[GIT_OID_HEXSZ + 1];
const char *commit_msg, *commit_summary;
git_buf their_label = GIT_BUF_INIT;
git_index *index_new = NULL, *index_repo = NULL;
git_index *index_new = NULL;
int error = 0;
assert(repo && commit);
GITERR_CHECK_VERSION(given_opts, GIT_CHERRY_PICK_OPTIONS_VERSION, "git_cherry_pick_options");
GITERR_CHECK_VERSION(given_opts, GIT_CHERRYPICK_OPTIONS_VERSION, "git_cherrypick_options");
if ((error = git_repository__ensure_not_bare(repo, "cherry-pick")) < 0)
return error;
@ -191,25 +191,22 @@ int git_cherry_pick(
if ((error = write_merge_msg(repo, commit_msg)) < 0 ||
(error = git_buf_printf(&their_label, "%.7s... %s", commit_oidstr, commit_summary)) < 0 ||
(error = cherry_pick_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
(error = write_cherry_pick_head(repo, commit_oidstr)) < 0 ||
(error = cherrypick_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 ||
(error = write_cherrypick_head(repo, commit_oidstr)) < 0 ||
(error = git_repository_head(&our_ref, repo)) < 0 ||
(error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 ||
(error = git_cherry_pick_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 ||
(error = git_merge__indexes(repo, index_new)) < 0 ||
(error = git_repository_index(&index_repo, repo)) < 0 ||
(error = git_merge__append_conflicts_to_merge_msg(repo, index_repo)) < 0 ||
(error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0)
(error = git_cherrypick_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 ||
(error = git_merge__check_result(repo, index_new)) < 0 ||
(error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 ||
(error = git_checkout_index(repo, index_new, &opts.checkout_opts)) < 0)
goto on_error;
goto done;
on_error:
cherry_pick_state_cleanup(repo);
cherrypick_state_cleanup(repo);
done:
git_index_free(index_new);
git_index_free(index_repo);
git_commit_free(our_commit);
git_reference_free(our_ref);
git_buf_free(&their_label);
@ -217,14 +214,10 @@ done:
return error;
}
int git_cherry_pick_init_opts(git_cherry_pick_options* opts, int version)
int git_cherrypick_init_options(
git_cherrypick_options *opts, unsigned int version)
{
if (version != GIT_CHERRY_PICK_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_cherry_pick_options", version);
return -1;
} else {
git_cherry_pick_options o = GIT_CHERRY_PICK_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o));
return 0;
}
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
opts, version, git_cherrypick_options, GIT_CHERRYPICK_OPTIONS_INIT);
return 0;
}

View File

@ -22,6 +22,9 @@
#include "refs.h"
#include "path.h"
#include "repository.h"
#include "odb.h"
static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature);
static int create_branch(
git_reference **branch,
@ -105,54 +108,6 @@ static int create_tracking_branch(
git_reference_name(*branch));
}
struct head_info {
git_repository *repo;
git_oid remote_head_oid;
git_buf branchname;
const git_refspec *refspec;
bool found;
};
static int reference_matches_remote_head(
const char *reference_name,
void *payload)
{
struct head_info *head_info = (struct head_info *)payload;
git_oid oid;
int error;
/* TODO: Should we guard against references
* which name doesn't start with refs/heads/ ?
*/
error = git_reference_name_to_id(&oid, head_info->repo, reference_name);
if (error == GIT_ENOTFOUND) {
/* If the reference doesn't exists, it obviously cannot match the
* expected oid. */
giterr_clear();
return 0;
}
if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
/* Determine the local reference name from the remote tracking one */
error = git_refspec_rtransform(
&head_info->branchname, head_info->refspec, reference_name);
if (!error &&
git_buf_len(&head_info->branchname) > 0 &&
!(error = git_buf_sets(
&head_info->branchname,
git_buf_cstr(&head_info->branchname) +
strlen(GIT_REFS_HEADS_DIR))))
{
head_info->found = true;
error = GIT_ITEROVER;
}
}
return error;
}
static int update_head_to_new_branch(
git_repository *repo,
const git_oid *target,
@ -161,7 +116,12 @@ static int update_head_to_new_branch(
const char *reflog_message)
{
git_reference *tracking_branch = NULL;
int error = create_tracking_branch(&tracking_branch, repo, target, name,
int error;
if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR))
name += strlen(GIT_REFS_HEADS_DIR);
error = create_tracking_branch(&tracking_branch, repo, target, name,
signature, reflog_message);
if (!error)
@ -171,6 +131,10 @@ static int update_head_to_new_branch(
git_reference_free(tracking_branch);
/* if it already existed, then the user's refspec created it for us, ignore it' */
if (error == GIT_EEXISTS)
error = 0;
return error;
}
@ -182,76 +146,58 @@ static int update_head_to_remote(
{
int error = 0;
size_t refs_len;
git_refspec dummy_spec;
git_refspec *refspec;
const git_remote_head *remote_head, **refs;
struct head_info head_info;
const git_oid *remote_head_id;
git_buf remote_master_name = GIT_BUF_INIT;
git_buf branch = GIT_BUF_INIT;
if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
return error;
/* Did we just clone an empty repository? */
if (refs_len == 0)
/* We cloned an empty repository or one with an unborn HEAD */
if (refs_len == 0 || strcmp(refs[0]->name, GIT_HEAD_FILE))
return setup_tracking_config(
repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);
/* Get the remote's HEAD. This is always the first ref in the list. */
/* We know we have HEAD, let's see where it points */
remote_head = refs[0];
assert(remote_head);
memset(&head_info, 0, sizeof(head_info));
git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
head_info.repo = repo;
head_info.refspec =
git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
remote_head_id = &remote_head->oid;
if (head_info.refspec == NULL) {
memset(&dummy_spec, 0, sizeof(git_refspec));
head_info.refspec = &dummy_spec;
error = git_remote_default_branch(&branch, remote);
if (error == GIT_ENOTFOUND) {
error = git_repository_set_head_detached(
repo, remote_head_id, signature, reflog_message);
goto cleanup;
}
refspec = git_remote__matching_refspec(remote, git_buf_cstr(&branch));
if (refspec == NULL) {
giterr_set(GITERR_NET, "the remote's default branch does not fit the refspec configuration");
error = GIT_EINVALIDSPEC;
goto cleanup;
}
/* Determine the remote tracking reference name from the local master */
if ((error = git_refspec_transform(
&remote_master_name,
head_info.refspec,
GIT_REFS_HEADS_MASTER_FILE)) < 0)
return error;
/* Check to see if the remote HEAD points to the remote master */
error = reference_matches_remote_head(
git_buf_cstr(&remote_master_name), &head_info);
if (error < 0 && error != GIT_ITEROVER)
refspec,
git_buf_cstr(&branch))) < 0)
goto cleanup;
if (head_info.found) {
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname),
signature, reflog_message);
goto cleanup;
}
/* Not master. Check all the other refs. */
error = git_reference_foreach_name(
repo, reference_matches_remote_head, &head_info);
if (error < 0 && error != GIT_ITEROVER)
goto cleanup;
if (head_info.found) {
error = update_head_to_new_branch(
repo,
&head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname),
signature, reflog_message);
} else {
error = git_repository_set_head_detached(
repo, &head_info.remote_head_oid, signature, reflog_message);
}
error = update_head_to_new_branch(
repo,
remote_head_id,
git_buf_cstr(&branch),
signature, reflog_message);
cleanup:
git_buf_free(&remote_master_name);
git_buf_free(&head_info.branchname);
git_buf_free(&branch);
return error;
}
@ -284,6 +230,29 @@ cleanup:
return retcode;
}
static int default_repository_create(git_repository **out, const char *path, int bare, void *payload)
{
GIT_UNUSED(payload);
return git_repository_init(out, path, bare);
}
static int default_remote_create(
git_remote **out,
git_repository *repo,
const char *name,
const char *url,
void *payload)
{
int error;
git_remote_callbacks *callbacks = payload;
if ((error = git_remote_create(out, repo, name, url)) < 0)
return error;
return git_remote_set_callbacks(*out, callbacks);
}
/*
* submodules?
*/
@ -296,16 +265,24 @@ static int create_and_configure_origin(
{
int error;
git_remote *origin = NULL;
const char *name;
char buf[GIT_PATH_MAX];
git_remote_create_cb remote_create = options->remote_cb;
void *payload = options->remote_cb_payload;
name = options->remote_name ? options->remote_name : "origin";
if ((error = git_remote_create(&origin, repo, name, url)) < 0)
goto on_error;
/* If the path exists and is a dir, the url should be the absolute path */
if (git_path_root(url) < 0 && git_path_exists(url) && git_path_isdir(url)) {
if (p_realpath(url, buf) == NULL)
return -1;
if (options->ignore_cert_errors)
git_remote_check_cert(origin, 0);
url = buf;
}
if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0)
if (!remote_create) {
remote_create = default_remote_create;
payload = (void *)&options->remote_callbacks;
}
if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0)
goto on_error;
if ((error = git_remote_save(origin)) < 0)
@ -336,59 +313,89 @@ static bool should_checkout(
return !git_repository_head_unborn(repo);
}
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature)
static int checkout_branch(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature, const char *reflog_message)
{
int error = 0, old_fetchhead;
git_strarray refspecs;
git_buf reflog_message = GIT_BUF_INIT;
int error;
assert(repo && remote);
if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch,
signature, reflog_message);
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote, signature, reflog_message);
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts);
return error;
}
static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature)
{
int error;
git_buf reflog_message = GIT_BUF_INIT;
git_remote *remote;
const git_remote_callbacks *callbacks;
assert(repo && _remote);
if (!git_repository_is_empty(repo)) {
giterr_set(GITERR_INVALID, "the repository is not empty");
return -1;
}
if ((error = git_remote_get_fetch_refspecs(&refspecs, remote)) < 0)
if ((error = git_remote_dup(&remote, _remote)) < 0)
return error;
callbacks = git_remote_get_callbacks(_remote);
if (!giterr__check_version(callbacks, 1, "git_remote_callbacks") &&
(error = git_remote_set_callbacks(remote, callbacks)) < 0)
goto cleanup;
if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0)
return error;
goto cleanup;
old_fetchhead = git_remote_update_fetchhead(remote);
git_remote_set_update_fetchhead(remote, 0);
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0)
goto cleanup;
if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch,
signature, git_buf_cstr(&reflog_message));
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote, signature, git_buf_cstr(&reflog_message));
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts);
error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message));
cleanup:
git_remote_set_update_fetchhead(remote, old_fetchhead);
/* Go back to the original refspecs */
{
int error_alt = git_remote_set_fetch_refspecs(remote, &refspecs);
if (!error)
error = error_alt;
}
git_strarray_free(&refspecs);
git_remote_free(remote);
git_buf_free(&reflog_message);
return error;
}
int git_clone__should_clone_local(const char *url_or_path, git_clone_local_t local)
{
git_buf fromurl = GIT_BUF_INIT;
const char *path = url_or_path;
bool is_url, is_local;
if (local == GIT_CLONE_NO_LOCAL)
return 0;
if ((is_url = git_path_is_local_file_url(url_or_path)) != 0) {
if (git_path_fromurl(&fromurl, url_or_path) < 0) {
is_local = -1;
goto done;
}
path = fromurl.ptr;
}
is_local = (!is_url || local != GIT_CLONE_LOCAL_AUTO) &&
git_path_isdir(path);
done:
git_buf_free(&fromurl);
return is_local;
}
int git_clone(
git_repository **out,
const char *url,
@ -400,6 +407,7 @@ int git_clone(
git_remote *origin;
git_clone_options options = GIT_CLONE_OPTIONS_INIT;
uint32_t rmdir_flags = GIT_RMDIR_REMOVE_FILES;
git_repository_create_cb repository_cb;
assert(out && url && local_path);
@ -419,12 +427,28 @@ int git_clone(
if (git_path_exists(local_path))
rmdir_flags |= GIT_RMDIR_SKIP_ROOT;
if ((error = git_repository_init(&repo, local_path, options.bare)) < 0)
if (options.repository_cb)
repository_cb = options.repository_cb;
else
repository_cb = default_repository_create;
if ((error = repository_cb(&repo, local_path, options.bare, options.repository_cb_payload)) < 0)
return error;
if (!(error = create_and_configure_origin(&origin, repo, url, &options))) {
error = git_clone_into(
repo, origin, &options.checkout_opts, options.checkout_branch, options.signature);
int clone_local = git_clone__should_clone_local(url, options.local);
int link = options.local != GIT_CLONE_LOCAL_NO_LINKS;
if (clone_local == 1)
error = clone_local_into(
repo, origin, &options.checkout_opts,
options.checkout_branch, link, options.signature);
else if (clone_local == 0)
error = clone_into(
repo, origin, &options.checkout_opts,
options.checkout_branch, options.signature);
else
error = -1;
git_remote_free(origin);
}
@ -445,14 +469,100 @@ int git_clone(
return error;
}
int git_clone_init_options(git_clone_options* opts, int version)
int git_clone_init_options(git_clone_options *opts, unsigned int version)
{
if (version != GIT_CLONE_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_clone_options", version);
return -1;
} else {
git_clone_options o = GIT_CLONE_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o));
return 0;
}
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
opts, version, git_clone_options, GIT_CLONE_OPTIONS_INIT);
return 0;
}
static const char *repository_base(git_repository *repo)
{
if (git_repository_is_bare(repo))
return git_repository_path(repo);
return git_repository_workdir(repo);
}
static bool can_link(const char *src, const char *dst, int link)
{
#ifdef GIT_WIN32
GIT_UNUSED(src);
GIT_UNUSED(dst);
GIT_UNUSED(link);
return false;
#else
struct stat st_src, st_dst;
if (!link)
return false;
if (p_stat(src, &st_src) < 0)
return false;
if (p_stat(dst, &st_dst) < 0)
return false;
return st_src.st_dev == st_dst.st_dev;
#endif
}
static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature)
{
int error, flags;
git_repository *src;
git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT;
git_buf reflog_message = GIT_BUF_INIT;
assert(repo && remote);
if (!git_repository_is_empty(repo)) {
giterr_set(GITERR_INVALID, "the repository is not empty");
return -1;
}
/*
* Let's figure out what path we should use for the source
* repo, if it's not rooted, the path should be relative to
* the repository's worktree/gitdir.
*/
if ((error = git_path_from_url_or_path(&src_path, git_remote_url(remote))) < 0)
return error;
/* Copy .git/objects/ from the source to the target */
if ((error = git_repository_open(&src, git_buf_cstr(&src_path))) < 0) {
git_buf_free(&src_path);
return error;
}
git_buf_joinpath(&src_odb, git_repository_path(src), GIT_OBJECTS_DIR);
git_buf_joinpath(&dst_odb, git_repository_path(repo), GIT_OBJECTS_DIR);
if (git_buf_oom(&src_odb) || git_buf_oom(&dst_odb)) {
error = -1;
goto cleanup;
}
flags = 0;
if (can_link(git_repository_path(src), git_repository_path(repo), link))
flags |= GIT_CPDIR_LINK_FILES;
if ((error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
flags, GIT_OBJECT_DIR_MODE)) < 0)
goto cleanup;
git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0)
goto cleanup;
error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message));
cleanup:
git_buf_free(&reflog_message);
git_buf_free(&src_path);
git_buf_free(&src_odb);
git_buf_free(&dst_odb);
git_repository_free(src);
return error;
}

12
src/clone.h Normal file
View File

@ -0,0 +1,12 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_clone_h__
#define INCLUDE_clone_h__
extern int git_clone__should_clone_local(const char *url, git_clone_local_t local);
#endif

View File

@ -34,6 +34,35 @@ void git_commit__free(void *_commit)
git__free(commit);
}
static int update_ref_for_commit(git_repository *repo, git_reference *ref, const char *update_ref, const git_oid *id, const git_signature *committer)
{
git_reference *ref2 = NULL;
int error;
git_commit *c;
const char *shortmsg;
git_buf reflog_msg = GIT_BUF_INIT;
if ((error = git_commit_lookup(&c, repo, id)) < 0) {
return error;
}
shortmsg = git_commit_summary(c);
git_buf_printf(&reflog_msg, "commit%s: %s",
git_commit_parentcount(c) == 0 ? " (initial)" : "",
shortmsg);
git_commit_free(c);
if (ref) {
error = git_reference_set_target(&ref2, ref, id, committer, git_buf_cstr(&reflog_msg));
git_reference_free(ref2);
} else {
error = git_reference__update_terminal(repo, update_ref, id, committer, git_buf_cstr(&reflog_msg));
}
git_buf_free(&reflog_msg);
return error;
}
int git_commit_create_from_callback(
git_oid *id,
git_repository *repo,
@ -46,6 +75,9 @@ int git_commit_create_from_callback(
git_commit_parent_callback parent_cb,
void *parent_payload)
{
git_reference *ref = NULL;
int error = 0, matched_parent = 0;
const git_oid *current_id = NULL;
git_buf commit = GIT_BUF_INIT;
size_t i = 0;
git_odb *odb;
@ -53,10 +85,31 @@ int git_commit_create_from_callback(
assert(id && repo && tree && parent_cb);
if (update_ref) {
error = git_reference_lookup_resolved(&ref, repo, update_ref, 10);
if (error < 0 && error != GIT_ENOTFOUND)
return error;
}
giterr_clear();
if (ref)
current_id = git_reference_target(ref);
git_oid__writebuf(&commit, "tree ", tree);
while ((parent = parent_cb(i++, parent_payload)) != NULL)
while ((parent = parent_cb(i, parent_payload)) != NULL) {
git_oid__writebuf(&commit, "parent ", parent);
if (i == 0 && current_id && git_oid_equal(current_id, parent))
matched_parent = 1;
i++;
}
if (ref && !matched_parent) {
git_reference_free(ref);
git_buf_free(&commit);
giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent");
return GIT_EMODIFIED;
}
git_signature__writebuf(&commit, "author ", author);
git_signature__writebuf(&commit, "committer ", committer);
@ -78,24 +131,8 @@ int git_commit_create_from_callback(
git_buf_free(&commit);
if (update_ref != NULL) {
int error;
git_commit *c;
const char *shortmsg;
git_buf reflog_msg = GIT_BUF_INIT;
if (git_commit_lookup(&c, repo, id) < 0)
goto on_error;
shortmsg = git_commit_summary(c);
git_buf_printf(&reflog_msg, "commit%s: %s",
git_commit_parentcount(c) == 0 ? " (initial)" : "",
shortmsg);
git_commit_free(c);
error = git_reference__update_terminal(repo, update_ref, id,
committer, git_buf_cstr(&reflog_msg));
git_buf_free(&reflog_msg);
error = update_ref_for_commit(repo, ref, update_ref, id, committer);
git_reference_free(ref);
return error;
}
@ -242,6 +279,8 @@ int git_commit_amend(
{
git_repository *repo;
git_oid tree_id;
git_reference *ref;
int error;
assert(id && commit_to_amend);
@ -266,9 +305,27 @@ int git_commit_amend(
git_oid_cpy(&tree_id, git_tree_id(tree));
}
return git_commit_create_from_callback(
id, repo, update_ref, author, committer, message_encoding, message,
if (update_ref) {
if ((error = git_reference_lookup_resolved(&ref, repo, update_ref, 5)) < 0)
return error;
if (git_oid_cmp(git_commit_id(commit_to_amend), git_reference_target(ref))) {
git_reference_free(ref);
giterr_set(GITERR_REFERENCE, "commit to amend is not the tip of the given branch");
return -1;
}
}
error = git_commit_create_from_callback(
id, repo, NULL, author, committer, message_encoding, message,
&tree_id, commit_parent_for_amend, (void *)commit_to_amend);
if (!error && update_ref) {
error = update_ref_for_commit(repo, ref, NULL, id, committer);
git_reference_free(ref);
}
return error;
}
int git_commit__parse(void *_commit, git_odb_object *odb_obj)

View File

@ -44,6 +44,7 @@
#else
# include <unistd.h>
# include <strings.h>
# ifdef GIT_THREADS
# include <pthread.h>
# include <sched.h>
@ -169,6 +170,11 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
}
#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \
TYPE _tmpl = TPL; \
GITERR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \
memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
/* NOTE: other giterr functions are in the public errors.h header file */
#include "util.h"

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