Update upstream source from tag 'upstream/0.27.0+dfsg.1'

Update to upstream version '0.27.0+dfsg.1'
with Debian dir 5579c7c802
This commit is contained in:
Pirate Praveen 2018-04-26 18:06:14 +05:30
commit 9fd6a8dfbe
532 changed files with 10699 additions and 4505 deletions

View File

@ -17,19 +17,27 @@ env:
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs=" - secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
- GITTEST_INVASIVE_FS_SIZE=1 - GITTEST_INVASIVE_FS_SIZE=1
matrix: matrix:
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release" - OPTIONS="-DTHREADSAFE=ON -DENABLE_TRACE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_WERROR=ON"
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON" - OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DENABLE_WERROR=ON"
dist: trusty
sudo: false
addons: addons:
apt: apt:
sources:
- sourceline: 'deb https://dl.bintray.com/libgit2/ci-dependencies trusty libgit2deps'
key_url: 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray'
packages: packages:
- cmake cmake
- libssh2-1-dev curl
- openssh-client libcurl3
- openssh-server libcurl3-gnutls
- valgrind libcurl4-gnutls-dev
libssh2-1-dev
sudo: false openssh-client
openssh-server
valgrind
matrix: matrix:
fast_finish: true fast_finish: true
@ -40,16 +48,18 @@ matrix:
- compiler: gcc - compiler: gcc
env: COVERITY=1 env: COVERITY=1
os: linux os: linux
dist: trusty
- compiler: gcc - compiler: gcc
env: env:
- VALGRIND=1 - VALGRIND=1
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug" OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
os: linux os: linux
dist: trusty
allow_failures: allow_failures:
- env: COVERITY=1 - env: COVERITY=1
install: install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi - if [ -f ./script/install-deps-${TRAVIS_OS_NAME}.sh ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
# Run the Build script and tests # Run the Build script and tests
script: script:

View File

@ -22,6 +22,7 @@ Dmitry Kakurin
Dmitry Kovega Dmitry Kovega
Emeric Fermas Emeric Fermas
Emmanuel Rodriguez Emmanuel Rodriguez
Eric Myhre
Florian Forster Florian Forster
Holger Weiss Holger Weiss
Ingmar Vanhassel Ingmar Vanhassel

View File

@ -1,4 +1,4 @@
v0.26 + 1 v0.27 + 1
--------- ---------
### Changes or improvements ### Changes or improvements
@ -9,6 +9,122 @@ v0.26 + 1
### Breaking API changes ### Breaking API changes
v0.27
---------
### Changes or improvements
* Improved `p_unlink` in `posix_w32.c` to try and make a file writable
before sleeping in the retry loop to prevent unnecessary calls to sleep.
* The CMake build infrastructure has been improved to speed up building time.
* A new CMake option "-DUSE_HTTPS=<backend>" makes it possible to explicitly
choose an HTTP backend.
* A new CMake option "-DSHA1_BACKEND=<backend>" makes it possible to explicitly
choose an SHA1 backend. The collision-detecting backend is now the default.
* A new CMake option "-DUSE_BUNDLED_ZLIB" makes it possible to explicitly use
the bundled zlib library.
* A new CMake option "-DENABLE_REPRODUCIBLE_BUILDS" makes it possible to
generate a reproducible static archive. This requires support from your
toolchain.
* The minimum required CMake version has been bumped to 2.8.11.
* Writing to a configuration file now preserves the case of the key given by the
caller for the case-insensitive portions of the key (existing sections are
used even if they don't match).
* We now support conditional includes in configuration files.
* Fix for handling re-reading of configuration files with includes.
* Fix for reading patches which contain exact renames only.
* Fix for reading patches with whitespace in the compared files' paths.
* We will now fill `FETCH_HEAD` from all passed refspecs instead of overwriting
with the last one.
* There is a new diff option, `GIT_DIFF_INDENT_HEURISTIC` which activates a
heuristic which takes into account whitespace and indentation in order to
produce better diffs when dealing with ambiguous diff hunks.
* Fix for pattern-based ignore rules where files ignored by a rule cannot be
un-ignored by another rule.
* Sockets opened by libgit2 are now being closed on exec(3) if the platform
supports it.
* Fix for peeling annotated tags from packed-refs files.
* Fix reading huge loose objects from the object database.
* Fix files not being treated as modified when only the file mode has changed.
* We now explicitly reject adding submodules to the index via
`git_index_add_frombuffer`.
* Fix handling of `GIT_DIFF_FIND_RENAMES_FROM_REWRITES` raising `SIGABRT` when
one file has been deleted and another file has been rewritten.
* Fix for WinHTTP not properly handling NTLM and Negotiate challenges.
* When using SSH-based transports, we now repeatedly ask for the passphrase to
decrypt the private key in case a wrong passphrase is being provided.
* When generating conflict markers, they will now use the same line endings as
the rest of the file.
### API additions
* The `git_merge_file_options` structure now contains a new setting,
`marker_size`. This allows users to set the size of markers that
delineate the sides of merged files in the output conflict file.
By default this is 7 (`GIT_MERGE_CONFLICT_MARKER_SIZE`), which
produces output markers like `<<<<<<<` and `>>>>>>>`.
* `git_remote_create_detached()` creates a remote that is not associated
to any repository (and does not apply configuration like 'insteadof' rules).
This is mostly useful for e.g. emulating `git ls-remote` behavior.
* `git_diff_patchid()` lets you generate patch IDs for diffs.
* `git_status_options` now has an additional field `baseline` to allow creating
status lists against different trees.
* New family of functions to allow creating notes for a specific notes commit
instead of for a notes reference.
* New family of functions to allow parsing message trailers. This API is still
experimental and may change in future releases.
### API removals
### Breaking API changes
* Signatures now distinguish between +0000 and -0000 UTC offsets.
* The certificate check callback in the WinHTTP transport will now receive the
`message_cb_payload` instead of the `cred_acquire_payload`.
* We are now reading symlinked directories under .git/refs.
* We now refuse creating branches named "HEAD".
* We now refuse reading and writing all-zero object IDs into the
object database.
* We now read the effective user's configuration file instead of the real user's
configuration in case libgit2 runs as part of a setuid binary.
* The `git_odb_open_rstream` function and its `readstream` callback in the
`git_odb_backend` interface have changed their signatures to allow providing
the object's size and type to the caller.
v0.26 v0.26
----- -----

View File

@ -12,11 +12,17 @@
# > cmake --build . --target install # > cmake --build . --target install
PROJECT(libgit2 C) PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
CMAKE_POLICY(SET CMP0015 NEW) CMAKE_POLICY(SET CMP0015 NEW)
IF (POLICY CMP0051)
CMAKE_POLICY(SET CMP0051 NEW)
ENDIF()
IF (POLICY CMP0042)
CMAKE_POLICY(SET CMP0042 NEW)
ENDIF()
# Add find modules to the path # Add find modules to the path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/Modules/")
INCLUDE(CheckLibraryExists) INCLUDE(CheckLibraryExists)
INCLUDE(CheckFunctionExists) INCLUDE(CheckFunctionExists)
@ -24,6 +30,11 @@ INCLUDE(CheckSymbolExists)
INCLUDE(CheckStructHasMember) INCLUDE(CheckStructHasMember)
INCLUDE(AddCFlagIfSupported) INCLUDE(AddCFlagIfSupported)
INCLUDE(FindPkgConfig) INCLUDE(FindPkgConfig)
INCLUDE(FindThreads)
INCLUDE(FindStatNsec)
INCLUDE(IdeSplitSources)
INCLUDE(FeatureSummary)
INCLUDE(EnableWarnings)
# Build options # Build options
# #
@ -37,22 +48,23 @@ OPTION( PROFILE "Generate profiling information" OFF )
OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( ENABLE_TRACE "Enables tracing support" OFF )
OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF )
OPTION( USE_SHA1DC "Use SHA-1 with collision detection" OFF ) SET(SHA1_BACKEND "CollisionDetection" CACHE STRING "Backend to use for SHA1. One of Generic, OpenSSL, Win32, CommonCrypto, CollisionDetection. ")
OPTION( USE_ICONV "Link with and use iconv library" OFF )
OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
OPTION( USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON )
OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF ) OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF )
OPTION( VALGRIND "Configure build for valgrind" OFF ) OPTION( VALGRIND "Configure build for valgrind" OFF )
OPTION( CURL "Use curl for HTTP if available" ON) OPTION( CURL "Use curl for HTTP if available" ON)
OPTION( USE_EXT_HTTP_PARSER "Use system HTTP_Parser if available" ON)
OPTION( DEBUG_POOL "Enable debug pool allocator" OFF ) OPTION( DEBUG_POOL "Enable debug pool allocator" OFF )
OPTION( ENABLE_WERROR "Enable compilation with -Werror" OFF )
OPTION( USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF )
IF(DEBUG_POOL) IF (UNIX AND NOT APPLE)
ADD_DEFINITIONS(-DGIT_DEBUG_POOL) OPTION( ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF )
ENDIF() ENDIF()
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") IF (APPLE)
SET( USE_ICONV ON ) OPTION( USE_ICONV "Link with and use iconv library" ON )
FIND_PACKAGE(Security)
FIND_PACKAGE(CoreFoundation REQUIRED)
ENDIF() ENDIF()
IF(MSVC) IF(MSVC)
@ -71,10 +83,6 @@ IF(MSVC)
# If you want to embed a copy of libssh2 into libgit2, pass a # If you want to embed a copy of libssh2 into libgit2, pass a
# path to libssh2 # path to libssh2
OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF ) OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF )
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
ENDIF() ENDIF()
@ -89,313 +97,21 @@ IF(MSVC)
OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF) OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF)
ENDIF() ENDIF()
IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$")
OPTION( USE_OPENSSL "Link with and use openssl library" ON )
ENDIF()
CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h"
HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C)
CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h"
HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_nsec sys/stat.h
HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C)
IF (HAVE_STRUCT_STAT_ST_MTIM)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h
HAVE_STRUCT_STAT_NSEC LANGUAGE C)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h
HAVE_STRUCT_STAT_NSEC LANGUAGE C)
ELSE ()
SET( HAVE_STRUCT_STAT_NSEC ON )
ENDIF()
IF (HAVE_STRUCT_STAT_NSEC OR WIN32)
OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON )
ENDIF()
# This variable will contain the libraries we need to put into
# libgit2.pc's Requires.private. That is, what we're linking to or
# what someone who's statically linking us needs to link to.
SET(LIBGIT2_PC_REQUIRES "")
# This will be set later if we use the system's http-parser library or
# use iconv (OSX) and will be written to the Libs.private field in the
# pc file.
SET(LIBGIT2_PC_LIBS "")
# Installation paths
#
SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.")
SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.")
SET(INCLUDE_INSTALL_DIR include CACHE PATH "Where to install headers to.")
# Set a couple variables to be substituted inside the .pc file.
# We can't just use LIB_INSTALL_DIR in the .pc file, as passing them as absolue
# or relative paths is both valid and supported by cmake.
SET (PKGCONFIG_PREFIX ${CMAKE_INSTALL_PREFIX})
IF(IS_ABSOLUTE ${LIB_INSTALL_DIR})
SET (PKGCONFIG_LIBDIR ${LIB_INSTALL_DIR})
ELSE(IS_ABSOLUTE ${LIB_INSTALL_DIR})
SET (PKGCONFIG_LIBDIR "\${prefix}/${LIB_INSTALL_DIR}")
ENDIF (IS_ABSOLUTE ${LIB_INSTALL_DIR})
IF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
SET (PKGCONFIG_INCLUDEDIR ${INCLUDE_INSTALL_DIR})
ELSE(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
SET (PKGCONFIG_INCLUDEDIR "\${prefix}/${INCLUDE_INSTALL_DIR}")
ENDIF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
FUNCTION(TARGET_OS_LIBRARIES target)
IF(WIN32)
TARGET_LINK_LIBRARIES(${target} ws2_32)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
TARGET_LINK_LIBRARIES(${target} socket nsl)
LIST(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Haiku")
TARGET_LINK_LIBRARIES(${target} network)
LIST(APPEND LIBGIT2_PC_LIBS "-lnetwork")
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
ENDIF()
CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" NEED_LIBRT)
IF(NEED_LIBRT)
TARGET_LINK_LIBRARIES(${target} rt)
LIST(APPEND LIBGIT2_PC_LIBS "-lrt")
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
ENDIF()
IF(THREADSAFE)
TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
LIST(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
SET(LIBGIT2_PC_LIBS ${LIBGIT2_PC_LIBS} PARENT_SCOPE)
ENDIF()
ENDFUNCTION()
# This function splits the sources files up into their appropriate
# subdirectories. This is especially useful for IDEs like Xcode and
# Visual Studio, so that you can navigate into the libgit2_clar project,
# and see the folders within the tests folder (instead of just seeing all
# source and tests in a single folder.)
FUNCTION(IDE_SPLIT_SOURCES target)
IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode)
GET_TARGET_PROPERTY(sources ${target} SOURCES)
FOREACH(source ${sources})
IF(source MATCHES ".*/")
STRING(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ "" rel ${source})
IF(rel)
STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel})
IF(rel)
STRING(REPLACE "/" "\\\\" rel ${rel})
SOURCE_GROUP(${rel} FILES ${source})
ENDIF()
ENDIF()
ENDIF()
ENDFOREACH()
ENDIF()
ENDFUNCTION()
FILE(STRINGS "include/git2/version.h" GIT2_HEADER REGEX "^#define LIBGIT2_VERSION \"[^\"]*\"$")
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}") STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"([0-9]+).*$" "\\1" LIBGIT2_VERSION_MAJOR "${GIT2_HEADER}")
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_MINOR "${GIT2_HEADER}") STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_MINOR "${GIT2_HEADER}")
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}") STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}") SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
FILE(STRINGS "include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$") FILE(STRINGS "${libgit2_SOURCE_DIR}/include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$")
STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}") STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
# Find required dependencies
INCLUDE_DIRECTORIES(src include)
IF (SECURITY_FOUND)
# OS X 10.7 and older do not have some functions we use, fall back to OpenSSL there
CHECK_LIBRARY_EXISTS("${SECURITY_DIRS}" SSLCreateContext "Security/SecureTransport.h" HAVE_NEWER_SECURITY)
IF (HAVE_NEWER_SECURITY)
MESSAGE("-- Found Security ${SECURITY_DIRS}")
LIST(APPEND LIBGIT2_PC_LIBS "-framework Security")
ELSE()
MESSAGE("-- Security framework is too old, falling back to OpenSSL")
SET(SECURITY_FOUND "NO")
SET(SECURITY_DIRS "")
SET(SECURITY_DIR "")
SET(USE_OPENSSL "ON")
ENDIF()
ENDIF()
IF (COREFOUNDATION_FOUND)
MESSAGE("-- Found CoreFoundation ${COREFOUNDATION_DIRS}")
LIST(APPEND LIBGIT2_PC_LIBS "-framework CoreFoundation")
ENDIF()
IF (WIN32 AND EMBED_SSH_PATH)
FILE(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
INCLUDE_DIRECTORIES("${EMBED_SSH_PATH}/include")
FILE(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
ADD_DEFINITIONS(-DGIT_SSH)
ENDIF()
IF (WIN32 AND WINHTTP)
ADD_DEFINITIONS(-DGIT_WINHTTP)
ADD_DEFINITIONS(-DGIT_HTTPS)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
IF (MINGW)
FIND_PROGRAM(DLLTOOL dlltool CMAKE_FIND_ROOT_PATH_BOTH)
IF (NOT DLLTOOL)
MESSAGE(FATAL_ERROR "Could not find dlltool command")
ENDIF ()
SET(LIBWINHTTP_PATH "${CMAKE_CURRENT_BINARY_DIR}/deps/winhttp")
FILE(MAKE_DIRECTORY ${LIBWINHTTP_PATH})
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(WINHTTP_DEF "${CMAKE_CURRENT_SOURCE_DIR}/deps/winhttp/winhttp64.def")
ELSE()
set(WINHTTP_DEF "${CMAKE_CURRENT_SOURCE_DIR}/deps/winhttp/winhttp.def")
ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${LIBWINHTTP_PATH}/libwinhttp.a
COMMAND ${DLLTOOL} -d ${WINHTTP_DEF} -k -D winhttp.dll -l libwinhttp.a
DEPENDS ${WINHTTP_DEF}
WORKING_DIRECTORY ${LIBWINHTTP_PATH}
)
SET_SOURCE_FILES_PROPERTIES(
${CMAKE_CURRENT_SOURCE_DIR}/src/transports/winhttp.c
PROPERTIES OBJECT_DEPENDS ${LIBWINHTTP_PATH}/libwinhttp.a
)
INCLUDE_DIRECTORIES(deps/winhttp)
LINK_DIRECTORIES(${LIBWINHTTP_PATH})
ENDIF ()
LINK_LIBRARIES(winhttp rpcrt4 crypt32 ole32)
LIST(APPEND LIBGIT2_PC_LIBS "-lwinhttp" "-lrpcrt4" "-lcrypt32" "-lole32")
ELSE ()
IF (CURL)
PKG_CHECK_MODULES(CURL libcurl)
ENDIF ()
IF (NOT AMIGA AND USE_OPENSSL)
FIND_PACKAGE(OpenSSL)
ENDIF ()
IF (CURL_FOUND)
ADD_DEFINITIONS(-DGIT_CURL)
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
LINK_DIRECTORIES(${CURL_LIBRARY_DIRS})
LINK_LIBRARIES(${CURL_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${CURL_LDFLAGS})
ENDIF()
ENDIF()
# Specify sha1 implementation
IF (USE_SHA1DC)
ADD_DEFINITIONS(-DGIT_SHA1_COLLISIONDETECT)
ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1)
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
FILE(GLOB SRC_SHA1 src/hash/hash_collisiondetect.c src/hash/sha1dc/*)
ELSEIF (WIN32 AND NOT MINGW)
ADD_DEFINITIONS(-DGIT_SHA1_WIN32)
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
ADD_DEFINITIONS(-DGIT_SHA1_COMMON_CRYPTO)
ELSEIF (OPENSSL_FOUND)
ADD_DEFINITIONS(-DGIT_SHA1_OPENSSL)
IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
LIST(APPEND LIBGIT2_PC_LIBS "-lssl")
ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl")
ENDIF ()
ELSE()
FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
ENDIF()
# Enable tracing
IF (ENABLE_TRACE STREQUAL "ON")
ADD_DEFINITIONS(-DGIT_TRACE)
ENDIF()
# Include POSIX regex when it is required
IF(WIN32 OR AMIGA OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
INCLUDE_DIRECTORIES(deps/regex)
SET(SRC_REGEX deps/regex/regex.c)
ENDIF()
# Optional external dependency: http-parser
FIND_PACKAGE(HTTP_Parser)
IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS})
LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser")
ELSE()
MESSAGE(STATUS "http-parser version 2 was not found; using bundled 3rd-party sources.")
INCLUDE_DIRECTORIES(deps/http-parser)
FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h)
ENDIF()
# Optional external dependency: zlib
FIND_PACKAGE(ZLIB)
IF (ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
LINK_LIBRARIES(${ZLIB_LIBRARIES})
IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
LIST(APPEND LIBGIT2_PC_LIBS "-lz")
ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib")
ENDIF()
ELSE()
MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
INCLUDE_DIRECTORIES(deps/zlib)
ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h)
ENDIF()
# Optional external dependency: libssh2
IF (USE_SSH)
PKG_CHECK_MODULES(LIBSSH2 libssh2)
ENDIF()
IF (LIBSSH2_FOUND)
ADD_DEFINITIONS(-DGIT_SSH)
INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIRS})
LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
#SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${LIBSSH2_LDFLAGS}")
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS)
ADD_DEFINITIONS(-DGIT_SSH_MEMORY_CREDENTIALS)
ENDIF()
ELSE()
MESSAGE(STATUS "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.")
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)
ENDIF()
IF (ICONV_FOUND)
ADD_DEFINITIONS(-DGIT_USE_ICONV)
INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
LIST(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
ENDIF()
# Platform specific compilation flags # Platform specific compilation flags
IF (MSVC) IF (MSVC)
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
@ -417,8 +133,9 @@ IF (MSVC)
ENDIF() ENDIF()
IF (MSVC_CRTDBG) IF (MSVC_CRTDBG)
SET(CRT_FLAG_DEBUG "${CRT_FLAG_DEBUG} /DGIT_MSVC_CRTDBG") SET(GIT_MSVC_CRTDBG 1)
SET(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}" "Dbghelp.lib") SET(CRT_FLAG_DEBUG "${CRT_FLAG_DEBUG}")
SET(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES} Dbghelp.lib")
ENDIF() ENDIF()
# /Zi - Create debugging information # /Zi - Create debugging information
@ -466,13 +183,17 @@ IF (MSVC)
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}") SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}") SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}")
SET(WIN_RC "src/win32/git2.rc")
ELSE () ELSE ()
IF (ENABLE_REPRODUCIBLE_BUILDS)
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Dqc <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> Dq <TARGET> <LINK_FLAGS> <OBJECTS>")
SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -D <TARGET>")
ENDIF()
SET(CMAKE_C_FLAGS "-D_GNU_SOURCE ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-D_GNU_SOURCE ${CMAKE_C_FLAGS}")
ADD_C_FLAG_IF_SUPPORTED(-Wall) ENABLE_WARNINGS(all)
ADD_C_FLAG_IF_SUPPORTED(-Wextra) ENABLE_WARNINGS(extra)
IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}")
@ -495,16 +216,17 @@ ELSE ()
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1) ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
ENDIF () ENDIF ()
ADD_C_FLAG_IF_SUPPORTED(-Wdocumentation) ENABLE_WARNINGS(documentation)
ADD_C_FLAG_IF_SUPPORTED(-Wno-missing-field-initializers) DISABLE_WARNINGS(missing-field-initializers)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-aliasing=2) ENABLE_WARNINGS(strict-aliasing)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-prototypes) ENABLE_WARNINGS(strict-prototypes)
ADD_C_FLAG_IF_SUPPORTED(-Wdeclaration-after-statement) ENABLE_WARNINGS(declaration-after-statement)
ADD_C_FLAG_IF_SUPPORTED(-Wno-unused-const-variable) ENABLE_WARNINGS(shift-count-overflow)
ADD_C_FLAG_IF_SUPPORTED(-Wno-unused-function) DISABLE_WARNINGS(unused-const-variable)
DISABLE_WARNINGS(unused-function)
IF (APPLE) # Apple deprecated OpenSSL IF (APPLE) # Apple deprecated OpenSSL
ADD_C_FLAG_IF_SUPPORTED(-Wno-deprecated-declarations) DISABLE_WARNINGS(deprecated-declarations)
ENDIF() ENDIF()
IF (PROFILE) IF (PROFILE)
@ -513,26 +235,6 @@ ELSE ()
ENDIF () ENDIF ()
ENDIF() ENDIF()
CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L)
IF (HAVE_REGCOMP_L)
ADD_DEFINITIONS(-DHAVE_REGCOMP_L)
ENDIF ()
CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
IF (HAVE_FUTIMENS)
ADD_DEFINITIONS(-DHAVE_FUTIMENS)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_r HAVE_QSORT_R)
IF (HAVE_QSORT_R)
ADD_DEFINITIONS(-DHAVE_QSORT_R)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
IF (HAVE_QSORT_S)
ADD_DEFINITIONS(-DHAVE_QSORT_S)
ENDIF ()
IF( NOT CMAKE_CONFIGURATION_TYPES ) IF( NOT CMAKE_CONFIGURATION_TYPES )
# Build Debug by default # Build Debug by default
IF (NOT CMAKE_BUILD_TYPE) IF (NOT CMAKE_BUILD_TYPE)
@ -543,177 +245,18 @@ ELSE()
# that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE # that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE
ENDIF() ENDIF()
IF (SECURITY_FOUND) ADD_SUBDIRECTORY(src)
ADD_DEFINITIONS(-DGIT_SECURE_TRANSPORT)
ADD_DEFINITIONS(-DGIT_HTTPS)
INCLUDE_DIRECTORIES(${SECURITY_INCLUDE_DIR})
ENDIF ()
IF (OPENSSL_FOUND)
ADD_DEFINITIONS(-DGIT_OPENSSL)
ADD_DEFINITIONS(-DGIT_HTTPS)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
ENDIF()
IF (THREADSAFE)
IF (NOT WIN32)
FIND_PACKAGE(Threads REQUIRED)
ENDIF()
ADD_DEFINITIONS(-DGIT_THREADS)
ENDIF()
IF (USE_NSEC)
ADD_DEFINITIONS(-DGIT_USE_NSEC)
ENDIF()
IF (HAVE_STRUCT_STAT_ST_MTIM)
ADD_DEFINITIONS(-DGIT_USE_STAT_MTIM)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
ADD_DEFINITIONS(-DGIT_USE_STAT_MTIMESPEC)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIME_NSEC)
ADD_DEFINITIONS(-DGIT_USE_STAT_MTIME_NSEC)
ENDIF()
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
# Collect sourcefiles
FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h)
# On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN)
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501)
FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h)
ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
ELSE()
IF (VALGRIND)
ADD_DEFINITIONS(-DNO_MMAP)
ENDIF()
FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h)
ENDIF()
FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h)
# Determine architecture of the machine
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
ADD_DEFINITIONS(-DGIT_ARCH_64)
ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
ADD_DEFINITIONS(-DGIT_ARCH_32)
ELSEIF (CMAKE_SIZEOF_VOID_P)
MESSAGE(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
ELSE()
MESSAGE(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
ENDIF()
# Compile and link libgit2
ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1} ${WIN_RC})
TARGET_LINK_LIBRARIES(git2 ${SECURITY_DIRS})
TARGET_LINK_LIBRARIES(git2 ${COREFOUNDATION_DIRS})
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)
# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
# Win64+MSVC+static libs = linker error
IF(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
SET_TARGET_PROPERTIES(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
ENDIF()
IDE_SPLIT_SOURCES(git2)
IF (SONAME)
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
ELSEIF (DEFINED LIBGIT2_PREFIX)
SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
ENDIF()
ENDIF()
STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libgit2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc @ONLY)
IF (MSVC_IDE)
# Precompiled headers
SET_TARGET_PROPERTIES(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
SET_SOURCE_FILES_PROPERTIES(src/win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
ENDIF ()
# Install
INSTALL(TARGETS git2
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
INSTALL(DIRECTORY include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} )
INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} )
# Tests # Tests
IF (NOT MSVC)
IF (NOT BUILD_SHARED_LIBS)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
ENDIF()
ENDIF ()
IF (BUILD_CLAR) IF (BUILD_CLAR)
FIND_PACKAGE(PythonInterp)
IF(NOT PYTHONINTERP_FOUND)
MESSAGE(FATAL_ERROR "Could not find a python interpeter, which is needed to build the tests. "
"Make sure python is available, or pass -DBUILD_CLAR=OFF to skip building the tests")
ENDIF()
SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources/")
SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests")
SET(CLAR_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.")
ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\")
ADD_DEFINITIONS(-DCLAR_TMPDIR=\"libgit2_tests\")
INCLUDE_DIRECTORIES(${CLAR_PATH})
FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h)
SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar_libgit2_trace.c" "${CLAR_PATH}/clar_libgit2_timer.c" "${CLAR_PATH}/clar.c")
ADD_CUSTOM_COMMAND(
OUTPUT ${CLAR_PATH}/clar.suite
COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline -xstress .
DEPENDS ${SRC_TEST}
WORKING_DIRECTORY ${CLAR_PATH}
)
SET_SOURCE_FILES_PROPERTIES(
${CLAR_PATH}/clar.c
PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite)
ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1})
TARGET_LINK_LIBRARIES(libgit2_clar ${COREFOUNDATION_DIRS})
TARGET_LINK_LIBRARIES(libgit2_clar ${SECURITY_DIRS})
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)
IDE_SPLIT_SOURCES(libgit2_clar)
IF (MSVC_IDE)
# Precompiled headers
SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
ENDIF ()
ENABLE_TESTING() ENABLE_TESTING()
IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND) ADD_SUBDIRECTORY(tests)
ADD_TEST(libgit2_clar libgit2_clar -ionline -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
ELSE ()
ADD_TEST(libgit2_clar libgit2_clar -v -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
ENDIF ()
# Add a test target which runs the cred callback tests, to be
# called after setting the url and user
ADD_TEST(libgit2_clar-cred_callback libgit2_clar -v -sonline::clone::cred_callback)
ADD_TEST(libgit2_clar-proxy_credentials_in_url libgit2_clar -v -sonline::clone::proxy_credentials_in_url)
ADD_TEST(libgit2_clar-proxy_credentials_request libgit2_clar -v -sonline::clone::proxy_credentials_request)
ENDIF () ENDIF ()
IF (TAGS) IF (TAGS)
@ -738,3 +281,11 @@ ENDIF ()
IF (BUILD_EXAMPLES) IF (BUILD_EXAMPLES)
ADD_SUBDIRECTORY(examples) ADD_SUBDIRECTORY(examples)
ENDIF () ENDIF ()
IF(CMAKE_VERSION VERSION_GREATER 3)
FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
ELSE()
PRINT_ENABLED_FEATURES()
PRINT_DISABLED_FEATURES()
ENDIF()

View File

@ -71,6 +71,22 @@ 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 in the first place, you're less likely to get feedback and have your change
merged in. merged in.
In addition to outlining your thought process in the PR's description, please
also try to document it in your commits. We welcome it if every commit has a
description of why you have been doing your changes alongside with your
reasoning why this is a good idea. The messages shall be written in
present-tense and in an imperative style (e.g. "Add feature foobar", not "Added
feature foobar" or "Adding feature foobar"). Lines should be wrapped at 80
characters so people with small screens are able to read the commit messages in
their terminal without any problem.
To make it easier to attribute commits to certain parts of our code base, we
also prefer to have the commit subject be prefixed with a "scope". E.g. if you
are changing code in our merging subsystem, make sure to prefix the subject with
"merge:". The first word following the colon shall start with an lowercase
letter. The maximum line length for the subject is 70 characters, preferably
shorter.
If you are starting to work on a particular area, feel free to submit a PR 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 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 not ready to merge). These early PRs are welcome and will help in getting

View File

@ -36,10 +36,6 @@ These are good small projects to get started with libgit2.
trick to this one will be doing it in a manner that is clean and trick to this one will be doing it in a manner that is clean and
simple, but still handles the various cases correctly (e.g. `-B/70%` simple, but still handles the various cases correctly (e.g. `-B/70%`
is apparently a legal setting). is apparently a legal setting).
* Implement the `--log-size` option for `examples/log.c`. I think all
the data is available, you would just need to add the code into the
`print_commit()` routine (along with a way of passing the option
into that function).
* As an extension to the matching idea for `examples/log.c`, add the * As an extension to the matching idea for `examples/log.c`, add the
`-i` option to use `strcasestr()` for matches. `-i` option to use `strcasestr()` for matches.
* For `examples/log.c`, implement the `--first-parent` option now that * For `examples/log.c`, implement the `--first-parent` option now that

View File

@ -6,8 +6,20 @@ libgit2 - the Git linkable library
[![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639) [![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639)
`libgit2` is a portable, pure C implementation of the Git core methods `libgit2` is a portable, pure C implementation of the Git core methods
provided as a re-entrant linkable library with a solid API, allowing you to provided as a linkable library with a solid API, allowing to build Git
write native speed custom Git applications in any language with bindings. functionality into your application. Language bindings like
[Rugged](https://github.com/libgit2/rugged) (Ruby),
[LibGit2Sharp](https://github.com/libgit2/libgit2sharp) (.NET),
[pygit2](http://www.pygit2.org/) (Python) and
[NodeGit](http://nodegit.org) (Node) allow you to build Git tooling
in your favorite language.
`libgit2` is used to power Git GUI clients like
[GitKraken](https://gitkraken.com/) and [gmaster](https://gmaster.io/)
and on Git hosting providers like [GitHub](https://github.com/),
[GitLab](https://gitlab.com/) and
[Visual Studio Team Services](https://visualstudio.com/team-services/).
We perform the merge every time you click "merge pull request".
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special `libgit2` is licensed under a **very permissive license** (GPLv2 with a special
Linking Exception). This basically means that you can link it (unmodified) Linking Exception). This basically means that you can link it (unmodified)
@ -15,6 +27,30 @@ with any kind of software without having to release its source code.
Additionally, the example code has been released to the public domain (see the Additionally, the example code has been released to the public domain (see the
[separate license](examples/COPYING) for more information). [separate license](examples/COPYING) for more information).
Quick Start
===========
**Prerequisites** for building libgit2:
1. [CMake](https://cmake.org/), and is recommended to be installed into
your `PATH`.
2. [Python](https://www.python.org) is used by our test framework, and
should be installed into your `PATH`.
3. C compiler: libgit2 is C90 and should compile on most compilers.
* Windows: Visual Studio is recommended
* Mac: Xcode is recommended
* Unix: gcc or clang is recommended.
**Build**
1. Create a build directory beneath the libgit2 source directory, and change
into it: `mkdir build && cd build`
2. Create the cmake build environment: `cmake ..`
3. Build libgit2: `cmake --build .`
Trouble with these steps? Read `TROUBLESHOOTING.md`. More detailed build
guidance is available below.
Getting Help Getting Help
============ ============
@ -40,6 +76,12 @@ on a specific repository, please provide a link to it if possible.
We ask that you not open a GitHub Issue for help, only for bug reports. We ask that you not open a GitHub Issue for help, only for bug reports.
**Reporting Security Issues**
In case you think to have found a security issue with libgit2, please do not
open a public issue. Instead, you can report the issue to the private mailing
list [security@libgit2.com](mailto:security@libgit2.com).
What It Can Do What It Can Do
============== ==============
@ -118,6 +160,9 @@ and internal API/coding conventions we use.
Building libgit2 - Using CMake Building libgit2 - Using CMake
============================== ==============================
Building
--------
`libgit2` builds cleanly on most platforms without any external dependencies. `libgit2` builds cleanly on most platforms without any external dependencies.
Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthreads` to be available; Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthreads` to be available;
they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
@ -133,19 +178,49 @@ On most systems you can build the library using the following commands
Alternatively you can point the CMake GUI tool to the CMakeLists.txt file and generate platform specific build project or IDE workspace. Alternatively you can point the CMake GUI tool to the CMakeLists.txt file and generate platform specific build project or IDE workspace.
Running Tests
-------------
Once built, you can run the tests from the `build` directory with the command Once built, you can run the tests from the `build` directory with the command
$ make test $ ctest -V
Alternatively you can run the test suite directly using, Alternatively you can run the test suite directly using,
$ ./libgit2_clar $ ./libgit2_clar
Invoking the test suite directly is useful because it allows you to execute
individual tests, or groups of tests using the `-s` flag. For example, to
run the index tests:
$ ./libgit2_clar -sindex
To run a single test named `index::racy::diff`, which corresponds to the test
function (`test_index_racy__diff`)[https://github.com/libgit2/libgit2/blob/master/tests/index/racy.c#L23]:
$ ./libgit2_clar -sindex::racy::diff
The test suite will print a `.` for every passing test, and an `F` for any
failing test. An `S` indicates that a test was skipped because it is not
applicable to your platform or is particularly expensive.
**Note:** There should be _no_ failing tests when you build an unmodified
source tree from a [release](https://github.com/libgit2/libgit2/releases),
or from the [master branch](https://github.com/libgit2/libgit2/tree/master).
Please contact us or [open an issue](https://github.com/libgit2/libgit2/issues)
if you see test failures.
Installation
------------
To install the library you can specify the install prefix by setting: To install the library you can specify the install prefix by setting:
$ cmake .. -DCMAKE_INSTALL_PREFIX=/install/prefix $ cmake .. -DCMAKE_INSTALL_PREFIX=/install/prefix
$ cmake --build . --target install $ cmake --build . --target install
Advanced Usage
--------------
For more advanced use or questions about CMake please read <https://cmake.org/Wiki/CMake_FAQ>. For more advanced use or questions about CMake please read <https://cmake.org/Wiki/CMake_FAQ>.
The following CMake variables are declared: The following CMake variables are declared:
@ -177,16 +252,6 @@ If you want to build a universal binary for Mac OS X, CMake sets it
all up for you if you use `-DCMAKE_OSX_ARCHITECTURES="i386;x86_64"` all up for you if you use `-DCMAKE_OSX_ARCHITECTURES="i386;x86_64"`
when configuring. when configuring.
Windows
-------
You need to run the CMake commands from the Visual Studio command
prompt, not the regular or Windows SDK one. Select the right generator
for your version with the `-G "Visual Studio X" option.
See [the website](http://libgit2.github.com/docs/guides/build-and-link/)
for more detailed instructions.
Android Android
------- -------
@ -228,6 +293,8 @@ Here are the bindings to libgit2 that are currently available:
* git2go <https://github.com/libgit2/git2go> * git2go <https://github.com/libgit2/git2go>
* GObject * GObject
* libgit2-glib <https://wiki.gnome.org/Projects/Libgit2-glib> * libgit2-glib <https://wiki.gnome.org/Projects/Libgit2-glib>
* Guile
* Guile-Git <https://gitlab.com/guile-git/guile-git>
* Haskell * Haskell
* hgit2 <https://github.com/jwiegley/gitlib> * hgit2 <https://github.com/jwiegley/gitlib>
* Java * Java

13
TROUBLESHOOTING.md Normal file
View File

@ -0,0 +1,13 @@
Troubleshooting libgit2 Problems
================================
CMake Failures
--------------
* **`Asked for OpenSSL TLS backend, but it wasn't found`**
CMake cannot find your SSL/TLS libraries. By default, libgit2 always
builds with HTTPS support, and you are encouraged to install the
OpenSSL libraries for your system (eg, `apt-get install libssl-dev`).
For development, if you simply want to disable HTTPS support entirely,
pass the `-DUSE_HTTPS=OFF` argument to `cmake` when configuring it.

View File

@ -9,13 +9,23 @@ environment:
GITTEST_INVASIVE_FS_SIZE: 1 GITTEST_INVASIVE_FS_SIZE: 1
matrix: matrix:
- GENERATOR: "Visual Studio 11" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010"
ARCH: 32 ARCH: 32
- GENERATOR: "Visual Studio 11 Win64" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010 Win64"
ARCH: 64 ARCH: 64
- GENERATOR: "MSYS Makefiles" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015"
ARCH: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015 Win64"
ARCH: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: i686 # this is for 32-bit MinGW-w64 ARCH: i686 # this is for 32-bit MinGW-w64
- GENERATOR: "MSYS Makefiles" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: 64 ARCH: 64
cache: cache:
- i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z - i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
@ -26,7 +36,7 @@ build_script:
mkdir build mkdir build
cd build cd build
if ($env:GENERATOR -ne "MSYS Makefiles") { if ($env:GENERATOR -ne "MSYS Makefiles") {
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D MSVC_CRTDBG=ON .. -G"$env:GENERATOR" cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON -D MSVC_CRTDBG=ON .. -G"$env:GENERATOR"
cmake --build . --config Debug cmake --build . --config Debug
} }
- cmd: | - cmd: |
@ -38,13 +48,8 @@ test_script:
# Run this early so we know it's ready by the time we need it # Run this early so we know it's ready by the time we need it
$proxyJob = Start-Job { java -jar $Env:APPVEYOR_BUILD_FOLDER\build\poxyproxy.jar -d --port 8080 --credentials foo:bar } $proxyJob = Start-Job { java -jar $Env:APPVEYOR_BUILD_FOLDER\build\poxyproxy.jar -d --port 8080 --credentials foo:bar }
ctest -V -R libgit2_clar ctest -V -R libgit2_clar
$env:GITTEST_REMOTE_URL="https://github.com/libgit2/non-existent"
$env:GITTEST_REMOTE_USER="libgit2test"
ctest -V -R libgit2_clar-cred_callback
Receive-Job -Job $proxyJob Receive-Job -Job $proxyJob
$env:GITTEST_REMOTE_PROXY_URL = "http://foo:bar@localhost:8080" $env:GITTEST_REMOTE_PROXY_URL = "localhost:8080"
ctest -V -R libgit2_clar-proxy_credentials_in_url
$env:GITTEST_REMOTE_PROXY_URL = "http://localhost:8080"
$env:GITTEST_REMOTE_PROXY_USER = "foo" $env:GITTEST_REMOTE_PROXY_USER = "foo"
$env:GITTEST_REMOTE_PROXY_PASS = "bar" $env:GITTEST_REMOTE_PROXY_PASS = "bar"
ctest -V -R libgit2_clar-proxy_credentials_request ctest -V -R libgit2_clar-proxy_credentials

View File

@ -0,0 +1,14 @@
MACRO(ENABLE_WARNINGS flag)
IF(ENABLE_WERROR)
ADD_C_FLAG_IF_SUPPORTED(-Werror=${flag})
ELSE()
ADD_C_FLAG_IF_SUPPORTED(-W${flag})
ENDIF()
ENDMACRO()
MACRO(DISABLE_WARNINGS flag)
ADD_C_FLAG_IF_SUPPORTED(-Wno-${flag})
IF(ENABLE_WERROR)
ADD_C_FLAG_IF_SUPPORTED(-Wno-error=${flag})
ENDIF()
ENDMACRO()

View File

@ -1,9 +1,26 @@
IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_DIRS) # Find CoreFoundation.framework
SET(COREFOUNDATION_FOUND TRUE) # This will define :
ELSE () #
# COREFOUNDATION_FOUND
# COREFOUNDATION_LIBRARIES
# COREFOUNDATION_LDFLAGS
#
FIND_PATH(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h) FIND_PATH(COREFOUNDATION_INCLUDE_DIR NAMES CoreFoundation.h)
FIND_LIBRARY(COREFOUNDATION_DIRS NAMES CoreFoundation) FIND_LIBRARY(COREFOUNDATION_LIBRARIES NAMES CoreFoundation)
IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_DIRS) IF (COREFOUNDATION_INCLUDE_DIR AND COREFOUNDATION_LIBRARIES)
IF (NOT CoreFoundation_FIND_QUIETLY)
MESSAGE("-- Found CoreFoundation ${COREFOUNDATION_LIBRARIES}")
ENDIF()
SET(COREFOUNDATION_FOUND TRUE) SET(COREFOUNDATION_FOUND TRUE)
SET(COREFOUNDATION_LDFLAGS "-framework CoreFoundation")
ENDIF () ENDIF ()
IF (CoreFoundation_FIND_REQUIRED AND NOT COREFOUNDATION_FOUND)
MESSAGE(FATAL "-- CoreFoundation not found")
ENDIF() ENDIF()
MARK_AS_ADVANCED(
COREFOUNDATION_INCLUDE_DIR
COREFOUNDATION_LIBRARIES
)

View File

@ -1,9 +1,28 @@
IF (SECURITY_INCLUDE_DIR AND SECURITY_DIRS) # Find Security.framework
SET(SECURITY_FOUND TRUE) # This will define :
ELSE () #
# SECURITY_FOUND
# SECURITY_LIBRARIES
# SECURITY_LDFLAGS
# SECURITY_HAS_SSLCREATECONTEXT
#
FIND_PATH(SECURITY_INCLUDE_DIR NAMES Security/Security.h) FIND_PATH(SECURITY_INCLUDE_DIR NAMES Security/Security.h)
FIND_LIBRARY(SECURITY_DIRS NAMES Security) FIND_LIBRARY(SECURITY_LIBRARIES NAMES Security)
IF (SECURITY_INCLUDE_DIR AND SECURITY_DIRS) IF (SECURITY_INCLUDE_DIR AND SECURITY_LIBRARIES)
IF (NOT Security_FIND_QUIETLY)
MESSAGE("-- Found Security ${SECURITY_LIBRARIES}")
ENDIF()
SET(SECURITY_FOUND TRUE) SET(SECURITY_FOUND TRUE)
SET(SECURITY_LDFLAGS "-framework Security")
CHECK_LIBRARY_EXISTS("${SECURITY_LIBRARIES}" SSLCreateContext "Security/SecureTransport.h" SECURITY_HAS_SSLCREATECONTEXT)
ENDIF () ENDIF ()
IF (Security_FIND_REQUIRED AND NOT SECURITY_FOUND)
MESSAGE(FATAL "-- Security not found")
ENDIF() ENDIF()
MARK_AS_ADVANCED(
SECURITY_INCLUDE_DIR
SECURITY_LIBRARIES
)

View File

@ -0,0 +1,20 @@
CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h"
HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C)
CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h"
HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_nsec sys/stat.h
HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C)
IF (HAVE_STRUCT_STAT_ST_MTIM)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h
HAVE_STRUCT_STAT_NSEC LANGUAGE C)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec sys/stat.h
HAVE_STRUCT_STAT_NSEC LANGUAGE C)
ELSE ()
SET( HAVE_STRUCT_STAT_NSEC ON )
ENDIF()
IF (HAVE_STRUCT_STAT_NSEC OR WIN32)
OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON )
ENDIF()

View File

@ -0,0 +1,22 @@
# This function splits the sources files up into their appropriate
# subdirectories. This is especially useful for IDEs like Xcode and
# Visual Studio, so that you can navigate into the libgit2_clar project,
# and see the folders within the tests folder (instead of just seeing all
# source and tests in a single folder.)
FUNCTION(IDE_SPLIT_SOURCES target)
IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode)
GET_TARGET_PROPERTY(sources ${target} SOURCES)
FOREACH(source ${sources})
IF(source MATCHES ".*/")
STRING(REPLACE ${libgit2_SOURCE_DIR}/ "" rel ${source})
IF(rel)
STRING(REGEX REPLACE "/([^/]*)$" "" rel ${rel})
IF(rel)
STRING(REPLACE "/" "\\\\" rel ${rel})
SOURCE_GROUP(${rel} FILES ${source})
ENDIF()
ENDIF()
ENDIF()
ENDFOREACH()
ENDIF()
ENDFUNCTION()

81
docs/release.md Normal file
View File

@ -0,0 +1,81 @@
# Releasing the library
We have three kinds of releases: "full" releases, maintenance releases and security releases. Full ones release the state of the `master` branch whereas maintenance releases provide bugfixes building on top of the currently released series. Security releases are also for the current series but only contain security fixes on top of the previous release.
## Full release
We aim to release once every six months. We start the process by opening an issue. This is accompanied with a feature freeze. From now until the release, only bug fixes are to be merged. Use the following as a base for the issue
Release v0.X
Let's release v0.X, codenamed: <something witty>
- [ ] Bump the versions in the headers
- [ ] Make a release candidate
- [ ] Plug any final leaks
- [ ] Fix any last-minute issues
- [ ] Make sure CHANGELOG reflects everything worth discussing
- [ ] Update the version in CHANGELOG and the header
- [ ] Produce a release candidate
- [ ] Tag
- [ ] Create maint/v0.X
- [ ] Update any bindings the core team works with
We tag at least one release candidate. This RC must carry the new version in the headers, including the SOVERSION. If there are no significant issues found, we can go straight to the release after a single RC. This is up to the discretion of the release manager. There is no set time to have the candidate out, but we should we should give downstream projects at least a week to give feedback.
Preparing the first release candidate includes updating the version number of libgit2 to the new version number. To do so, a pull request shall be submitted that adjusts the version number in the following places:
- CHANGELOG.md
- include/git2/version.h
As soon as the pull request is merged, the merge commit shall be tagged with a lightweight tag.
The tagging happens via GitHub's "releases" tab which lets us attach release notes to a particular tag. In the description we include the changes in `CHANGELOG.md` between the last full release. Use the following as a base for the release notes
This is the first release of the v0.X series, <codename>. The changelog follows.
followed by the three sections in the changelog. For release candidates we can avoid copying the full changelog and only include any new entries.
During the freeze, and certainly after the first release candidate, any bindings the core team work with should be updated in order to discover any issues that might come up with the multitude of approaches to memory management, embedding or linking.
Create a branch `maint/v0.X` at the current state of `master` after you've created the tag. This will be used for maintenance releases and lets our dependents track the latest state of the series.
## Maintenance release
Every once in a while, when we feel we've accumulated a significant amount of backportable fixes in the mainline branch, we produce a maintenance release in order to provide fixes or improvements for those who track the releases. This also lets our users and integrators receive updates without having to upgrade to the next full release.
As a rule of thumb, it's a good idea to produce a maintenance release for the current series when we're getting ready for a full release. This gives the (still) current series a last round of fixes without having to upgrade (which with us potentially means adjusting to API changes).
Start by opening an issue. Use the following as a base.
Release v0.X.Y
Enough fixes have accumulated, let's release v0.X.Y
- [ ] Select the changes we want to backport
- [ ] Update maint/v0.X
- [ ] Tag
The list of changes to backport does not need to be comprehensive and we might not backport something if the code in mainline has diverged significantly. These fixes do not include those which require API or ABI changes as we release under the same SOVERSION.
Do not merge into the `maint/v0.X` until we are getting ready to produce a new release. There is always the possibility that we will need to produce a security release and those must only include the relevant security fixes and not arbitrary fixes we were planning on releasing at some point.
Here we do not use release candidates as the changes are supposed to be small and proven.
## Security releases
This is the same as a maintenance release, except that the fix itself will most likely be developed in a private repository and will only be visible to a select group of people until the release.
Everything else remains the same. Occasionally we might opt to backport a security fix to the previous series, based on how recently we started the new series and how serious the issue is.
## Updating documentation
We use docurium to generate our documentation. It is a tool written in ruby which leverages libclang's documentation parser. Install docurium
gem install docurium
and run it against our description file with the tip of master checked out.
cm doc api.docurium
It will start up a few proceses and write out the results as a new commit onto the `gh-pages` branch. That can be pushed to GitHub to update what will show up on our documentation reference site.

15
examples/.gitignore vendored
View File

@ -1,15 +0,0 @@
general
showindex
diff
rev-list
blame
cat-file
init
log
rev-parse
remote
status
tag
for-each-ref
describe
*.dSYM

View File

@ -1,4 +1,7 @@
FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h) LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h common.?)
ADD_EXECUTABLE(cgit2 ${SRC_EXAMPLE_GIT2}) ADD_EXECUTABLE(cgit2 ${SRC_EXAMPLE_GIT2})
IF(WIN32 OR ANDROID) IF(WIN32 OR ANDROID)
TARGET_LINK_LIBRARIES(cgit2 git2) TARGET_LINK_LIBRARIES(cgit2 git2)

View File

@ -1,17 +0,0 @@
.PHONY: all
CC = gcc
CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers
LFLAGS = -L../build -lgit2 -lz
APPS = general showindex diff rev-list cat-file status log rev-parse init blame tag remote
APPS += for-each-ref
APPS += describe
all: $(APPS)
% : %.c
$(CC) -o $@ common.c $(CFLAGS) $< $(LFLAGS)
clean:
$(RM) $(APPS)
$(RM) -r *.dSYM

View File

@ -235,3 +235,13 @@ void treeish_to_tree(
git_object_free(obj); git_object_free(obj);
} }
void *xrealloc(void *oldp, size_t newsz)
{
void *p = realloc(oldp, newsz);
if (p == NULL) {
fprintf(stderr, "Cannot allocate memory, exiting.\n");
exit(1);
}
return p;
}

View File

@ -103,3 +103,8 @@ extern int diff_output(
*/ */
extern void treeish_to_tree( extern void treeish_to_tree(
git_tree **out, git_repository *repo, const char *treeish); git_tree **out, git_repository *repo, const char *treeish);
/**
* A realloc that exits on failure
*/
extern void *xrealloc(void *oldp, size_t newsz);

View File

@ -47,16 +47,6 @@ typedef struct {
typedef struct args_info args_info; typedef struct args_info args_info;
static void *xrealloc(void *oldp, size_t newsz)
{
void *p = realloc(oldp, newsz);
if (p == NULL) {
fprintf(stderr, "Cannot allocate memory, exiting.\n");
exit(1);
}
return p;
}
static void opts_add_commit(describe_options *opts, const char *commit) static void opts_add_commit(describe_options *opts, const char *commit)
{ {
size_t sz; size_t sz;

View File

@ -724,6 +724,7 @@ static void config_files(const char *repo_path, git_repository* repo)
int32_t autocorrect; int32_t autocorrect;
git_config *cfg; git_config *cfg;
git_config *snap_cfg; git_config *snap_cfg;
int error_code;
printf("\n*Config Listing*\n"); printf("\n*Config Listing*\n");
@ -740,9 +741,33 @@ static void config_files(const char *repo_path, git_repository* repo)
git_config_get_string(&email, snap_cfg, "user.email"); git_config_get_string(&email, snap_cfg, "user.email");
printf("Email: %s\n", email); printf("Email: %s\n", email);
/** error_code = git_config_get_int32(&autocorrect, cfg, "help.autocorrect");
* Remember to free the configurations after usage. switch (error_code)
*/ {
case 0:
printf("Autocorrect: %d\n", autocorrect);
break;
case GIT_ENOTFOUND:
printf("Autocorrect: Undefined\n");
break;
default:
check_error(error_code, "get_int32 failed");
}
git_config_free(cfg); git_config_free(cfg);
check_error(git_repository_config_snapshot(&snap_cfg, repo), "config snapshot");
error_code = git_config_get_string(&email, snap_cfg, "user.email");
switch (error_code)
{
case 0:
printf("Email: %s\n", email);
break;
case GIT_ENOTFOUND:
printf("Email: Undefined\n");
break;
default:
check_error(error_code, "get_string failed");
}
git_config_free(snap_cfg); git_config_free(snap_cfg);
} }

View File

@ -50,6 +50,7 @@ static int add_revision(struct log_state *s, const char *revstr);
/** log_options holds other command line options that affect log output */ /** log_options holds other command line options that affect log output */
struct log_options { struct log_options {
int show_diff; int show_diff;
int show_log_size;
int skip, limit; int skip, limit;
int min_parents, max_parents; int min_parents, max_parents;
git_time_t before; git_time_t before;
@ -63,7 +64,7 @@ struct log_options {
static int parse_options( static int parse_options(
struct log_state *s, struct log_options *opt, int argc, char **argv); struct log_state *s, struct log_options *opt, int argc, char **argv);
static void print_time(const git_time *intime, const char *prefix); static void print_time(const git_time *intime, const char *prefix);
static void print_commit(git_commit *commit); static void print_commit(git_commit *commit, struct log_options *opts);
static int match_with_parent(git_commit *commit, int i, git_diff_options *); static int match_with_parent(git_commit *commit, int i, git_diff_options *);
/** utility functions for filtering */ /** utility functions for filtering */
@ -148,7 +149,7 @@ int main(int argc, char *argv[])
break; break;
} }
print_commit(commit); print_commit(commit, &opt);
if (opt.show_diff) { if (opt.show_diff) {
git_tree *a = NULL, *b = NULL; git_tree *a = NULL, *b = NULL;
@ -337,7 +338,7 @@ static void print_time(const git_time *intime, const char *prefix)
} }
/** Helper to print a commit object. */ /** Helper to print a commit object. */
static void print_commit(git_commit *commit) static void print_commit(git_commit *commit, struct log_options *opts)
{ {
char buf[GIT_OID_HEXSZ + 1]; char buf[GIT_OID_HEXSZ + 1];
int i, count; int i, count;
@ -347,6 +348,10 @@ static void print_commit(git_commit *commit)
git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
printf("commit %s\n", buf); printf("commit %s\n", buf);
if (opts->show_log_size) {
printf("log size %d\n", (int)strlen(git_commit_message(commit)));
}
if ((count = (int)git_commit_parentcount(commit)) > 1) { if ((count = (int)git_commit_parentcount(commit)) > 1) {
printf("Merge:"); printf("Merge:");
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
@ -470,6 +475,8 @@ static int parse_options(
/** Found valid --min_parents. */; /** Found valid --min_parents. */;
else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch"))
opt->show_diff = 1; opt->show_diff = 1;
else if (!strcmp(a, "--log-size"))
opt->show_log_size = 1;
else else
usage("Unsupported argument", a); usage("Unsupported argument", a);
} }

396
examples/merge.c Normal file
View File

@ -0,0 +1,396 @@
/*
* libgit2 "merge" example - shows how to perform merges
*
* Written by the libgit2 contributors
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "common.h"
#include <assert.h>
#ifdef _MSC_VER
#define snprintf sprintf_s
#endif
/** The following example demonstrates how to do merges with libgit2.
*
* It will merge whatever commit-ish you pass in into the current branch.
*
* Recognized options are :
* --no-commit: don't actually commit the merge.
*
*/
typedef struct {
const char **heads;
size_t heads_count;
git_annotated_commit **annotated;
size_t annotated_count;
int no_commit : 1;
} merge_options;
static void print_usage(void)
{
fprintf(stderr, "usage: merge [--no-commit] <commit...>\n");
exit(1);
}
static void merge_options_init(merge_options *opts)
{
memset(opts, 0, sizeof(*opts));
opts->heads = NULL;
opts->heads_count = 0;
opts->annotated = NULL;
opts->annotated_count = 0;
}
static void opts_add_refish(merge_options *opts, const char *refish)
{
size_t sz;
assert(opts != NULL);
sz = ++opts->heads_count * sizeof(opts->heads[0]);
opts->heads = xrealloc(opts->heads, sz);
opts->heads[opts->heads_count - 1] = refish;
}
static void parse_options(const char **repo_path, merge_options *opts, int argc, char **argv)
{
struct args_info args = ARGS_INFO_INIT;
if (argc <= 1)
print_usage();
for (args.pos = 1; args.pos < argc; ++args.pos) {
const char *curr = argv[args.pos];
if (curr[0] != '-') {
opts_add_refish(opts, curr);
} else if (!strcmp(curr, "--no-commit")) {
opts->no_commit = 1;
} else if (match_str_arg(repo_path, &args, "--git-dir")) {
continue;
} else {
print_usage();
}
}
}
static int resolve_refish(git_annotated_commit **commit, git_repository *repo, const char *refish)
{
git_reference *ref;
int err = 0;
git_oid oid;
assert(commit != NULL);
err = git_reference_dwim(&ref, repo, refish);
if (err == GIT_OK) {
git_annotated_commit_from_ref(commit, repo, ref);
git_reference_free(ref);
return 0;
}
err = git_oid_fromstr(&oid, refish);
if (err == GIT_OK) {
err = git_annotated_commit_lookup(commit, repo, &oid);
}
return err;
}
static int resolve_heads(git_repository *repo, merge_options *opts)
{
git_annotated_commit **annotated = calloc(opts->heads_count, sizeof(git_annotated_commit *));
size_t annotated_count = 0, i;
int err = 0;
for (i = 0; i < opts->heads_count; i++) {
err = resolve_refish(&annotated[annotated_count++], repo, opts->heads[i]);
if (err != 0) {
fprintf(stderr, "failed to resolve refish %s: %s\n", opts->heads[i], giterr_last()->message);
annotated_count--;
continue;
}
}
if (annotated_count != opts->heads_count) {
fprintf(stderr, "unable to parse some refish\n");
free(annotated);
return -1;
}
opts->annotated = annotated;
opts->annotated_count = annotated_count;
return 0;
}
static int perform_fastforward(git_repository *repo, const git_oid *target_oid, int is_unborn)
{
git_checkout_options ff_checkout_options = GIT_CHECKOUT_OPTIONS_INIT;
git_reference *target_ref;
git_reference *new_target_ref;
git_object *target = NULL;
int err = 0;
if (is_unborn) {
const char *symbolic_ref;
git_reference *head_ref;
/* HEAD reference is unborn, lookup manually so we don't try to resolve it */
err = git_reference_lookup(&head_ref, repo, "HEAD");
if (err != 0) {
fprintf(stderr, "failed to lookup HEAD ref\n");
return -1;
}
/* Grab the reference HEAD should be pointing to */
symbolic_ref = git_reference_symbolic_target(head_ref);
/* Create our master reference on the target OID */
err = git_reference_create(&target_ref, repo, symbolic_ref, target_oid, 0, NULL);
if (err != 0) {
fprintf(stderr, "failed to create master reference\n");
return -1;
}
git_reference_free(head_ref);
} else {
/* HEAD exists, just lookup and resolve */
err = git_repository_head(&target_ref, repo);
if (err != 0) {
fprintf(stderr, "failed to get HEAD reference\n");
return -1;
}
}
/* Lookup the target object */
err = git_object_lookup(&target, repo, target_oid, GIT_OBJ_COMMIT);
if (err != 0) {
fprintf(stderr, "failed to lookup OID %s\n", git_oid_tostr_s(target_oid));
return -1;
}
/* Checkout the result so the workdir is in the expected state */
ff_checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
err = git_checkout_tree(repo, target, &ff_checkout_options);
if (err != 0) {
fprintf(stderr, "failed to checkout HEAD reference\n");
return -1;
}
/* Move the target reference to the target OID */
err = git_reference_set_target(&new_target_ref, target_ref, target_oid, NULL);
if (err != 0) {
fprintf(stderr, "failed to move HEAD reference\n");
return -1;
}
git_reference_free(target_ref);
git_reference_free(new_target_ref);
git_object_free(target);
return 0;
}
static void output_conflicts(git_index *index)
{
git_index_conflict_iterator *conflicts;
const git_index_entry *ancestor;
const git_index_entry *our;
const git_index_entry *their;
int err = 0;
check_lg2(git_index_conflict_iterator_new(&conflicts, index), "failed to create conflict iterator", NULL);
while ((err = git_index_conflict_next(&ancestor, &our, &their, conflicts)) == 0) {
fprintf(stderr, "conflict: a:%s o:%s t:%s\n",
ancestor ? ancestor->path : "NULL",
our->path ? our->path : "NULL",
their->path ? their->path : "NULL");
}
if (err != GIT_ITEROVER) {
fprintf(stderr, "error iterating conflicts\n");
}
git_index_conflict_iterator_free(conflicts);
}
static int create_merge_commit(git_repository *repo, git_index *index, merge_options *opts)
{
git_oid tree_oid, commit_oid;
git_tree *tree;
git_signature *sign;
git_reference *merge_ref = NULL;
git_annotated_commit *merge_commit;
git_reference *head_ref;
git_commit **parents = calloc(opts->annotated_count + 1, sizeof(git_commit *));
const char *msg_target = NULL;
size_t msglen = 0;
char *msg;
size_t i;
int err;
/* Grab our needed references */
check_lg2(git_repository_head(&head_ref, repo), "failed to get repo HEAD", NULL);
if (resolve_refish(&merge_commit, repo, opts->heads[0])) {
fprintf(stderr, "failed to resolve refish %s", opts->heads[0]);
return -1;
}
/* Maybe that's a ref, so DWIM it */
err = git_reference_dwim(&merge_ref, repo, opts->heads[0]);
check_lg2(err, "failed to DWIM reference", giterr_last()->message);
/* Grab a signature */
check_lg2(git_signature_now(&sign, "Me", "me@example.com"), "failed to create signature", NULL);
#define MERGE_COMMIT_MSG "Merge %s '%s'"
/* Prepare a standard merge commit message */
if (merge_ref != NULL) {
check_lg2(git_branch_name(&msg_target, merge_ref), "failed to get branch name of merged ref", NULL);
} else {
msg_target = git_oid_tostr_s(git_annotated_commit_id(merge_commit));
}
msglen = snprintf(NULL, 0, MERGE_COMMIT_MSG, (merge_ref ? "branch" : "commit"), msg_target);
if (msglen > 0) msglen++;
msg = malloc(msglen);
err = snprintf(msg, msglen, MERGE_COMMIT_MSG, (merge_ref ? "branch" : "commit"), msg_target);
/* This is only to silence the compiler */
if (err < 0) goto cleanup;
/* Setup our parent commits */
err = git_reference_peel((git_object **)&parents[0], head_ref, GIT_OBJ_COMMIT);
check_lg2(err, "failed to peel head reference", NULL);
for (i = 0; i < opts->annotated_count; i++) {
git_commit_lookup(&parents[i + 1], repo, git_annotated_commit_id(opts->annotated[i]));
}
/* Prepare our commit tree */
check_lg2(git_index_write_tree(&tree_oid, index), "failed to write merged tree", NULL);
check_lg2(git_tree_lookup(&tree, repo, &tree_oid), "failed to lookup tree", NULL);
/* Commit time ! */
err = git_commit_create(&commit_oid,
repo, git_reference_name(head_ref),
sign, sign,
NULL, msg,
tree,
opts->annotated_count + 1, (const git_commit **)parents);
check_lg2(err, "failed to create commit", NULL);
/* We're done merging, cleanup the repository state */
git_repository_state_cleanup(repo);
cleanup:
free(parents);
return err;
}
int main(int argc, char **argv)
{
git_repository *repo = NULL;
merge_options opts;
git_index *index;
git_repository_state_t state;
git_merge_analysis_t analysis;
git_merge_preference_t preference;
const char *path = ".";
int err = 0;
merge_options_init(&opts);
parse_options(&path, &opts, argc, argv);
git_libgit2_init();
check_lg2(git_repository_open_ext(&repo, path, 0, NULL),
"Could not open repository", NULL);
state = git_repository_state(repo);
if (state != GIT_REPOSITORY_STATE_NONE) {
fprintf(stderr, "repository is in unexpected state %d\n", state);
goto cleanup;
}
err = resolve_heads(repo, &opts);
if (err != 0)
goto cleanup;
err = git_merge_analysis(&analysis, &preference,
repo,
(const git_annotated_commit **)opts.annotated,
opts.annotated_count);
check_lg2(err, "merge analysis failed", NULL);
if (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) {
printf("Already up-to-date\n");
return 0;
} else if (analysis & GIT_MERGE_ANALYSIS_UNBORN ||
(analysis & GIT_MERGE_ANALYSIS_FASTFORWARD &&
!(preference & GIT_MERGE_PREFERENCE_NO_FASTFORWARD))) {
const git_oid *target_oid;
if (analysis & GIT_MERGE_ANALYSIS_UNBORN) {
printf("Unborn\n");
} else {
printf("Fast-forward\n");
}
/* Since this is a fast-forward, there can be only one merge head */
target_oid = git_annotated_commit_id(opts.annotated[0]);
assert(opts.annotated_count == 1);
return perform_fastforward(repo, target_oid, (analysis & GIT_MERGE_ANALYSIS_UNBORN));
} else if (analysis & GIT_MERGE_ANALYSIS_NORMAL) {
git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
merge_opts.flags = 0;
merge_opts.file_flags = GIT_MERGE_FILE_STYLE_DIFF3;
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE|GIT_CHECKOUT_ALLOW_CONFLICTS;
if (preference & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY) {
printf("Fast-forward is preferred, but only a merge is possible\n");
return -1;
}
err = git_merge(repo,
(const git_annotated_commit **)opts.annotated, opts.annotated_count,
&merge_opts, &checkout_opts);
check_lg2(err, "merge failed", NULL);
}
/* If we get here, we actually performed the merge above */
check_lg2(git_repository_index(&index, repo), "failed to get repository index", NULL);
if (git_index_has_conflicts(index)) {
/* Handle conflicts */
output_conflicts(index);
} else if (!opts.no_commit) {
create_merge_commit(repo, index, &opts);
printf("Merge made\n");
}
cleanup:
free(opts.heads);
free(opts.annotated);
git_repository_free(repo);
git_libgit2_shutdown();
return 0;
}

View File

@ -16,6 +16,43 @@
# define UNUSED(x) x # define UNUSED(x) x
#endif #endif
static int readline(char **out)
{
int c, error = 0, length = 0, allocated = 0;
char *line = NULL;
errno = 0;
while ((c = getchar()) != EOF) {
if (length == allocated) {
allocated += 16;
if ((line = realloc(line, allocated)) == NULL) {
error = -1;
goto error;
}
}
if (c == '\n')
break;
line[length++] = c;
}
if (errno != 0) {
error = -1;
goto error;
}
line[length] = '\0';
*out = line;
line = NULL;
error = length;
error:
free(line);
return error;
}
int cred_acquire_cb(git_cred **out, int cred_acquire_cb(git_cred **out,
const char * UNUSED(url), const char * UNUSED(url),
const char * UNUSED(username_from_url), const char * UNUSED(username_from_url),
@ -26,14 +63,14 @@ int cred_acquire_cb(git_cred **out,
int error; int error;
printf("Username: "); printf("Username: ");
if (getline(&username, NULL, stdin) < 0) { if (readline(&username) < 0) {
fprintf(stderr, "Unable to read username: %s", strerror(errno)); fprintf(stderr, "Unable to read username: %s", strerror(errno));
return -1; return -1;
} }
/* Yup. Right there on your terminal. Careful where you copy/paste output. */ /* Yup. Right there on your terminal. Careful where you copy/paste output. */
printf("Password: "); printf("Password: ");
if (getline(&password, NULL, stdin) < 0) { if (readline(&password) < 0) {
fprintf(stderr, "Unable to read password: %s", strerror(errno)); fprintf(stderr, "Unable to read password: %s", strerror(errno));
free(username); free(username);
return -1; return -1;

View File

@ -8,13 +8,6 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
struct dl_data {
git_remote *remote;
git_fetch_options *fetch_opts;
int ret;
int finished;
};
static int progress_cb(const char *str, int len, void *data) static int progress_cb(const char *str, int len, void *data)
{ {
(void)data; (void)data;

View File

@ -2,10 +2,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../common.h"
#include "common.h" #include "common.h"
// This part is not strictly libgit2-dependent, but you can use this /* This part is not strictly libgit2-dependent, but you can use this
// as a starting point for a git-like tool * as a starting point for a git-like tool */
struct { struct {
char *name; char *name;
@ -18,20 +19,12 @@ struct {
{ NULL, NULL} { NULL, NULL}
}; };
static int run_command(git_cb fn, int argc, char **argv) static int run_command(git_cb fn, git_repository *repo, struct args_info args)
{ {
int error; int error;
git_repository *repo;
// Before running the actual command, create an instance of the local /* Run the command. If something goes wrong, print the error message to stderr */
// repository and pass it to the function. error = fn(repo, args.argc - args.pos, &args.argv[args.pos]);
error = git_repository_open(&repo, ".git");
if (error < 0)
repo = NULL;
// Run the command. If something goes wrong, print the error message to stderr
error = fn(repo, argc, argv);
if (error < 0) { if (error < 0) {
if (giterr_last() == NULL) if (giterr_last() == NULL)
fprintf(stderr, "Error without message"); fprintf(stderr, "Error without message");
@ -39,9 +32,6 @@ static int run_command(git_cb fn, int argc, char **argv)
fprintf(stderr, "Bad news:\n %s\n", giterr_last()->message); fprintf(stderr, "Bad news:\n %s\n", giterr_last()->message);
} }
if(repo)
git_repository_free(repo);
return !!error; return !!error;
} }
@ -49,6 +39,10 @@ int main(int argc, char **argv)
{ {
int i; int i;
int return_code = 1; int return_code = 1;
int error;
git_repository *repo;
struct args_info args = ARGS_INFO_INIT;
const char *git_dir = NULL;
if (argc < 2) { if (argc < 2) {
fprintf(stderr, "usage: %s <cmd> [repo]\n", argv[0]); fprintf(stderr, "usage: %s <cmd> [repo]\n", argv[0]);
@ -57,9 +51,30 @@ int main(int argc, char **argv)
git_libgit2_init(); git_libgit2_init();
for (args.pos = 1; args.pos < args.argc; ++args.pos) {
char *a = args.argv[args.pos];
if (a[0] != '-') {
/* non-arg */
break;
} else if (optional_str_arg(&git_dir, &args, "--git-dir", ".git")) {
continue;
} else if (!strcmp(a, "--")) {
/* arg separator */
break;
}
}
/* Before running the actual command, create an instance of the local
* repository and pass it to the function. */
error = git_repository_open(&repo, git_dir);
if (error < 0)
repo = NULL;
for (i = 0; commands[i].name != NULL; ++i) { for (i = 0; commands[i].name != NULL; ++i) {
if (!strcmp(argv[1], commands[i].name)) { if (!strcmp(args.argv[args.pos], commands[i].name)) {
return_code = run_command(commands[i].fn, --argc, ++argv); return_code = run_command(commands[i].fn, repo, args);
goto shutdown; goto shutdown;
} }
} }
@ -67,6 +82,8 @@ int main(int argc, char **argv)
fprintf(stderr, "Command not found: %s\n", argv[1]); fprintf(stderr, "Command not found: %s\n", argv[1]);
shutdown: shutdown:
git_repository_free(repo);
git_libgit2_shutdown(); git_libgit2_shutdown();
return return_code; return return_code;

View File

@ -53,6 +53,7 @@ ok Jeff King <peff@peff.net>
ok Johannes Schindelin <Johannes.Schindelin@gmx.de> ok Johannes Schindelin <Johannes.Schindelin@gmx.de>
ok Johannes Sixt <j6t@kdbg.org> ok Johannes Sixt <j6t@kdbg.org>
ask Jonathan Nieder <jrnieder@gmail.com> ask Jonathan Nieder <jrnieder@gmail.com>
ok Jonathan Tan <jonathantanmy@google.com>
ok Junio C Hamano <gitster@pobox.com> ok Junio C Hamano <gitster@pobox.com>
ok Kristian Høgsberg <krh@redhat.com> ok Kristian Høgsberg <krh@redhat.com>
ok Linus Torvalds <torvalds@linux-foundation.org> ok Linus Torvalds <torvalds@linux-foundation.org>

View File

@ -62,5 +62,6 @@
#include "git2/tree.h" #include "git2/tree.h"
#include "git2/types.h" #include "git2/types.h"
#include "git2/version.h" #include "git2/version.h"
#include "git2/worktree.h"
#endif #endif

View File

@ -199,6 +199,8 @@ GIT_EXTERN(int) git_config_new(git_config **out);
* @param path path to the configuration file to add * @param path path to the configuration file to add
* @param level the priority level of the backend * @param level the priority level of the backend
* @param force replace config file at the given priority level * @param force replace config file at the given priority level
* @param repo optional repository to allow parsing of
* conditional includes
* @return 0 on success, GIT_EEXISTS when adding more than one file * @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0), * for a given priority level (and force_replace set to 0),
* GIT_ENOTFOUND when the file doesn't exist or error code * GIT_ENOTFOUND when the file doesn't exist or error code
@ -207,6 +209,7 @@ GIT_EXTERN(int) git_config_add_file_ondisk(
git_config *cfg, git_config *cfg,
const char *path, const char *path,
git_config_level_t level, git_config_level_t level,
const git_repository *repo,
int force); int force);
/** /**
@ -398,6 +401,10 @@ GIT_EXTERN(int) git_config_get_string_buf(git_buf *out, const git_config *cfg, c
* *
* The callback will be called on each variable found * The callback will be called on each variable found
* *
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the section and variable parts are lower-cased. The
* subsection is left unchanged.
*
* @param cfg where to look for the variable * @param cfg where to look for the variable
* @param name the variable's name * @param name the variable's name
* @param regexp regular expression to filter which variables we're * @param regexp regular expression to filter which variables we're
@ -410,6 +417,10 @@ GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const cha
/** /**
* Get each value of a multivar * Get each value of a multivar
* *
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the section and variable parts are lower-cased. The
* subsection is left unchanged.
*
* @param out pointer to store the iterator * @param out pointer to store the iterator
* @param cfg where to look for the variable * @param cfg where to look for the variable
* @param name the variable's name * @param name the variable's name
@ -487,6 +498,8 @@ GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const c
/** /**
* Set a multivar in the local config file. * Set a multivar in the local config file.
* *
* The regular expression is applied case-sensitively on the value.
*
* @param cfg where to look for the variable * @param cfg where to look for the variable
* @param name the variable's name * @param name the variable's name
* @param regexp a regular expression to indicate which values to replace * @param regexp a regular expression to indicate which values to replace
@ -506,6 +519,8 @@ GIT_EXTERN(int) git_config_delete_entry(git_config *cfg, const char *name);
/** /**
* Deletes one or several entries from a multivar in the local config file. * Deletes one or several entries from a multivar in the local config file.
* *
* The regular expression is applied case-sensitively on the value.
*
* @param cfg where to look for the variables * @param cfg where to look for the variables
* @param name the variable's name * @param name the variable's name
* @param regexp a regular expression to indicate which values to delete * @param regexp a regular expression to indicate which values to delete
@ -552,6 +567,10 @@ GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_con
* Use `git_config_next` to advance the iteration and * Use `git_config_next` to advance the iteration and
* `git_config_iterator_free` when done. * `git_config_iterator_free` when done.
* *
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the section and variable parts are lower-cased. The
* subsection is left unchanged.
*
* @param out pointer to store the iterator * @param out pointer to store the iterator
* @param cfg where to ge the variables from * @param cfg where to ge the variables from
* @param regexp regular expression to match the names * @param regexp regular expression to match the names
@ -565,8 +584,12 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi
* regular expression that filters which config keys are passed to the * regular expression that filters which config keys are passed to the
* callback. * callback.
* *
* The pointers passed to the callback are only valid as long as the * The regular expression is applied case-sensitively on the normalized form of
* iteration is ongoing. * the variable name: the section and variable parts are lower-cased. The
* subsection is left unchanged.
*
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the case-insensitive parts are lower-case.
* *
* @param cfg where to get the variables from * @param cfg where to get the variables from
* @param regexp regular expression to match against config names * @param regexp regular expression to match against config names
@ -693,6 +716,10 @@ GIT_EXTERN(int) git_config_parse_path(git_buf *out, const char *value);
* This behaviors like `git_config_foreach_match` except instead of all config * This behaviors like `git_config_foreach_match` except instead of all config
* entries it just enumerates through the given backend entry. * entries it just enumerates through the given backend entry.
* *
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the section and variable parts are lower-cased. The
* subsection is left unchanged.
*
* @param backend where to get the variables from * @param backend where to get the variables from
* @param regexp regular expression to match against config names (can be NULL) * @param regexp regular expression to match against config names (can be NULL)
* @param callback the function to call on each variable * @param callback the function to call on each variable

View File

@ -23,7 +23,7 @@ GIT_BEGIN_DECL
/** /**
* Reference lookup strategy * Reference lookup strategy
* *
* These behave like the --tags and --all optios to git-describe, * These behave like the --tags and --all options to git-describe,
* namely they say to look for any reference in either refs/tags/ or * namely they say to look for any reference in either refs/tags/ or
* refs/ respectively. * refs/ respectively.
*/ */

View File

@ -200,12 +200,18 @@ typedef enum {
/** Use the "patience diff" algorithm */ /** Use the "patience diff" algorithm */
GIT_DIFF_PATIENCE = (1u << 28), GIT_DIFF_PATIENCE = (1u << 28),
/** Take extra time to find minimal diff */ /** Take extra time to find minimal diff */
GIT_DIFF_MINIMAL = (1 << 29), GIT_DIFF_MINIMAL = (1u << 29),
/** Include the necessary deflate / delta information so that `git-apply` /** Include the necessary deflate / delta information so that `git-apply`
* can apply given diff information to binary files. * can apply given diff information to binary files.
*/ */
GIT_DIFF_SHOW_BINARY = (1 << 30), GIT_DIFF_SHOW_BINARY = (1u << 30),
/** Use a heuristic that takes indentation and whitespace into account
* which generally can produce better diffs when dealing with ambiguous
* diff hunks.
*/
GIT_DIFF_INDENT_HEURISTIC = (1u << 31),
} git_diff_option_t; } git_diff_option_t;
/** /**
@ -515,12 +521,12 @@ typedef int(*git_diff_binary_cb)(
* Structure describing a hunk of a diff. * Structure describing a hunk of a diff.
*/ */
typedef struct { typedef struct {
int old_start; /** Starting line number in old_file */ int old_start; /**< Starting line number in old_file */
int old_lines; /** Number of lines in old_file */ int old_lines; /**< Number of lines in old_file */
int new_start; /** Starting line number in new_file */ int new_start; /**< Starting line number in new_file */
int new_lines; /** Number of lines in new_file */ int new_lines; /**< Number of lines in new_file */
size_t header_len; /** Number of bytes in header text */ size_t header_len; /**< Number of bytes in header text */
char header[GIT_DIFF_HUNK_HEADER_SIZE]; /** Header text, NUL-byte terminated */ char header[GIT_DIFF_HUNK_HEADER_SIZE]; /**< Header text, NUL-byte terminated */
} git_diff_hunk; } git_diff_hunk;
/** /**
@ -1400,6 +1406,51 @@ GIT_EXTERN(int) git_diff_format_email_init_options(
git_diff_format_email_options *opts, git_diff_format_email_options *opts,
unsigned int version); unsigned int version);
/**
* Patch ID options structure
*
* Initialize with `GIT_DIFF_PATCHID_OPTIONS_INIT` macro to
* correctly set the default values and version.
*/
typedef struct git_diff_patchid_options {
unsigned int version;
} git_diff_patchid_options;
#define GIT_DIFF_PATCHID_OPTIONS_VERSION 1
#define GIT_DIFF_PATCHID_OPTIONS_INIT { GIT_DIFF_PATCHID_OPTIONS_VERSION }
/**
* Initialize `git_diff_patchid_options` structure.
*
* Initializes the structure with default values. Equivalent to
* creating an instance with `GIT_DIFF_PATCHID_OPTIONS_INIT`.
*/
GIT_EXTERN(int) git_diff_patchid_init_options(
git_diff_patchid_options *opts,
unsigned int version);
/**
* Calculate the patch ID for the given patch.
*
* Calculate a stable patch ID for the given patch by summing the
* hash of the file diffs, ignoring whitespace and line numbers.
* This can be used to derive whether two diffs are the same with
* a high probability.
*
* Currently, this function only calculates stable patch IDs, as
* defined in git-patch-id(1), and should in fact generate the
* same IDs as the upstream git project does.
*
* @param out Pointer where the calculated patch ID shoul be
* stored
* @param diff The diff to calculate the ID for
* @param opts Options for how to calculate the patch ID. This is
* intended for future changes, as currently no options are
* available.
* @return 0 on success, an error code otherwise.
*/
GIT_EXTERN(int) git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts);
GIT_END_DECL GIT_END_DECL
/** @} */ /** @} */

View File

@ -40,6 +40,9 @@ GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_reposi
/** /**
* Determine if a commit is the descendant of another commit. * Determine if a commit is the descendant of another commit.
* *
* Note that a commit is not considered a descendant of itself, in contrast
* to `git merge-base --is-ancestor`.
*
* @param commit a previously loaded commit. * @param commit a previously loaded commit.
* @param ancestor a potential ancestor commit. * @param ancestor a potential ancestor commit.
* @return 1 if the given commit is a descendant of the potential ancestor, * @return 1 if the given commit is a descendant of the potential ancestor,

View File

@ -162,6 +162,8 @@ typedef enum {
GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7), GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7),
} git_merge_file_flag_t; } git_merge_file_flag_t;
#define GIT_MERGE_CONFLICT_MARKER_SIZE 7
/** /**
* Options for merging a file * Options for merging a file
*/ */
@ -191,6 +193,10 @@ typedef struct {
/** see `git_merge_file_flag_t` above */ /** see `git_merge_file_flag_t` above */
git_merge_file_flag_t flags; git_merge_file_flag_t flags;
/** The size of conflict markers (eg, "<<<<<<<"). Default is
* GIT_MERGE_CONFLICT_MARKER_SIZE. */
unsigned short marker_size;
} git_merge_file_options; } git_merge_file_options;
#define GIT_MERGE_FILE_OPTIONS_VERSION 1 #define GIT_MERGE_FILE_OPTIONS_VERSION 1

View File

@ -19,10 +19,9 @@
GIT_BEGIN_DECL GIT_BEGIN_DECL
/** /**
* Clean up message from excess whitespace and make sure that the last line * Clean up excess whitespace and make sure there is a trailing newline in the message.
* ends with a '\n'.
* *
* Optionally, can remove lines starting with a "#". * Optionally, it can remove lines which start with the comment character.
* *
* @param out The user-allocated git_buf which will be filled with the * @param out The user-allocated git_buf which will be filled with the
* cleaned up message. * cleaned up message.
@ -38,6 +37,47 @@ GIT_BEGIN_DECL
*/ */
GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char); GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char);
/**
* Represents a single git message trailer.
*/
typedef struct {
const char *key;
const char *value;
} git_message_trailer;
/**
* Represents an array of git message trailers.
*
* Struct members under the private comment are private, subject to change
* and should not be used by callers.
*/
typedef struct {
git_message_trailer *trailers;
size_t count;
/* private */
char *_trailer_block;
} git_message_trailer_array;
/**
* Parse trailers out of a message, filling the array pointed to by +arr+.
*
* Trailers are key/value pairs in the last paragraph of a message, not
* including any patches or conflicts that may be present.
*
* @param arr A pre-allocated git_message_trailer_array struct to be filled in
* with any trailers found during parsing.
* @param message The message to be parsed
* @return 0 on success, or non-zero on error.
*/
GIT_EXTERN(int) git_message_trailers(git_message_trailer_array *arr, const char *message);
/**
* Clean's up any allocated memory in the git_message_trailer_array filled by
* a call to git_message_trailers.
*/
GIT_EXTERN(void) git_message_trailer_array_free(git_message_trailer_array *arr);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL

View File

@ -51,6 +51,20 @@ GIT_EXTERN(int) git_note_iterator_new(
git_repository *repo, git_repository *repo,
const char *notes_ref); const char *notes_ref);
/**
* Creates a new iterator for notes from a commit
*
* The iterator must be freed manually by the user.
*
* @param out pointer to the iterator
* @param notes_commit a pointer to the notes commit object
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_note_commit_iterator_new(
git_note_iterator **out,
git_commit *notes_commit);
/** /**
* Frees an git_note_iterator * Frees an git_note_iterator
* *
@ -94,6 +108,25 @@ GIT_EXTERN(int) git_note_read(
const char *notes_ref, const char *notes_ref,
const git_oid *oid); const git_oid *oid);
/**
* Read the note for an object from a note commit
*
* The note must be freed manually by the user.
*
* @param out pointer to the read note; NULL in case of error
* @param repo repository where to look up the note
* @param notes_commit a pointer to the notes commit object
* @param oid OID of the git object to read the note from
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_note_commit_read(
git_note **out,
git_repository *repo,
git_commit *notes_commit,
const git_oid *oid);
/** /**
* Get the note author * Get the note author
* *
@ -153,6 +186,36 @@ GIT_EXTERN(int) git_note_create(
const char *note, const char *note,
int force); int force);
/**
* Add a note for an object from a commit
*
* This function will create a notes commit for a given object,
* the commit is a dangling commit, no reference is created.
*
* @param notes_commit_out pointer to store the commit (optional);
* NULL in case of error
* @param notes_blob_out a point to the id of a note blob (optional)
* @param repo repository where the note will live
* @param parent Pointer to parent note
* or NULL if this shall start a new notes tree
* @param author signature of the notes commit author
* @param committer signature of the notes commit committer
* @param oid OID of the git object to decorate
* @param note Content of the note to add for object oid
* @param allow_note_overwrite Overwrite existing note
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_note_commit_create(
git_oid *notes_commit_out,
git_oid *notes_blob_out,
git_repository *repo,
git_commit *parent,
const git_signature *author,
const git_signature *committer,
const git_oid *oid,
const char *note,
int allow_note_overwrite);
/** /**
* Remove the note for an object * Remove the note for an object
@ -173,6 +236,32 @@ GIT_EXTERN(int) git_note_remove(
const git_signature *committer, const git_signature *committer,
const git_oid *oid); const git_oid *oid);
/**
* Remove the note for an object
*
* @param notes_commit_out pointer to store the new notes commit (optional);
* NULL in case of error.
* When removing a note a new tree containing all notes
* sans the note to be removed is created and a new commit
* pointing to that tree is also created.
* In the case where the resulting tree is an empty tree
* a new commit pointing to this empty tree will be returned.
* @param repo repository where the note lives
* @param notes_commit a pointer to the notes commit object
* @param author signature of the notes commit author
* @param committer signature of the notes commit committer
* @param oid OID of the git object to remove the note from
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_note_commit_remove(
git_oid *notes_commit_out,
git_repository *repo,
git_commit *notes_commit,
const git_signature *author,
const git_signature *committer,
const git_oid *oid);
/** /**
* Free a git_note object * Free a git_note object
* *

View File

@ -357,11 +357,18 @@ GIT_EXTERN(void) git_odb_stream_free(git_odb_stream *stream);
* @see git_odb_stream * @see git_odb_stream
* *
* @param out pointer where to store the stream * @param out pointer where to store the stream
* @param len pointer where to store the length of the object
* @param type pointer where to store the type of the object
* @param db object database where the stream will read from * @param db object database where the stream will read from
* @param oid oid of the object the stream will read from * @param oid oid of the object the stream will read from
* @return 0 if the stream was created; error code otherwise * @return 0 if the stream was created; error code otherwise
*/ */
GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const git_oid *oid); GIT_EXTERN(int) git_odb_open_rstream(
git_odb_stream **out,
size_t *len,
git_otype *type,
git_odb *db,
const git_oid *oid);
/** /**
* Open a stream for writing a pack file to the ODB. * Open a stream for writing a pack file to the ODB.

View File

@ -96,7 +96,7 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer(
git_patch **out, git_patch **out,
const git_blob *old_blob, const git_blob *old_blob,
const char *old_as_path, const char *old_as_path,
const char *buffer, const void *buffer,
size_t buffer_len, size_t buffer_len,
const char *buffer_as_path, const char *buffer_as_path,
const git_diff_options *opts); const git_diff_options *opts);
@ -124,7 +124,7 @@ GIT_EXTERN(int) git_patch_from_buffers(
const void *old_buffer, const void *old_buffer,
size_t old_len, size_t old_len,
const char *old_as_path, const char *old_as_path,
const char *new_buffer, const void *new_buffer,
size_t new_len, size_t new_len,
const char *new_as_path, const char *new_as_path,
const git_diff_options *opts); const git_diff_options *opts);

View File

@ -26,32 +26,49 @@ typedef struct git_pathspec_match_list git_pathspec_match_list;
/** /**
* Options controlling how pathspec match should be executed * Options controlling how pathspec match should be executed
* */
* - GIT_PATHSPEC_IGNORE_CASE forces match to ignore case; otherwise typedef enum {
GIT_PATHSPEC_DEFAULT = 0,
/**
* GIT_PATHSPEC_IGNORE_CASE forces match to ignore case; otherwise
* match will use native case sensitivity of platform filesystem * match will use native case sensitivity of platform filesystem
* - GIT_PATHSPEC_USE_CASE forces case sensitive match; otherwise */
GIT_PATHSPEC_IGNORE_CASE = (1u << 0),
/**
* GIT_PATHSPEC_USE_CASE forces case sensitive match; otherwise
* match will use native case sensitivity of platform filesystem * match will use native case sensitivity of platform filesystem
* - GIT_PATHSPEC_NO_GLOB disables glob patterns and just uses simple */
GIT_PATHSPEC_USE_CASE = (1u << 1),
/**
* GIT_PATHSPEC_NO_GLOB disables glob patterns and just uses simple
* string comparison for matching * string comparison for matching
* - GIT_PATHSPEC_NO_MATCH_ERROR means the match functions return error */
GIT_PATHSPEC_NO_GLOB = (1u << 2),
/**
* GIT_PATHSPEC_NO_MATCH_ERROR means the match functions return error
* code GIT_ENOTFOUND if no matches are found; otherwise no matches is * code GIT_ENOTFOUND if no matches are found; otherwise no matches is
* still success (return 0) but `git_pathspec_match_list_entrycount` * still success (return 0) but `git_pathspec_match_list_entrycount`
* will indicate 0 matches. * will indicate 0 matches.
* - GIT_PATHSPEC_FIND_FAILURES means that the `git_pathspec_match_list` */
GIT_PATHSPEC_NO_MATCH_ERROR = (1u << 3),
/**
* GIT_PATHSPEC_FIND_FAILURES means that the `git_pathspec_match_list`
* should track which patterns matched which files so that at the end of * should track which patterns matched which files so that at the end of
* the match we can identify patterns that did not match any files. * the match we can identify patterns that did not match any files.
* - GIT_PATHSPEC_FAILURES_ONLY means that the `git_pathspec_match_list` */
GIT_PATHSPEC_FIND_FAILURES = (1u << 4),
/**
* GIT_PATHSPEC_FAILURES_ONLY means that the `git_pathspec_match_list`
* does not need to keep the actual matching filenames. Use this to * does not need to keep the actual matching filenames. Use this to
* just test if there were any matches at all or in combination with * just test if there were any matches at all or in combination with
* GIT_PATHSPEC_FIND_FAILURES to validate a pathspec. * GIT_PATHSPEC_FIND_FAILURES to validate a pathspec.
*/ */
typedef enum {
GIT_PATHSPEC_DEFAULT = 0,
GIT_PATHSPEC_IGNORE_CASE = (1u << 0),
GIT_PATHSPEC_USE_CASE = (1u << 1),
GIT_PATHSPEC_NO_GLOB = (1u << 2),
GIT_PATHSPEC_NO_MATCH_ERROR = (1u << 3),
GIT_PATHSPEC_FIND_FAILURES = (1u << 4),
GIT_PATHSPEC_FAILURES_ONLY = (1u << 5), GIT_PATHSPEC_FAILURES_ONLY = (1u << 5),
} git_pathspec_flag_t; } git_pathspec_flag_t;

View File

@ -433,6 +433,9 @@ typedef int (*git_reference_foreach_name_cb)(const char *name, void *payload);
* passed to this method. Returning a non-zero value from the callback * passed to this method. Returning a non-zero value from the callback
* will terminate the iteration. * will terminate the iteration.
* *
* Note that the callback function is responsible to call `git_reference_free`
* on each reference passed to it.
*
* @param repo Repository where to find the refs * @param repo Repository where to find the refs
* @param callback Function which will be called for every listed ref * @param callback Function which will be called for every listed ref
* @param payload Additional data to pass to the callback * @param payload Additional data to pass to the callback

View File

@ -75,6 +75,24 @@ GIT_EXTERN(int) git_remote_create_anonymous(
git_repository *repo, git_repository *repo,
const char *url); const char *url);
/**
* Create a remote without a connected local repo
*
* Create a remote with the given url in-memory. You can use this when
* you have a URL instead of a remote's name.
*
* Contrasted with git_remote_create_anonymous, a detached remote
* will not consider any repo configuration values (such as insteadof url
* substitutions).
*
* @param out pointer to the new remote objects
* @param url the remote repository's URL
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_create_detached(
git_remote **out,
const char *url);
/** /**
* Get the information for a particular remote * Get the information for a particular remote
* *
@ -367,6 +385,20 @@ typedef struct {
*/ */
typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload); typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload);
/**
* Callback used to inform of the update status from the remote.
*
* Called for each updated reference on push. If `status` is
* not `NULL`, the update was rejected by the remote server
* and `status` contains the reason given.
*
* @param refname refname specifying to the remote ref
* @param status status message sent from the remote
* @param data data provided by the caller
* @return 0 on success, otherwise an error
*/
typedef int (*git_push_update_reference_cb)(const char *refname, const char *status, void *data);
/** /**
* The callback settings structure * The callback settings structure
* *
@ -434,11 +466,9 @@ struct git_remote_callbacks {
git_push_transfer_progress push_transfer_progress; git_push_transfer_progress push_transfer_progress;
/** /**
* Called for each updated reference on push. If `status` is * See documentation of git_push_update_reference_cb
* not `NULL`, the update was rejected by the remote server
* and `status` contains the reason given.
*/ */
int (*push_update_reference)(const char *refname, const char *status, void *data); git_push_update_reference_cb push_update_reference;
/** /**
* Called once between the negotiation step and the upload. It * Called once between the negotiation step and the upload. It

View File

@ -440,7 +440,7 @@ typedef enum {
* @param item The repository item for which to retrieve the path * @param item The repository item for which to retrieve the path
* @return 0, GIT_ENOTFOUND if the path cannot exist or an error code * @return 0, GIT_ENOTFOUND if the path cannot exist or an error code
*/ */
GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item); GIT_EXTERN(int) git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item);
/** /**
* Get the path of this repository * Get the path of this repository
@ -451,7 +451,7 @@ GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git
* @param repo A repository object * @param repo A repository object
* @return the path to the repository * @return the path to the repository
*/ */
GIT_EXTERN(const char *) git_repository_path(git_repository *repo); GIT_EXTERN(const char *) git_repository_path(const git_repository *repo);
/** /**
* Get the path of the working directory for this repository * Get the path of the working directory for this repository
@ -462,7 +462,7 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
* @param repo A repository object * @param repo A repository object
* @return the path to the working dir, if it exists * @return the path to the working dir, if it exists
*/ */
GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo); GIT_EXTERN(const char *) git_repository_workdir(const git_repository *repo);
/** /**
* Get the path of the shared common directory for this repository * Get the path of the shared common directory for this repository
@ -473,7 +473,7 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
* @param repo A repository object * @param repo A repository object
* @return the path to the common dir * @return the path to the common dir
*/ */
GIT_EXTERN(const char *) git_repository_commondir(git_repository *repo); GIT_EXTERN(const char *) git_repository_commondir(const git_repository *repo);
/** /**
* Set the path to the working directory for this repository * Set the path to the working directory for this repository
@ -501,7 +501,7 @@ GIT_EXTERN(int) git_repository_set_workdir(
* @param repo Repo to test * @param repo Repo to test
* @return 1 if the repository is bare, 0 otherwise. * @return 1 if the repository is bare, 0 otherwise.
*/ */
GIT_EXTERN(int) git_repository_is_bare(git_repository *repo); GIT_EXTERN(int) git_repository_is_bare(const git_repository *repo);
/** /**
* Check if a repository is a linked work tree * Check if a repository is a linked work tree
@ -509,7 +509,7 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
* @param repo Repo to test * @param repo Repo to test
* @return 1 if the repository is a linked work tree, 0 otherwise. * @return 1 if the repository is a linked work tree, 0 otherwise.
*/ */
GIT_EXTERN(int) git_repository_is_worktree(git_repository *repo); GIT_EXTERN(int) git_repository_is_worktree(const git_repository *repo);
/** /**
* Get the configuration file for this repository. * Get the configuration file for this repository.

View File

@ -61,7 +61,7 @@ typedef enum {
*/ */
GIT_EXTERN(int) git_reset( GIT_EXTERN(int) git_reset(
git_repository *repo, git_repository *repo,
git_object *target, const git_object *target,
git_reset_t reset_type, git_reset_t reset_type,
const git_checkout_options *checkout_opts); const git_checkout_options *checkout_opts);
@ -79,7 +79,7 @@ GIT_EXTERN(int) git_reset(
*/ */
GIT_EXTERN(int) git_reset_from_annotated( GIT_EXTERN(int) git_reset_from_annotated(
git_repository *repo, git_repository *repo,
git_annotated_commit *commit, const git_annotated_commit *commit,
git_reset_t reset_type, git_reset_t reset_type,
const git_checkout_options *checkout_opts); const git_checkout_options *checkout_opts);
@ -103,8 +103,8 @@ GIT_EXTERN(int) git_reset_from_annotated(
*/ */
GIT_EXTERN(int) git_reset_default( GIT_EXTERN(int) git_reset_default(
git_repository *repo, git_repository *repo,
git_object *target, const git_object *target,
git_strarray* pathspecs); const git_strarray* pathspecs);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL

View File

@ -173,12 +173,16 @@ typedef enum {
* The `pathspec` is an array of path patterns to match (using * The `pathspec` is an array of path patterns to match (using
* fnmatch-style matching), or just an array of paths to match exactly if * fnmatch-style matching), or just an array of paths to match exactly if
* `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags. * `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified in the flags.
*
* The `baseline` is the tree to be used for comparison to the working directory
* and index; defaults to HEAD.
*/ */
typedef struct { typedef struct {
unsigned int version; unsigned int version;
git_status_show_t show; git_status_show_t show;
unsigned int flags; unsigned int flags;
git_strarray pathspec; git_strarray pathspec;
git_tree *baseline;
} git_status_options; } git_status_options;
#define GIT_STATUS_OPTIONS_VERSION 1 #define GIT_STATUS_OPTIONS_VERSION 1

View File

@ -58,7 +58,7 @@ struct git_config_backend {
struct git_config *cfg; struct git_config *cfg;
/* Open means open the file/database and parse if necessary */ /* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *, git_config_level_t level); int (*open)(struct git_config_backend *, git_config_level_t level, const git_repository *repo);
int (*get)(struct git_config_backend *, const char *key, git_config_entry **entry); int (*get)(struct git_config_backend *, const char *key, git_config_entry **entry);
int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set)(struct git_config_backend *, const char *key, const char *value);
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
@ -111,6 +111,8 @@ GIT_EXTERN(int) git_config_init_backend(
* @param cfg the configuration to add the file to * @param cfg the configuration to add the file to
* @param file the configuration file (backend) to add * @param file the configuration file (backend) to add
* @param level the priority level of the backend * @param level the priority level of the backend
* @param repo optional repository to allow parsing of
* conditional includes
* @param force if a config file already exists for the given * @param force if a config file already exists for the given
* priority level, replace it * priority level, replace it
* @return 0 on success, GIT_EEXISTS when adding more than one file * @return 0 on success, GIT_EEXISTS when adding more than one file
@ -120,6 +122,7 @@ GIT_EXTERN(int) git_config_add_backend(
git_config *cfg, git_config *cfg,
git_config_backend *file, git_config_backend *file,
git_config_level_t level, git_config_level_t level,
const git_repository *repo,
int force); int force);
/** @} */ /** @} */

View File

@ -11,6 +11,7 @@
#include "git2/types.h" #include "git2/types.h"
#include "git2/oid.h" #include "git2/oid.h"
#include "git2/odb.h" #include "git2/odb.h"
#include "git2/buffer.h"
/** /**
* @file git2/sys/mempack.h * @file git2/sys/mempack.h
@ -38,10 +39,10 @@ GIT_BEGIN_DECL
* Subsequent reads will also be served from the in-memory store * Subsequent reads will also be served from the in-memory store
* to ensure consistency, until the memory store is dumped. * to ensure consistency, until the memory store is dumped.
* *
* @param out Poiter where to store the ODB backend * @param out Pointer where to store the ODB backend
* @return 0 on success; error code otherwise * @return 0 on success; error code otherwise
*/ */
int git_mempack_new(git_odb_backend **out); GIT_EXTERN(int) git_mempack_new(git_odb_backend **out);
/** /**
* Dump all the queued in-memory writes to a packfile. * Dump all the queued in-memory writes to a packfile.
@ -64,7 +65,7 @@ int git_mempack_new(git_odb_backend **out);
* @param backend The mempack backend * @param backend The mempack backend
* @return 0 on success; error code otherwise * @return 0 on success; error code otherwise
*/ */
int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend); GIT_EXTERN(int) git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend);
/** /**
* Reset the memory packer by clearing all the queued objects. * Reset the memory packer by clearing all the queued objects.
@ -78,7 +79,7 @@ int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backe
* *
* @param backend The mempack backend * @param backend The mempack backend
*/ */
void git_mempack_reset(git_odb_backend *backend); GIT_EXTERN(void) git_mempack_reset(git_odb_backend *backend);
GIT_END_DECL GIT_END_DECL

View File

@ -56,7 +56,8 @@ struct git_odb_backend {
git_odb_stream **, git_odb_backend *, git_off_t, git_otype); git_odb_stream **, git_odb_backend *, git_off_t, git_otype);
int (* readstream)( int (* readstream)(
git_odb_stream **, git_odb_backend *, const git_oid *); git_odb_stream **, size_t *, git_otype *,
git_odb_backend *, const git_oid *);
int (* exists)( int (* exists)(
git_odb_backend *, const git_oid *); git_odb_backend *, const git_oid *);

View File

@ -1,16 +0,0 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_transport_h
#define INCLUDE_sys_git_transport_h
#include "git2/net.h"
#include "git2/types.h"
GIT_BEGIN_DECL
GIT_END_DECL

View File

@ -307,9 +307,10 @@ GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(
* pointer may not be valid past the next operation in this * pointer may not be valid past the next operation in this
* builder. Duplicate the entry if you want to keep it. * builder. Duplicate the entry if you want to keep it.
* *
* No attempt is being made to ensure that the provided oid points * By default the entry that you are inserting will be checked for
* to an existing git object in the object database, nor that the * validity; that it exists in the object database and is of the
* attributes make sense regarding the type of the pointed at object. * correct type. If you do not want this behavior, set the
* `GIT_OPT_ENABLE_STRICT_OBJECT_CREATION` library option to false.
* *
* @param out Pointer to store the entry (optional) * @param out Pointer to store the entry (optional)
* @param bld Tree builder * @param bld Tree builder

View File

@ -159,6 +159,7 @@ typedef struct git_packbuilder git_packbuilder;
typedef struct git_time { typedef struct git_time {
git_time_t time; /**< time in seconds from epoch */ git_time_t time; /**< time in seconds from epoch */
int offset; /**< timezone offset, in minutes */ int offset; /**< timezone offset, in minutes */
char sign; /**< indicator for questionable '-0000' offsets in signature */
} git_time; } git_time;
/** An action signature (e.g. for committers, taggers, etc) */ /** An action signature (e.g. for committers, taggers, etc) */

View File

@ -7,12 +7,12 @@
#ifndef INCLUDE_git_version_h__ #ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__ #define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.26.0" #define LIBGIT2_VERSION "0.27.0"
#define LIBGIT2_VER_MAJOR 0 #define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 26 #define LIBGIT2_VER_MINOR 27
#define LIBGIT2_VER_REVISION 0 #define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_PATCH 0 #define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 26 #define LIBGIT2_SOVERSION 27
#endif #endif

View File

@ -123,7 +123,7 @@ GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo,
* @param reason Reason why the working tree is being locked * @param reason Reason why the working tree is being locked
* @return 0 on success, non-zero otherwise * @return 0 on success, non-zero otherwise
*/ */
GIT_EXTERN(int) git_worktree_lock(git_worktree *wt, char *reason); GIT_EXTERN(int) git_worktree_lock(git_worktree *wt, const char *reason);
/** /**
* Unlock a locked worktree * Unlock a locked worktree

View File

@ -19,5 +19,5 @@ fi
cd build cd build
gcc --version gcc --version
cmake --version cmake --version
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON .. -G"$GENERATOR" cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON .. -G"$GENERATOR"
cmake --build . --config RelWithDebInfo cmake --build . --config RelWithDebInfo

View File

@ -10,6 +10,15 @@ fi
if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -) export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -)
# Set up a ramdisk for us to put our test data on to speed up tests on macOS
export CLAR_TMP="$HOME"/_clar_tmp
mkdir -p $CLAR_TMP
# 5*2M sectors aka ~5GB of space
device=$(hdiutil attach -nomount ram://$((5 * 2 * 1024 * 1024)))
newfs_hfs $device
mount -t hfs $device $CLAR_TMP
fi fi
# Should we ask Travis to cache this file? # Should we ask Travis to cache this file?
@ -43,46 +52,51 @@ ctest -V -R libgit2_clar || exit $?
killall git-daemon killall git-daemon
if [ "$TRAVIS_OS_NAME" = "osx" ]; then # Set up sshd
echo 'PasswordAuthentication yes' | sudo tee -a /etc/sshd_config mkdir ~/sshd/
fi cat >~/sshd/sshd_config<<-EOF
Port 2222
ListenAddress 0.0.0.0
Protocol 2
HostKey ${HOME}/sshd/id_rsa
PidFile ${HOME}/sshd/pid
RSAAuthentication yes
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
# Required here as sshd will simply close connection otherwise
UsePAM no
EOF
ssh-keygen -t rsa -f ~/sshd/id_rsa -N "" -q
/usr/sbin/sshd -f ~/sshd/sshd_config
# Set up keys
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts while read algorithm key comment; do
echo "[localhost]:2222 $algorithm $key" >>~/.ssh/known_hosts
done <~/sshd/id_rsa.pub
# Get the fingerprint for localhost and remove the colons so we can parse it as # Get the fingerprint for localhost and remove the colons so we can parse it as
# a hex number. The Mac version is newer so it has a different output format. # a hex number. The Mac version is newer so it has a different output format.
if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F localhost -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :) export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
else else
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F localhost -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':') export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
fi fi
export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git" # Use the SSH server
export GITTEST_REMOTE_URL="ssh://localhost:2222/$HOME/_temp/test.git"
export GITTEST_REMOTE_USER=$USER export GITTEST_REMOTE_USER=$USER
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa" export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub" export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE="" export GITTEST_REMOTE_SSH_PASSPHRASE=""
ctest -V -R libgit2_clar-ssh || exit $?
if [ -e ./libgit2_clar ]; then
./libgit2_clar -sonline::push -sonline::clone::ssh_cert &&
./libgit2_clar -sonline::clone::ssh_with_paths || exit $?
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
./libgit2_clar -sonline::clone::cred_callback || exit $?
fi
# Use the proxy we started at the beginning # Use the proxy we started at the beginning
export GITTEST_REMOTE_PROXY_URL="http://foo:bar@localhost:8080/" export GITTEST_REMOTE_PROXY_URL="localhost:8080"
./libgit2_clar -sonline::clone::proxy_credentials_in_url || exit $?
export GITTEST_REMOTE_PROXY_URL="http://localhost:8080/"
export GITTEST_REMOTE_PROXY_USER="foo" export GITTEST_REMOTE_PROXY_USER="foo"
export GITTEST_REMOTE_PROXY_PASS="bar" export GITTEST_REMOTE_PROXY_PASS="bar"
./libgit2_clar -sonline::clone::proxy_credentials_request || exit $? ctest -V -R libgit2_clar-proxy_credentials || exit $?
fi kill $(cat "$HOME/sshd/pid")
export GITTEST_REMOTE_URL="https://github.com/libgit2/non-existent"
export GITTEST_REMOTE_USER="libgit2test"
ctest -V -R libgit2_clar-cred_callback

463
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,463 @@
IF(DEBUG_POOL)
SET(GIT_DEBUG_POOL 1)
ENDIF()
ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator")
# This variable will contain the libraries we need to put into
# libgit2.pc's Requires.private. That is, what we're linking to or
# what someone who's statically linking us needs to link to.
SET(LIBGIT2_PC_REQUIRES "")
# This will be set later if we use the system's http-parser library or
# use iconv (OSX) and will be written to the Libs.private field in the
# pc file.
SET(LIBGIT2_PC_LIBS "")
SET(LIBGIT2_INCLUDES
"${CMAKE_CURRENT_BINARY_DIR}"
"${libgit2_SOURCE_DIR}/src"
"${libgit2_SOURCE_DIR}/include")
SET(LIBGIT2_LIBS "")
SET(LIBGIT2_LIBDIRS "")
# Installation paths
#
SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.")
SET(LIB_INSTALL_DIR lib CACHE PATH "Where to install libraries to.")
SET(INCLUDE_INSTALL_DIR include CACHE PATH "Where to install headers to.")
# Set a couple variables to be substituted inside the .pc file.
# We can't just use LIB_INSTALL_DIR in the .pc file, as passing them as absolue
# or relative paths is both valid and supported by cmake.
SET (PKGCONFIG_PREFIX ${CMAKE_INSTALL_PREFIX})
IF(IS_ABSOLUTE ${LIB_INSTALL_DIR})
SET (PKGCONFIG_LIBDIR ${LIB_INSTALL_DIR})
ELSE(IS_ABSOLUTE ${LIB_INSTALL_DIR})
SET (PKGCONFIG_LIBDIR "\${prefix}/${LIB_INSTALL_DIR}")
ENDIF (IS_ABSOLUTE ${LIB_INSTALL_DIR})
IF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
SET (PKGCONFIG_INCLUDEDIR ${INCLUDE_INSTALL_DIR})
ELSE(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
SET (PKGCONFIG_INCLUDEDIR "\${prefix}/${INCLUDE_INSTALL_DIR}")
ENDIF(IS_ABSOLUTE ${INCLUDE_INSTALL_DIR})
# Enable tracing
IF (ENABLE_TRACE STREQUAL "ON")
SET(GIT_TRACE 1)
ENDIF()
ADD_FEATURE_INFO(tracing GIT_TRACE "tracing support")
CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L)
IF (HAVE_REGCOMP_L)
SET(GIT_USE_REGCOMP_L 1)
ENDIF ()
CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
IF (HAVE_FUTIMENS)
SET(GIT_USE_FUTIMENS 1)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_r HAVE_QSORT_R)
IF (HAVE_QSORT_R)
ADD_DEFINITIONS(-DHAVE_QSORT_R)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
IF (HAVE_QSORT_S)
ADD_DEFINITIONS(-DHAVE_QSORT_S)
ENDIF ()
# Find required dependencies
IF(WIN32)
LIST(APPEND LIBGIT2_LIBS ws2_32)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
LIST(APPEND LIBGIT2_LIBS socket nsl)
LIST(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Haiku")
LIST(APPEND LIBGIT2_LIBS network)
LIST(APPEND LIBGIT2_PC_LIBS "-lnetwork")
ENDIF()
CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" NEED_LIBRT)
IF(NEED_LIBRT)
LIST(APPEND LIBGIT2_LIBS rt)
LIST(APPEND LIBGIT2_PC_LIBS "-lrt")
ENDIF()
IF(THREADSAFE)
LIST(APPEND LIBGIT2_LIBS ${CMAKE_THREAD_LIBS_INIT})
LIST(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
ADD_FEATURE_INFO(threadsafe THREADSAFE "threadsafe support")
IF (WIN32 AND EMBED_SSH_PATH)
FILE(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
LIST(APPEND LIBGIT2_INCLUDES "${EMBED_SSH_PATH}/include")
FILE(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"")
SET(GIT_SSH 1)
ENDIF()
IF (WIN32 AND WINHTTP)
SET(GIT_WINHTTP 1)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
IF (MINGW)
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/winhttp" "${libgit2_BINARY_DIR}/deps/winhttp")
LIST(APPEND LIBGIT2_LIBS winhttp)
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/winhttp")
LIST(APPEND LIBGIT2_LIBDIRS ${LIBWINHTTP_PATH})
ELSE()
LIST(APPEND LIBGIT2_LIBS "winhttp")
LIST(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
ENDIF ()
LIST(APPEND LIBGIT2_LIBS "rpcrt4" "crypt32" "ole32")
LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
ELSE ()
IF (CURL)
PKG_CHECK_MODULES(CURL libcurl)
ENDIF ()
IF (CURL_FOUND)
SET(GIT_CURL 1)
LIST(APPEND LIBGIT2_INCLUDES ${CURL_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBDIRS ${CURL_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_LIBS ${CURL_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${CURL_LDFLAGS})
ENDIF()
ADD_FEATURE_INFO(cURL GIT_CURL "cURL for HTTP proxy support")
ENDIF()
IF (USE_HTTPS)
IF (CMAKE_SYSTEM_NAME MATCHES "Darwin")
FIND_PACKAGE(Security)
FIND_PACKAGE(CoreFoundation)
ENDIF()
# Auto-select TLS backend
IF (USE_HTTPS STREQUAL ON)
IF (SECURITY_FOUND)
IF (SECURITY_HAS_SSLCREATECONTEXT)
SET(HTTPS_BACKEND "SecureTransport")
ELSE()
MESSAGE("-- Security framework is too old, falling back to OpenSSL")
SET(HTTPS_BACKEND "OpenSSL")
ENDIF()
ELSEIF (WINHTTP)
SET(HTTPS_BACKEND "WinHTTP")
ELSE()
SET(HTTPS_BACKEND "OpenSSL")
ENDIF()
ELSE()
# Backend was explicitly set
SET(HTTPS_BACKEND ${USE_HTTPS})
ENDIF()
# Check that we can find what's required for the selected backend
IF (HTTPS_BACKEND STREQUAL "SecureTransport")
IF (NOT COREFOUNDATION_FOUND)
MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, CoreFoundation.framework not found")
ENDIF()
IF (NOT SECURITY_FOUND)
MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, Security.framework not found")
ENDIF()
IF (NOT SECURITY_HAS_SSLCREATECONTEXT)
MESSAGE(FATAL_ERROR "Cannot use SecureTransport backend, SSLCreateContext not supported")
ENDIF()
SET(GIT_SECURE_TRANSPORT 1)
LIST(APPEND LIBGIT2_INCLUDES ${SECURITY_INCLUDE_DIR})
LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_LIBRARIES} ${SECURITY_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${COREFOUNDATION_LDFLAGS} ${SECURITY_LDFLAGS})
ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
FIND_PACKAGE(OpenSSL)
IF (NOT OPENSSL_FOUND)
MESSAGE(FATAL_ERROR "Asked for OpenSSL TLS backend, but it wasn't found")
ENDIF()
SET(GIT_OPENSSL 1)
LIST(APPEND LIBGIT2_INCLUDES ${OPENSSL_INCLUDE_DIR})
LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${OPENSSL_LDFLAGS})
LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
ELSEIF (HTTPS_BACKEND STREQUAL "WinHTTP")
# WinHTTP setup was handled in the WinHTTP-specific block above
ELSE()
MESSAGE(FATAL_ERROR "Asked for backend ${HTTPS_BACKEND} but it wasn't found")
ENDIF()
ADD_FEATURE_INFO(HTTPS ON "using ${HTTPS_BACKEND}")
SET(GIT_HTTPS 1)
ELSE()
ADD_FEATURE_INFO(HTTPS OFF "no support")
ENDIF()
# Specify sha1 implementation
IF(SHA1_BACKEND STREQUAL "OpenSSL")
IF(NOT OPENSSL_FOUND)
FIND_PACKAGE(OpenSSL)
IF(NOT OPENSSL_FOUND)
MESSAGE(FATAL_ERROR "Requested OpenSSL SHA1 backend, but OpenSSL could not be found")
ENDIF()
ENDIF()
ADD_FEATURE_INFO(SHA ON "using OpenSSL")
SET(GIT_SHA1_OPENSSL 1)
IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
LIST(APPEND LIBGIT2_PC_LIBS "-lssl")
ELSE()
LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
ENDIF()
ELSEIF(SHA1_BACKEND STREQUAL "CollisionDetection")
ADD_FEATURE_INFO(SHA ON "using CollisionDetection")
SET(GIT_SHA1_COLLISIONDETECT 1)
ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1)
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
FILE(GLOB SRC_SHA1 hash/hash_collisiondetect.c hash/sha1dc/*)
ELSEIF(SHA1_BACKEND STREQUAL "Generic")
ADD_FEATURE_INFO(SHA ON "using Generic")
FILE(GLOB SRC_SHA1 hash/hash_generic.c)
ELSEIF(SHA1_BACKEND STREQUAL "Win32")
ADD_FEATURE_INFO(SHA ON "using Win32")
SET(GIT_SHA1_WIN32 1)
FILE(GLOB SRC_SHA1 hash/hash_win32.c)
ELSEIF(SHA1_BACKEND STREQUAL "CommonCrypto")
ADD_FEATURE_INFO(SHA ON "using CommonCrypto")
SET(GIT_SHA1_COMMON_CRYPTO 1)
ELSE()
MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend ${SHA1_BACKEND}")
ENDIF()
# Include POSIX regex when it is required
IF(WIN32 OR AMIGA OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/regex" "${libgit2_BINARY_DIR}/deps/regex")
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/regex")
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:regex>)
ENDIF()
# Optional external dependency: http-parser
FIND_PACKAGE(HTTP_Parser)
IF (USE_EXT_HTTP_PARSER AND HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
LIST(APPEND LIBGIT2_INCLUDES ${HTTP_PARSER_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBS ${HTTP_PARSER_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser")
ADD_FEATURE_INFO(http-parser ON "http-parser support")
ELSE()
MESSAGE(STATUS "http-parser version 2 was not found or disabled; using bundled 3rd-party sources.")
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/http-parser" "${libgit2_BINARY_DIR}/deps/http-parser")
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/http-parser")
LIST(APPEND LIBGIT2_OBJECTS "$<TARGET_OBJECTS:http-parser>")
ADD_FEATURE_INFO(http-parser ON "http-parser support (bundled)")
ENDIF()
# Optional external dependency: zlib
IF(NOT USE_BUNDLED_ZLIB)
FIND_PACKAGE(ZLIB)
IF(ZLIB_FOUND)
LIST(APPEND LIBGIT2_INCLUDES ${ZLIB_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBS ${ZLIB_LIBRARIES})
IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
LIST(APPEND LIBGIT2_LIBS "z")
LIST(APPEND LIBGIT2_PC_LIBS "-lz")
ELSE()
LIST(APPEND LIBGIT2_PC_REQUIRES "zlib")
ENDIF()
ADD_FEATURE_INFO(zlib ON "using system zlib")
ELSE()
MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
ENDIF()
ENDIF()
IF(USE_BUNDLED_ZLIB OR NOT ZLIB_FOUND)
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/zlib" "${libgit2_BINARY_DIR}/deps/zlib")
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/zlib")
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:zlib>)
ADD_FEATURE_INFO(zlib ON "using bundled zlib")
ENDIF()
# Optional external dependency: libssh2
IF (USE_SSH)
PKG_CHECK_MODULES(LIBSSH2 libssh2)
ENDIF()
IF (LIBSSH2_FOUND)
SET(GIT_SSH 1)
LIST(APPEND LIBGIT2_INCLUDES ${LIBSSH2_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBS ${LIBSSH2_LIBRARIES})
LIST(APPEND LIBGIT2_LIBDIRS ${LIBSSH2_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
#SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${LIBSSH2_LDFLAGS}")
CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS)
SET(GIT_SSH_MEMORY_CREDENTIALS 1)
ENDIF()
ELSE()
MESSAGE(STATUS "LIBSSH2 not found. Set CMAKE_PREFIX_PATH if it is installed outside of the default search path.")
ENDIF()
ADD_FEATURE_INFO(SSH GIT_SSH "SSH transport support")
# Optional external dependency: libgssapi
IF (USE_GSSAPI)
FIND_PACKAGE(GSSAPI)
ENDIF()
IF (GSSAPI_FOUND)
SET(GIT_GSSAPI 1)
LIST(APPEND LIBGIT2_LIBS ${GSSAPI_LIBRARIES})
ENDIF()
ADD_FEATURE_INFO(SPNEGO GIT_GSSAPI "SPNEGO authentication support")
# Optional external dependency: iconv
IF (USE_ICONV)
FIND_PACKAGE(Iconv)
ENDIF()
IF (ICONV_FOUND)
SET(GIT_USE_ICONV 1)
LIST(APPEND LIBGIT2_INCLUDES ${ICONV_INCLUDE_DIR})
LIST(APPEND LIBGIT2_LIBS ${ICONV_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
ENDIF()
ADD_FEATURE_INFO(iconv GIT_USE_ICONV "iconv encoding conversion support")
IF (THREADSAFE)
IF (NOT WIN32)
FIND_PACKAGE(Threads REQUIRED)
ENDIF()
SET(GIT_THREADS 1)
ENDIF()
IF (USE_NSEC)
SET(GIT_USE_NSEC 1)
ENDIF()
IF (HAVE_STRUCT_STAT_ST_MTIM)
SET(GIT_USE_STAT_MTIM 1)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIMESPEC)
SET(GIT_USE_STAT_MTIMESPEC 1)
ELSEIF (HAVE_STRUCT_STAT_ST_MTIME_NSEC)
SET(GIT_USE_STAT_MTIME_NSEC 1)
ENDIF()
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
# Collect sourcefiles
FILE(GLOB SRC_H
"${libgit2_SOURCE_DIR}/include/git2.h"
"${libgit2_SOURCE_DIR}/include/git2/*.h"
"${libgit2_SOURCE_DIR}/include/git2/sys/*.h")
# On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN)
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501)
IF(MSVC)
SET(WIN_RC "win32/git2.rc")
ENDIF()
FILE(GLOB SRC_OS win32/*.c win32/*.h)
ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
ELSE()
IF (VALGRIND)
ADD_DEFINITIONS(-DNO_MMAP)
ENDIF()
FILE(GLOB SRC_OS unix/*.c unix/*.h)
ENDIF()
FILE(GLOB SRC_GIT2 *.c *.h
streams/*.c streams/*.h
transports/*.c transports/*.h
xdiff/*.c xdiff/*.h)
# Determine architecture of the machine
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(GIT_ARCH_64 1)
ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
SET(GIT_ARCH_32 1)
ELSEIF (CMAKE_SIZEOF_VOID_P)
MESSAGE(FATAL_ERROR "Unsupported architecture (pointer size is ${CMAKE_SIZEOF_VOID_P} bytes)")
ELSE()
MESSAGE(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)")
ENDIF()
CONFIGURE_FILE(features.h.in git2/sys/features.h)
SET(LIBGIT2_SOURCES ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_SSH} ${SRC_SHA1})
ADD_LIBRARY(git2internal OBJECT ${LIBGIT2_SOURCES})
IDE_SPLIT_SOURCES(git2internal)
LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal>)
IF (${CMAKE_VERSION} VERSION_LESS 2.8.12)
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
ELSE()
TARGET_INCLUDE_DIRECTORIES(git2internal
PRIVATE ${LIBGIT2_INCLUDES}
PUBLIC ${libgit2_SOURCE_DIR}/include)
ENDIF()
SET(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
SET(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
SET(LIBGIT2_LIBS ${LIBGIT2_LIBS} PARENT_SCOPE)
SET(LIBGIT2_LIBDIRS ${LIBGIT2_LIBDIRS} PARENT_SCOPE)
IF(XCODE_VERSION)
# This is required for Xcode to actually link the libgit2 library
# when using only object libraries.
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.c "")
LIST(APPEND LIBGIT2_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/dummy.c)
ENDIF()
# Compile and link libgit2
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
ADD_LIBRARY(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
TARGET_LINK_LIBRARIES(git2 ${LIBGIT2_LIBS})
SET_TARGET_PROPERTIES(git2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
SET_TARGET_PROPERTIES(git2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
SET_TARGET_PROPERTIES(git2 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
# Win64+MSVC+static libs = linker error
IF(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
SET_TARGET_PROPERTIES(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
ENDIF()
IDE_SPLIT_SOURCES(git2)
IF (SONAME)
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
ELSEIF (DEFINED LIBGIT2_PREFIX)
SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
ENDIF()
ENDIF()
LIST(REMOVE_DUPLICATES LIBGIT2_PC_REQUIRES)
STRING(REPLACE ";" " " LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES}")
STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
CONFIGURE_FILE(${libgit2_SOURCE_DIR}/libgit2.pc.in ${libgit2_BINARY_DIR}/libgit2.pc @ONLY)
IF (MSVC_IDE)
# Precompiled headers
SET_TARGET_PROPERTIES(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
SET_SOURCE_FILES_PROPERTIES(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
ENDIF ()
# Install
INSTALL(TARGETS git2
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
INSTALL(FILES ${libgit2_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
INSTALL(DIRECTORY ${libgit2_SOURCE_DIR}/include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} )
INSTALL(FILES ${libgit2_SOURCE_DIR}/include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} )

View File

@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h"
#include "annotated_commit.h" #include "annotated_commit.h"
#include "refs.h" #include "refs.h"
#include "cache.h" #include "cache.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_annotated_commit_h__ #ifndef INCLUDE_annotated_commit_h__
#define INCLUDE_annotated_commit_h__ #define INCLUDE_annotated_commit_h__
#include "common.h"
#include "oidarray.h" #include "oidarray.h"
#include "git2/oid.h" #include "git2/oid.h"

View File

@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "apply.h"
#include <assert.h> #include <assert.h>
#include "git2/patch.h" #include "git2/patch.h"
@ -12,7 +14,6 @@
#include "array.h" #include "array.h"
#include "patch.h" #include "patch.h"
#include "fileops.h" #include "fileops.h"
#include "apply.h"
#include "delta.h" #include "delta.h"
#include "zstream.h" #include "zstream.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_apply_h__ #ifndef INCLUDE_apply_h__
#define INCLUDE_apply_h__ #define INCLUDE_apply_h__
#include "common.h"
#include "git2/patch.h" #include "git2/patch.h"
#include "buffer.h" #include "buffer.h"

View File

@ -1,4 +1,12 @@
#include "common.h" /*
* 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 "attr.h"
#include "repository.h" #include "repository.h"
#include "sysdir.h" #include "sysdir.h"
#include "config.h" #include "config.h"
@ -48,12 +56,16 @@ int git_attr_get(
git_attr_file *file; git_attr_file *file;
git_attr_name attr; git_attr_name attr;
git_attr_rule *rule; git_attr_rule *rule;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
assert(value && repo && name); assert(value && repo && name);
*value = NULL; *value = NULL;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) if (git_repository_is_bare(repo))
dir_flag = GIT_DIR_FLAG_FALSE;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1; return -1;
if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0) if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0)
@ -106,13 +118,17 @@ int git_attr_get_many_with_session(
git_attr_rule *rule; git_attr_rule *rule;
attr_get_many_info *info = NULL; attr_get_many_info *info = NULL;
size_t num_found = 0; size_t num_found = 0;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
if (!num_attr) if (!num_attr)
return 0; return 0;
assert(values && repo && names); assert(values && repo && names);
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) if (git_repository_is_bare(repo))
dir_flag = GIT_DIR_FLAG_FALSE;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1; return -1;
if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0) if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0)
@ -188,10 +204,14 @@ int git_attr_foreach(
git_attr_rule *rule; git_attr_rule *rule;
git_attr_assignment *assign; git_attr_assignment *assign;
git_strmap *seen = NULL; git_strmap *seen = NULL;
git_dir_flag dir_flag = GIT_DIR_FLAG_UNKNOWN;
assert(repo && callback); assert(repo && callback);
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) if (git_repository_is_bare(repo))
dir_flag = GIT_DIR_FLAG_FALSE;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), dir_flag) < 0)
return -1; return -1;
if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 || if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 ||

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_h__ #ifndef INCLUDE_attr_h__
#define INCLUDE_attr_h__ #define INCLUDE_attr_h__
#include "common.h"
#include "attr_file.h" #include "attr_file.h"
#include "attrcache.h" #include "attrcache.h"

View File

@ -1,7 +1,14 @@
#include "common.h" /*
* 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 "attr_file.h"
#include "repository.h" #include "repository.h"
#include "filebuf.h" #include "filebuf.h"
#include "attr_file.h"
#include "attrcache.h" #include "attrcache.h"
#include "git2/blob.h" #include "git2/blob.h"
#include "git2/tree.h" #include "git2/tree.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_file_h__ #ifndef INCLUDE_attr_file_h__
#define INCLUDE_attr_file_h__ #define INCLUDE_attr_file_h__
#include "common.h"
#include "git2/oid.h" #include "git2/oid.h"
#include "git2/attr.h" #include "git2/attr.h"
#include "vector.h" #include "vector.h"

View File

@ -1,4 +1,12 @@
#include "common.h" /*
* 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 "attrcache.h"
#include "repository.h" #include "repository.h"
#include "attr_file.h" #include "attr_file.h"
#include "config.h" #include "config.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_attrcache_h__ #ifndef INCLUDE_attrcache_h__
#define INCLUDE_attrcache_h__ #define INCLUDE_attrcache_h__
#include "common.h"
#include "attr_file.h" #include "attr_file.h"
#include "strmap.h" #include "strmap.h"

View File

@ -6,6 +6,7 @@
*/ */
#include "blame.h" #include "blame.h"
#include "git2/commit.h" #include "git2/commit.h"
#include "git2/revparse.h" #include "git2/revparse.h"
#include "git2/revwalk.h" #include "git2/revwalk.h"

View File

@ -1,8 +1,9 @@
#ifndef INCLUDE_blame_h__ #ifndef INCLUDE_blame_h__
#define INCLUDE_blame_h__ #define INCLUDE_blame_h__
#include "git2/blame.h"
#include "common.h" #include "common.h"
#include "git2/blame.h"
#include "vector.h" #include "vector.h"
#include "diff.h" #include "diff.h"
#include "array.h" #include "array.h"

View File

@ -6,6 +6,7 @@
*/ */
#include "blame_git.h" #include "blame_git.h"
#include "commit.h" #include "commit.h"
#include "blob.h" #include "blob.h"
#include "xdiff/xinclude.h" #include "xdiff/xinclude.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_blame_git__ #ifndef INCLUDE_blame_git__
#define INCLUDE_blame_git__ #define INCLUDE_blame_git__
#include "common.h"
#include "blame.h" #include "blame.h"
int git_blame__get_origin( int git_blame__get_origin(

View File

@ -5,14 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "blob.h"
#include "git2/common.h" #include "git2/common.h"
#include "git2/object.h" #include "git2/object.h"
#include "git2/repository.h" #include "git2/repository.h"
#include "git2/odb_backend.h" #include "git2/odb_backend.h"
#include "common.h"
#include "filebuf.h" #include "filebuf.h"
#include "blob.h"
#include "filter.h" #include "filter.h"
#include "buf_text.h" #include "buf_text.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_blob_h__ #ifndef INCLUDE_blob_h__
#define INCLUDE_blob_h__ #define INCLUDE_blob_h__
#include "common.h"
#include "git2/blob.h" #include "git2/blob.h"
#include "repository.h" #include "repository.h"
#include "odb.h" #include "odb.h"

View File

@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h" #include "branch.h"
#include "commit.h" #include "commit.h"
#include "tag.h" #include "tag.h"
#include "config.h" #include "config.h"
@ -69,6 +70,12 @@ static int create_branch(
assert(branch_name && commit && ref_out); assert(branch_name && commit && ref_out);
assert(git_object_owner((const git_object *)commit) == repository); assert(git_object_owner((const git_object *)commit) == repository);
if (!git__strcmp(branch_name, "HEAD")) {
giterr_set(GITERR_REFERENCE, "'HEAD' is not a valid branch name");
error = -1;
goto cleanup;
}
if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) { if (force && !bare && git_branch_lookup(&branch, repository, branch_name, GIT_BRANCH_LOCAL) == 0) {
error = git_branch_is_head(branch); error = git_branch_is_head(branch);
git_reference_free(branch); git_reference_free(branch);

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_branch_h__ #ifndef INCLUDE_branch_h__
#define INCLUDE_branch_h__ #define INCLUDE_branch_h__
#include "common.h"
#include "buffer.h" #include "buffer.h"
int git_branch_upstream__name( int git_branch_upstream__name(

View File

@ -188,7 +188,7 @@ bool git_buf_text_is_binary(const git_buf *buf)
git_bom_t bom; git_bom_t bom;
int printable = 0, nonprintable = 0; int printable = 0, nonprintable = 0;
scan += git_buf_text_detect_bom(&bom, buf, 0); scan += git_buf_text_detect_bom(&bom, buf);
if (bom > GIT_BOM_UTF8) if (bom > GIT_BOM_UTF8)
return 1; return 1;
@ -215,18 +215,18 @@ bool git_buf_text_contains_nul(const git_buf *buf)
return (memchr(buf->ptr, '\0', buf->size) != NULL); return (memchr(buf->ptr, '\0', buf->size) != NULL);
} }
int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf, size_t offset) int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf)
{ {
const char *ptr; const char *ptr;
size_t len; size_t len;
*bom = GIT_BOM_NONE; *bom = GIT_BOM_NONE;
/* need at least 2 bytes after offset to look for any BOM */ /* need at least 2 bytes to look for any BOM */
if (buf->size < offset + 2) if (buf->size < 2)
return 0; return 0;
ptr = buf->ptr + offset; ptr = buf->ptr;
len = buf->size - offset; len = buf->size;
switch (*ptr++) { switch (*ptr++) {
case 0: case 0:
@ -274,7 +274,7 @@ bool git_buf_text_gather_stats(
memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats));
/* BOM detection */ /* BOM detection */
skip = git_buf_text_detect_bom(&stats->bom, buf, 0); skip = git_buf_text_detect_bom(&stats->bom, buf);
if (skip_bom) if (skip_bom)
scan += skip; scan += skip;

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_buf_text_h__ #ifndef INCLUDE_buf_text_h__
#define INCLUDE_buf_text_h__ #define INCLUDE_buf_text_h__
#include "common.h"
#include "buffer.h" #include "buffer.h"
typedef enum { typedef enum {
@ -97,11 +99,9 @@ extern bool git_buf_text_contains_nul(const git_buf *buf);
* *
* @param bom Set to the type of BOM detected or GIT_BOM_NONE * @param bom Set to the type of BOM detected or GIT_BOM_NONE
* @param buf Buffer in which to check the first bytes for a BOM * @param buf Buffer in which to check the first bytes for a BOM
* @param offset Offset into buffer to look for BOM
* @return Number of bytes of BOM data (or 0 if no BOM found) * @return Number of bytes of BOM data (or 0 if no BOM found)
*/ */
extern int git_buf_text_detect_bom( extern int git_buf_text_detect_bom(git_bom_t *bom, const git_buf *buf);
git_bom_t *bom, const git_buf *buf, size_t offset);
/** /**
* Gather stats for a piece of text * Gather stats for a piece of text

View File

@ -455,6 +455,36 @@ on_error:
return -1; return -1;
} }
#define HEX_DECODE(c) ((c | 32) % 39 - 9)
int git_buf_decode_percent(
git_buf *buf,
const char *str,
size_t str_len)
{
size_t str_pos, new_size;
GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, str_len);
GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
ENSURE_SIZE(buf, new_size);
for (str_pos = 0; str_pos < str_len; buf->size++, str_pos++) {
if (str[str_pos] == '%' &&
str_len > str_pos + 2 &&
isxdigit(str[str_pos + 1]) &&
isxdigit(str[str_pos + 2])) {
buf->ptr[buf->size] = (HEX_DECODE(str[str_pos + 1]) << 4) +
HEX_DECODE(str[str_pos + 2]);
str_pos += 2;
} else {
buf->ptr[buf->size] = str[str_pos];
}
}
buf->ptr[buf->size] = '\0';
return 0;
}
int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
{ {
size_t expected_size, new_size; size_t expected_size, new_size;

View File

@ -190,6 +190,9 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len);
/* Decode the given "base85" and write the result to the buffer */ /* Decode the given "base85" and write the result to the buffer */
int git_buf_decode_base85(git_buf *buf, const char *base64, size_t len, size_t output_len); int git_buf_decode_base85(git_buf *buf, const char *base64, size_t len, size_t output_len);
/* Decode the given percent-encoded string and write the result to the buffer */
int git_buf_decode_percent(git_buf *buf, const char *str, size_t len);
/* /*
* Insert, remove or replace a portion of the buffer. * Insert, remove or replace a portion of the buffer.
* *

View File

@ -5,12 +5,12 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h" #include "cache.h"
#include "repository.h" #include "repository.h"
#include "commit.h" #include "commit.h"
#include "thread-utils.h" #include "thread-utils.h"
#include "util.h" #include "util.h"
#include "cache.h"
#include "odb.h" #include "odb.h"
#include "object.h" #include "object.h"
#include "git2/oid.h" #include "git2/oid.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_cache_h__ #ifndef INCLUDE_cache_h__
#define INCLUDE_cache_h__ #define INCLUDE_cache_h__
#include "common.h"
#include "git2/common.h" #include "git2/common.h"
#include "git2/oid.h" #include "git2/oid.h"
#include "git2/odb.h" #include "git2/odb.h"

View File

@ -4,8 +4,8 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with * This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#ifndef INCLUDE_compat_h__ #ifndef INCLUDE_cc_compat_h__
#define INCLUDE_compat_h__ #define INCLUDE_cc_compat_h__
#include <stdarg.h> #include <stdarg.h>
@ -84,4 +84,4 @@
# endif # endif
#endif #endif
#endif /* INCLUDE_compat_h__ */ #endif

View File

@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include <assert.h>
#include "checkout.h" #include "checkout.h"
#include <assert.h>
#include "git2/repository.h" #include "git2/repository.h"
#include "git2/refs.h" #include "git2/refs.h"
#include "git2/tree.h" #include "git2/tree.h"
@ -70,6 +70,7 @@ typedef struct {
git_buf tmp; git_buf tmp;
unsigned int strategy; unsigned int strategy;
int can_symlink; int can_symlink;
int respect_filemode;
bool reload_submodules; bool reload_submodules;
size_t total_steps; size_t total_steps;
size_t completed_steps; size_t completed_steps;
@ -159,6 +160,22 @@ GIT_INLINE(bool) is_workdir_base_or_new(
git_oid__cmp(&newitem->id, workdir_id) == 0); git_oid__cmp(&newitem->id, workdir_id) == 0);
} }
GIT_INLINE(bool) is_filemode_changed(git_filemode_t a, git_filemode_t b, int respect_filemode)
{
/* If core.filemode = false, ignore links in the repository and executable bit changes */
if (!respect_filemode) {
if (a == S_IFLNK)
a = GIT_FILEMODE_BLOB;
if (b == S_IFLNK)
b = GIT_FILEMODE_BLOB;
a &= ~0111;
b &= ~0111;
}
return (a != b);
}
static bool checkout_is_workdir_modified( static bool checkout_is_workdir_modified(
checkout_data *data, checkout_data *data,
const git_diff_file *baseitem, const git_diff_file *baseitem,
@ -192,16 +209,23 @@ static bool checkout_is_workdir_modified(
return rval; return rval;
} }
/* 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 * Look at the cache to decide if the workdir is modified: if the
* of hashing the file. If so, we allow the checkout to proceed if the * cache contents match the workdir contents, then we do not need
* oid is identical (ie, the staged item is what we're trying to check * to examine the working directory directly, instead we can
* out.) * examine the cache to see if _it_ has been modified. This allows
* us to avoid touching the disk.
*/ */
if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) { ie = git_index_get_bypath(data->index, wditem->path, 0);
if (git_index_time_eq(&wditem->mtime, &ie->mtime) &&
wditem->file_size == ie->file_size) if (ie != NULL &&
return !is_workdir_base_or_new(&ie->id, baseitem, newitem); git_index_time_eq(&wditem->mtime, &ie->mtime) &&
wditem->file_size == ie->file_size &&
!is_filemode_changed(wditem->mode, ie->mode, data->respect_filemode)) {
/* The workdir is modified iff the index entry is modified */
return !is_workdir_base_or_new(&ie->id, baseitem, newitem) ||
is_filemode_changed(baseitem->mode, ie->mode, data->respect_filemode);
} }
/* depending on where base is coming from, we may or may not know /* depending on where base is coming from, we may or may not know
@ -214,6 +238,9 @@ static bool checkout_is_workdir_modified(
if (S_ISDIR(wditem->mode)) if (S_ISDIR(wditem->mode))
return false; return false;
if (is_filemode_changed(baseitem->mode, wditem->mode, data->respect_filemode))
return true;
if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0) if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
return false; return false;
@ -2005,8 +2032,11 @@ static int checkout_write_entry(
(error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0) (error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0)
return error; return error;
if (!S_ISGITLINK(side->mode))
return checkout_write_content(data, return checkout_write_content(data,
&side->id, fullpath->ptr, hint_path, side->mode, &st); &side->id, fullpath->ptr, hint_path, side->mode, &st);
return 0;
} }
static int checkout_write_entries( static int checkout_write_entries(
@ -2428,6 +2458,10 @@ static int checkout_data_init(
&data->can_symlink, repo, GIT_CVAR_SYMLINKS)) < 0) &data->can_symlink, repo, GIT_CVAR_SYMLINKS)) < 0)
goto cleanup; goto cleanup;
if ((error = git_repository__cvar(
&data->respect_filemode, repo, GIT_CVAR_FILEMODE)) < 0)
goto cleanup;
if (!data->opts.baseline && !data->opts.baseline_index) { if (!data->opts.baseline && !data->opts.baseline_index) {
data->opts_free_baseline = true; data->opts_free_baseline = true;
error = 0; error = 0;

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_checkout_h__ #ifndef INCLUDE_checkout_h__
#define INCLUDE_checkout_h__ #define INCLUDE_checkout_h__
#include "common.h"
#include "git2/checkout.h" #include "git2/checkout.h"
#include "iterator.h" #include "iterator.h"

View File

@ -6,6 +6,7 @@
*/ */
#include "common.h" #include "common.h"
#include "repository.h" #include "repository.h"
#include "filebuf.h" #include "filebuf.h"
#include "merge.h" #include "merge.h"

View File

@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "clone.h"
#include <assert.h> #include <assert.h>
#include "git2/clone.h" #include "git2/clone.h"
@ -16,7 +18,6 @@
#include "git2/commit.h" #include "git2/commit.h"
#include "git2/tree.h" #include "git2/tree.h"
#include "common.h"
#include "remote.h" #include "remote.h"
#include "fileops.h" #include "fileops.h"
#include "refs.h" #include "refs.h"

View File

@ -7,6 +7,10 @@
#ifndef INCLUDE_clone_h__ #ifndef INCLUDE_clone_h__
#define INCLUDE_clone_h__ #define INCLUDE_clone_h__
#include "common.h"
#include "git2/clone.h"
extern int git_clone__should_clone_local(const char *url, git_clone_local_t local); extern int git_clone__should_clone_local(const char *url, git_clone_local_t local);
#endif #endif

View File

@ -5,13 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "commit.h"
#include "git2/common.h" #include "git2/common.h"
#include "git2/object.h" #include "git2/object.h"
#include "git2/repository.h" #include "git2/repository.h"
#include "git2/signature.h" #include "git2/signature.h"
#include "git2/sys/commit.h" #include "git2/sys/commit.h"
#include "common.h"
#include "odb.h" #include "odb.h"
#include "commit.h" #include "commit.h"
#include "signature.h" #include "signature.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_h__ #ifndef INCLUDE_commit_h__
#define INCLUDE_commit_h__ #define INCLUDE_commit_h__
#include "common.h"
#include "git2/commit.h" #include "git2/commit.h"
#include "tree.h" #include "tree.h"
#include "repository.h" #include "repository.h"

View File

@ -6,7 +6,7 @@
*/ */
#include "commit_list.h" #include "commit_list.h"
#include "common.h"
#include "revwalk.h" #include "revwalk.h"
#include "pool.h" #include "pool.h"
#include "odb.h" #include "odb.h"

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_list_h__ #ifndef INCLUDE_commit_list_h__
#define INCLUDE_commit_list_h__ #define INCLUDE_commit_list_h__
#include "common.h"
#include "git2/oid.h" #include "git2/oid.h"
#define PARENT1 (1 << 0) #define PARENT1 (1 << 0)

View File

@ -7,6 +7,10 @@
#ifndef INCLUDE_common_h__ #ifndef INCLUDE_common_h__
#define INCLUDE_common_h__ #define INCLUDE_common_h__
#ifndef LIBGIT2_NO_FEATURES_H
# include "git2/sys/features.h"
#endif
#include "git2/common.h" #include "git2/common.h"
#include "cc-compat.h" #include "cc-compat.h"
@ -47,10 +51,6 @@
# ifdef GIT_THREADS # ifdef GIT_THREADS
# include "win32/thread.h" # include "win32/thread.h"
# endif # endif
# if defined(GIT_MSVC_CRTDBG)
# include "win32/w32_stack.h"
# include "win32/w32_crtdbg_stacktrace.h"
# endif
#else #else
@ -230,6 +230,12 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \ GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four)) { return -1; } GIT_ADD_SIZET_OVERFLOW(out, *(out), four)) { return -1; }
#define GITERR_CHECK_ALLOC_ADD5(out, one, two, three, four, five) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), five)) { return -1; }
/** Check for multiplicative overflow, failing if it would occur. */ /** Check for multiplicative overflow, failing if it would occur. */
#define GITERR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \ #define GITERR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; } if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }
@ -238,4 +244,4 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
#include "util.h" #include "util.h"
#endif /* INCLUDE_common_h__ */ #endif

View File

@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h"
#include "sysdir.h"
#include "config.h" #include "config.h"
#include "sysdir.h"
#include "git2/config.h" #include "git2/config.h"
#include "git2/sys/config.h" #include "git2/sys/config.h"
#include "vector.h" #include "vector.h"
@ -99,6 +99,7 @@ int git_config_add_file_ondisk(
git_config *cfg, git_config *cfg,
const char *path, const char *path,
git_config_level_t level, git_config_level_t level,
const git_repository *repo,
int force) int force)
{ {
git_config_backend *file = NULL; git_config_backend *file = NULL;
@ -116,7 +117,7 @@ int git_config_add_file_ondisk(
if (git_config_file__ondisk(&file, path) < 0) if (git_config_file__ondisk(&file, path) < 0)
return -1; return -1;
if ((res = git_config_add_backend(cfg, file, level, force)) < 0) { if ((res = git_config_add_backend(cfg, file, level, repo, force)) < 0) {
/* /*
* free manually; the file is not owned by the config * free manually; the file is not owned by the config
* instance yet and will not be freed on cleanup * instance yet and will not be freed on cleanup
@ -138,7 +139,7 @@ int git_config_open_ondisk(git_config **out, const char *path)
if (git_config_new(&config) < 0) if (git_config_new(&config) < 0)
return -1; return -1;
if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0) if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, NULL, 0)) < 0)
git_config_free(config); git_config_free(config);
else else
*out = config; *out = config;
@ -164,7 +165,7 @@ int git_config_snapshot(git_config **out, git_config *in)
if ((error = internal->file->snapshot(&b, internal->file)) < 0) if ((error = internal->file->snapshot(&b, internal->file)) < 0)
break; break;
if ((error = git_config_add_backend(config, b, internal->level, 0)) < 0) { if ((error = git_config_add_backend(config, b, internal->level, NULL, 0)) < 0) {
b->free(b); b->free(b);
break; break;
} }
@ -307,6 +308,7 @@ int git_config_add_backend(
git_config *cfg, git_config *cfg,
git_config_backend *file, git_config_backend *file,
git_config_level_t level, git_config_level_t level,
const git_repository *repo,
int force) int force)
{ {
file_internal *internal; file_internal *internal;
@ -316,7 +318,7 @@ int git_config_add_backend(
GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend"); GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
if ((result = file->open(file, level)) < 0) if ((result = file->open(file, level, repo)) < 0)
return result; return result;
internal = git__malloc(sizeof(file_internal)); internal = git__malloc(sizeof(file_internal));
@ -1147,20 +1149,20 @@ int git_config_open_default(git_config **out)
if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) { if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
error = git_config_add_file_ondisk(cfg, buf.ptr, error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_GLOBAL, 0); GIT_CONFIG_LEVEL_GLOBAL, NULL, 0);
} }
if (!error && !git_config_find_xdg(&buf)) if (!error && !git_config_find_xdg(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr, error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_XDG, 0); GIT_CONFIG_LEVEL_XDG, NULL, 0);
if (!error && !git_config_find_system(&buf)) if (!error && !git_config_find_system(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr, error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_SYSTEM, 0); GIT_CONFIG_LEVEL_SYSTEM, NULL, 0);
if (!error && !git_config_find_programdata(&buf)) if (!error && !git_config_find_programdata(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr, error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_PROGRAMDATA, 0); GIT_CONFIG_LEVEL_PROGRAMDATA, NULL, 0);
git_buf_free(&buf); git_buf_free(&buf);

View File

@ -7,6 +7,8 @@
#ifndef INCLUDE_config_h__ #ifndef INCLUDE_config_h__
#define INCLUDE_config_h__ #define INCLUDE_config_h__
#include "common.h"
#include "git2.h" #include "git2.h"
#include "git2/config.h" #include "git2/config.h"
#include "vector.h" #include "vector.h"

View File

@ -6,6 +6,7 @@
*/ */
#include "common.h" #include "common.h"
#include "fileops.h" #include "fileops.h"
#include "repository.h" #include "repository.h"
#include "config.h" #include "config.h"

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,14 @@
#ifndef INCLUDE_config_file_h__ #ifndef INCLUDE_config_file_h__
#define INCLUDE_config_file_h__ #define INCLUDE_config_file_h__
#include "common.h"
#include "git2/sys/config.h" #include "git2/sys/config.h"
#include "git2/config.h" #include "git2/config.h"
GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level) GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level, const git_repository *repo)
{ {
return cfg->open(cfg, level); return cfg->open(cfg, level, repo);
} }
GIT_INLINE(void) git_config_file_free(git_config_backend *cfg) GIT_INLINE(void) git_config_file_free(git_config_backend *cfg)
@ -69,4 +71,3 @@ GIT_INLINE(int) git_config_file_unlock(git_config_backend *cfg, int success)
extern int git_config_file_normalize_section(char *start, char *end); extern int git_config_file_normalize_section(char *start, char *end);
#endif #endif

525
src/config_parse.c Normal file
View File

@ -0,0 +1,525 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "config_parse.h"
#include "buf_text.h"
#include <ctype.h>
static void set_parse_error(git_config_parser *reader, int col, const char *error_str)
{
giterr_set(GITERR_CONFIG, "failed to parse config file: %s (in %s:%"PRIuZ", column %d)",
error_str, reader->file->path, reader->ctx.line_num, col);
}
GIT_INLINE(int) config_keychar(int c)
{
return isalnum(c) || c == '-';
}
static int strip_comments(char *line, int in_quotes)
{
int quote_count = in_quotes, backslash_count = 0;
char *ptr;
for (ptr = line; *ptr; ++ptr) {
if (ptr[0] == '"' && ptr > line && ptr[-1] != '\\')
quote_count++;
if ((ptr[0] == ';' || ptr[0] == '#') &&
(quote_count % 2) == 0 &&
(backslash_count % 2) == 0) {
ptr[0] = '\0';
break;
}
if (ptr[0] == '\\')
backslash_count++;
else
backslash_count = 0;
}
/* skip any space at the end */
while (ptr > line && git__isspace(ptr[-1])) {
ptr--;
}
ptr[0] = '\0';
return quote_count;
}
static int parse_section_header_ext(git_config_parser *reader, const char *line, const char *base_name, char **section_name)
{
int c, rpos;
char *first_quote, *last_quote;
git_buf buf = GIT_BUF_INIT;
size_t quoted_len, alloc_len, base_name_len = strlen(base_name);
/*
* base_name is what came before the space. We should be at the
* first quotation mark, except for now, line isn't being kept in
* sync so we only really use it to calculate the length.
*/
first_quote = strchr(line, '"');
if (first_quote == NULL) {
set_parse_error(reader, 0, "Missing quotation marks in section header");
goto end_error;
}
last_quote = strrchr(line, '"');
quoted_len = last_quote - first_quote;
if (quoted_len == 0) {
set_parse_error(reader, 0, "Missing closing quotation mark in section header");
goto end_error;
}
GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
if (git_buf_grow(&buf, alloc_len) < 0 ||
git_buf_printf(&buf, "%s.", base_name) < 0)
goto end_error;
rpos = 0;
line = first_quote;
c = line[++rpos];
/*
* At the end of each iteration, whatever is stored in c will be
* added to the string. In case of error, jump to out
*/
do {
switch (c) {
case 0:
set_parse_error(reader, 0, "Unexpected end-of-line in section header");
goto end_error;
case '"':
goto end_parse;
case '\\':
c = line[++rpos];
if (c == 0) {
set_parse_error(reader, rpos, "Unexpected end-of-line in section header");
goto end_error;
}
default:
break;
}
git_buf_putc(&buf, (char)c);
c = line[++rpos];
} while (line + rpos < last_quote);
end_parse:
if (git_buf_oom(&buf))
goto end_error;
if (line[rpos] != '"' || line[rpos + 1] != ']') {
set_parse_error(reader, rpos, "Unexpected text after closing quotes");
git_buf_free(&buf);
return -1;
}
*section_name = git_buf_detach(&buf);
return 0;
end_error:
git_buf_free(&buf);
return -1;
}
static int parse_section_header(git_config_parser *reader, char **section_out)
{
char *name, *name_end;
int name_length, c, pos;
int result;
char *line;
size_t line_len;
git_parse_advance_ws(&reader->ctx);
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
if (line == NULL)
return -1;
/* find the end of the variable's name */
name_end = strrchr(line, ']');
if (name_end == NULL) {
git__free(line);
set_parse_error(reader, 0, "Missing ']' in section header");
return -1;
}
GITERR_CHECK_ALLOC_ADD(&line_len, (size_t)(name_end - line), 1);
name = git__malloc(line_len);
GITERR_CHECK_ALLOC(name);
name_length = 0;
pos = 0;
/* Make sure we were given a section header */
c = line[pos++];
assert(c == '[');
c = line[pos++];
do {
if (git__isspace(c)){
name[name_length] = '\0';
result = parse_section_header_ext(reader, line, name, section_out);
git__free(line);
git__free(name);
return result;
}
if (!config_keychar(c) && c != '.') {
set_parse_error(reader, pos, "Unexpected character in header");
goto fail_parse;
}
name[name_length++] = (char)git__tolower(c);
} while ((c = line[pos++]) != ']');
if (line[pos - 1] != ']') {
set_parse_error(reader, pos, "Unexpected end of file");
goto fail_parse;
}
git__free(line);
name[name_length] = 0;
*section_out = name;
return 0;
fail_parse:
git__free(line);
git__free(name);
return -1;
}
static int skip_bom(git_parse_ctx *parser)
{
git_buf buf = GIT_BUF_INIT_CONST(parser->content, parser->content_len);
git_bom_t bom;
int bom_offset = git_buf_text_detect_bom(&bom, &buf);
if (bom == GIT_BOM_UTF8)
git_parse_advance_chars(parser, bom_offset);
/* TODO: reference implementation is pretty stupid with BoM */
return 0;
}
/*
(* basic types *)
digit = "0".."9"
integer = digit { digit }
alphabet = "a".."z" + "A" .. "Z"
section_char = alphabet | "." | "-"
extension_char = (* any character except newline *)
any_char = (* any character *)
variable_char = "alphabet" | "-"
(* actual grammar *)
config = { section }
section = header { definition }
header = "[" section [subsection | subsection_ext] "]"
subsection = "." section
subsection_ext = "\"" extension "\""
section = section_char { section_char }
extension = extension_char { extension_char }
definition = variable_name ["=" variable_value] "\n"
variable_name = variable_char { variable_char }
variable_value = string | boolean | integer
string = quoted_string | plain_string
quoted_string = "\"" plain_string "\""
plain_string = { any_char }
boolean = boolean_true | boolean_false
boolean_true = "yes" | "1" | "true" | "on"
boolean_false = "no" | "0" | "false" | "off"
*/
/* '\"' -> '"' etc */
static int unescape_line(
char **out, bool *is_multi, const char *ptr, int quote_count)
{
char *str, *fixed, *esc;
size_t ptr_len = strlen(ptr), alloc_len;
*is_multi = false;
if (GIT_ADD_SIZET_OVERFLOW(&alloc_len, ptr_len, 1) ||
(str = git__malloc(alloc_len)) == NULL) {
return -1;
}
fixed = str;
while (*ptr != '\0') {
if (*ptr == '"') {
quote_count++;
} else if (*ptr != '\\') {
*fixed++ = *ptr;
} else {
/* backslash, check the next char */
ptr++;
/* if we're at the end, it's a multiline, so keep the backslash */
if (*ptr == '\0') {
*is_multi = true;
goto done;
}
if ((esc = strchr(git_config_escapes, *ptr)) != NULL) {
*fixed++ = git_config_escaped[esc - git_config_escapes];
} else {
git__free(str);
giterr_set(GITERR_CONFIG, "invalid escape at %s", ptr);
return -1;
}
}
ptr++;
}
done:
*fixed = '\0';
*out = str;
return 0;
}
static int parse_multiline_variable(git_config_parser *reader, git_buf *value, int in_quotes)
{
char *line = NULL, *proc_line = NULL;
int quote_count;
bool multiline;
/* Check that the next line exists */
git_parse_advance_line(&reader->ctx);
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
if (line == NULL)
return -1;
/* We've reached the end of the file, there is no continuation.
* (this is not an error).
*/
if (line[0] == '\0') {
git__free(line);
return 0;
}
quote_count = strip_comments(line, !!in_quotes);
/* If it was just a comment, pretend it didn't exist */
if (line[0] == '\0') {
git__free(line);
return parse_multiline_variable(reader, value, quote_count);
/* TODO: unbounded recursion. This **could** be exploitable */
}
if (unescape_line(&proc_line, &multiline, line, in_quotes) < 0) {
git__free(line);
return -1;
}
/* add this line to the multiline var */
git_buf_puts(value, proc_line);
git__free(line);
git__free(proc_line);
/*
* If we need to continue reading the next line, let's just
* keep putting stuff in the buffer
*/
if (multiline)
return parse_multiline_variable(reader, value, quote_count);
return 0;
}
GIT_INLINE(bool) is_namechar(char c)
{
return isalnum(c) || c == '-';
}
static int parse_name(
char **name, const char **value, git_config_parser *reader, const char *line)
{
const char *name_end = line, *value_start;
*name = NULL;
*value = NULL;
while (*name_end && is_namechar(*name_end))
name_end++;
if (line == name_end) {
set_parse_error(reader, 0, "Invalid configuration key");
return -1;
}
value_start = name_end;
while (*value_start && git__isspace(*value_start))
value_start++;
if (*value_start == '=') {
*value = value_start + 1;
} else if (*value_start) {
set_parse_error(reader, 0, "Invalid configuration key");
return -1;
}
if ((*name = git__strndup(line, name_end - line)) == NULL)
return -1;
return 0;
}
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value)
{
const char *value_start = NULL;
char *line;
int quote_count;
bool multiline;
git_parse_advance_ws(&reader->ctx);
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
if (line == NULL)
return -1;
quote_count = strip_comments(line, 0);
/* If there is no value, boolean true is assumed */
*var_value = NULL;
if (parse_name(var_name, &value_start, reader, line) < 0)
goto on_error;
/*
* Now, let's try to parse the value
*/
if (value_start != NULL) {
while (git__isspace(value_start[0]))
value_start++;
if (unescape_line(var_value, &multiline, value_start, 0) < 0)
goto on_error;
if (multiline) {
git_buf multi_value = GIT_BUF_INIT;
git_buf_attach(&multi_value, *var_value, 0);
if (parse_multiline_variable(reader, &multi_value, quote_count) < 0 ||
git_buf_oom(&multi_value)) {
git_buf_free(&multi_value);
goto on_error;
}
*var_value = git_buf_detach(&multi_value);
}
}
git__free(line);
return 0;
on_error:
git__free(*var_name);
git__free(line);
return -1;
}
int git_config_parse(
git_config_parser *parser,
git_config_parser_section_cb on_section,
git_config_parser_variable_cb on_variable,
git_config_parser_comment_cb on_comment,
git_config_parser_eof_cb on_eof,
void *data)
{
git_parse_ctx *ctx;
char *current_section = NULL, *var_name, *var_value;
int result = 0;
ctx = &parser->ctx;
skip_bom(ctx);
for (; ctx->remain_len > 0; git_parse_advance_line(ctx)) {
const char *line_start = parser->ctx.line;
size_t line_len = parser->ctx.line_len;
char c;
/*
* Get either first non-whitespace character or, if that does
* not exist, the first whitespace character. This is required
* to preserve whitespaces when writing back the file.
*/
if (git_parse_peek(&c, ctx, GIT_PARSE_PEEK_SKIP_WHITESPACE) < 0 &&
git_parse_peek(&c, ctx, 0) < 0)
continue;
switch (c) {
case '[': /* section header, new section begins */
git__free(current_section);
current_section = NULL;
if ((result = parse_section_header(parser, &current_section)) == 0 && on_section) {
result = on_section(parser, current_section, line_start, line_len, data);
}
break;
case '\n': /* comment or whitespace-only */
case '\r':
case ' ':
case '\t':
case ';':
case '#':
if (on_comment) {
result = on_comment(parser, line_start, line_len, data);
}
break;
default: /* assume variable declaration */
if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, data);
}
break;
}
if (result < 0)
goto out;
}
if (on_eof)
result = on_eof(parser, current_section, data);
out:
git__free(current_section);
return result;
}

64
src/config_parse.h Normal file
View File

@ -0,0 +1,64 @@
/*
* 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_config_parse_h__
#define INCLUDE_config_parse_h__
#include "common.h"
#include "array.h"
#include "oid.h"
#include "parse.h"
static const char *git_config_escapes = "ntb\"\\";
static const char *git_config_escaped = "\n\t\b\"\\";
typedef struct config_file {
git_oid checksum;
char *path;
git_array_t(struct config_file) includes;
} git_config_file;
typedef struct {
struct config_file *file;
git_parse_ctx ctx;
} git_config_parser;
typedef int (*git_config_parser_section_cb)(
git_config_parser *parser,
const char *current_section,
const char *line,
size_t line_len,
void *data);
typedef int (*git_config_parser_variable_cb)(
git_config_parser *parser,
const char *current_section,
char *var_name,
char *var_value,
const char *line,
size_t line_len,
void *data);
typedef int (*git_config_parser_comment_cb)(
git_config_parser *parser,
const char *line,
size_t line_len,
void *data);
typedef int (*git_config_parser_eof_cb)(
git_config_parser *parser,
const char *current_section,
void *data);
int git_config_parse(
git_config_parser *parser,
git_config_parser_section_cb on_section,
git_config_parser_variable_cb on_variable,
git_config_parser_comment_cb on_comment,
git_config_parser_eof_cb on_eof,
void *data);
#endif

View File

@ -5,12 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h"
#include "git2/attr.h" #include "git2/attr.h"
#include "git2/blob.h" #include "git2/blob.h"
#include "git2/index.h" #include "git2/index.h"
#include "git2/sys/filter.h" #include "git2/sys/filter.h"
#include "common.h"
#include "fileops.h" #include "fileops.h"
#include "hash.h" #include "hash.h"
#include "filter.h" #include "filter.h"

View File

@ -6,6 +6,7 @@
#define INCLUDE_git_delta_h__ #define INCLUDE_git_delta_h__
#include "common.h" #include "common.h"
#include "pack.h" #include "pack.h"
typedef struct git_delta_index git_delta_index; typedef struct git_delta_index git_delta_index;

View File

@ -4,12 +4,14 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with * This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#include "common.h"
#include "git2/describe.h" #include "git2/describe.h"
#include "git2/strarray.h" #include "git2/strarray.h"
#include "git2/diff.h" #include "git2/diff.h"
#include "git2/status.h" #include "git2/status.h"
#include "common.h"
#include "commit.h" #include "commit.h"
#include "commit_list.h" #include "commit_list.h"
#include "oidmap.h" #include "oidmap.h"

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