mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-10 21:45:40 +00:00
Merge remote-tracking branch 'upstream/master' into cmn/ssh-retry
This commit is contained in:
commit
6a0d2b43ee
@ -46,10 +46,11 @@ after_success:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install valgrind; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; 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:
|
||||
|
47
CHANGELOG.md
Normal file
47
CHANGELOG.md
Normal file
@ -0,0 +1,47 @@
|
||||
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 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.
|
||||
|
||||
* 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.
|
@ -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")
|
||||
@ -208,6 +209,14 @@ 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)
|
||||
@ -387,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)
|
||||
|
||||
@ -453,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)
|
||||
|
@ -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
|
||||
|
||||
|
47
PROJECTS.md
47
PROJECTS.md
@ -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
|
||||
@ -52,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.
|
||||
@ -67,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")
|
||||
|
@ -168,6 +168,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,7 +184,7 @@ 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
|
||||
|
324
cmake/Modules/FindGSSAPI.cmake
Normal file
324
cmake/Modules/FindGSSAPI.cmake
Normal 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)
|
2
deps/http-parser/http_parser.h
vendored
2
deps/http-parser/http_parser.h
vendored
@ -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
68
deps/zlib/adler32.c
vendored
@ -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
83
deps/zlib/crc32.c
vendored
@ -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
2
deps/zlib/crc32.h
vendored
@ -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
261
deps/zlib/deflate.c
vendored
@ -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
12
deps/zlib/deflate.h
vendored
@ -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
640
deps/zlib/infback.c
vendored
Normal 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
6
deps/zlib/inffast.c
vendored
@ -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 */
|
||||
|
6
deps/zlib/inffixed.h
vendored
6
deps/zlib/inffixed.h
vendored
@ -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
136
deps/zlib/inflate.c
vendored
@ -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
54
deps/zlib/inftrees.c
vendored
@ -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
54
deps/zlib/trees.c
vendored
@ -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
4
deps/zlib/zconf.h
vendored
@ -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
343
deps/zlib/zlib.h
vendored
@ -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
23
deps/zlib/zutil.c
vendored
@ -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
103
deps/zlib/zutil.h
vendored
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
/** @} */
|
||||
|
@ -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
|
||||
|
@ -28,21 +28,21 @@ 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` struct to initialize
|
||||
* @param version Version of struct; pass `GIT_CHERRY_PICK_OPTIONS_VERSION`
|
||||
* @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_options(
|
||||
git_cherry_pick_options *opts,
|
||||
GIT_EXTERN(int) git_cherrypick_init_options(
|
||||
git_cherrypick_options *opts,
|
||||
unsigned int version);
|
||||
|
||||
/**
|
||||
@ -53,16 +53,16 @@ GIT_EXTERN(int) git_cherry_pick_init_options(
|
||||
*
|
||||
* @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_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);
|
||||
@ -72,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
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "indexer.h"
|
||||
#include "checkout.h"
|
||||
#include "remote.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -51,6 +52,47 @@ typedef enum {
|
||||
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
|
||||
*
|
||||
@ -72,7 +114,11 @@ typedef struct git_clone_options {
|
||||
git_checkout_options checkout_opts;
|
||||
|
||||
/**
|
||||
* Callbacks to use for reporting fetch progress.
|
||||
* 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;
|
||||
|
||||
@ -82,23 +128,11 @@ typedef struct git_clone_options {
|
||||
*/
|
||||
int bare;
|
||||
|
||||
/**
|
||||
* Set to 1 if errors validating the remote host's certificate
|
||||
* should be ignored.
|
||||
*/
|
||||
int ignore_cert_errors;
|
||||
|
||||
/**
|
||||
* Whether to use a fetch or copy the object database.
|
||||
*/
|
||||
git_clone_local_t local;
|
||||
|
||||
/**
|
||||
* The name to be given to the remote that will be
|
||||
* created. The default is "origin".
|
||||
*/
|
||||
const char *remote_name;
|
||||
|
||||
/**
|
||||
* The name of the branch to checkout. NULL means use the
|
||||
* remote's default branch.
|
||||
@ -110,6 +144,33 @@ typedef struct git_clone_options {
|
||||
* 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
|
||||
@ -130,9 +191,9 @@ GIT_EXTERN(int) git_clone_init_options(
|
||||
/**
|
||||
* 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
|
||||
@ -149,59 +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);
|
||||
|
||||
/**
|
||||
* Perform a local clone into a repository
|
||||
*
|
||||
* A "local clone" bypasses any git-aware protocols and simply copies
|
||||
* over the object database from the source repository. It is often
|
||||
* faster than a git-aware clone, but no verification of the data is
|
||||
* performed, and can copy over too much data.
|
||||
*
|
||||
* @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 link wether to use hardlinks instead of copying
|
||||
* objects. This is only possible if both repositories are on the same
|
||||
* filesystem.
|
||||
* @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_local_into(
|
||||
git_repository *repo,
|
||||
git_remote *remote,
|
||||
const git_checkout_options *co_opts,
|
||||
const char *branch,
|
||||
int link,
|
||||
const git_signature *signature);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -152,6 +152,12 @@ typedef enum {
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@ -237,6 +243,7 @@ typedef enum {
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -418,22 +418,6 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
|
||||
*/
|
||||
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.
|
||||
|
@ -662,7 +662,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,
|
||||
|
@ -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
|
||||
|
@ -59,7 +59,7 @@ GIT_EXTERN(int) git_revert_init_options(
|
||||
* @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,
|
||||
|
@ -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;
|
||||
@ -133,20 +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_UPDATE_INDEX = (1u << 13),
|
||||
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 \
|
||||
|
354
include/git2/sys/transport.h
Normal file
354
include/git2/sys/transport.h
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* 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,
|
||||
/* 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 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` 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
|
@ -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,10 +20,6 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/*
|
||||
*** Begin interface for credentials acquisition ***
|
||||
*/
|
||||
|
||||
/** Authentication type requested */
|
||||
typedef enum {
|
||||
/* git_cred_userpass_plaintext */
|
||||
@ -69,14 +61,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
|
||||
*/
|
||||
@ -247,319 +245,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` 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);
|
||||
|
||||
/* 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
|
||||
|
@ -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
|
||||
|
@ -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,16 @@ 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);
|
||||
|
||||
/**
|
||||
* Opaque structure representing a submodule.
|
||||
*/
|
||||
|
@ -40,5 +40,8 @@ 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
|
||||
./libgit2_clar -sonline::push -sonline::clone::cred_callback &&
|
||||
rm -rf $HOME/_temp/test.git &&
|
||||
git init --bare $HOME/_temp/test.git && # create an empty one
|
||||
./libgit2_clar -sonline::clone::ssh_with_paths
|
||||
fi
|
||||
|
@ -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) {
|
||||
|
@ -378,6 +378,18 @@ bool git_attr_fnmatch__match(
|
||||
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);
|
||||
}
|
||||
|
||||
@ -522,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++;
|
||||
}
|
||||
|
||||
|
@ -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';
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
77
src/buffer.c
77
src/buffer.c
@ -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
|
||||
@ -141,6 +142,16 @@ int git_buf_set(git_buf *buf, const void *data, size_t len)
|
||||
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);
|
||||
@ -178,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;
|
||||
@ -196,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++ = '=';
|
||||
}
|
||||
|
||||
@ -218,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);
|
||||
|
||||
|
@ -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.
|
||||
|
18
src/cache.c
18
src/cache.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
git_oidmap *map;
|
||||
git_mutex lock;
|
||||
git_rwlock lock;
|
||||
ssize_t used_memory;
|
||||
} git_cache;
|
||||
|
||||
|
141
src/checkout.c
141
src/checkout.c
@ -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
|
||||
@ -401,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);
|
||||
@ -414,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);
|
||||
@ -443,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);
|
||||
@ -788,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;
|
||||
@ -819,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;
|
||||
|
||||
@ -957,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,
|
||||
@ -1010,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) {
|
||||
@ -1027,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);
|
||||
@ -1036,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;
|
||||
@ -1802,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;
|
||||
@ -1864,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;
|
||||
|
||||
@ -1876,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)
|
||||
{
|
||||
@ -1919,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");
|
||||
@ -1943,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 */
|
||||
@ -1963,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);
|
||||
}
|
||||
@ -2063,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 |
|
||||
@ -2132,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:
|
||||
@ -2154,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) {
|
||||
@ -2162,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)
|
||||
@ -2178,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);
|
||||
|
||||
|
@ -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,10 +214,10 @@ done:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_cherry_pick_init_options(
|
||||
git_cherry_pick_options *opts, unsigned int version)
|
||||
int git_cherrypick_init_options(
|
||||
git_cherrypick_options *opts, unsigned int version)
|
||||
{
|
||||
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
|
||||
opts, version, git_cherry_pick_options, GIT_CHERRY_PICK_OPTIONS_INIT);
|
||||
opts, version, git_cherrypick_options, GIT_CHERRYPICK_OPTIONS_INIT);
|
||||
return 0;
|
||||
}
|
||||
|
101
src/clone.c
101
src/clone.c
@ -24,6 +24,8 @@
|
||||
#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,
|
||||
git_repository *repo,
|
||||
@ -229,6 +231,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?
|
||||
*/
|
||||
@ -241,8 +266,9 @@ 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;
|
||||
|
||||
/* 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)) {
|
||||
@ -252,14 +278,12 @@ static int create_and_configure_origin(
|
||||
url = buf;
|
||||
}
|
||||
|
||||
name = options->remote_name ? options->remote_name : "origin";
|
||||
if ((error = git_remote_create(&origin, repo, name, url)) < 0)
|
||||
goto on_error;
|
||||
if (!remote_create) {
|
||||
remote_create = default_remote_create;
|
||||
payload = (void *)&options->remote_callbacks;
|
||||
}
|
||||
|
||||
if (options->ignore_cert_errors)
|
||||
git_remote_check_cert(origin, 0);
|
||||
|
||||
if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0)
|
||||
if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if ((error = git_remote_save(origin)) < 0)
|
||||
@ -307,7 +331,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
|
||||
return error;
|
||||
}
|
||||
|
||||
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 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;
|
||||
@ -347,27 +371,30 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_clone__should_clone_local(const char *url, git_clone_local_t local)
|
||||
int git_clone__should_clone_local(const char *url_or_path, git_clone_local_t local)
|
||||
{
|
||||
const char *path;
|
||||
int is_url;
|
||||
git_buf fromurl = GIT_BUF_INIT;
|
||||
const char *path = url_or_path;
|
||||
bool is_url, is_local;
|
||||
|
||||
if (local == GIT_CLONE_NO_LOCAL)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
is_url = !git__prefixcmp(url, "file://");
|
||||
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;
|
||||
}
|
||||
|
||||
if (is_url && local != GIT_CLONE_LOCAL && local != GIT_CLONE_LOCAL_NO_LINKS )
|
||||
return false;
|
||||
path = fromurl.ptr;
|
||||
}
|
||||
|
||||
path = url;
|
||||
if (is_url)
|
||||
path = url + strlen("file://");
|
||||
is_local = (!is_url || local != GIT_CLONE_LOCAL_AUTO) &&
|
||||
git_path_isdir(path);
|
||||
|
||||
if ((git_path_exists(path) && git_path_isdir(path)) && local != GIT_CLONE_NO_LOCAL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
done:
|
||||
git_buf_free(&fromurl);
|
||||
return is_local;
|
||||
}
|
||||
|
||||
int git_clone(
|
||||
@ -381,6 +408,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);
|
||||
|
||||
@ -400,20 +428,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))) {
|
||||
if (git_clone__should_clone_local(url, options.local)) {
|
||||
int link = options.local != GIT_CLONE_LOCAL_NO_LINKS;
|
||||
error = git_clone_local_into(
|
||||
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 {
|
||||
error = git_clone_into(
|
||||
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);
|
||||
}
|
||||
@ -452,6 +488,9 @@ static const char *repository_base(git_repository *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
|
||||
|
||||
@ -470,7 +509,7 @@ static bool can_link(const char *src, const char *dst, int link)
|
||||
#endif
|
||||
}
|
||||
|
||||
int git_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 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;
|
||||
|
@ -1522,6 +1522,9 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
||||
|
||||
git_filebuf_write(&file, reader->buffer.ptr, reader->buffer.size);
|
||||
|
||||
if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n')
|
||||
git_filebuf_write(&file, "\n", 1);
|
||||
|
||||
/* And now if we just need to add a variable */
|
||||
if (!section_matches && write_section(&file, section) < 0)
|
||||
goto rewrite_fail;
|
||||
@ -1536,9 +1539,6 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
|
||||
}
|
||||
|
||||
/* If we are here, there is at least a section line */
|
||||
if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n')
|
||||
git_filebuf_write(&file, "\n", 1);
|
||||
|
||||
q = quotes_for_value(value);
|
||||
git_filebuf_printf(&file, "\t%s = %s%s%s\n", name, q, value, q);
|
||||
}
|
||||
@ -1649,7 +1649,7 @@ static int is_multiline_var(const char *str)
|
||||
}
|
||||
|
||||
/* An odd number means last backslash wasn't escaped, so it's multiline */
|
||||
return (end > str) && (count & 1);
|
||||
return count & 1;
|
||||
}
|
||||
|
||||
static int parse_multiline_variable(struct reader *reader, git_buf *value, int in_quotes)
|
||||
|
@ -286,7 +286,8 @@ static int crlf_check(
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE)
|
||||
if (ca.crlf_action == GIT_CRLF_GUESS &&
|
||||
ca.auto_crlf == GIT_AUTO_CRLF_FALSE)
|
||||
return GIT_PASSTHROUGH;
|
||||
|
||||
if (ca.auto_crlf == GIT_AUTO_CRLF_INPUT &&
|
||||
|
21
src/diff.c
21
src/diff.c
@ -92,6 +92,10 @@ static int diff_delta__from_one(
|
||||
if (status == GIT_DELTA_UNTRACKED &&
|
||||
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED))
|
||||
return 0;
|
||||
|
||||
if (status == GIT_DELTA_UNREADABLE &&
|
||||
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE))
|
||||
return 0;
|
||||
|
||||
if (!git_pathspec__match(
|
||||
&diff->pathspec, entry->path,
|
||||
@ -196,6 +200,7 @@ static git_diff_delta *diff_delta__last_for_item(
|
||||
if (git_oid__cmp(&delta->new_file.id, &item->id) == 0)
|
||||
return delta;
|
||||
break;
|
||||
case GIT_DELTA_UNREADABLE:
|
||||
case GIT_DELTA_UNTRACKED:
|
||||
if (diff->strcomp(delta->new_file.path, item->path) == 0 &&
|
||||
git_oid__cmp(&delta->new_file.id, &item->id) == 0)
|
||||
@ -293,6 +298,10 @@ bool git_diff_delta__should_skip(
|
||||
(flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0)
|
||||
return true;
|
||||
|
||||
if (delta->status == GIT_DELTA_UNREADABLE &&
|
||||
(flags & GIT_DIFF_INCLUDE_UNREADABLE) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -734,6 +743,11 @@ static int maybe_modified(
|
||||
else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
|
||||
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE))
|
||||
status = GIT_DELTA_TYPECHANGE;
|
||||
else if (nmode == GIT_FILEMODE_UNREADABLE) {
|
||||
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
||||
error = diff_delta__from_one(diff, GIT_DELTA_UNREADABLE, nitem);
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
||||
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem);
|
||||
@ -954,6 +968,13 @@ static int handle_unmatched_new_item(
|
||||
}
|
||||
}
|
||||
|
||||
else if (nitem->mode == GIT_FILEMODE_UNREADABLE) {
|
||||
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED))
|
||||
delta_type = GIT_DELTA_UNTRACKED;
|
||||
else
|
||||
delta_type = GIT_DELTA_UNREADABLE;
|
||||
}
|
||||
|
||||
/* Actually create the record for this item if necessary */
|
||||
if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0)
|
||||
return error;
|
||||
|
@ -112,6 +112,7 @@ int git_diff_file_content__init_from_diff(
|
||||
has_data = !use_old &&
|
||||
(diff->opts.flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) != 0;
|
||||
break;
|
||||
case GIT_DELTA_UNREADABLE:
|
||||
case GIT_DELTA_MODIFIED:
|
||||
case GIT_DELTA_COPIED:
|
||||
case GIT_DELTA_RENAMED:
|
||||
|
@ -82,14 +82,15 @@ char git_diff_status_char(git_delta_t status)
|
||||
char code;
|
||||
|
||||
switch (status) {
|
||||
case GIT_DELTA_ADDED: code = 'A'; break;
|
||||
case GIT_DELTA_DELETED: code = 'D'; break;
|
||||
case GIT_DELTA_MODIFIED: code = 'M'; break;
|
||||
case GIT_DELTA_RENAMED: code = 'R'; break;
|
||||
case GIT_DELTA_COPIED: code = 'C'; break;
|
||||
case GIT_DELTA_IGNORED: code = 'I'; break;
|
||||
case GIT_DELTA_UNTRACKED: code = '?'; break;
|
||||
default: code = ' '; break;
|
||||
case GIT_DELTA_ADDED: code = 'A'; break;
|
||||
case GIT_DELTA_DELETED: code = 'D'; break;
|
||||
case GIT_DELTA_MODIFIED: code = 'M'; break;
|
||||
case GIT_DELTA_RENAMED: code = 'R'; break;
|
||||
case GIT_DELTA_COPIED: code = 'C'; break;
|
||||
case GIT_DELTA_IGNORED: code = 'I'; break;
|
||||
case GIT_DELTA_UNTRACKED: code = '?'; break;
|
||||
case GIT_DELTA_UNREADABLE: code = 'X'; break;
|
||||
default: code = ' '; break;
|
||||
}
|
||||
|
||||
return code;
|
||||
@ -351,7 +352,7 @@ static int print_binary_hunk(diff_print_info *pi, git_blob *old, git_blob *new)
|
||||
else
|
||||
git_buf_putc(pi->buf, (char)chunk_len - 26 + 'a' - 1);
|
||||
|
||||
git_buf_put_base85(pi->buf, scan, chunk_len);
|
||||
git_buf_encode_base85(pi->buf, scan, chunk_len);
|
||||
git_buf_putc(pi->buf, '\n');
|
||||
|
||||
if (git_buf_oom(pi->buf)) {
|
||||
@ -441,6 +442,7 @@ static int diff_print_patch_file(
|
||||
if (S_ISDIR(delta->new_file.mode) ||
|
||||
delta->status == GIT_DELTA_UNMODIFIED ||
|
||||
delta->status == GIT_DELTA_IGNORED ||
|
||||
delta->status == GIT_DELTA_UNREADABLE ||
|
||||
(delta->status == GIT_DELTA_UNTRACKED &&
|
||||
(pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0))
|
||||
return 0;
|
||||
|
@ -114,7 +114,7 @@ static git_diff_delta *diff_delta__merge_like_cgit_reversed(
|
||||
if ((dup = diff_delta__dup(a, pool)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (b->status == GIT_DELTA_UNMODIFIED || b->status == GIT_DELTA_UNTRACKED)
|
||||
if (b->status == GIT_DELTA_UNMODIFIED || b->status == GIT_DELTA_UNTRACKED || b->status == GIT_DELTA_UNREADABLE)
|
||||
return dup;
|
||||
|
||||
if (dup->status == GIT_DELTA_DELETED) {
|
||||
@ -732,6 +732,7 @@ static bool is_rename_source(
|
||||
switch (delta->status) {
|
||||
case GIT_DELTA_ADDED:
|
||||
case GIT_DELTA_UNTRACKED:
|
||||
case GIT_DELTA_UNREADABLE:
|
||||
case GIT_DELTA_IGNORED:
|
||||
return false;
|
||||
|
||||
@ -786,6 +787,7 @@ GIT_INLINE(bool) delta_is_new_only(git_diff_delta *delta)
|
||||
{
|
||||
return (delta->status == GIT_DELTA_ADDED ||
|
||||
delta->status == GIT_DELTA_UNTRACKED ||
|
||||
delta->status == GIT_DELTA_UNREADABLE ||
|
||||
delta->status == GIT_DELTA_IGNORED);
|
||||
}
|
||||
|
||||
|
16
src/errors.c
16
src/errors.c
@ -45,15 +45,19 @@ void giterr_set(int error_class, const char *string, ...)
|
||||
#endif
|
||||
int error_code = (error_class == GITERR_OS) ? errno : 0;
|
||||
|
||||
va_start(arglist, string);
|
||||
git_buf_vprintf(&buf, string, arglist);
|
||||
va_end(arglist);
|
||||
if (string) {
|
||||
va_start(arglist, string);
|
||||
git_buf_vprintf(&buf, string, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
if (error_class == GITERR_OS)
|
||||
git_buf_PUTS(&buf, ": ");
|
||||
}
|
||||
|
||||
if (error_class == GITERR_OS) {
|
||||
#ifdef GIT_WIN32
|
||||
char * win32_error = git_win32_get_error_message(win32_error_code);
|
||||
if (win32_error) {
|
||||
git_buf_PUTS(&buf, ": ");
|
||||
git_buf_puts(&buf, win32_error);
|
||||
git__free(win32_error);
|
||||
|
||||
@ -61,10 +65,8 @@ void giterr_set(int error_class, const char *string, ...)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (error_code) {
|
||||
git_buf_PUTS(&buf, ": ");
|
||||
if (error_code)
|
||||
git_buf_puts(&buf, strerror(error_code));
|
||||
}
|
||||
|
||||
if (error_code)
|
||||
errno = 0;
|
||||
|
@ -334,8 +334,6 @@ int git_filebuf_commit(git_filebuf *file)
|
||||
|
||||
file->fd = -1;
|
||||
|
||||
p_unlink(file->path_original);
|
||||
|
||||
if (p_rename(file->path_lock, file->path_original) < 0) {
|
||||
giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original);
|
||||
goto on_error;
|
||||
|
@ -355,8 +355,9 @@ int git_futils_mkdir(
|
||||
if (p_mkdir(make_path.ptr, mode) < 0) {
|
||||
int tmp_errno = giterr_system_last();
|
||||
|
||||
/* ignore error if directory already exists */
|
||||
if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
||||
/* ignore error if not at end or if directory already exists */
|
||||
if (lastch == '\0' &&
|
||||
(p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode))) {
|
||||
giterr_system_set(tmp_errno);
|
||||
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
|
||||
goto done;
|
||||
@ -374,7 +375,8 @@ int git_futils_mkdir(
|
||||
if (((flags & GIT_MKDIR_CHMOD_PATH) != 0 ||
|
||||
(lastch == '\0' && (flags & GIT_MKDIR_CHMOD) != 0)) &&
|
||||
st.st_mode != mode &&
|
||||
(error = p_chmod(make_path.ptr, mode)) < 0) {
|
||||
(error = p_chmod(make_path.ptr, mode)) < 0 &&
|
||||
lastch == '\0') {
|
||||
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", make_path.ptr);
|
||||
goto done;
|
||||
}
|
||||
|
75
src/global.c
75
src/global.c
@ -16,6 +16,14 @@ git_mutex git__mwindow_mutex;
|
||||
|
||||
#define MAX_SHUTDOWN_CB 8
|
||||
|
||||
#ifdef GIT_SSL
|
||||
# include <openssl/ssl.h>
|
||||
SSL_CTX *git__ssl_ctx;
|
||||
# ifdef GIT_THREADS
|
||||
static git_mutex *openssl_locks;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
|
||||
static git_atomic git__n_shutdown_callbacks;
|
||||
static git_atomic git__n_inits;
|
||||
@ -39,6 +47,62 @@ static void git__shutdown(void)
|
||||
|
||||
}
|
||||
|
||||
#if defined(GIT_THREADS) && defined(GIT_SSL)
|
||||
void openssl_locking_function(int mode, int n, const char *file, int line)
|
||||
{
|
||||
int lock;
|
||||
|
||||
GIT_UNUSED(file);
|
||||
GIT_UNUSED(line);
|
||||
|
||||
lock = mode & CRYPTO_LOCK;
|
||||
|
||||
if (lock) {
|
||||
git_mutex_lock(&openssl_locks[n]);
|
||||
} else {
|
||||
git_mutex_unlock(&openssl_locks[n]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void init_ssl(void)
|
||||
{
|
||||
#ifdef GIT_SSL
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
git__ssl_ctx = SSL_CTX_new(SSLv23_method());
|
||||
SSL_CTX_set_mode(git__ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_verify(git__ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx)) {
|
||||
SSL_CTX_free(git__ssl_ctx);
|
||||
git__ssl_ctx = NULL;
|
||||
}
|
||||
|
||||
# ifdef GIT_THREADS
|
||||
{
|
||||
int num_locks, i;
|
||||
|
||||
num_locks = CRYPTO_num_locks();
|
||||
openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
|
||||
if (openssl_locks == NULL) {
|
||||
SSL_CTX_free(git__ssl_ctx);
|
||||
git__ssl_ctx = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_locks; i++) {
|
||||
if (git_mutex_init(&openssl_locks[i]) != 0) {
|
||||
SSL_CTX_free(git__ssl_ctx);
|
||||
git__ssl_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTO_set_locking_callback(openssl_locking_function);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the global state with TLS
|
||||
*
|
||||
@ -168,10 +232,14 @@ static void init_once(void)
|
||||
return;
|
||||
pthread_key_create(&_tls_key, &cb__free_status);
|
||||
|
||||
|
||||
/* Initialize any other subsystems that have global state */
|
||||
if ((init_error = git_hash_global_init()) >= 0)
|
||||
init_error = git_sysdir_global_init();
|
||||
|
||||
/* OpenSSL needs to be initialized from the main thread */
|
||||
init_ssl();
|
||||
|
||||
GIT_MEMORY_BARRIER;
|
||||
}
|
||||
|
||||
@ -225,6 +293,13 @@ static git_global_st __state;
|
||||
|
||||
int git_threads_init(void)
|
||||
{
|
||||
static int ssl_inited = 0;
|
||||
|
||||
if (!ssl_inited) {
|
||||
init_ssl();
|
||||
ssl_inited = 1;
|
||||
}
|
||||
|
||||
git_atomic_inc(&git__n_inits);
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,8 +13,14 @@
|
||||
typedef struct {
|
||||
git_error *last_error;
|
||||
git_error error_t;
|
||||
char oid_fmt[41];
|
||||
} git_global_st;
|
||||
|
||||
#ifdef GIT_SSL
|
||||
# include <openssl/ssl.h>
|
||||
extern SSL_CTX *git__ssl_ctx;
|
||||
#endif
|
||||
|
||||
git_global_st *git__global_state(void);
|
||||
|
||||
extern git_mutex git__mwindow_mutex;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "oidmap.h"
|
||||
#include "zstream.h"
|
||||
|
||||
extern git_mutex git__mwindow_mutex;
|
||||
|
||||
#define UINT31_MAX (0x7FFFFFFF)
|
||||
|
||||
struct entry {
|
||||
@ -433,6 +435,8 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
|
||||
git_map map;
|
||||
int error;
|
||||
|
||||
assert(data && size);
|
||||
|
||||
/* the offset needs to be at the beginning of the a page boundary */
|
||||
page_start = (offset / page_size) * page_size;
|
||||
page_offset = offset - page_start;
|
||||
@ -451,9 +455,12 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
|
||||
{
|
||||
git_off_t current_size = idx->pack->mwf.size;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
/* add the extra space we need at the end */
|
||||
if (p_ftruncate(idx->pack->mwf.fd, current_size + size) < 0) {
|
||||
giterr_system_set(errno);
|
||||
giterr_set(GITERR_OS, "Failed to increase size of pack file '%s'", idx->pack->pack_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1044,6 +1051,11 @@ void git_indexer_free(git_indexer *idx)
|
||||
}
|
||||
|
||||
git_vector_free_deep(&idx->deltas);
|
||||
git_packfile_free(idx->pack);
|
||||
|
||||
if (!git_mutex_lock(&git__mwindow_mutex)) {
|
||||
git_packfile_free(idx->pack);
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
}
|
||||
|
||||
git__free(idx);
|
||||
}
|
||||
|
188
src/merge.c
188
src/merge.c
@ -228,8 +228,11 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
|
||||
return -1;
|
||||
|
||||
git_vector_foreach(twos, i, two) {
|
||||
git_commit_list_parse(walk, two);
|
||||
if (git_commit_list_parse(walk, two) < 0)
|
||||
return -1;
|
||||
|
||||
two->flags |= PARENT2;
|
||||
|
||||
if (git_pqueue_insert(&list, two) < 0)
|
||||
return -1;
|
||||
}
|
||||
@ -2193,8 +2196,7 @@ static int merge_normalize_checkout_opts(
|
||||
memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options));
|
||||
else {
|
||||
git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
|
||||
default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE |
|
||||
GIT_CHECKOUT_ALLOW_CONFLICTS;
|
||||
default_checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
||||
|
||||
memcpy(checkout_opts, &default_checkout_opts, sizeof(git_checkout_options));
|
||||
}
|
||||
@ -2226,64 +2228,6 @@ static int merge_normalize_checkout_opts(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int merge_affected_paths(git_vector *paths, git_repository *repo, git_index *index_new)
|
||||
{
|
||||
git_tree *head_tree = NULL;
|
||||
git_iterator *iter_head = NULL, *iter_new = NULL;
|
||||
git_diff *merged_list = NULL;
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
git_diff_delta *delta;
|
||||
size_t i;
|
||||
const git_index_entry *e;
|
||||
char *path;
|
||||
int error = 0;
|
||||
|
||||
if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
|
||||
(error = git_iterator_for_tree(&iter_head, head_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
|
||||
(error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
|
||||
(error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0)
|
||||
goto done;
|
||||
|
||||
git_vector_foreach(&merged_list->deltas, i, delta) {
|
||||
path = git__strdup(delta->new_file.path);
|
||||
GITERR_CHECK_ALLOC(path);
|
||||
|
||||
if ((error = git_vector_insert(paths, path)) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < git_index_entrycount(index_new); i++) {
|
||||
e = git_index_get_byindex(index_new, i);
|
||||
|
||||
if (git_index_entry_stage(e) != 0 &&
|
||||
(git_vector_last(paths) == NULL ||
|
||||
strcmp(git_vector_last(paths), e->path) != 0)) {
|
||||
|
||||
path = git__strdup(e->path);
|
||||
GITERR_CHECK_ALLOC(path);
|
||||
|
||||
if ((error = git_vector_insert(paths, path)) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
on_error:
|
||||
git_vector_foreach(paths, i, path)
|
||||
git__free(path);
|
||||
|
||||
git_vector_clear(paths);
|
||||
|
||||
done:
|
||||
git_tree_free(head_tree);
|
||||
git_iterator_free(iter_head);
|
||||
git_iterator_free(iter_new);
|
||||
git_diff_free(merged_list);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
|
||||
{
|
||||
git_tree *head_tree = NULL;
|
||||
@ -2372,30 +2316,43 @@ done:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_merge__indexes(git_repository *repo, git_index *index_new)
|
||||
int git_merge__check_result(git_repository *repo, git_index *index_new)
|
||||
{
|
||||
git_index *index_repo = NULL;
|
||||
int index_repo_caps = 0;
|
||||
git_tree *head_tree = NULL;
|
||||
git_iterator *iter_head = NULL, *iter_new = NULL;
|
||||
git_diff *merged_list = NULL;
|
||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||
git_diff_delta *delta;
|
||||
git_vector paths = GIT_VECTOR_INIT;
|
||||
size_t index_conflicts = 0, wd_conflicts = 0, conflicts, i;
|
||||
char *path;
|
||||
size_t i, index_conflicts = 0, wd_conflicts = 0, conflicts;
|
||||
const git_index_entry *e;
|
||||
const git_index_name_entry *name;
|
||||
const git_index_reuc_entry *reuc;
|
||||
int error = 0;
|
||||
|
||||
if ((error = git_repository_index(&index_repo, repo)) < 0)
|
||||
if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
|
||||
(error = git_iterator_for_tree(&iter_head, head_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
|
||||
(error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
|
||||
(error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0)
|
||||
goto done;
|
||||
|
||||
/* Set the index to case sensitive to handle the merge */
|
||||
index_repo_caps = git_index_caps(index_repo);
|
||||
git_vector_foreach(&merged_list->deltas, i, delta) {
|
||||
if ((error = git_vector_insert(&paths, (char *)delta->new_file.path)) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((error = git_index_set_caps(index_repo, (index_repo_caps & ~GIT_INDEXCAP_IGNORE_CASE))) < 0)
|
||||
goto done;
|
||||
for (i = 0; i < git_index_entrycount(index_new); i++) {
|
||||
e = git_index_get_byindex(index_new, i);
|
||||
|
||||
if (git_index_entry_stage(e) != 0 &&
|
||||
(git_vector_last(&paths) == NULL ||
|
||||
strcmp(git_vector_last(&paths), e->path) != 0)) {
|
||||
|
||||
if ((error = git_vector_insert(&paths, (char *)e->path)) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the index and workdir state do not prevent merging */
|
||||
if ((error = merge_affected_paths(&paths, repo, index_new)) < 0 ||
|
||||
(error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 ||
|
||||
if ((error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 ||
|
||||
(error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0)
|
||||
goto done;
|
||||
|
||||
@ -2403,68 +2360,14 @@ int git_merge__indexes(git_repository *repo, git_index *index_new)
|
||||
giterr_set(GITERR_MERGE, "%d uncommitted change%s would be overwritten by merge",
|
||||
conflicts, (conflicts != 1) ? "s" : "");
|
||||
error = GIT_EMERGECONFLICT;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Remove removed items from the index */
|
||||
git_vector_foreach(&paths, i, path) {
|
||||
if (git_index_get_bypath(index_new, path, 0) == NULL) {
|
||||
if ((error = git_index_remove(index_repo, path, 0)) < 0 &&
|
||||
error != GIT_ENOTFOUND)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add updated items to the index */
|
||||
git_vector_foreach(&paths, i, path) {
|
||||
if ((e = git_index_get_bypath(index_new, path, 0)) != NULL) {
|
||||
if ((error = git_index_add(index_repo, e)) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add conflicts */
|
||||
git_index_conflict_cleanup(index_repo);
|
||||
|
||||
for (i = 0; i < git_index_entrycount(index_new); i++) {
|
||||
e = git_index_get_byindex(index_new, i);
|
||||
|
||||
if (git_index_entry_stage(e) != 0 &&
|
||||
(error = git_index_add(index_repo, e)) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Add name entries */
|
||||
git_index_name_clear(index_repo);
|
||||
|
||||
for (i = 0; i < git_index_name_entrycount(index_new); i++) {
|
||||
name = git_index_name_get_byindex(index_new, i);
|
||||
|
||||
if ((error = git_index_name_add(index_repo,
|
||||
name->ancestor, name->ours, name->theirs)) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Add the reuc */
|
||||
git_index_reuc_clear(index_repo);
|
||||
|
||||
for (i = 0; i < git_index_reuc_entrycount(index_new); i++) {
|
||||
reuc = (git_index_reuc_entry *)git_index_reuc_get_byindex(index_new, i);
|
||||
|
||||
if ((error = git_index_reuc_add(index_repo, reuc->path,
|
||||
reuc->mode[0], &reuc->oid[0],
|
||||
reuc->mode[1], &reuc->oid[1],
|
||||
reuc->mode[2], &reuc->oid[2])) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (index_repo != NULL)
|
||||
git_index_set_caps(index_repo, index_repo_caps);
|
||||
|
||||
git_index_free(index_repo);
|
||||
git_vector_free_deep(&paths);
|
||||
git_vector_free(&paths);
|
||||
git_tree_free(head_tree);
|
||||
git_iterator_free(iter_head);
|
||||
git_iterator_free(iter_new);
|
||||
git_diff_free(merged_list);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -2479,12 +2382,14 @@ int git_merge__append_conflicts_to_merge_msg(
|
||||
size_t i;
|
||||
int error;
|
||||
|
||||
if (!git_index_has_conflicts(index))
|
||||
return 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_APPEND, GIT_MERGE_FILE_MODE)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_index_has_conflicts(index))
|
||||
git_filebuf_printf(&file, "\nConflicts:\n");
|
||||
git_filebuf_printf(&file, "\nConflicts:\n");
|
||||
|
||||
for (i = 0; i < git_index_entrycount(index); i++) {
|
||||
const git_index_entry *e = git_index_get_byindex(index, i);
|
||||
@ -2509,7 +2414,6 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int merge_state_cleanup(git_repository *repo)
|
||||
{
|
||||
const char *state_files[] = {
|
||||
@ -2657,7 +2561,7 @@ int git_merge(
|
||||
git_checkout_options checkout_opts;
|
||||
git_merge_head *ancestor_head = NULL, *our_head = NULL;
|
||||
git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL;
|
||||
git_index *index_new = NULL, *index_repo = NULL;
|
||||
git_index *index_new = NULL;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
@ -2697,10 +2601,9 @@ int git_merge(
|
||||
/* TODO: recursive, octopus, etc... */
|
||||
|
||||
if ((error = git_merge_trees(&index_new, repo, ancestor_tree, our_tree, their_trees[0], 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, &checkout_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, &checkout_opts)) < 0)
|
||||
goto on_error;
|
||||
|
||||
goto done;
|
||||
@ -2710,7 +2613,6 @@ on_error:
|
||||
|
||||
done:
|
||||
git_index_free(index_new);
|
||||
git_index_free(index_repo);
|
||||
|
||||
git_tree_free(ancestor_tree);
|
||||
git_tree_free(our_tree);
|
||||
|
@ -149,7 +149,7 @@ int git_merge__setup(
|
||||
const git_merge_head *heads[],
|
||||
size_t heads_len);
|
||||
|
||||
int git_merge__indexes(git_repository *repo, git_index *index_new);
|
||||
int git_merge__check_result(git_repository *repo, git_index *index_new);
|
||||
|
||||
int git_merge__append_conflicts_to_merge_msg(git_repository *repo, git_index *index);
|
||||
|
||||
|
125
src/mwindow.c
125
src/mwindow.c
@ -11,6 +11,10 @@
|
||||
#include "fileops.h"
|
||||
#include "map.h"
|
||||
#include "global.h"
|
||||
#include "strmap.h"
|
||||
#include "pack.h"
|
||||
|
||||
GIT__USE_STRMAP;
|
||||
|
||||
#define DEFAULT_WINDOW_SIZE \
|
||||
(sizeof(void*) >= 8 \
|
||||
@ -26,20 +30,127 @@ size_t git_mwindow__mapped_limit = DEFAULT_MAPPED_LIMIT;
|
||||
/* Whenever you want to read or modify this, grab git__mwindow_mutex */
|
||||
static git_mwindow_ctl mem_ctl;
|
||||
|
||||
/*
|
||||
* Free all the windows in a sequence, typically because we're done
|
||||
* with the file
|
||||
/* Global list of mwindow files, to open packs once across repos */
|
||||
git_strmap *git__pack_cache = NULL;
|
||||
|
||||
/**
|
||||
* Run under mwindow lock
|
||||
*/
|
||||
int git_mwindow_files_init(void)
|
||||
{
|
||||
if (git__pack_cache)
|
||||
return 0;
|
||||
|
||||
return git_strmap_alloc(&git__pack_cache);
|
||||
}
|
||||
|
||||
void git_mwindow_files_free(void)
|
||||
{
|
||||
git_strmap *tmp = git__pack_cache;
|
||||
|
||||
git__pack_cache = NULL;
|
||||
git_strmap_free(tmp);
|
||||
}
|
||||
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
|
||||
{
|
||||
int error;
|
||||
char *packname;
|
||||
git_strmap_iter pos;
|
||||
struct git_pack_file *pack;
|
||||
|
||||
if ((error = git_packfile__name(&packname, path)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_mutex_lock(&git__mwindow_mutex) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to lock mwindow mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_mwindow_files_init() < 0) {
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
git__free(packname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = git_strmap_lookup_index(git__pack_cache, packname);
|
||||
git__free(packname);
|
||||
|
||||
if (git_strmap_valid_index(git__pack_cache, pos)) {
|
||||
pack = git_strmap_value_at(git__pack_cache, pos);
|
||||
git_atomic_inc(&pack->refcount);
|
||||
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
*out = pack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we didn't find it, we need to create it */
|
||||
if ((error = git_packfile_alloc(&pack, path)) < 0) {
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
git_atomic_inc(&pack->refcount);
|
||||
|
||||
git_strmap_insert(git__pack_cache, pack->pack_name, pack, error);
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
|
||||
if (error < 0) {
|
||||
git_packfile_free(pack);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = pack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_mwindow_put_pack(struct git_pack_file *pack)
|
||||
{
|
||||
int count;
|
||||
git_strmap_iter pos;
|
||||
|
||||
if (git_mutex_lock(&git__mwindow_mutex) < 0)
|
||||
return;
|
||||
|
||||
/* put before get would be a corrupted state */
|
||||
assert(git__pack_cache);
|
||||
|
||||
pos = git_strmap_lookup_index(git__pack_cache, pack->pack_name);
|
||||
/* if we cannot find it, the state is corrupted */
|
||||
assert(git_strmap_valid_index(git__pack_cache, pos));
|
||||
|
||||
count = git_atomic_dec(&pack->refcount);
|
||||
if (count == 0) {
|
||||
git_strmap_delete_at(git__pack_cache, pos);
|
||||
git_packfile_free(pack);
|
||||
}
|
||||
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
void git_mwindow_free_all(git_mwindow_file *mwf)
|
||||
{
|
||||
git_mwindow_ctl *ctl = &mem_ctl;
|
||||
size_t i;
|
||||
|
||||
if (git_mutex_lock(&git__mwindow_mutex)) {
|
||||
giterr_set(GITERR_THREAD, "unable to lock mwindow mutex");
|
||||
return;
|
||||
}
|
||||
|
||||
git_mwindow_free_all_locked(mwf);
|
||||
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free all the windows in a sequence, typically because we're done
|
||||
* with the file
|
||||
*/
|
||||
void git_mwindow_free_all_locked(git_mwindow_file *mwf)
|
||||
{
|
||||
git_mwindow_ctl *ctl = &mem_ctl;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Remove these windows from the global list
|
||||
*/
|
||||
@ -67,8 +178,6 @@ void git_mwindow_free_all(git_mwindow_file *mwf)
|
||||
mwf->windows = w->next;
|
||||
git__free(w);
|
||||
}
|
||||
|
||||
git_mutex_unlock(&git__mwindow_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,10 +36,18 @@ typedef struct git_mwindow_ctl {
|
||||
} git_mwindow_ctl;
|
||||
|
||||
int git_mwindow_contains(git_mwindow *win, git_off_t offset);
|
||||
void git_mwindow_free_all(git_mwindow_file *mwf);
|
||||
void git_mwindow_free_all(git_mwindow_file *mwf); /* locks */
|
||||
void git_mwindow_free_all_locked(git_mwindow_file *mwf); /* run under lock */
|
||||
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, size_t extra, unsigned int *left);
|
||||
int git_mwindow_file_register(git_mwindow_file *mwf);
|
||||
void git_mwindow_file_deregister(git_mwindow_file *mwf);
|
||||
void git_mwindow_close(git_mwindow **w_cursor);
|
||||
|
||||
int git_mwindow_files_init(void);
|
||||
void git_mwindow_files_free(void);
|
||||
|
||||
struct git_pack_file; /* just declaration to avoid cyclical includes */
|
||||
int git_mwindow_get_pack(struct git_pack_file **out, const char *path);
|
||||
void git_mwindow_put_pack(struct git_pack_file *pack);
|
||||
|
||||
#endif
|
||||
|
28
src/netops.c
28
src/netops.c
@ -13,6 +13,7 @@
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
#else
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# ifdef _MSC_VER
|
||||
# pragma comment(lib, "ws2_32")
|
||||
@ -33,6 +34,7 @@
|
||||
#include "posix.h"
|
||||
#include "buffer.h"
|
||||
#include "http_parser.h"
|
||||
#include "global.h"
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
static void net_set_error(const char *str)
|
||||
@ -157,7 +159,7 @@ void gitno_buffer_setup_callback(
|
||||
void gitno_buffer_setup(gitno_socket *socket, gitno_buffer *buf, char *data, size_t len)
|
||||
{
|
||||
#ifdef GIT_SSL
|
||||
if (socket->ssl.ctx) {
|
||||
if (socket->ssl.ssl) {
|
||||
gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv_ssl, NULL);
|
||||
return;
|
||||
}
|
||||
@ -202,7 +204,6 @@ static int gitno_ssl_teardown(gitno_ssl *ssl)
|
||||
ret = 0;
|
||||
|
||||
SSL_free(ssl->ssl);
|
||||
SSL_CTX_free(ssl->ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -390,18 +391,12 @@ static int ssl_setup(gitno_socket *socket, const char *host, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
socket->ssl.ctx = SSL_CTX_new(SSLv23_method());
|
||||
if (socket->ssl.ctx == NULL)
|
||||
return ssl_set_error(&socket->ssl, 0);
|
||||
if (git__ssl_ctx == NULL) {
|
||||
giterr_set(GITERR_NET, "OpenSSL initialization failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSL_CTX_set_mode(socket->ssl.ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_verify(socket->ssl.ctx, SSL_VERIFY_NONE, NULL);
|
||||
if (!SSL_CTX_set_default_verify_paths(socket->ssl.ctx))
|
||||
return ssl_set_error(&socket->ssl, 0);
|
||||
|
||||
socket->ssl.ssl = SSL_new(socket->ssl.ctx);
|
||||
socket->ssl.ssl = SSL_new(git__ssl_ctx);
|
||||
if (socket->ssl.ssl == NULL)
|
||||
return ssl_set_error(&socket->ssl, 0);
|
||||
|
||||
@ -538,7 +533,7 @@ int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags)
|
||||
size_t off = 0;
|
||||
|
||||
#ifdef GIT_SSL
|
||||
if (socket->ssl.ctx)
|
||||
if (socket->ssl.ssl)
|
||||
return gitno_send_ssl(&socket->ssl, msg, len, flags);
|
||||
#endif
|
||||
|
||||
@ -559,7 +554,7 @@ int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags)
|
||||
int gitno_close(gitno_socket *s)
|
||||
{
|
||||
#ifdef GIT_SSL
|
||||
if (s->ssl.ctx &&
|
||||
if (s->ssl.ssl &&
|
||||
gitno_ssl_teardown(&s->ssl) < 0)
|
||||
return -1;
|
||||
#endif
|
||||
@ -723,6 +718,9 @@ int gitno_extract_url_parts(
|
||||
if (u.field_set & (1 << UF_PATH)) {
|
||||
*path = git__substrdup(_path, u.field_data[UF_PATH].len);
|
||||
GITERR_CHECK_ALLOC(*path);
|
||||
} else {
|
||||
giterr_set(GITERR_NET, "invalid url, missing path");
|
||||
return GIT_EINVALIDSPEC;
|
||||
}
|
||||
|
||||
if (u.field_set & (1 << UF_USERINFO)) {
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
struct gitno_ssl {
|
||||
#ifdef GIT_SSL
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
#else
|
||||
size_t dummy;
|
||||
|
@ -210,7 +210,7 @@ static int packfile_load__cb(void *data, git_buf *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = git_packfile_alloc(&pack, path->ptr);
|
||||
error = git_mwindow_get_pack(&pack, path->ptr);
|
||||
|
||||
/* ignore missing .pack file as git does */
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
@ -605,7 +605,7 @@ static void pack_backend__free(git_odb_backend *_backend)
|
||||
|
||||
for (i = 0; i < backend->packs.length; ++i) {
|
||||
struct git_pack_file *p = git_vector_get(&backend->packs, i);
|
||||
git_packfile_free(p);
|
||||
git_mwindow_put_pack(p);
|
||||
}
|
||||
|
||||
git_vector_free(&backend->packs);
|
||||
@ -647,7 +647,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
|
||||
if (pack_backend__alloc(&backend, 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_packfile_alloc(&packfile, idx) < 0 ||
|
||||
if (git_mwindow_get_pack(&packfile, idx) < 0 ||
|
||||
git_vector_insert(&backend->packs, packfile) < 0)
|
||||
{
|
||||
pack_backend__free((git_odb_backend *)backend);
|
||||
@ -664,6 +664,9 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
|
||||
struct pack_backend *backend = NULL;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
if (git_mwindow_files_init() < 0)
|
||||
return -1;
|
||||
|
||||
if (pack_backend__alloc(&backend, 8) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "common.h"
|
||||
#include "git2/oid.h"
|
||||
#include "repository.h"
|
||||
#include "global.h"
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
@ -99,6 +100,13 @@ void git_oid_pathfmt(char *str, const git_oid *oid)
|
||||
str = fmt_one(str, oid->id[i]);
|
||||
}
|
||||
|
||||
char *git_oid_tostr_s(const git_oid *oid)
|
||||
{
|
||||
char *str = GIT_GLOBAL->oid_fmt;
|
||||
git_oid_nfmt(str, GIT_OID_HEXSZ + 1, oid);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *git_oid_allocfmt(const git_oid *oid)
|
||||
{
|
||||
char *str = git__malloc(GIT_OID_HEXSZ + 1);
|
||||
|
11
src/oid.h
11
src/oid.h
@ -9,6 +9,17 @@
|
||||
|
||||
#include "git2/oid.h"
|
||||
|
||||
/**
|
||||
* Format a git_oid into a newly allocated c-string.
|
||||
*
|
||||
* The c-string is owned by the caller and needs to be manually freed.
|
||||
*
|
||||
* @param id the oid structure to format
|
||||
* @return the c-string; NULL if memory is exhausted. Caller must
|
||||
* deallocate the string with git__free().
|
||||
*/
|
||||
char *git_oid_allocfmt(const git_oid *id);
|
||||
|
||||
GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
|
||||
{
|
||||
int i;
|
||||
|
25
src/pack.c
25
src/pack.c
@ -744,7 +744,7 @@ cleanup:
|
||||
git__free(obj->data);
|
||||
|
||||
if (elem)
|
||||
*obj_offset = elem->offset;
|
||||
*obj_offset = curpos;
|
||||
|
||||
git_array_clear(chain);
|
||||
return error;
|
||||
@ -968,10 +968,10 @@ void git_packfile_free(struct git_pack_file *p)
|
||||
|
||||
cache_free(&p->bases);
|
||||
|
||||
git_mwindow_free_all(&p->mwf);
|
||||
|
||||
if (p->mwf.fd >= 0)
|
||||
if (p->mwf.fd >= 0) {
|
||||
git_mwindow_free_all_locked(&p->mwf);
|
||||
p_close(p->mwf.fd);
|
||||
}
|
||||
|
||||
pack_index_free(p);
|
||||
|
||||
@ -1063,6 +1063,23 @@ cleanup:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_packfile__name(char **out, const char *path)
|
||||
{
|
||||
size_t path_len;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
path_len = strlen(path);
|
||||
|
||||
if (path_len < strlen(".idx"))
|
||||
return git_odb__error_notfound("invalid packfile path", NULL);
|
||||
|
||||
if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
|
||||
return -1;
|
||||
|
||||
*out = git_buf_detach(&buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
@ -90,6 +90,7 @@ struct git_pack_file {
|
||||
git_mwindow_file mwf;
|
||||
git_map index_map;
|
||||
git_mutex lock; /* protect updates to mwf and index_map */
|
||||
git_atomic refcount;
|
||||
|
||||
uint32_t num_objects;
|
||||
uint32_t num_bad_objects;
|
||||
@ -123,6 +124,8 @@ typedef struct git_packfile_stream {
|
||||
|
||||
size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type);
|
||||
|
||||
int git_packfile__name(char **out, const char *path);
|
||||
|
||||
int git_packfile_unpack_header(
|
||||
size_t *size_p,
|
||||
git_otype *type_p,
|
||||
|
73
src/path.c
73
src/path.c
@ -377,26 +377,33 @@ static int error_invalid_local_file_uri(const char *uri)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int local_file_url_prefixlen(const char *file_url)
|
||||
{
|
||||
int len = -1;
|
||||
|
||||
if (git__prefixcmp(file_url, "file://") == 0) {
|
||||
if (file_url[7] == '/')
|
||||
len = 8;
|
||||
else if (git__prefixcmp(file_url + 7, "localhost/") == 0)
|
||||
len = 17;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool git_path_is_local_file_url(const char *file_url)
|
||||
{
|
||||
return (local_file_url_prefixlen(file_url) > 0);
|
||||
}
|
||||
|
||||
int git_path_fromurl(git_buf *local_path_out, const char *file_url)
|
||||
{
|
||||
int offset = 0, len;
|
||||
int offset;
|
||||
|
||||
assert(local_path_out && file_url);
|
||||
|
||||
if (git__prefixcmp(file_url, "file://") != 0)
|
||||
return error_invalid_local_file_uri(file_url);
|
||||
|
||||
offset += 7;
|
||||
len = (int)strlen(file_url);
|
||||
|
||||
if (offset < len && file_url[offset] == '/')
|
||||
offset++;
|
||||
else if (offset < len && git__prefixcmp(file_url + offset, "localhost/") == 0)
|
||||
offset += 10;
|
||||
else
|
||||
return error_invalid_local_file_uri(file_url);
|
||||
|
||||
if (offset >= len || file_url[offset] == '/')
|
||||
if ((offset = local_file_url_prefixlen(file_url)) < 0 ||
|
||||
file_url[offset] == '\0' || file_url[offset] == '/')
|
||||
return error_invalid_local_file_uri(file_url);
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
@ -404,7 +411,6 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
|
||||
#endif
|
||||
|
||||
git_buf_clear(local_path_out);
|
||||
|
||||
return git__percent_decode(local_path_out, file_url + offset);
|
||||
}
|
||||
|
||||
@ -1104,20 +1110,29 @@ int git_path_dirload_with_stat(
|
||||
|
||||
if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
|
||||
(error = git_path_lstat(full.ptr, &ps->st)) < 0) {
|
||||
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
/* file was removed between readdir and lstat */
|
||||
git_vector_remove(contents, i--);
|
||||
continue;
|
||||
} else {
|
||||
/* Treat the file as unreadable if we get any other error */
|
||||
memset(&ps->st, 0, sizeof(ps->st));
|
||||
ps->st.st_mode = GIT_FILEMODE_UNREADABLE;
|
||||
}
|
||||
|
||||
break;
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(ps->st.st_mode)) {
|
||||
ps->path[ps->path_len++] = '/';
|
||||
ps->path[ps->path_len] = '\0';
|
||||
}
|
||||
else if (!S_ISREG(ps->st.st_mode) && !S_ISLNK(ps->st.st_mode)) {
|
||||
/* skip everything but dirs, plain files, and symlinks */
|
||||
git_vector_remove(contents, i--);
|
||||
}
|
||||
}
|
||||
|
||||
/* sort now that directory suffix is added */
|
||||
@ -1130,18 +1145,8 @@ int git_path_dirload_with_stat(
|
||||
|
||||
int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* If url_or_path begins with file:// treat it as a URL */
|
||||
if (!git__prefixcmp(url_or_path, "file://")) {
|
||||
if ((error = git_path_fromurl(local_path_out, url_or_path)) < 0) {
|
||||
return error;
|
||||
}
|
||||
} else { /* We assume url_or_path is already a path */
|
||||
if ((error = git_buf_sets(local_path_out, url_or_path)) < 0) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (git_path_is_local_file_url(url_or_path))
|
||||
return git_path_fromurl(local_path_out, url_or_path);
|
||||
else
|
||||
return git_buf_sets(local_path_out, url_or_path);
|
||||
}
|
||||
|
10
src/path.h
10
src/path.h
@ -8,6 +8,7 @@
|
||||
#define INCLUDE_path_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "posix.h"
|
||||
#include "buffer.h"
|
||||
#include "vector.h"
|
||||
|
||||
@ -127,6 +128,14 @@ GIT_INLINE(int) git_path_is_relative(const char *p)
|
||||
return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string is at end of path segment (i.e. looking at '/' or '\0')
|
||||
*/
|
||||
GIT_INLINE(int) git_path_at_end_of_segment(const char *p)
|
||||
{
|
||||
return !*p || *p == '/';
|
||||
}
|
||||
|
||||
extern int git__percent_decode(git_buf *decoded_out, const char *input);
|
||||
|
||||
/**
|
||||
@ -439,6 +448,7 @@ extern int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen);
|
||||
extern bool git_path_does_fs_decompose_unicode(const char *root);
|
||||
|
||||
/* Used for paths to repositories on the filesystem */
|
||||
extern bool git_path_is_local_file_url(const char *file_url);
|
||||
extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path);
|
||||
|
||||
#endif
|
||||
|
@ -146,7 +146,7 @@ GIT_INLINE(void) pool_remove_page(
|
||||
void *git_pool_malloc(git_pool *pool, uint32_t items)
|
||||
{
|
||||
git_pool_page *scan = pool->open, *prev;
|
||||
uint32_t size = items * pool->item_size;
|
||||
uint32_t size = ((items * pool->item_size) + 7) & ~7;
|
||||
void *ptr = NULL;
|
||||
|
||||
pool->has_string_alloc = 0;
|
||||
|
74
src/posix.h
74
src/posix.h
@ -12,23 +12,61 @@
|
||||
#include <time.h>
|
||||
#include "fnmatch.h"
|
||||
|
||||
/* stat: file mode type testing macros */
|
||||
#ifndef S_IFGITLINK
|
||||
#define S_IFGITLINK 0160000
|
||||
#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
|
||||
#endif
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define S_IFLNK 0120000
|
||||
#undef _S_IFLNK
|
||||
#define _S_IFLNK S_IFLNK
|
||||
#endif
|
||||
|
||||
#ifndef S_IXUSR
|
||||
#define S_IXUSR 00100
|
||||
#endif
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISFIFO
|
||||
#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO)
|
||||
#endif
|
||||
|
||||
/* if S_ISGID is not defined, then don't try to set it */
|
||||
#ifndef S_ISGID
|
||||
#define S_ISGID 0
|
||||
#endif
|
||||
|
||||
#if !defined(O_BINARY)
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#if !defined(O_CLOEXEC)
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/* access() mode parameter #defines */
|
||||
#ifndef F_OK
|
||||
#define F_OK 0 /* existence check */
|
||||
#endif
|
||||
#ifndef W_OK
|
||||
#define W_OK 2 /* write mode check */
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 4 /* read mode check */
|
||||
#endif
|
||||
|
||||
/* Determine whether an errno value indicates that a read or write failed
|
||||
* because the descriptor is blocked.
|
||||
*/
|
||||
@ -38,6 +76,12 @@
|
||||
#define GIT_ISBLOCKED(e) ((e) == EAGAIN)
|
||||
#endif
|
||||
|
||||
/* define some standard errnos that the runtime may be missing. for example,
|
||||
* mingw lacks EAFNOSUPPORT. */
|
||||
#ifndef EAFNOSUPPORT
|
||||
#define EAFNOSUPPORT (INT_MAX-1)
|
||||
#endif
|
||||
|
||||
typedef int git_file;
|
||||
|
||||
/**
|
||||
@ -56,8 +100,6 @@ typedef int git_file;
|
||||
extern int p_read(git_file fd, void *buf, size_t cnt);
|
||||
extern int p_write(git_file fd, const void *buf, size_t cnt);
|
||||
|
||||
#define p_fstat(f,b) fstat(f, b)
|
||||
#define p_lseek(f,n,w) lseek(f, n, w)
|
||||
#define p_close(fd) close(fd)
|
||||
#define p_umask(m) umask(m)
|
||||
|
||||
@ -66,30 +108,6 @@ extern int p_creat(const char *path, mode_t mode);
|
||||
extern int p_getcwd(char *buffer_out, size_t size);
|
||||
extern int p_rename(const char *from, const char *to);
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
|
||||
#define p_stat(p,b) stat(p, b)
|
||||
#define p_chdir(p) chdir(p)
|
||||
#define p_rmdir(p) rmdir(p)
|
||||
#define p_chmod(p,m) chmod(p, m)
|
||||
#define p_access(p,m) access(p,m)
|
||||
#define p_ftruncate(fd, sz) ftruncate(fd, sz)
|
||||
#define p_recv(s,b,l,f) recv(s,b,l,f)
|
||||
#define p_send(s,b,l,f) send(s,b,l,f)
|
||||
typedef int GIT_SOCKET;
|
||||
#define INVALID_SOCKET -1
|
||||
|
||||
#define p_localtime_r localtime_r
|
||||
#define p_gmtime_r gmtime_r
|
||||
|
||||
#else
|
||||
|
||||
typedef SOCKET GIT_SOCKET;
|
||||
extern struct tm * p_localtime_r (const time_t *timer, struct tm *result);
|
||||
extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Platform-dependent methods
|
||||
*/
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define GIT_FETCH_HEAD_FILE "FETCH_HEAD"
|
||||
#define GIT_MERGE_HEAD_FILE "MERGE_HEAD"
|
||||
#define GIT_REVERT_HEAD_FILE "REVERT_HEAD"
|
||||
#define GIT_CHERRY_PICK_HEAD_FILE "CHERRY_PICK_HEAD"
|
||||
#define GIT_CHERRYPICK_HEAD_FILE "CHERRY_PICK_HEAD"
|
||||
#define GIT_BISECT_LOG_FILE "BISECT_LOG"
|
||||
#define GIT_REBASE_MERGE_DIR "rebase-merge/"
|
||||
#define GIT_REBASE_MERGE_INTERACTIVE_FILE GIT_REBASE_MERGE_DIR "interactive"
|
||||
@ -63,7 +63,7 @@ struct git_reference {
|
||||
} target;
|
||||
|
||||
git_oid peel;
|
||||
char name[0];
|
||||
char name[GIT_FLEX_ARRAY];
|
||||
};
|
||||
|
||||
git_reference *git_reference__set_name(git_reference *ref, const char *name);
|
||||
|
@ -181,39 +181,75 @@ int git_refspec_dst_matches(const git_refspec *refspec, const char *refname)
|
||||
static int refspec_transform(
|
||||
git_buf *out, const char *from, const char *to, const char *name)
|
||||
{
|
||||
size_t to_len = to ? strlen(to) : 0;
|
||||
size_t from_len = from ? strlen(from) : 0;
|
||||
size_t name_len = name ? strlen(name) : 0;
|
||||
const char *from_star, *to_star;
|
||||
const char *name_slash, *from_slash;
|
||||
size_t replacement_len, star_offset;
|
||||
|
||||
git_buf_sanitize(out);
|
||||
git_buf_clear(out);
|
||||
|
||||
if (git_buf_set(out, to, to_len) < 0)
|
||||
return -1;
|
||||
/*
|
||||
* There are two parts to each side of a refspec, the bit
|
||||
* before the star and the bit after it. The star can be in
|
||||
* the middle of the pattern, so we need to look at each bit
|
||||
* individually.
|
||||
*/
|
||||
from_star = strchr(from, '*');
|
||||
to_star = strchr(to, '*');
|
||||
|
||||
if (to_len > 0) {
|
||||
/* No '*' at the end of 'to' means that refspec is mapped to one
|
||||
* specific branch, so no actual transformation is needed.
|
||||
*/
|
||||
if (out->ptr[to_len - 1] != '*')
|
||||
return 0;
|
||||
git_buf_shorten(out, 1); /* remove trailing '*' copied from 'to' */
|
||||
}
|
||||
assert(from_star && to_star);
|
||||
|
||||
if (from_len > 0) /* ignore trailing '*' from 'from' */
|
||||
from_len--;
|
||||
if (from_len > name_len)
|
||||
from_len = name_len;
|
||||
/* star offset, both in 'from' and in 'name' */
|
||||
star_offset = from_star - from;
|
||||
|
||||
return git_buf_put(out, name + from_len, name_len - from_len);
|
||||
/* the first half is copied over */
|
||||
git_buf_put(out, to, to_star - to);
|
||||
|
||||
/* then we copy over the replacement, from the star's offset to the next slash in 'name' */
|
||||
name_slash = strchr(name + star_offset, '/');
|
||||
if (!name_slash)
|
||||
name_slash = strrchr(name, '\0');
|
||||
|
||||
/* if there is no slash after the star in 'from', we want to copy everything over */
|
||||
from_slash = strchr(from + star_offset, '/');
|
||||
if (!from_slash)
|
||||
name_slash = strrchr(name, '\0');
|
||||
|
||||
replacement_len = (name_slash - name) - star_offset;
|
||||
git_buf_put(out, name + star_offset, replacement_len);
|
||||
|
||||
return git_buf_puts(out, to_star + 1);
|
||||
}
|
||||
|
||||
int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name)
|
||||
{
|
||||
assert(out && spec && name);
|
||||
git_buf_sanitize(out);
|
||||
|
||||
if (!git_refspec_src_matches(spec, name)) {
|
||||
giterr_set(GITERR_INVALID, "ref '%s' doesn't match the source", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!spec->pattern)
|
||||
return git_buf_puts(out, spec->dst);
|
||||
|
||||
return refspec_transform(out, spec->src, spec->dst, name);
|
||||
}
|
||||
|
||||
int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name)
|
||||
{
|
||||
assert(out && spec && name);
|
||||
git_buf_sanitize(out);
|
||||
|
||||
if (!git_refspec_dst_matches(spec, name)) {
|
||||
giterr_set(GITERR_INVALID, "ref '%s' doesn't match the destination", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!spec->pattern)
|
||||
return git_buf_puts(out, spec->src);
|
||||
|
||||
return refspec_transform(out, spec->dst, spec->src, name);
|
||||
}
|
||||
|
||||
|
33
src/remote.c
33
src/remote.c
@ -267,9 +267,11 @@ int git_remote_dup(git_remote **dest, git_remote *source)
|
||||
|
||||
if (source->pushurl != NULL) {
|
||||
remote->pushurl = git__strdup(source->pushurl);
|
||||
GITERR_CHECK_ALLOC(remote->pushurl);
|
||||
GITERR_CHECK_ALLOC(remote->pushurl);
|
||||
}
|
||||
|
||||
remote->transport_cb = source->transport_cb;
|
||||
remote->transport_cb_payload = source->transport_cb_payload;
|
||||
remote->repo = source->repo;
|
||||
remote->download_tags = source->download_tags;
|
||||
remote->check_cert = source->check_cert;
|
||||
@ -659,8 +661,14 @@ int git_remote_connect(git_remote *remote, git_direction direction)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A transport could have been supplied in advance with
|
||||
* git_remote_set_transport */
|
||||
/* If we don't have a transport object yet, and the caller specified a
|
||||
* custom transport factory, use that */
|
||||
if (!t && remote->transport_cb &&
|
||||
(error = remote->transport_cb(&t, remote, remote->transport_cb_payload)) < 0)
|
||||
return error;
|
||||
|
||||
/* If we still don't have a transport, then use the global
|
||||
* transport registrations which map URI schemes to transport factories */
|
||||
if (!t && (error = git_transport_new(&t, remote, url)) < 0)
|
||||
return error;
|
||||
|
||||
@ -691,6 +699,11 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
|
||||
{
|
||||
assert(remote);
|
||||
|
||||
if (!remote->transport) {
|
||||
giterr_set(GITERR_NET, "No transport bound to this remote");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return remote->transport->ls(out, size, remote->transport);
|
||||
}
|
||||
|
||||
@ -1262,18 +1275,20 @@ const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote)
|
||||
return &remote->callbacks;
|
||||
}
|
||||
|
||||
int git_remote_set_transport(git_remote *remote, git_transport *transport)
|
||||
int git_remote_set_transport(
|
||||
git_remote *remote,
|
||||
git_transport_cb transport_cb,
|
||||
void *payload)
|
||||
{
|
||||
assert(remote && transport);
|
||||
|
||||
GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
|
||||
assert(remote);
|
||||
|
||||
if (remote->transport) {
|
||||
giterr_set(GITERR_NET, "A transport is already bound to this remote");
|
||||
return -1;
|
||||
}
|
||||
|
||||
remote->transport = transport;
|
||||
remote->transport_cb = transport_cb;
|
||||
remote->transport_cb_payload = payload;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1932,6 +1947,8 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
|
||||
size_t heads_len, i;
|
||||
int error;
|
||||
|
||||
assert(out);
|
||||
|
||||
if ((error = git_remote_ls(&heads, &heads_len, remote)) < 0)
|
||||
return error;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "git2/remote.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#include "refspec.h"
|
||||
#include "vector.h"
|
||||
@ -22,6 +23,8 @@ struct git_remote {
|
||||
git_vector refs;
|
||||
git_vector refspecs;
|
||||
git_vector active_refspecs;
|
||||
git_transport_cb transport_cb;
|
||||
void *transport_cb_payload;
|
||||
git_transport *transport;
|
||||
git_repository *repo;
|
||||
git_remote_callbacks callbacks;
|
||||
|
@ -1915,8 +1915,8 @@ int git_repository_state(git_repository *repo)
|
||||
state = GIT_REPOSITORY_STATE_MERGE;
|
||||
else if(git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE))
|
||||
state = GIT_REPOSITORY_STATE_REVERT;
|
||||
else if(git_path_contains_file(&repo_path, GIT_CHERRY_PICK_HEAD_FILE))
|
||||
state = GIT_REPOSITORY_STATE_CHERRY_PICK;
|
||||
else if(git_path_contains_file(&repo_path, GIT_CHERRYPICK_HEAD_FILE))
|
||||
state = GIT_REPOSITORY_STATE_CHERRYPICK;
|
||||
else if(git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
|
||||
state = GIT_REPOSITORY_STATE_BISECT;
|
||||
|
||||
@ -1958,7 +1958,7 @@ static const char *state_files[] = {
|
||||
GIT_MERGE_MODE_FILE,
|
||||
GIT_MERGE_MSG_FILE,
|
||||
GIT_REVERT_HEAD_FILE,
|
||||
GIT_CHERRY_PICK_HEAD_FILE,
|
||||
GIT_CHERRYPICK_HEAD_FILE,
|
||||
GIT_BISECT_LOG_FILE,
|
||||
GIT_REBASE_MERGE_DIR,
|
||||
GIT_REBASE_APPLY_DIR,
|
||||
|
10
src/revert.c
10
src/revert.c
@ -174,7 +174,7 @@ int git_revert(
|
||||
char commit_oidstr[GIT_OID_HEXSZ + 1];
|
||||
const char *commit_msg;
|
||||
git_buf their_label = GIT_BUF_INIT;
|
||||
git_index *index_new = NULL, *index_repo = NULL;
|
||||
git_index *index_new = NULL;
|
||||
int error;
|
||||
|
||||
assert(repo && commit);
|
||||
@ -199,10 +199,9 @@ int git_revert(
|
||||
(error = git_repository_head(&our_ref, repo)) < 0 ||
|
||||
(error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 ||
|
||||
(error = git_revert_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_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;
|
||||
@ -212,7 +211,6 @@ on_error:
|
||||
|
||||
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);
|
||||
|
@ -48,9 +48,6 @@ static int mark_uninteresting(git_revwalk *walk, git_commit_list_node *commit)
|
||||
|
||||
assert(commit);
|
||||
|
||||
git_array_init_to_size(pending, 2);
|
||||
GITERR_CHECK_ARRAY(pending);
|
||||
|
||||
do {
|
||||
commit->uninteresting = 1;
|
||||
|
||||
|
13
src/status.c
13
src/status.c
@ -62,6 +62,9 @@ static unsigned int workdir_delta2status(
|
||||
case GIT_DELTA_UNTRACKED:
|
||||
st = GIT_STATUS_WT_NEW;
|
||||
break;
|
||||
case GIT_DELTA_UNREADABLE:
|
||||
st = GIT_STATUS_WT_UNREADABLE;
|
||||
break;
|
||||
case GIT_DELTA_DELETED:
|
||||
st = GIT_STATUS_WT_DELETED;
|
||||
break;
|
||||
@ -310,6 +313,10 @@ int git_status_list_new(
|
||||
diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES;
|
||||
if ((flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0)
|
||||
diffopt.flags = diffopt.flags | GIT_DIFF_UPDATE_INDEX;
|
||||
if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE) != 0)
|
||||
diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE;
|
||||
if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED) != 0)
|
||||
diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED;
|
||||
|
||||
if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0)
|
||||
findopt.flags = findopt.flags |
|
||||
@ -329,8 +336,9 @@ int git_status_list_new(
|
||||
|
||||
if (show != GIT_STATUS_SHOW_INDEX_ONLY) {
|
||||
if ((error = git_diff_index_to_workdir(
|
||||
&status->idx2wd, repo, index, &diffopt)) < 0)
|
||||
&status->idx2wd, repo, index, &diffopt)) < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 &&
|
||||
(error = git_diff_find_similar(status->idx2wd, &findopt)) < 0)
|
||||
@ -407,8 +415,9 @@ int git_status_foreach_ext(
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
if ((error = git_status_list_new(&status, repo, opts)) < 0)
|
||||
if ((error = git_status_list_new(&status, repo, opts)) < 0) {
|
||||
return error;
|
||||
}
|
||||
|
||||
git_vector_foreach(&status->paired, i, status_entry) {
|
||||
const char *path = status_entry->head_to_index ?
|
||||
|
@ -7,7 +7,8 @@
|
||||
#ifndef INCLUDE_strlen_h__
|
||||
#define INCLUDE_strlen_h__
|
||||
|
||||
#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__) || defined(__MidnightBSD__)
|
||||
#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__) || defined(__MidnightBSD__) ||\
|
||||
(defined(_MSC_VER) && _MSC_VER < 1500)
|
||||
# define NO_STRNLEN
|
||||
#endif
|
||||
|
||||
|
@ -53,12 +53,6 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(GIT_WIN32)
|
||||
#define git_thread_yield() Sleep(0)
|
||||
#else
|
||||
#define git_thread_yield() sched_yield()
|
||||
#endif
|
||||
|
||||
/* Pthreads Mutex */
|
||||
#define git_mutex pthread_mutex_t
|
||||
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
|
||||
@ -186,7 +180,6 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
||||
#define git_thread unsigned int
|
||||
#define git_thread_create(thread, attr, start_routine, arg) 0
|
||||
#define git_thread_join(id, status) (void)0
|
||||
#define git_thread_yield() (void)0
|
||||
|
||||
/* Pthreads Mutex */
|
||||
#define git_mutex unsigned int
|
||||
|
10
src/trace.h
10
src/trace.h
@ -46,8 +46,16 @@ GIT_INLINE(void) git_trace__write_fmt(
|
||||
|
||||
#else
|
||||
|
||||
GIT_INLINE(void) git_trace__null(
|
||||
git_trace_level_t level,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
GIT_UNUSED(level);
|
||||
GIT_UNUSED(fmt);
|
||||
}
|
||||
|
||||
#define git_trace_level() ((void)0)
|
||||
#define git_trace(lvl, ...) ((void)0)
|
||||
#define git_trace git_trace__null
|
||||
|
||||
#endif
|
||||
|
||||
|
155
src/transport.c
155
src/transport.c
@ -9,11 +9,11 @@
|
||||
#include "git2/remote.h"
|
||||
#include "git2/net.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/transport.h"
|
||||
#include "path.h"
|
||||
|
||||
typedef struct transport_definition {
|
||||
char *prefix;
|
||||
unsigned priority;
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
} transport_definition;
|
||||
@ -24,51 +24,54 @@ static git_smart_subtransport_definition git_subtransport_definition = { git_sma
|
||||
static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 };
|
||||
#endif
|
||||
|
||||
static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
|
||||
static transport_definition local_transport_definition = { "file://", git_transport_local, NULL };
|
||||
#ifdef GIT_SSH
|
||||
static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
|
||||
static transport_definition ssh_transport_definition = { "ssh://", git_transport_smart, &ssh_subtransport_definition };
|
||||
#else
|
||||
static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
|
||||
static transport_definition dummy_transport_definition = { NULL, git_transport_dummy, NULL };
|
||||
#endif
|
||||
|
||||
static transport_definition transports[] = {
|
||||
{"git://", 1, git_transport_smart, &git_subtransport_definition},
|
||||
{"http://", 1, git_transport_smart, &http_subtransport_definition},
|
||||
{"https://", 1, git_transport_smart, &http_subtransport_definition},
|
||||
{"file://", 1, git_transport_local, NULL},
|
||||
{ "git://", git_transport_smart, &git_subtransport_definition },
|
||||
{ "http://", git_transport_smart, &http_subtransport_definition },
|
||||
{ "https://", git_transport_smart, &http_subtransport_definition },
|
||||
{ "file://", git_transport_local, NULL },
|
||||
#ifdef GIT_SSH
|
||||
{"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
|
||||
{ "ssh://", git_transport_smart, &ssh_subtransport_definition },
|
||||
#endif
|
||||
{NULL, 0, 0}
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static git_vector additional_transports = GIT_VECTOR_INIT;
|
||||
static git_vector custom_transports = GIT_VECTOR_INIT;
|
||||
|
||||
#define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1
|
||||
|
||||
static int transport_find_fn(const char *url, git_transport_cb *callback, void **param)
|
||||
static int transport_find_fn(
|
||||
git_transport_cb *out,
|
||||
const char *url,
|
||||
void **param)
|
||||
{
|
||||
size_t i = 0;
|
||||
unsigned priority = 0;
|
||||
transport_definition *definition = NULL, *definition_iter;
|
||||
transport_definition *d, *definition = NULL;
|
||||
|
||||
// First, check to see if it's an obvious URL, which a URL scheme
|
||||
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
|
||||
definition_iter = &transports[i];
|
||||
|
||||
if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
|
||||
continue;
|
||||
|
||||
if (definition_iter->priority > priority)
|
||||
definition = definition_iter;
|
||||
/* Find a user transport who wants to deal with this URI */
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
|
||||
definition = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
git_vector_foreach(&additional_transports, i, definition_iter) {
|
||||
if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix)))
|
||||
continue;
|
||||
/* Find a system transport for this URI */
|
||||
if (!definition) {
|
||||
for (i = 0; i < GIT_TRANSPORT_COUNT; ++i) {
|
||||
d = &transports[i];
|
||||
|
||||
if (definition_iter->priority > priority)
|
||||
definition = definition_iter;
|
||||
if (strncasecmp(url, d->prefix, strlen(d->prefix)) == 0) {
|
||||
definition = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
@ -90,7 +93,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
|
||||
#ifdef GIT_SSH
|
||||
definition = &ssh_transport_definition;
|
||||
#else
|
||||
definition = &dummy_transport_definition;
|
||||
definition = &dummy_transport_definition;
|
||||
#endif
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
@ -100,9 +103,9 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
|
||||
#endif
|
||||
|
||||
if (!definition)
|
||||
return -1;
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
*callback = definition->fn;
|
||||
*out = definition->fn;
|
||||
*param = definition->param;
|
||||
|
||||
return 0;
|
||||
@ -128,74 +131,96 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url)
|
||||
void *param;
|
||||
int error;
|
||||
|
||||
if (transport_find_fn(url, &fn, ¶m) < 0) {
|
||||
if ((error = transport_find_fn(&fn, url, ¶m)) == GIT_ENOTFOUND) {
|
||||
giterr_set(GITERR_NET, "Unsupported URL protocol");
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = fn(&transport, owner, param);
|
||||
if (error < 0)
|
||||
} else if (error < 0)
|
||||
return error;
|
||||
|
||||
if ((error = fn(&transport, owner, param)) < 0)
|
||||
return error;
|
||||
|
||||
GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
|
||||
|
||||
*out = transport;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_transport_register(
|
||||
const char *prefix,
|
||||
unsigned priority,
|
||||
const char *scheme,
|
||||
git_transport_cb cb,
|
||||
void *param)
|
||||
{
|
||||
transport_definition *d;
|
||||
git_buf prefix = GIT_BUF_INIT;
|
||||
transport_definition *d, *definition = NULL;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
d = git__calloc(sizeof(transport_definition), 1);
|
||||
GITERR_CHECK_ALLOC(d);
|
||||
assert(scheme);
|
||||
assert(cb);
|
||||
|
||||
d->prefix = git__strdup(prefix);
|
||||
|
||||
if (!d->prefix)
|
||||
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
|
||||
goto on_error;
|
||||
|
||||
d->priority = priority;
|
||||
d->fn = cb;
|
||||
d->param = param;
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strcasecmp(d->prefix, prefix.ptr) == 0) {
|
||||
error = GIT_EEXISTS;
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (git_vector_insert(&additional_transports, d) < 0)
|
||||
definition = git__calloc(1, sizeof(transport_definition));
|
||||
GITERR_CHECK_ALLOC(definition);
|
||||
|
||||
definition->prefix = git_buf_detach(&prefix);
|
||||
definition->fn = cb;
|
||||
definition->param = param;
|
||||
|
||||
if (git_vector_insert(&custom_transports, definition) < 0)
|
||||
goto on_error;
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git__free(d->prefix);
|
||||
git__free(d);
|
||||
return -1;
|
||||
git_buf_free(&prefix);
|
||||
git__free(definition);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_transport_unregister(
|
||||
const char *prefix,
|
||||
unsigned priority)
|
||||
int git_transport_unregister(const char *scheme)
|
||||
{
|
||||
git_buf prefix = GIT_BUF_INIT;
|
||||
transport_definition *d;
|
||||
unsigned i;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
git_vector_foreach(&additional_transports, i, d) {
|
||||
if (d->priority == priority && !strcasecmp(d->prefix, prefix)) {
|
||||
if (git_vector_remove(&additional_transports, i) < 0)
|
||||
return -1;
|
||||
assert(scheme);
|
||||
|
||||
if ((error = git_buf_printf(&prefix, "%s://", scheme)) < 0)
|
||||
goto done;
|
||||
|
||||
git_vector_foreach(&custom_transports, i, d) {
|
||||
if (strcasecmp(d->prefix, prefix.ptr) == 0) {
|
||||
if ((error = git_vector_remove(&custom_transports, i)) < 0)
|
||||
goto done;
|
||||
|
||||
git__free(d->prefix);
|
||||
git__free(d);
|
||||
|
||||
if (!additional_transports.length)
|
||||
git_vector_free(&additional_transports);
|
||||
if (!custom_transports.length)
|
||||
git_vector_free(&custom_transports);
|
||||
|
||||
return 0;
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return GIT_ENOTFOUND;
|
||||
error = GIT_ENOTFOUND;
|
||||
|
||||
done:
|
||||
git_buf_free(&prefix);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* from remote.h */
|
||||
@ -204,7 +229,7 @@ int git_remote_valid_url(const char *url)
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
|
||||
return !transport_find_fn(url, &fn, ¶m);
|
||||
return !transport_find_fn(&fn, url, ¶m);
|
||||
}
|
||||
|
||||
int git_remote_supported_url(const char* url)
|
||||
@ -212,7 +237,7 @@ int git_remote_supported_url(const char* url)
|
||||
git_transport_cb fn;
|
||||
void *param;
|
||||
|
||||
if (transport_find_fn(url, &fn, ¶m) < 0)
|
||||
if (transport_find_fn(&fn, url, ¶m) < 0)
|
||||
return 0;
|
||||
|
||||
return fn != &git_transport_dummy;
|
||||
|
71
src/transports/auth.c
Normal file
71
src/transports/auth.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "git2.h"
|
||||
#include "buffer.h"
|
||||
#include "auth.h"
|
||||
|
||||
static int basic_next_token(
|
||||
git_buf *out, git_http_auth_context *ctx, git_cred *c)
|
||||
{
|
||||
git_cred_userpass_plaintext *cred;
|
||||
git_buf raw = GIT_BUF_INIT;
|
||||
int error = -1;
|
||||
|
||||
GIT_UNUSED(ctx);
|
||||
|
||||
if (c->credtype != GIT_CREDTYPE_USERPASS_PLAINTEXT) {
|
||||
giterr_set(GITERR_INVALID, "invalid credential type for basic auth");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
cred = (git_cred_userpass_plaintext *)c;
|
||||
|
||||
git_buf_printf(&raw, "%s:%s", cred->username, cred->password);
|
||||
|
||||
if (git_buf_oom(&raw) ||
|
||||
git_buf_puts(out, "Authorization: Basic ") < 0 ||
|
||||
git_buf_encode_base64(out, git_buf_cstr(&raw), raw.size) < 0 ||
|
||||
git_buf_puts(out, "\r\n") < 0)
|
||||
goto on_error;
|
||||
|
||||
error = 0;
|
||||
|
||||
on_error:
|
||||
if (raw.size)
|
||||
git__memzero(raw.ptr, raw.size);
|
||||
|
||||
git_buf_free(&raw);
|
||||
return error;
|
||||
}
|
||||
|
||||
static git_http_auth_context basic_context = {
|
||||
GIT_AUTHTYPE_BASIC,
|
||||
GIT_CREDTYPE_USERPASS_PLAINTEXT,
|
||||
NULL,
|
||||
basic_next_token,
|
||||
NULL
|
||||
};
|
||||
|
||||
int git_http_auth_basic(
|
||||
git_http_auth_context **out, const gitno_connection_data *connection_data)
|
||||
{
|
||||
GIT_UNUSED(connection_data);
|
||||
|
||||
*out = &basic_context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_http_auth_dummy(
|
||||
git_http_auth_context **out, const gitno_connection_data *connection_data)
|
||||
{
|
||||
GIT_UNUSED(connection_data);
|
||||
|
||||
*out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
63
src/transports/auth.h
Normal file
63
src/transports/auth.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_http_auth_h__
|
||||
#define INCLUDE_http_auth_h__
|
||||
|
||||
#include "git2.h"
|
||||
#include "netops.h"
|
||||
|
||||
typedef enum {
|
||||
GIT_AUTHTYPE_BASIC = 1,
|
||||
GIT_AUTHTYPE_NEGOTIATE = 2,
|
||||
} git_http_authtype_t;
|
||||
|
||||
typedef struct git_http_auth_context git_http_auth_context;
|
||||
|
||||
struct git_http_auth_context {
|
||||
/** Type of scheme */
|
||||
git_http_authtype_t type;
|
||||
|
||||
/** Supported credentials */
|
||||
git_credtype_t credtypes;
|
||||
|
||||
/** Sets the challenge on the authentication context */
|
||||
int (*set_challenge)(git_http_auth_context *ctx, const char *challenge);
|
||||
|
||||
/** Gets the next authentication token from the context */
|
||||
int (*next_token)(git_buf *out, git_http_auth_context *ctx, git_cred *cred);
|
||||
|
||||
/** Frees the authentication context */
|
||||
void (*free)(git_http_auth_context *ctx);
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/** Type of scheme */
|
||||
git_http_authtype_t type;
|
||||
|
||||
/** Name of the scheme (as used in the Authorization header) */
|
||||
const char *name;
|
||||
|
||||
/** Credential types this scheme supports */
|
||||
git_credtype_t credtypes;
|
||||
|
||||
/** Function to initialize an authentication context */
|
||||
int (*init_context)(
|
||||
git_http_auth_context **out,
|
||||
const gitno_connection_data *connection_data);
|
||||
} git_http_auth_scheme;
|
||||
|
||||
int git_http_auth_dummy(
|
||||
git_http_auth_context **out,
|
||||
const gitno_connection_data *connection_data);
|
||||
|
||||
int git_http_auth_basic(
|
||||
git_http_auth_context **out,
|
||||
const gitno_connection_data *connection_data);
|
||||
|
||||
#endif
|
||||
|
275
src/transports/auth_negotiate.c
Normal file
275
src/transports/auth_negotiate.c
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef GIT_GSSAPI
|
||||
|
||||
#include "git2.h"
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
#include "auth.h"
|
||||
|
||||
#include <gssapi.h>
|
||||
#include <krb5.h>
|
||||
|
||||
static gss_OID_desc negotiate_oid_spnego =
|
||||
{ 6, (void *) "\x2b\x06\x01\x05\x05\x02" };
|
||||
static gss_OID_desc negotiate_oid_krb5 =
|
||||
{ 9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
|
||||
|
||||
static gss_OID negotiate_oids[] =
|
||||
{ &negotiate_oid_spnego, &negotiate_oid_krb5, NULL };
|
||||
|
||||
typedef struct {
|
||||
git_http_auth_context parent;
|
||||
unsigned configured : 1,
|
||||
complete : 1;
|
||||
git_buf target;
|
||||
char *challenge;
|
||||
gss_ctx_id_t gss_context;
|
||||
gss_OID oid;
|
||||
} http_auth_negotiate_context;
|
||||
|
||||
static void negotiate_err_set(
|
||||
OM_uint32 status_major,
|
||||
OM_uint32 status_minor,
|
||||
const char *message)
|
||||
{
|
||||
gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
|
||||
OM_uint32 status_display, context = 0;
|
||||
|
||||
if (gss_display_status(&status_display, status_major, GSS_C_GSS_CODE,
|
||||
GSS_C_NO_OID, &context, &buffer) == GSS_S_COMPLETE) {
|
||||
giterr_set(GITERR_NET, "%s: %.*s (%d.%d)",
|
||||
message, (int)buffer.length, (const char *)buffer.value,
|
||||
status_major, status_minor);
|
||||
gss_release_buffer(&status_minor, &buffer);
|
||||
} else {
|
||||
giterr_set(GITERR_NET, "%s: unknown negotiate error (%d.%d)",
|
||||
message, status_major, status_minor);
|
||||
}
|
||||
}
|
||||
|
||||
static int negotiate_set_challenge(
|
||||
git_http_auth_context *c,
|
||||
const char *challenge)
|
||||
{
|
||||
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
|
||||
|
||||
assert(ctx && ctx->configured && challenge);
|
||||
|
||||
git__free(ctx->challenge);
|
||||
|
||||
ctx->challenge = git__strdup(challenge);
|
||||
GITERR_CHECK_ALLOC(ctx->challenge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int negotiate_next_token(
|
||||
git_buf *buf,
|
||||
git_http_auth_context *c,
|
||||
git_cred *cred)
|
||||
{
|
||||
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
|
||||
OM_uint32 status_major, status_minor;
|
||||
gss_buffer_desc target_buffer = GSS_C_EMPTY_BUFFER,
|
||||
input_token = GSS_C_EMPTY_BUFFER,
|
||||
output_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER;
|
||||
git_buf input_buf = GIT_BUF_INIT;
|
||||
gss_name_t server = NULL;
|
||||
gss_OID mech;
|
||||
size_t challenge_len;
|
||||
int error = 0;
|
||||
|
||||
assert(buf && ctx && ctx->configured && cred && cred->credtype == GIT_CREDTYPE_DEFAULT);
|
||||
|
||||
if (ctx->complete)
|
||||
return 0;
|
||||
|
||||
target_buffer.value = (void *)ctx->target.ptr;
|
||||
target_buffer.length = ctx->target.size;
|
||||
|
||||
status_major = gss_import_name(&status_minor, &target_buffer,
|
||||
GSS_C_NT_HOSTBASED_SERVICE, &server);
|
||||
|
||||
if (GSS_ERROR(status_major)) {
|
||||
negotiate_err_set(status_major, status_minor,
|
||||
"Could not parse principal");
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0;
|
||||
|
||||
if (challenge_len < 9) {
|
||||
giterr_set(GITERR_NET, "No negotiate challenge sent from server");
|
||||
error = -1;
|
||||
goto done;
|
||||
} else if (challenge_len > 9) {
|
||||
if (git_buf_decode_base64(&input_buf,
|
||||
ctx->challenge + 10, challenge_len - 10) < 0) {
|
||||
giterr_set(GITERR_NET, "Invalid negotiate challenge from server");
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
input_token.value = input_buf.ptr;
|
||||
input_token.length = input_buf.size;
|
||||
input_token_ptr = &input_token;
|
||||
} else if (ctx->gss_context != GSS_C_NO_CONTEXT) {
|
||||
giterr_set(GITERR_NET, "Could not restart authentication");
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mech = &negotiate_oid_spnego;
|
||||
|
||||
if (GSS_ERROR(status_major = gss_init_sec_context(
|
||||
&status_minor,
|
||||
GSS_C_NO_CREDENTIAL,
|
||||
&ctx->gss_context,
|
||||
server,
|
||||
mech,
|
||||
GSS_C_DELEG_FLAG | GSS_C_MUTUAL_FLAG,
|
||||
GSS_C_INDEFINITE,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,
|
||||
input_token_ptr,
|
||||
NULL,
|
||||
&output_token,
|
||||
NULL,
|
||||
NULL))) {
|
||||
negotiate_err_set(status_major, status_minor, "Negotiate failure");
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* This message merely told us auth was complete; we do not respond. */
|
||||
if (status_major == GSS_S_COMPLETE) {
|
||||
ctx->complete = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
git_buf_puts(buf, "Authorization: Negotiate ");
|
||||
git_buf_encode_base64(buf, output_token.value, output_token.length);
|
||||
git_buf_puts(buf, "\r\n");
|
||||
|
||||
if (git_buf_oom(buf))
|
||||
error = -1;
|
||||
|
||||
done:
|
||||
gss_release_name(&status_minor, &server);
|
||||
gss_release_buffer(&status_minor, (gss_buffer_t) &output_token);
|
||||
git_buf_free(&input_buf);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void negotiate_context_free(git_http_auth_context *c)
|
||||
{
|
||||
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
|
||||
OM_uint32 status_minor;
|
||||
|
||||
if (ctx->gss_context != GSS_C_NO_CONTEXT) {
|
||||
gss_delete_sec_context(
|
||||
&status_minor, &ctx->gss_context, GSS_C_NO_BUFFER);
|
||||
ctx->gss_context = GSS_C_NO_CONTEXT;
|
||||
}
|
||||
|
||||
git_buf_free(&ctx->target);
|
||||
|
||||
git__free(ctx->challenge);
|
||||
|
||||
ctx->configured = 0;
|
||||
ctx->complete = 0;
|
||||
ctx->oid = NULL;
|
||||
|
||||
git__free(ctx);
|
||||
}
|
||||
|
||||
static int negotiate_init_context(
|
||||
http_auth_negotiate_context *ctx,
|
||||
const gitno_connection_data *connection_data)
|
||||
{
|
||||
OM_uint32 status_major, status_minor;
|
||||
gss_OID item, *oid;
|
||||
gss_OID_set mechanism_list;
|
||||
size_t i;
|
||||
|
||||
/* Query supported mechanisms looking for SPNEGO) */
|
||||
if (GSS_ERROR(status_major =
|
||||
gss_indicate_mechs(&status_minor, &mechanism_list))) {
|
||||
negotiate_err_set(status_major, status_minor,
|
||||
"could not query mechanisms");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mechanism_list) {
|
||||
for (oid = negotiate_oids; *oid; oid++) {
|
||||
for (i = 0; i < mechanism_list->count; i++) {
|
||||
item = &mechanism_list->elements[i];
|
||||
|
||||
if (item->length == (*oid)->length &&
|
||||
memcmp(item->elements, (*oid)->elements, item->length) == 0) {
|
||||
ctx->oid = *oid;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ctx->oid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gss_release_oid_set(&status_minor, &mechanism_list);
|
||||
|
||||
if (!ctx->oid) {
|
||||
giterr_set(GITERR_NET, "Negotiate authentication is not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
git_buf_puts(&ctx->target, "HTTP@");
|
||||
git_buf_puts(&ctx->target, connection_data->host);
|
||||
|
||||
if (git_buf_oom(&ctx->target))
|
||||
return -1;
|
||||
|
||||
ctx->gss_context = GSS_C_NO_CONTEXT;
|
||||
ctx->configured = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_http_auth_negotiate(
|
||||
git_http_auth_context **out,
|
||||
const gitno_connection_data *connection_data)
|
||||
{
|
||||
http_auth_negotiate_context *ctx;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
ctx = git__calloc(1, sizeof(http_auth_negotiate_context));
|
||||
GITERR_CHECK_ALLOC(ctx);
|
||||
|
||||
if (negotiate_init_context(ctx, connection_data) < 0) {
|
||||
git__free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->parent.type = GIT_AUTHTYPE_NEGOTIATE;
|
||||
ctx->parent.credtypes = GIT_CREDTYPE_DEFAULT;
|
||||
ctx->parent.set_challenge = negotiate_set_challenge;
|
||||
ctx->parent.next_token = negotiate_next_token;
|
||||
ctx->parent.free = negotiate_context_free;
|
||||
|
||||
*out = (git_http_auth_context *)ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* GIT_GSSAPI */
|
||||
|
27
src/transports/auth_negotiate.h
Normal file
27
src/transports/auth_negotiate.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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_auth_negotiate_h__
|
||||
#define INCLUDE_auth_negotiate_h__
|
||||
|
||||
#include "git2.h"
|
||||
#include "auth.h"
|
||||
|
||||
#ifdef GIT_GSSAPI
|
||||
|
||||
extern int git_http_auth_negotiate(
|
||||
git_http_auth_context **out,
|
||||
const gitno_connection_data *connection_data);
|
||||
|
||||
#else
|
||||
|
||||
#define git_http_auth_negotiate git_http_auth_dummy
|
||||
|
||||
#endif /* GIT_GSSAPI */
|
||||
|
||||
#endif
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "git2.h"
|
||||
#include "buffer.h"
|
||||
#include "netops.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
|
||||
|
||||
|
@ -11,6 +11,13 @@
|
||||
#include "buffer.h"
|
||||
#include "netops.h"
|
||||
#include "smart.h"
|
||||
#include "auth.h"
|
||||
#include "auth_negotiate.h"
|
||||
|
||||
git_http_auth_scheme auth_schemes[] = {
|
||||
{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
|
||||
{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
|
||||
};
|
||||
|
||||
static const char *upload_pack_service = "upload-pack";
|
||||
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
|
||||
@ -20,7 +27,6 @@ static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive
|
||||
static const char *receive_pack_service_url = "/git-receive-pack";
|
||||
static const char *get_verb = "GET";
|
||||
static const char *post_verb = "POST";
|
||||
static const char *basic_authtype = "Basic";
|
||||
|
||||
#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
|
||||
|
||||
@ -35,10 +41,6 @@ enum last_cb {
|
||||
VALUE
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GIT_HTTP_AUTH_BASIC = 1,
|
||||
} http_authmechanism_t;
|
||||
|
||||
typedef struct {
|
||||
git_smart_subtransport_stream parent;
|
||||
const char *service;
|
||||
@ -58,9 +60,6 @@ typedef struct {
|
||||
transport_smart *owner;
|
||||
gitno_socket socket;
|
||||
gitno_connection_data connection_data;
|
||||
git_cred *cred;
|
||||
git_cred *url_cred;
|
||||
http_authmechanism_t auth_mechanism;
|
||||
bool connected;
|
||||
|
||||
/* Parser structures */
|
||||
@ -76,6 +75,11 @@ typedef struct {
|
||||
enum last_cb last_cb;
|
||||
int parse_error;
|
||||
unsigned parse_finished : 1;
|
||||
|
||||
/* Authentication */
|
||||
git_cred *cred;
|
||||
git_cred *url_cred;
|
||||
git_vector auth_contexts;
|
||||
} http_subtransport;
|
||||
|
||||
typedef struct {
|
||||
@ -88,28 +92,91 @@ typedef struct {
|
||||
size_t *bytes_read;
|
||||
} parser_context;
|
||||
|
||||
static int apply_basic_credential(git_buf *buf, git_cred *cred)
|
||||
static bool credtype_match(git_http_auth_scheme *scheme, void *data)
|
||||
{
|
||||
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
|
||||
git_buf raw = GIT_BUF_INIT;
|
||||
int error = -1;
|
||||
unsigned int credtype = *(unsigned int *)data;
|
||||
|
||||
git_buf_printf(&raw, "%s:%s", c->username, c->password);
|
||||
return !!(scheme->credtypes & credtype);
|
||||
}
|
||||
|
||||
if (git_buf_oom(&raw) ||
|
||||
git_buf_puts(buf, "Authorization: Basic ") < 0 ||
|
||||
git_buf_put_base64(buf, git_buf_cstr(&raw), raw.size) < 0 ||
|
||||
git_buf_puts(buf, "\r\n") < 0)
|
||||
goto on_error;
|
||||
static bool challenge_match(git_http_auth_scheme *scheme, void *data)
|
||||
{
|
||||
const char *scheme_name = scheme->name;
|
||||
const char *challenge = (const char *)data;
|
||||
size_t scheme_len;
|
||||
|
||||
error = 0;
|
||||
scheme_len = strlen(scheme_name);
|
||||
return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
|
||||
(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
|
||||
}
|
||||
|
||||
on_error:
|
||||
if (raw.size)
|
||||
memset(raw.ptr, 0x0, raw.size);
|
||||
static int auth_context_match(
|
||||
git_http_auth_context **out,
|
||||
http_subtransport *t,
|
||||
bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
|
||||
void *data)
|
||||
{
|
||||
git_http_auth_scheme *scheme = NULL;
|
||||
git_http_auth_context *context = NULL, *c;
|
||||
size_t i;
|
||||
|
||||
git_buf_free(&raw);
|
||||
return error;
|
||||
*out = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
|
||||
if (scheme_match(&auth_schemes[i], data)) {
|
||||
scheme = &auth_schemes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scheme)
|
||||
return 0;
|
||||
|
||||
/* See if authentication has already started for this scheme */
|
||||
git_vector_foreach(&t->auth_contexts, i, c) {
|
||||
if (c->type == scheme->type) {
|
||||
context = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
if (scheme->init_context(&context, &t->connection_data) < 0)
|
||||
return -1;
|
||||
else if (!context)
|
||||
return 0;
|
||||
else if (git_vector_insert(&t->auth_contexts, context) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apply_credentials(git_buf *buf, http_subtransport *t)
|
||||
{
|
||||
git_cred *cred = t->cred;
|
||||
git_http_auth_context *context;
|
||||
|
||||
/* Apply the credentials given to us in the URL */
|
||||
if (!cred && t->connection_data.user && t->connection_data.pass) {
|
||||
if (!t->url_cred &&
|
||||
git_cred_userpass_plaintext_new(&t->url_cred,
|
||||
t->connection_data.user, t->connection_data.pass) < 0)
|
||||
return -1;
|
||||
|
||||
cred = t->url_cred;
|
||||
}
|
||||
|
||||
if (!cred)
|
||||
return 0;
|
||||
|
||||
/* Get or create a context for the best scheme for this cred type */
|
||||
if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
|
||||
return -1;
|
||||
|
||||
return context->next_token(buf, context, cred);
|
||||
}
|
||||
|
||||
static int gen_request(
|
||||
@ -137,19 +204,9 @@ static int gen_request(
|
||||
git_buf_puts(buf, "Accept: */*\r\n");
|
||||
|
||||
/* Apply credentials to the request */
|
||||
if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
|
||||
t->auth_mechanism == GIT_HTTP_AUTH_BASIC &&
|
||||
apply_basic_credential(buf, t->cred) < 0)
|
||||
if (apply_credentials(buf, t) < 0)
|
||||
return -1;
|
||||
|
||||
/* Use url-parsed basic auth if username and password are both provided */
|
||||
if (!t->cred && t->connection_data.user && t->connection_data.pass) {
|
||||
if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred,
|
||||
t->connection_data.user, t->connection_data.pass) < 0)
|
||||
return -1;
|
||||
if (apply_basic_credential(buf, t->url_cred) < 0) return -1;
|
||||
}
|
||||
|
||||
git_buf_puts(buf, "\r\n");
|
||||
|
||||
if (git_buf_oom(buf))
|
||||
@ -158,20 +215,26 @@ static int gen_request(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_unauthorized_response(
|
||||
static int parse_authenticate_response(
|
||||
git_vector *www_authenticate,
|
||||
int *allowed_types,
|
||||
http_authmechanism_t *auth_mechanism)
|
||||
http_subtransport *t,
|
||||
int *allowed_types)
|
||||
{
|
||||
unsigned i;
|
||||
char *entry;
|
||||
git_http_auth_context *context;
|
||||
char *challenge;
|
||||
size_t i;
|
||||
|
||||
git_vector_foreach(www_authenticate, i, entry) {
|
||||
if (!strncmp(entry, basic_authtype, 5) &&
|
||||
(entry[5] == '\0' || entry[5] == ' ')) {
|
||||
*allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
|
||||
*auth_mechanism = GIT_HTTP_AUTH_BASIC;
|
||||
}
|
||||
git_vector_foreach(www_authenticate, i, challenge) {
|
||||
if (auth_context_match(&context, t, challenge_match, challenge) < 0)
|
||||
return -1;
|
||||
else if (!context)
|
||||
continue;
|
||||
|
||||
if (context->set_challenge &&
|
||||
context->set_challenge(context, challenge) < 0)
|
||||
return -1;
|
||||
|
||||
*allowed_types |= context->credtypes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -248,7 +311,7 @@ static int on_headers_complete(http_parser *parser)
|
||||
http_subtransport *t = ctx->t;
|
||||
http_stream *s = ctx->s;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int error = 0, no_callback = 0;
|
||||
int error = 0, no_callback = 0, allowed_auth_types = 0;
|
||||
|
||||
/* Both parse_header_name and parse_header_value are populated
|
||||
* and ready for consumption. */
|
||||
@ -256,26 +319,26 @@ static int on_headers_complete(http_parser *parser)
|
||||
if (on_header_ready(t) < 0)
|
||||
return t->parse_error = PARSE_ERROR_GENERIC;
|
||||
|
||||
/* Check for an authentication failure. */
|
||||
/* Capture authentication headers which may be a 401 (authentication
|
||||
* is not complete) or a 200 (simply informing us that auth *is*
|
||||
* complete.)
|
||||
*/
|
||||
if (parse_authenticate_response(&t->www_authenticate, t,
|
||||
&allowed_auth_types) < 0)
|
||||
return t->parse_error = PARSE_ERROR_GENERIC;
|
||||
|
||||
if (parser->status_code == 401 &&
|
||||
get_verb == s->verb) {
|
||||
if (!t->owner->cred_acquire_payload) {
|
||||
/* Check for an authentication failure. */
|
||||
if (parser->status_code == 401 && get_verb == s->verb) {
|
||||
if (!t->owner->cred_acquire_cb) {
|
||||
no_callback = 1;
|
||||
} else {
|
||||
int allowed_types = 0;
|
||||
|
||||
if (parse_unauthorized_response(&t->www_authenticate,
|
||||
&allowed_types, &t->auth_mechanism) < 0)
|
||||
return t->parse_error = PARSE_ERROR_GENERIC;
|
||||
|
||||
if (allowed_types &&
|
||||
(!t->cred || 0 == (t->cred->credtype & allowed_types))) {
|
||||
if (allowed_auth_types &&
|
||||
(!t->cred || 0 == (t->cred->credtype & allowed_auth_types))) {
|
||||
|
||||
error = t->owner->cred_acquire_cb(&t->cred,
|
||||
t->owner->url,
|
||||
t->connection_data.user,
|
||||
allowed_types,
|
||||
allowed_auth_types,
|
||||
t->owner->cred_acquire_payload);
|
||||
|
||||
if (error == GIT_PASSTHROUGH) {
|
||||
@ -286,7 +349,8 @@ static int on_headers_complete(http_parser *parser)
|
||||
assert(t->cred);
|
||||
|
||||
/* Successfully acquired a credential. */
|
||||
return t->parse_error = PARSE_ERROR_REPLAY;
|
||||
t->parse_error = PARSE_ERROR_REPLAY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,7 +388,8 @@ static int on_headers_complete(http_parser *parser)
|
||||
t->connected = 0;
|
||||
s->redirect_count++;
|
||||
|
||||
return t->parse_error = PARSE_ERROR_REPLAY;
|
||||
t->parse_error = PARSE_ERROR_REPLAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for a 200 HTTP status code. */
|
||||
@ -382,6 +447,13 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
||||
parser_context *ctx = (parser_context *) parser->data;
|
||||
http_subtransport *t = ctx->t;
|
||||
|
||||
/* If our goal is to replay the request (either an auth failure or
|
||||
* a redirect) then don't bother buffering since we're ignoring the
|
||||
* content anyway.
|
||||
*/
|
||||
if (t->parse_error == PARSE_ERROR_REPLAY)
|
||||
return 0;
|
||||
|
||||
if (ctx->buf_size < len) {
|
||||
giterr_set(GITERR_NET, "Can't fit data in the buffer");
|
||||
return t->parse_error = PARSE_ERROR_GENERIC;
|
||||
@ -456,7 +528,7 @@ static int http_connect(http_subtransport *t)
|
||||
|
||||
if (t->connected &&
|
||||
http_should_keep_alive(&t->parser) &&
|
||||
http_body_is_final(&t->parser))
|
||||
t->parse_finished)
|
||||
return 0;
|
||||
|
||||
if (t->socket.socket)
|
||||
@ -502,10 +574,8 @@ replay:
|
||||
|
||||
clear_parser_state(t);
|
||||
|
||||
if (gen_request(&request, s, 0) < 0) {
|
||||
giterr_set(GITERR_NET, "Failed to generate request");
|
||||
if (gen_request(&request, s, 0) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
||||
git_buf_free(&request);
|
||||
@ -537,7 +607,23 @@ replay:
|
||||
}
|
||||
|
||||
while (!*bytes_read && !t->parse_finished) {
|
||||
t->parse_buffer.offset = 0;
|
||||
size_t data_offset;
|
||||
|
||||
/*
|
||||
* Make the parse_buffer think it's as full of data as
|
||||
* the buffer, so it won't try to recv more data than
|
||||
* we can put into it.
|
||||
*
|
||||
* data_offset is the actual data offset from which we
|
||||
* should tell the parser to start reading.
|
||||
*/
|
||||
if (buf_size >= t->parse_buffer.len) {
|
||||
t->parse_buffer.offset = 0;
|
||||
} else {
|
||||
t->parse_buffer.offset = t->parse_buffer.len - buf_size;
|
||||
}
|
||||
|
||||
data_offset = t->parse_buffer.offset;
|
||||
|
||||
if (gitno_recv(&t->parse_buffer) < 0)
|
||||
return -1;
|
||||
@ -558,8 +644,8 @@ replay:
|
||||
|
||||
bytes_parsed = http_parser_execute(&t->parser,
|
||||
&t->settings,
|
||||
t->parse_buffer.data,
|
||||
t->parse_buffer.offset);
|
||||
t->parse_buffer.data + data_offset,
|
||||
t->parse_buffer.offset - data_offset);
|
||||
|
||||
t->parser.data = NULL;
|
||||
|
||||
@ -577,7 +663,7 @@ replay:
|
||||
if (t->parse_error < 0)
|
||||
return -1;
|
||||
|
||||
if (bytes_parsed != t->parse_buffer.offset) {
|
||||
if (bytes_parsed != t->parse_buffer.offset - data_offset) {
|
||||
giterr_set(GITERR_NET,
|
||||
"HTTP parser error: %s",
|
||||
http_errno_description((enum http_errno)t->parser.http_errno));
|
||||
@ -604,10 +690,8 @@ static int http_stream_write_chunked(
|
||||
|
||||
clear_parser_state(t);
|
||||
|
||||
if (gen_request(&request, s, 0) < 0) {
|
||||
giterr_set(GITERR_NET, "Failed to generate request");
|
||||
if (gen_request(&request, s, 0) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
||||
git_buf_free(&request);
|
||||
@ -679,10 +763,8 @@ static int http_stream_write_single(
|
||||
|
||||
clear_parser_state(t);
|
||||
|
||||
if (gen_request(&request, s, len) < 0) {
|
||||
giterr_set(GITERR_NET, "Failed to generate request");
|
||||
if (gen_request(&request, s, len) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0)
|
||||
goto on_error;
|
||||
@ -849,6 +931,8 @@ static int http_action(
|
||||
static int http_close(git_smart_subtransport *subtransport)
|
||||
{
|
||||
http_subtransport *t = (http_subtransport *) subtransport;
|
||||
git_http_auth_context *context;
|
||||
size_t i;
|
||||
|
||||
clear_parser_state(t);
|
||||
|
||||
@ -867,6 +951,13 @@ static int http_close(git_smart_subtransport *subtransport)
|
||||
t->url_cred = NULL;
|
||||
}
|
||||
|
||||
git_vector_foreach(&t->auth_contexts, i, context) {
|
||||
if (context->free)
|
||||
context->free(context);
|
||||
}
|
||||
|
||||
git_vector_clear(&t->auth_contexts);
|
||||
|
||||
gitno_connection_data_free_ptrs(&t->connection_data);
|
||||
|
||||
return 0;
|
||||
@ -878,6 +969,7 @@ static void http_free(git_smart_subtransport *subtransport)
|
||||
|
||||
http_close(subtransport);
|
||||
|
||||
git_vector_free(&t->auth_contexts);
|
||||
git__free(t);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "netops.h"
|
||||
#include "buffer.h"
|
||||
#include "push.h"
|
||||
#include "git2/sys/transport.h"
|
||||
|
||||
#define GIT_SIDE_BAND_DATA 1
|
||||
#define GIT_SIDE_BAND_PROGRESS 2
|
||||
|
@ -592,7 +592,9 @@ int git_smart__download_pack(
|
||||
}
|
||||
} else if (pkt->type == GIT_PKT_DATA) {
|
||||
git_pkt_data *p = (git_pkt_data *) pkt;
|
||||
error = writepack->append(writepack, p->data, p->len, stats);
|
||||
|
||||
if (p->len)
|
||||
error = writepack->append(writepack, p->data, p->len, stats);
|
||||
} else if (pkt->type == GIT_PKT_FLUSH) {
|
||||
/* A flush indicates the end of the packfile */
|
||||
git__free(pkt);
|
||||
|
@ -5,6 +5,10 @@
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#ifdef GIT_SSH
|
||||
#include <libssh2.h>
|
||||
#endif
|
||||
|
||||
#include "git2.h"
|
||||
#include "buffer.h"
|
||||
#include "netops.h"
|
||||
@ -13,8 +17,6 @@
|
||||
|
||||
#ifdef GIT_SSH
|
||||
|
||||
#include <libssh2.h>
|
||||
|
||||
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
|
||||
|
||||
static const char prefix_ssh[] = "ssh://";
|
||||
@ -35,6 +37,9 @@ typedef struct {
|
||||
git_smart_subtransport parent;
|
||||
transport_smart *owner;
|
||||
ssh_stream *current_stream;
|
||||
git_cred *cred;
|
||||
char *cmd_uploadpack;
|
||||
char *cmd_receivepack;
|
||||
} ssh_subtransport;
|
||||
|
||||
static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *username);
|
||||
@ -134,11 +139,22 @@ static int ssh_stream_write(
|
||||
size_t len)
|
||||
{
|
||||
ssh_stream *s = (ssh_stream *)stream;
|
||||
size_t off = 0;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (!s->sent_command && send_command(s) < 0)
|
||||
return -1;
|
||||
|
||||
if (libssh2_channel_write(s->channel, buffer, len) < LIBSSH2_ERROR_NONE) {
|
||||
do {
|
||||
ret = libssh2_channel_write(s->channel, buffer + off, len - off);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
off += ret;
|
||||
|
||||
} while (off < len);
|
||||
|
||||
if (ret < 0) {
|
||||
ssh_error(s->session, "SSH could not write data");
|
||||
return -1;
|
||||
}
|
||||
@ -552,7 +568,9 @@ static int ssh_uploadpack_ls(
|
||||
const char *url,
|
||||
git_smart_subtransport_stream **stream)
|
||||
{
|
||||
return _git_ssh_setup_conn(t, url, cmd_uploadpack, stream);
|
||||
const char *cmd = t->cmd_uploadpack ? t->cmd_uploadpack : cmd_uploadpack;
|
||||
|
||||
return _git_ssh_setup_conn(t, url, cmd, stream);
|
||||
}
|
||||
|
||||
static int ssh_uploadpack(
|
||||
@ -576,7 +594,9 @@ static int ssh_receivepack_ls(
|
||||
const char *url,
|
||||
git_smart_subtransport_stream **stream)
|
||||
{
|
||||
if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0)
|
||||
const char *cmd = t->cmd_receivepack ? t->cmd_receivepack : cmd_receivepack;
|
||||
|
||||
if (_git_ssh_setup_conn(t, url, cmd, stream) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -641,6 +661,8 @@ static void _ssh_free(git_smart_subtransport *subtransport)
|
||||
|
||||
assert(!t->current_stream);
|
||||
|
||||
git__free(t->cmd_uploadpack);
|
||||
git__free(t->cmd_receivepack);
|
||||
git__free(t);
|
||||
}
|
||||
|
||||
@ -720,3 +742,46 @@ int git_smart_subtransport_ssh(
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload)
|
||||
{
|
||||
#ifdef GIT_SSH
|
||||
git_strarray *paths = (git_strarray *) payload;
|
||||
git_transport *transport;
|
||||
transport_smart *smart;
|
||||
ssh_subtransport *t;
|
||||
int error;
|
||||
git_smart_subtransport_definition ssh_definition = {
|
||||
git_smart_subtransport_ssh,
|
||||
0, /* no RPC */
|
||||
};
|
||||
|
||||
if (paths->count != 2) {
|
||||
giterr_set(GITERR_SSH, "invalid ssh paths, must be two strings");
|
||||
return GIT_EINVALIDSPEC;
|
||||
}
|
||||
|
||||
if ((error = git_transport_smart(&transport, owner, &ssh_definition)) < 0)
|
||||
return error;
|
||||
|
||||
smart = (transport_smart *) transport;
|
||||
t = (ssh_subtransport *) smart->wrapped;
|
||||
|
||||
t->cmd_uploadpack = git__strdup(paths->strings[0]);
|
||||
GITERR_CHECK_ALLOC(t->cmd_uploadpack);
|
||||
t->cmd_receivepack = git__strdup(paths->strings[1]);
|
||||
GITERR_CHECK_ALLOC(t->cmd_receivepack);
|
||||
|
||||
*out = transport;
|
||||
return 0;
|
||||
#else
|
||||
GIT_UNUSED(owner);
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
assert(out);
|
||||
*out = NULL;
|
||||
|
||||
giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
@ -36,6 +36,10 @@
|
||||
#define CACHED_POST_BODY_BUF_SIZE 4096
|
||||
#define UUID_LENGTH_CCH 32
|
||||
|
||||
#ifndef WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH
|
||||
#define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0
|
||||
#endif
|
||||
|
||||
static const char *prefix_http = "http://";
|
||||
static const char *prefix_https = "https://";
|
||||
static const char *upload_pack_service = "upload-pack";
|
||||
@ -97,7 +101,7 @@ static int apply_basic_credential(HINTERNET request, git_cred *cred)
|
||||
|
||||
if (git_buf_oom(&raw) ||
|
||||
git_buf_puts(&buf, "Authorization: Basic ") < 0 ||
|
||||
git_buf_put_base64(&buf, git_buf_cstr(&raw), raw.size) < 0)
|
||||
git_buf_encode_base64(&buf, git_buf_cstr(&raw), raw.size) < 0)
|
||||
goto on_error;
|
||||
|
||||
if ((wide_len = git__utf8_to_16_alloc(&wide, git_buf_cstr(&buf))) < 0) {
|
||||
@ -745,9 +749,9 @@ replay:
|
||||
|
||||
/* Verify that we got the correct content-type back */
|
||||
if (post_verb == s->verb)
|
||||
snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-result", s->service);
|
||||
p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-result", s->service);
|
||||
else
|
||||
snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service);
|
||||
p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service);
|
||||
|
||||
if (git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8) < 0) {
|
||||
giterr_set(GITERR_OS, "Failed to convert expected content-type to wide characters");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user