summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2017-10-29 12:08:00 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2017-10-29 12:08:00 +0100
commit1b9cc2ece515aba1d11c48c42c7a62d58a61c3f0 (patch)
tree65cc0b52e659521377150783f5c03dfad70e9ebb /src
parent5efe9d125f09a44e1581cf7d37cf4d36161f5d4d (diff)
parent524c1d3c9eef1f63d058ca5d4a61af7d5588ebfb (diff)
downloadlibgit2-1b9cc2ece515aba1d11c48c42c7a62d58a61c3f0.tar.gz
Merge remote-tracking branch 'upstream/master' into diff-indent-heuristic
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt400
-rw-r--r--src/annotated_commit.c2
-rw-r--r--src/annotated_commit.h2
-rw-r--r--src/apply.c7
-rw-r--r--src/apply.h2
-rw-r--r--src/attr.c50
-rw-r--r--src/attr.h2
-rw-r--r--src/attr_file.c29
-rw-r--r--src/attr_file.h4
-rw-r--r--src/attrcache.c59
-rw-r--r--src/attrcache.h7
-rw-r--r--src/blame.c1
-rw-r--r--src/blame.h3
-rw-r--r--src/blame_git.c21
-rw-r--r--src/blame_git.h2
-rw-r--r--src/blob.c14
-rw-r--r--src/blob.h2
-rw-r--r--src/branch.c64
-rw-r--r--src/branch.h2
-rw-r--r--src/buf_text.h2
-rw-r--r--src/buffer.c31
-rw-r--r--src/buffer.h7
-rw-r--r--src/cache.c52
-rw-r--r--src/cache.h4
-rw-r--r--src/checkout.c75
-rw-r--r--src/checkout.h2
-rw-r--r--src/cherrypick.c9
-rw-r--r--src/clone.c8
-rw-r--r--src/clone.h4
-rw-r--r--src/commit.c26
-rw-r--r--src/commit.h2
-rw-r--r--src/commit_list.c17
-rw-r--r--src/commit_list.h3
-rw-r--r--src/common.h13
-rw-r--r--src/config.c109
-rw-r--r--src/config.h2
-rw-r--r--src/config_cache.c2
-rw-r--r--src/config_file.c343
-rw-r--r--src/config_file.h3
-rw-r--r--src/crlf.c5
-rw-r--r--src/curl_stream.c23
-rw-r--r--src/curl_stream.h2
-rw-r--r--src/delta.c8
-rw-r--r--src/delta.h1
-rw-r--r--src/describe.c30
-rw-r--r--src/diff.c185
-rw-r--r--src/diff.h2
-rw-r--r--src/diff_driver.c19
-rw-r--r--src/diff_driver.h1
-rw-r--r--src/diff_file.c7
-rw-r--r--src/diff_file.h1
-rw-r--r--src/diff_generate.c9
-rw-r--r--src/diff_generate.h6
-rw-r--r--src/diff_parse.c13
-rw-r--r--src/diff_parse.h2
-rw-r--r--src/diff_print.c12
-rw-r--r--src/diff_stats.c30
-rw-r--r--src/diff_tform.c9
-rw-r--r--src/diff_tform.h4
-rw-r--r--src/diff_xdiff.c9
-rw-r--r--src/diff_xdiff.h2
-rw-r--r--src/errors.c2
-rw-r--r--src/features.h.in36
-rw-r--r--src/fetch.c6
-rw-r--r--src/fetch.h4
-rw-r--r--src/fetchhead.c26
-rw-r--r--src/fetchhead.h3
-rw-r--r--src/filebuf.c34
-rw-r--r--src/filebuf.h6
-rw-r--r--src/fileops.c176
-rw-r--r--src/fileops.h30
-rw-r--r--src/filter.c55
-rw-r--r--src/filter.h1
-rw-r--r--src/fnmatch.c4
-rw-r--r--src/global.c28
-rw-r--r--src/global.h7
-rw-r--r--src/graph.c4
-rw-r--r--src/hash.c1
-rw-r--r--src/hash.h10
-rw-r--r--src/hash/hash_collisiondetect.h47
-rw-r--r--src/hash/hash_generic.c4
-rw-r--r--src/hash/hash_generic.h2
-rw-r--r--src/hash/hash_win32.c4
-rw-r--r--src/hash/hash_win32.h1
-rw-r--r--src/hash/sha1dc/sha1.c1856
-rw-r--r--src/hash/sha1dc/sha1.h110
-rw-r--r--src/hash/sha1dc/ubc_check.c372
-rw-r--r--src/hash/sha1dc/ubc_check.h52
-rw-r--r--src/hashsig.c7
-rw-r--r--src/ident.c2
-rw-r--r--src/idxmap.c133
-rw-r--r--src/idxmap.h76
-rw-r--r--src/ignore.c112
-rw-r--r--src/ignore.h4
-rw-r--r--src/index.c178
-rw-r--r--src/index.h2
-rw-r--r--src/indexer.c109
-rw-r--r--src/indexer.h16
-rw-r--r--src/integer.h12
-rw-r--r--src/iterator.c3
-rw-r--r--src/iterator.h1
-rw-r--r--src/merge.c243
-rw-r--r--src/merge.h2
-rw-r--r--src/merge_driver.c33
-rw-r--r--src/merge_driver.h2
-rw-r--r--src/merge_file.c3
-rw-r--r--src/message.h2
-rw-r--r--src/mwindow.c8
-rw-r--r--src/mwindow.h2
-rw-r--r--src/netops.c12
-rw-r--r--src/netops.h3
-rw-r--r--src/notes.c6
-rw-r--r--src/object.c14
-rw-r--r--src/object.h2
-rw-r--r--src/object_api.c5
-rw-r--r--src/odb.c151
-rw-r--r--src/odb.h30
-rw-r--r--src/odb_loose.c39
-rw-r--r--src/odb_mempack.c33
-rw-r--r--src/odb_pack.c3
-rw-r--r--src/offmap.c83
-rw-r--r--src/offmap.h48
-rw-r--r--src/oid.c13
-rw-r--r--src/oid.h11
-rw-r--r--src/oidarray.c3
-rw-r--r--src/oidarray.h1
-rw-r--r--src/oidmap.c105
-rw-r--r--src/oidmap.h41
-rw-r--r--src/openssl_stream.c93
-rw-r--r--src/openssl_stream.h108
-rw-r--r--src/pack-objects.c39
-rw-r--r--src/pack-objects.h1
-rw-r--r--src/pack.c107
-rw-r--r--src/pack.h4
-rw-r--r--src/patch.c11
-rw-r--r--src/patch.h2
-rw-r--r--src/patch_generate.c100
-rw-r--r--src/patch_generate.h1
-rw-r--r--src/patch_parse.c67
-rw-r--r--src/patch_parse.h4
-rw-r--r--src/path.c121
-rw-r--r--src/path.h1
-rw-r--r--src/pathspec.c7
-rw-r--r--src/pathspec.h3
-rw-r--r--src/pool.c8
-rw-r--r--src/pool.h1
-rw-r--r--src/posix.c9
-rw-r--r--src/posix.h11
-rw-r--r--src/pqueue.c18
-rw-r--r--src/pqueue.h3
-rw-r--r--src/proxy.c3
-rw-r--r--src/proxy.h4
-rw-r--r--src/push.c19
-rw-r--r--src/push.h2
-rw-r--r--src/rebase.c59
-rw-r--r--src/refdb.c13
-rw-r--r--src/refdb.h2
-rw-r--r--src/refdb_fs.c321
-rw-r--r--src/refdb_fs.h4
-rw-r--r--src/reflog.c5
-rw-r--r--src/reflog.h1
-rw-r--r--src/refs.c159
-rw-r--r--src/refs.h18
-rw-r--r--src/refspec.c4
-rw-r--r--src/refspec.h2
-rw-r--r--src/remote.c72
-rw-r--r--src/remote.h2
-rw-r--r--src/repository.c620
-rw-r--r--src/repository.h37
-rw-r--r--src/reset.c13
-rw-r--r--src/revert.c9
-rw-r--r--src/revparse.c40
-rw-r--r--src/revwalk.c463
-rw-r--r--src/revwalk.h2
-rw-r--r--src/settings.c38
-rw-r--r--src/sha1_lookup.c222
-rw-r--r--src/sha1_lookup.h8
-rw-r--r--src/signature.c12
-rw-r--r--src/signature.h2
-rw-r--r--src/socket_stream.c20
-rw-r--r--src/socket_stream.h2
-rw-r--r--src/sortedcache.c42
-rw-r--r--src/sortedcache.h2
-rw-r--r--src/stash.c13
-rw-r--r--src/status.c12
-rw-r--r--src/status.h2
-rw-r--r--src/stransport_stream.c2
-rw-r--r--src/stransport_stream.h2
-rw-r--r--src/strmap.c95
-rw-r--r--src/strmap.h54
-rw-r--r--src/submodule.c335
-rw-r--r--src/submodule.h5
-rw-r--r--src/sysdir.c19
-rw-r--r--src/sysdir.h13
-rw-r--r--src/tag.c32
-rw-r--r--src/tag.h2
-rw-r--r--src/thread-utils.c1
-rw-r--r--src/thread-utils.h6
-rw-r--r--src/tls_stream.c3
-rw-r--r--src/tls_stream.h2
-rw-r--r--src/trace.c6
-rw-r--r--src/trace.h2
-rw-r--r--src/transaction.c25
-rw-r--r--src/transport.c4
-rw-r--r--src/transports/auth.c3
-rw-r--r--src/transports/auth.h2
-rw-r--r--src/transports/auth_negotiate.c11
-rw-r--r--src/transports/auth_negotiate.h1
-rw-r--r--src/transports/cred.c4
-rw-r--r--src/transports/cred.h2
-rw-r--r--src/transports/cred_helpers.c1
-rw-r--r--src/transports/git.c8
-rw-r--r--src/transports/http.c23
-rw-r--r--src/transports/local.c10
-rw-r--r--src/transports/smart.c20
-rw-r--r--src/transports/smart.h5
-rw-r--r--src/transports/smart_pkt.c26
-rw-r--r--src/transports/smart_protocol.c41
-rw-r--r--src/transports/ssh.c35
-rw-r--r--src/transports/ssh.h2
-rw-r--r--src/transports/winhttp.c297
-rw-r--r--src/tree-cache.c5
-rw-r--r--src/tree-cache.h1
-rw-r--r--src/tree.c101
-rw-r--r--src/tree.h2
-rw-r--r--src/tsort.c1
-rw-r--r--src/unix/map.c7
-rw-r--r--src/unix/posix.h25
-rw-r--r--src/unix/pthread.h2
-rw-r--r--src/unix/realpath.c5
-rw-r--r--src/util.c12
-rw-r--r--src/util.h134
-rw-r--r--src/varint.c3
-rw-r--r--src/varint.h2
-rw-r--r--src/vector.c21
-rw-r--r--src/vector.h5
-rw-r--r--src/win32/dir.c9
-rw-r--r--src/win32/dir.h1
-rw-r--r--src/win32/error.c2
-rw-r--r--src/win32/error.h2
-rw-r--r--src/win32/findfile.c5
-rw-r--r--src/win32/findfile.h2
-rw-r--r--src/win32/map.c14
-rw-r--r--src/win32/path_w32.c4
-rw-r--r--src/win32/path_w32.h1
-rw-r--r--src/win32/posix.h6
-rw-r--r--src/win32/posix_w32.c451
-rw-r--r--src/win32/precompiled.h3
-rw-r--r--src/win32/thread.c19
-rw-r--r--src/win32/thread.h4
-rw-r--r--src/win32/utf-conv.c1
-rw-r--r--src/win32/utf-conv.h3
-rw-r--r--src/win32/w32_buffer.c2
-rw-r--r--src/win32/w32_buffer.h2
-rw-r--r--src/win32/w32_crtdbg_stacktrace.c7
-rw-r--r--src/win32/w32_crtdbg_stacktrace.h83
-rw-r--r--src/win32/w32_stack.c3
-rw-r--r--src/win32/w32_stack.h2
-rw-r--r--src/win32/w32_util.c2
-rw-r--r--src/win32/w32_util.h4
-rw-r--r--src/worktree.c557
-rw-r--r--src/worktree.h37
-rw-r--r--src/zstream.c7
-rw-r--r--src/zstream.h3
264 files changed, 8990 insertions, 2840 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 000000000..3392a4218
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,400 @@
+IF(DEBUG_POOL)
+ SET(GIT_DEBUG_POOL 1)
+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 "")
+
+SET(LIBGIT2_INCLUDES
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_SOURCE_DIR}/src"
+ "${CMAKE_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()
+
+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()
+
+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")
+ LIST(APPEND LIBGIT2_LIBS ${SECURITY_DIRS})
+ ELSE()
+ MESSAGE("-- Security framework is too old, falling back to OpenSSL")
+ SET(SECURITY_FOUND "NO")
+ SET(USE_OPENSSL "ON")
+ ENDIF()
+ENDIF()
+
+IF (COREFOUNDATION_FOUND)
+ MESSAGE("-- Found CoreFoundation ${COREFOUNDATION_DIRS}")
+ LIST(APPEND LIBGIT2_PC_LIBS "-framework CoreFoundation")
+ LIST(APPEND LIBGIT2_LIBS ${COREFOUNDATION_DIRS})
+ENDIF()
+
+
+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)
+ SET(GIT_HTTPS 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("${CMAKE_SOURCE_DIR}/deps/winhttp" "${CMAKE_BINARY_DIR}/deps/winhttp")
+ LIST(APPEND LIBGIT2_LIBS winhttp)
+ LIST(APPEND LIBGIT2_INCLUDES "${CMAKE_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 (NOT AMIGA AND USE_OPENSSL)
+ FIND_PACKAGE(OpenSSL)
+ 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()
+ENDIF()
+
+# Specify sha1 implementation
+IF (USE_SHA1DC)
+ 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 (WIN32 AND NOT MINGW)
+ SET(GIT_SHA1_WIN32 1)
+ FILE(GLOB SRC_SHA1 hash/hash_win32.c)
+ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ SET(GIT_SHA1_COMMON_CRYPTO 1)
+ELSEIF (OPENSSL_FOUND)
+ SET(GIT_SHA1_OPENSSL 1)
+ 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 hash/hash_generic.c)
+ENDIF()
+
+
+# Include POSIX regex when it is required
+IF(WIN32 OR AMIGA OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+ ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/deps/regex" "${CMAKE_BINARY_DIR}/deps/regex")
+ LIST(APPEND LIBGIT2_INCLUDES "${CMAKE_SOURCE_DIR}/deps/regex")
+ LIST(APPEND LIBGIT2_LIBS 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")
+ELSE()
+ MESSAGE(STATUS "http-parser version 2 was not found or disabled; using bundled 3rd-party sources.")
+ ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/deps/http-parser" "${CMAKE_BINARY_DIR}/deps/http-parser")
+ LIST(APPEND LIBGIT2_INCLUDES "${CMAKE_SOURCE_DIR}/deps/http-parser")
+ LIST(APPEND LIBGIT2_LIBS http-parser)
+ENDIF()
+
+# Optional external dependency: 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()
+ SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib")
+ ENDIF()
+ELSE()
+ MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
+ ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/deps/zlib" "${CMAKE_BINARY_DIR}/deps/zlib")
+ LIST(APPEND LIBGIT2_INCLUDES "${CMAKE_SOURCE_DIR}/deps/zlib")
+ LIST(APPEND LIBGIT2_LIBS 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()
+
+# 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()
+
+# 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()
+
+IF (SECURITY_FOUND)
+ SET(GIT_SECURE_TRANSPORT 1)
+ SET(GIT_HTTPS 1)
+ LIST(APPEND LIBGIT2_INCLUDES ${SECURITY_INCLUDE_DIR})
+ENDIF ()
+
+IF (OPENSSL_FOUND)
+ SET(GIT_OPENSSL 1)
+ SET(GIT_HTTPS 1)
+ LIST(APPEND LIBGIT2_INCLUDES ${OPENSSL_INCLUDE_DIR})
+ LIST(APPEND LIBGIT2_LIBS ${OPENSSL_LIBRARIES})
+ENDIF()
+
+
+
+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
+ "${CMAKE_SOURCE_DIR}/include/git2.h"
+ "${CMAKE_SOURCE_DIR}/include/git2/*.h"
+ "${CMAKE_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 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(GIT2INTERNAL_OBJECTS ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_SSH} ${SRC_SHA1})
+
+IF (CMAKE_VERSION VERSION_GREATER 2.8.7)
+ ADD_LIBRARY(git2internal OBJECT ${GIT2INTERNAL_OBJECTS})
+ IDE_SPLIT_SOURCES(git2internal)
+ SET(GIT2INTERNAL_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 ${CMAKE_SOURCE_DIR}/include)
+ ENDIF()
+ELSE()
+ INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
+ENDIF()
+
+SET(GIT2INTERNAL_OBJECTS ${GIT2INTERNAL_OBJECTS} PARENT_SCOPE)
+SET(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
+SET(LIBGIT2_LIBS ${LIBGIT2_LIBS} PARENT_SCOPE)
+SET(LIBGIT2_LIBDIRS ${LIBGIT2_LIBDIRS} PARENT_SCOPE)
+
+# Compile and link libgit2
+LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
+ADD_LIBRARY(git2 ${WIN_RC} ${GIT2INTERNAL_OBJECTS})
+TARGET_LINK_LIBRARIES(git2 ${LIBGIT2_LIBS})
+
+SET_TARGET_PROPERTIES(git2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+SET_TARGET_PROPERTIES(git2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+SET_TARGET_PROPERTIES(git2 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_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()
+STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libgit2.pc.in ${CMAKE_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 ${CMAKE_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
+INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} )
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} )
diff --git a/src/annotated_commit.c b/src/annotated_commit.c
index c2c770cba..72ba80a22 100644
--- a/src/annotated_commit.c
+++ b/src/annotated_commit.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "annotated_commit.h"
+
#include "refs.h"
#include "cache.h"
diff --git a/src/annotated_commit.h b/src/annotated_commit.h
index 3ac8b5f69..b390066b2 100644
--- a/src/annotated_commit.h
+++ b/src/annotated_commit.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_annotated_commit_h__
#define INCLUDE_annotated_commit_h__
+#include "common.h"
+
#include "oidarray.h"
#include "git2/oid.h"
diff --git a/src/apply.c b/src/apply.c
index f70172469..7801a0a54 100644
--- a/src/apply.c
+++ b/src/apply.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "apply.h"
+
#include <assert.h>
#include "git2/patch.h"
@@ -12,7 +14,6 @@
#include "array.h"
#include "patch.h"
#include "fileops.h"
-#include "apply.h"
#include "delta.h"
#include "zstream.h"
@@ -173,7 +174,7 @@ static int apply_hunk(
git_diff_line *line = git_array_get(patch->lines, linenum);
if (!line) {
- error = apply_err("Preimage does not contain line %d", linenum);
+ error = apply_err("preimage does not contain line %"PRIuZ, linenum);
goto done;
}
@@ -193,7 +194,7 @@ static int apply_hunk(
line_num = hunk->hunk.new_start ? hunk->hunk.new_start - 1 : 0;
if (!find_hunk_linenum(&line_num, image, &preimage, line_num)) {
- error = apply_err("Hunk at line %d did not apply",
+ error = apply_err("hunk at line %d did not apply",
hunk->hunk.new_start);
goto done;
}
diff --git a/src/apply.h b/src/apply.h
index 96e0f55b5..b29460c0b 100644
--- a/src/apply.h
+++ b/src/apply.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_apply_h__
#define INCLUDE_apply_h__
+#include "common.h"
+
#include "git2/patch.h"
#include "buffer.h"
diff --git a/src/attr.c b/src/attr.c
index d43a15f50..17309d0eb 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -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 "sysdir.h"
#include "config.h"
@@ -7,8 +15,6 @@
#include "git2/oid.h"
#include <ctype.h>
-GIT__USE_STRMAP
-
const char *git_attr__true = "[internal]__TRUE__";
const char *git_attr__false = "[internal]__FALSE__";
const char *git_attr__unset = "[internal]__UNSET__";
@@ -209,7 +215,7 @@ int git_attr_foreach(
if (git_strmap_exists(seen, assign->name))
continue;
- git_strmap_insert(seen, assign->name, assign, error);
+ git_strmap_insert(seen, assign->name, assign, &error);
if (error < 0)
goto cleanup;
@@ -292,7 +298,7 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
int error = 0;
const char *workdir = git_repository_workdir(repo);
git_index *idx = NULL;
- git_buf sys = GIT_BUF_INIT;
+ git_buf path = GIT_BUF_INIT;
if (attr_session && attr_session->init_setup)
return 0;
@@ -304,40 +310,45 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
* definitions will be available for later file parsing
*/
- error = system_attr_file(&sys, attr_session);
+ error = system_attr_file(&path, attr_session);
if (error == 0)
error = preload_attr_file(
- repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, sys.ptr);
+ repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, path.ptr);
if (error != GIT_ENOTFOUND)
- return error;
-
- git_buf_free(&sys);
+ goto out;
if ((error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
- return error;
+ goto out;
+
+ if ((error = git_repository_item_path(&path,
+ repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
+ goto out;
if ((error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
- git_repository_path(repo), GIT_ATTR_FILE_INREPO)) < 0)
- return error;
+ path.ptr, GIT_ATTR_FILE_INREPO)) < 0)
+ goto out;
if (workdir != NULL &&
(error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0)
- return error;
+ goto out;
if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
(error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0)
- return error;
+ goto out;
if (attr_session)
attr_session->init_setup = 1;
+out:
+ git_buf_free(&path);
+
return error;
}
@@ -472,7 +483,7 @@ static int collect_attr_files(
git_vector *files)
{
int error = 0;
- git_buf dir = GIT_BUF_INIT;
+ git_buf dir = GIT_BUF_INIT, attrfile = GIT_BUF_INIT;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
@@ -494,9 +505,13 @@ static int collect_attr_files(
* - $GIT_PREFIX/etc/gitattributes
*/
+ error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO);
+ if (error < 0)
+ goto cleanup;
+
error = push_attr_file(
repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
- git_repository_path(repo), GIT_ATTR_FILE_INREPO);
+ attrfile.ptr, GIT_ATTR_FILE_INREPO);
if (error < 0)
goto cleanup;
@@ -538,6 +553,7 @@ static int collect_attr_files(
cleanup:
if (error < 0)
release_attr_files(files);
+ git_buf_free(&attrfile);
git_buf_free(&dir);
return error;
diff --git a/src/attr.h b/src/attr.h
index f9f216d07..977565205 100644
--- a/src/attr.h
+++ b/src/attr.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_h__
#define INCLUDE_attr_h__
+#include "common.h"
+
#include "attr_file.h"
#include "attrcache.h"
diff --git a/src/attr_file.c b/src/attr_file.c
index 11d149358..55d0c3865 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -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 "filebuf.h"
-#include "attr_file.h"
#include "attrcache.h"
#include "git2/blob.h"
#include "git2/tree.h"
@@ -30,7 +37,7 @@ int git_attr_file__new(
GITERR_CHECK_ALLOC(attrs);
if (git_mutex_init(&attrs->lock) < 0) {
- giterr_set(GITERR_OS, "Failed to initialize lock");
+ giterr_set(GITERR_OS, "failed to initialize lock");
git__free(attrs);
return -1;
}
@@ -49,7 +56,7 @@ int git_attr_file__clear_rules(git_attr_file *file, bool need_lock)
git_attr_rule *rule;
if (need_lock && git_mutex_lock(&file->lock) < 0) {
- giterr_set(GITERR_OS, "Failed to lock attribute file");
+ giterr_set(GITERR_OS, "failed to lock attribute file");
return -1;
}
@@ -140,7 +147,7 @@ int git_attr_file__load(
break;
}
default:
- giterr_set(GITERR_INVALID, "Unknown file source %d", source);
+ giterr_set(GITERR_INVALID, "unknown file source %d", source);
return -1;
}
@@ -212,7 +219,7 @@ int git_attr_file__out_of_date(
}
default:
- giterr_set(GITERR_INVALID, "Invalid file type %d", file->source);
+ giterr_set(GITERR_INVALID, "invalid file type %d", file->source);
return -1;
}
}
@@ -238,7 +245,7 @@ int git_attr_file__parse_buffer(
context = attrs->entry->path;
if (git_mutex_lock(&attrs->lock) < 0) {
- giterr_set(GITERR_OS, "Failed to lock attribute file");
+ giterr_set(GITERR_OS, "failed to lock attribute file");
return -1;
}
@@ -395,9 +402,13 @@ bool git_attr_fnmatch__match(
if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) {
bool samename;
- /* for attribute checks or root ignore checks, fail match */
+ /*
+ * for attribute checks or checks at the root of this match's
+ * containing_dir (or root of the repository if no containing_dir),
+ * do not match.
+ */
if (!(match->flags & GIT_ATTR_FNMATCH_IGNORE) ||
- path->basename == path->path)
+ path->basename == relpath)
return false;
flags |= FNM_LEADING_DIR;
diff --git a/src/attr_file.h b/src/attr_file.h
index 388ecf4c0..fedf55af5 100644
--- a/src/attr_file.h
+++ b/src/attr_file.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_attr_file_h__
#define INCLUDE_attr_file_h__
+#include "common.h"
+
#include "git2/oid.h"
#include "git2/attr.h"
#include "vector.h"
@@ -15,7 +17,7 @@
#include "fileops.h"
#define GIT_ATTR_FILE ".gitattributes"
-#define GIT_ATTR_FILE_INREPO "info/attributes"
+#define GIT_ATTR_FILE_INREPO "attributes"
#define GIT_ATTR_FILE_SYSTEM "gitattributes"
#define GIT_ATTR_FILE_XDG "attributes"
diff --git a/src/attrcache.c b/src/attrcache.c
index a57110684..65e7b4655 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -1,18 +1,24 @@
-#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 "attr_file.h"
#include "config.h"
#include "sysdir.h"
#include "ignore.h"
-GIT__USE_STRMAP
-
GIT_INLINE(int) attr_cache_lock(git_attr_cache *cache)
{
GIT_UNUSED(cache); /* avoid warning if threading is off */
if (git_mutex_lock(&cache->lock) < 0) {
- giterr_set(GITERR_OS, "Unable to get attr cache lock");
+ giterr_set(GITERR_OS, "unable to get attr cache lock");
return -1;
}
return 0;
@@ -82,7 +88,7 @@ static int attr_cache_make_entry(
&entry, git_repository_workdir(repo), path, &cache->pool);
if (!error) {
- git_strmap_insert(cache->files, entry->path, entry, error);
+ git_strmap_insert(cache->files, entry->path, entry, &error);
if (error > 0)
error = 0;
}
@@ -105,8 +111,11 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
GIT_REFCOUNT_OWN(file, entry);
GIT_REFCOUNT_INC(file);
- old = git__compare_and_swap(
- &entry->file[file->source], entry->file[file->source], file);
+ /*
+ * Replace the existing value if another thread has
+ * created it in the meantime.
+ */
+ old = git__swap(entry->file[file->source], file);
if (old) {
GIT_REFCOUNT_OWN(old, NULL);
@@ -121,20 +130,22 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
{
int error = 0;
git_attr_file_entry *entry;
+ git_attr_file *old = NULL;
if (!file)
return 0;
+
if ((error = attr_cache_lock(cache)) < 0)
return error;
if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL)
- file = git__compare_and_swap(&entry->file[file->source], file, NULL);
+ old = git__compare_and_swap(&entry->file[file->source], file, NULL);
attr_cache_unlock(cache);
- if (file) {
- GIT_REFCOUNT_OWN(file, NULL);
- git_attr_file__free(file);
+ if (old) {
+ GIT_REFCOUNT_OWN(old, NULL);
+ git_attr_file__free(old);
}
return error;
@@ -287,14 +298,16 @@ static int attr_cache__lookup_path(
const char *cfgval = entry->value;
/* expand leading ~/ as needed */
- if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' &&
- !git_sysdir_find_global_file(&buf, &cfgval[2]))
- *out = git_buf_detach(&buf);
- else if (cfgval)
+ if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') {
+ if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2])))
+ *out = git_buf_detach(&buf);
+ } else if (cfgval) {
*out = git__strdup(cfgval);
+ }
}
- else if (!git_sysdir_find_xdg_file(&buf, fallback))
+ else if (!git_sysdir_find_xdg_file(&buf, fallback)) {
*out = git_buf_detach(&buf);
+ }
git_config_entry_free(entry);
git_buf_free(&buf);
@@ -309,7 +322,7 @@ static void attr_cache__free(git_attr_cache *cache)
if (!cache)
return;
- unlock = (git_mutex_lock(&cache->lock) == 0);
+ unlock = (attr_cache_lock(cache) == 0);
if (cache->files != NULL) {
git_attr_file_entry *entry;
@@ -345,13 +358,13 @@ static void attr_cache__free(git_attr_cache *cache)
cache->cfg_excl_file = NULL;
if (unlock)
- git_mutex_unlock(&cache->lock);
+ attr_cache_unlock(cache);
git_mutex_free(&cache->lock);
git__free(cache);
}
-int git_attr_cache__do_init(git_repository *repo)
+int git_attr_cache__init(git_repository *repo)
{
int ret = 0;
git_attr_cache *cache = git_repository_attr_cache(repo);
@@ -365,7 +378,7 @@ int git_attr_cache__do_init(git_repository *repo)
/* set up lock */
if (git_mutex_init(&cache->lock) < 0) {
- giterr_set(GITERR_OS, "Unable to initialize lock for attr cache");
+ giterr_set(GITERR_OS, "unable to initialize lock for attr cache");
git__free(cache);
return -1;
}
@@ -429,11 +442,11 @@ int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
if (macro->assigns.length == 0)
return 0;
- if (git_mutex_lock(&cache->lock) < 0) {
- giterr_set(GITERR_OS, "Unable to get attr cache lock");
+ if (attr_cache_lock(cache) < 0) {
+ giterr_set(GITERR_OS, "unable to get attr cache lock");
error = -1;
} else {
- git_strmap_insert(macros, macro->match.pattern, macro, error);
+ git_strmap_insert(macros, macro->match.pattern, macro, &error);
git_mutex_unlock(&cache->lock);
}
diff --git a/src/attrcache.h b/src/attrcache.h
index 44e1ffdce..f528911ea 100644
--- a/src/attrcache.h
+++ b/src/attrcache.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_attrcache_h__
#define INCLUDE_attrcache_h__
+#include "common.h"
+
#include "attr_file.h"
#include "strmap.h"
@@ -22,10 +24,7 @@ typedef struct {
git_pool pool;
} git_attr_cache;
-extern int git_attr_cache__do_init(git_repository *repo);
-
-#define git_attr_cache__init(REPO) \
- (git_repository_attr_cache(REPO) ? 0 : git_attr_cache__do_init(REPO))
+extern int git_attr_cache__init(git_repository *repo);
/* get file - loading and reload as needed */
extern int git_attr_cache__get(
diff --git a/src/blame.c b/src/blame.c
index 2c8584ba5..a923bf003 100644
--- a/src/blame.c
+++ b/src/blame.c
@@ -6,6 +6,7 @@
*/
#include "blame.h"
+
#include "git2/commit.h"
#include "git2/revparse.h"
#include "git2/revwalk.h"
diff --git a/src/blame.h b/src/blame.h
index d8db8d5c1..8fd3ee5b1 100644
--- a/src/blame.h
+++ b/src/blame.h
@@ -1,8 +1,9 @@
#ifndef INCLUDE_blame_h__
#define INCLUDE_blame_h__
-#include "git2/blame.h"
#include "common.h"
+
+#include "git2/blame.h"
#include "vector.h"
#include "diff.h"
#include "array.h"
diff --git a/src/blame_git.c b/src/blame_git.c
index 96785c75b..3c221b318 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -6,6 +6,7 @@
*/
#include "blame_git.h"
+
#include "commit.h"
#include "blob.h"
#include "xdiff/xinclude.h"
@@ -478,14 +479,15 @@ cleanup:
* The blobs of origin and porigin exactly match, so everything origin is
* suspected for can be blamed on the parent.
*/
-static void pass_whole_blame(git_blame *blame,
+static int pass_whole_blame(git_blame *blame,
git_blame__origin *origin, git_blame__origin *porigin)
{
git_blame__entry *e;
- if (!porigin->blob)
- git_object_lookup((git_object**)&porigin->blob, blame->repository,
- git_blob_id(origin->blob), GIT_OBJ_BLOB);
+ if (!porigin->blob &&
+ git_object_lookup((git_object**)&porigin->blob, blame->repository,
+ git_blob_id(origin->blob), GIT_OBJ_BLOB) < 0)
+ return -1;
for (e=blame->ent; e; e=e->next) {
if (!same_suspect(e->suspect, origin))
continue;
@@ -493,6 +495,8 @@ static void pass_whole_blame(git_blame *blame,
origin_decref(e->suspect);
e->suspect = porigin;
}
+
+ return 0;
}
static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
@@ -514,11 +518,12 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
if (!num_parents) {
git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit));
goto finish;
- }
- else if (num_parents < (int)ARRAY_SIZE(sg_buf))
+ } else if (num_parents < (int)ARRAY_SIZE(sg_buf))
memset(sg_buf, 0, sizeof(sg_buf));
- else
+ else {
sg_origin = git__calloc(num_parents, sizeof(*sg_origin));
+ GITERR_CHECK_ALLOC(sg_origin);
+ }
for (i=0; i<num_parents; i++) {
git_commit *p;
@@ -543,7 +548,7 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
}
if (porigin->blob && origin->blob &&
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
- pass_whole_blame(blame, origin, porigin);
+ error = pass_whole_blame(blame, origin, porigin);
origin_decref(porigin);
goto finish;
}
diff --git a/src/blame_git.h b/src/blame_git.h
index 1891b0e1f..48b85a20d 100644
--- a/src/blame_git.h
+++ b/src/blame_git.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_blame_git__
#define INCLUDE_blame_git__
+#include "common.h"
+
#include "blame.h"
int git_blame__get_origin(
diff --git a/src/blob.c b/src/blob.c
index 1926c9e58..3396fe74f 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -5,14 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "blob.h"
+
#include "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/odb_backend.h"
-#include "common.h"
#include "filebuf.h"
-#include "blob.h"
#include "filter.h"
#include "buf_text.h"
@@ -96,7 +96,7 @@ static int write_file_stream(
p_close(fd);
if (written != file_size || read_len < 0) {
- giterr_set(GITERR_OS, "Failed to read file into stream");
+ giterr_set(GITERR_OS, "failed to read file into stream");
error = -1;
}
@@ -142,7 +142,7 @@ static int write_symlink(
read_len = p_readlink(path, link_data, link_size);
if (read_len != (ssize_t)link_size) {
- giterr_set(GITERR_OS, "Failed to create blob. Can't read symlink '%s'", path);
+ giterr_set(GITERR_OS, "failed to create blob: cannot read symlink '%s'", path);
git__free(link_data);
return -1;
}
@@ -186,7 +186,7 @@ int git_blob__create_from_paths(
goto done;
if (S_ISDIR(st.st_mode)) {
- giterr_set(GITERR_ODB, "cannot create blob from '%s'; it is a directory", content_path);
+ giterr_set(GITERR_ODB, "cannot create blob from '%s': it is a directory", content_path);
error = GIT_EDIRECTORY;
goto done;
}
@@ -326,8 +326,8 @@ int git_blob_create_fromstream(git_writestream **out, git_repository *repo, cons
stream->parent.close = blob_writestream_close;
stream->parent.free = blob_writestream_free;
- if ((error = git_buf_joinpath(&path,
- git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
+ if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
+ || (error = git_buf_joinpath(&path, path.ptr, "streamed")) < 0)
goto cleanup;
if ((error = git_filebuf_open_withsize(&stream->fbuf, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY,
diff --git a/src/blob.h b/src/blob.h
index 4cd9f1e0c..3f1f97719 100644
--- a/src/blob.h
+++ b/src/blob.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_blob_h__
#define INCLUDE_blob_h__
+#include "common.h"
+
#include "git2/blob.h"
#include "repository.h"
#include "odb.h"
diff --git a/src/branch.c b/src/branch.c
index 51c35d7ff..0697a77fb 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "branch.h"
+
#include "commit.h"
#include "tag.h"
#include "config.h"
@@ -13,6 +14,7 @@
#include "refs.h"
#include "remote.h"
#include "annotated_commit.h"
+#include "worktree.h"
#include "git2/branch.h"
@@ -33,7 +35,7 @@ static int retrieve_branch_reference(
/* OOM */;
else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
giterr_set(
- GITERR_REFERENCE, "Cannot locate %s branch '%s'",
+ GITERR_REFERENCE, "cannot locate %s branch '%s'",
is_remote ? "remote-tracking" : "local", branch_name);
*branch_reference_out = branch; /* will be NULL on error */
@@ -46,7 +48,7 @@ static int not_a_local_branch(const char *reference_name)
{
giterr_set(
GITERR_INVALID,
- "Reference '%s' is not a local branch.", reference_name);
+ "reference '%s' is not a local branch.", reference_name);
return -1;
}
@@ -58,16 +60,17 @@ static int create_branch(
const char *from,
int force)
{
- int is_head = 0;
+ int is_unmovable_head = 0;
git_reference *branch = NULL;
git_buf canonical_branch_name = GIT_BUF_INIT,
log_message = GIT_BUF_INIT;
int error = -1;
+ int bare = git_repository_is_bare(repository);
assert(branch_name && commit && ref_out);
assert(git_object_owner((const git_object *)commit) == repository);
- if (force && 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);
git_reference_free(branch);
branch = NULL;
@@ -75,11 +78,11 @@ static int create_branch(
if (error < 0)
goto cleanup;
- is_head = error;
+ is_unmovable_head = error;
}
- if (is_head && force) {
- giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is "
+ if (is_unmovable_head && force) {
+ giterr_set(GITERR_REFERENCE, "cannot force update branch '%s' as it is "
"the current HEAD of the repository.", branch_name);
error = -1;
goto cleanup;
@@ -125,6 +128,31 @@ int git_branch_create_from_annotated(
repository, branch_name, commit->commit, commit->description, force);
}
+static int branch_equals(git_repository *repo, const char *path, void *payload)
+{
+ git_reference *branch = (git_reference *) payload;
+ git_reference *head = NULL;
+ int equal = 0;
+
+ if (git_reference__read_head(&head, repo, path) < 0 ||
+ git_reference_type(head) != GIT_REF_SYMBOLIC)
+ goto done;
+
+ equal = !git__strcmp(head->target.symbolic, branch->name);
+
+done:
+ git_reference_free(head);
+ return equal;
+}
+
+int git_branch_is_checked_out(const git_reference *branch)
+{
+ assert(branch && git_reference_is_branch(branch));
+
+ return git_repository_foreach_head(git_reference_owner(branch),
+ branch_equals, (void *) branch) == 1;
+}
+
int git_branch_delete(git_reference *branch)
{
int is_head;
@@ -134,7 +162,7 @@ int git_branch_delete(git_reference *branch)
assert(branch);
if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
- giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.",
+ giterr_set(GITERR_INVALID, "reference '%s' is not a valid branch.",
git_reference_name(branch));
return GIT_ENOTFOUND;
}
@@ -143,11 +171,17 @@ int git_branch_delete(git_reference *branch)
return is_head;
if (is_head) {
- giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is "
+ giterr_set(GITERR_REFERENCE, "cannot delete branch '%s' as it is "
"the current HEAD of the repository.", git_reference_name(branch));
return -1;
}
+ if (git_reference_is_branch(branch) && git_branch_is_checked_out(branch)) {
+ giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is "
+ "the current HEAD of a linked repository.", git_reference_name(branch));
+ return -1;
+ }
+
if (git_buf_join(&config_section, '.', "branch",
git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
goto on_error;
@@ -305,7 +339,7 @@ int git_branch_name(
branch_name += strlen(GIT_REFS_REMOTES_DIR);
} else {
giterr_set(GITERR_INVALID,
- "Reference '%s' is neither a local nor a remote branch.", ref->name);
+ "reference '%s' is neither a local nor a remote branch.", ref->name);
return -1;
}
*out = branch_name;
@@ -435,7 +469,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
/* Verify that this is a remote branch */
if (!git_reference__is_remote(refname)) {
- giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.",
+ giterr_set(GITERR_INVALID, "reference '%s' is not a remote branch.",
refname);
error = GIT_ERROR;
goto cleanup;
@@ -462,7 +496,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
git_remote_free(remote);
giterr_set(GITERR_REFERENCE,
- "Reference '%s' is ambiguous", refname);
+ "reference '%s' is ambiguous", refname);
error = GIT_EAMBIGUOUS;
goto cleanup;
}
@@ -476,7 +510,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna
error = git_buf_puts(buf, remote_name);
} else {
giterr_set(GITERR_REFERENCE,
- "Could not determine remote for '%s'", refname);
+ "could not determine remote for '%s'", refname);
error = GIT_ENOTFOUND;
}
@@ -565,7 +599,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
local = 0;
else {
giterr_set(GITERR_REFERENCE,
- "Cannot set upstream for branch '%s'", shortname);
+ "cannot set upstream for branch '%s'", shortname);
return GIT_ENOTFOUND;
}
diff --git a/src/branch.h b/src/branch.h
index d02f2af0d..5ae227c05 100644
--- a/src/branch.h
+++ b/src/branch.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_branch_h__
#define INCLUDE_branch_h__
+#include "common.h"
+
#include "buffer.h"
int git_branch_upstream__name(
diff --git a/src/buf_text.h b/src/buf_text.h
index c9c55af89..163bef1ad 100644
--- a/src/buf_text.h
+++ b/src/buf_text.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_buf_text_h__
#define INCLUDE_buf_text_h__
+#include "common.h"
+
#include "buffer.h"
typedef enum {
diff --git a/src/buffer.c b/src/buffer.c
index d135ebe4a..6dfcbfbe6 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -18,18 +18,19 @@ char git_buf__initbuf[1];
char git_buf__oom[1];
#define ENSURE_SIZE(b, d) \
- if ((d) > buf->asize && git_buf_grow(b, (d)) < 0)\
+ if ((d) > (b)->asize && git_buf_grow((b), (d)) < 0)\
return -1;
-void git_buf_init(git_buf *buf, size_t initial_size)
+int git_buf_init(git_buf *buf, size_t initial_size)
{
buf->asize = 0;
buf->size = 0;
buf->ptr = git_buf__initbuf;
- if (initial_size)
- git_buf_grow(buf, initial_size);
+ ENSURE_SIZE(buf, initial_size);
+
+ return 0;
}
int git_buf_try_grow(
@@ -577,7 +578,7 @@ char *git_buf_detach(git_buf *buf)
return data;
}
-void git_buf_attach(git_buf *buf, char *ptr, size_t asize)
+int git_buf_attach(git_buf *buf, char *ptr, size_t asize)
{
git_buf_free(buf);
@@ -588,9 +589,10 @@ void git_buf_attach(git_buf *buf, char *ptr, size_t asize)
buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
else /* pass 0 to fall back on strlen + 1 */
buf->asize = buf->size + 1;
- } else {
- git_buf_grow(buf, asize);
}
+
+ ENSURE_SIZE(buf, asize);
+ return 0;
}
void git_buf_attach_notowned(git_buf *buf, const char *ptr, size_t size)
@@ -724,9 +726,7 @@ int git_buf_join(
GITERR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
- if (git_buf_grow(buf, alloc_len) < 0)
- return -1;
- assert(buf->ptr);
+ ENSURE_SIZE(buf, alloc_len);
/* fix up internal pointers */
if (offset_a >= 0)
@@ -780,8 +780,7 @@ int git_buf_join3(
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b);
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, len_c);
GITERR_CHECK_ALLOC_ADD(&len_total, len_total, 1);
- if (git_buf_grow(buf, len_total) < 0)
- return -1;
+ ENSURE_SIZE(buf, len_total);
tgt = buf->ptr;
@@ -962,14 +961,14 @@ int git_buf_unquote(git_buf *buf)
case '0': case '1': case '2': case '3':
if (j == buf->size-3) {
giterr_set(GITERR_INVALID,
- "Truncated quoted character \\%c", ch);
+ "truncated quoted character \\%c", ch);
return -1;
}
if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' ||
buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') {
giterr_set(GITERR_INVALID,
- "Truncated quoted character \\%c%c%c",
+ "truncated quoted character \\%c%c%c",
buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]);
return -1;
}
@@ -981,7 +980,7 @@ int git_buf_unquote(git_buf *buf)
break;
default:
- giterr_set(GITERR_INVALID, "Invalid quoted character \\%c", ch);
+ giterr_set(GITERR_INVALID, "invalid quoted character \\%c", ch);
return -1;
}
}
@@ -995,6 +994,6 @@ int git_buf_unquote(git_buf *buf)
return 0;
invalid:
- giterr_set(GITERR_INVALID, "Invalid quoted line");
+ giterr_set(GITERR_INVALID, "invalid quoted line");
return -1;
}
diff --git a/src/buffer.h b/src/buffer.h
index cdfca6d99..b0aece488 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -34,7 +34,7 @@ GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf)
* For the cases where GIT_BUF_INIT cannot be used to do static
* initialization.
*/
-extern void git_buf_init(git_buf *buf, size_t initial_size);
+extern int git_buf_init(git_buf *buf, size_t initial_size);
/**
* Resize the buffer allocation to make more space.
@@ -66,13 +66,14 @@ extern int git_buf_try_grow(
* library, when providing git_buf's, may wish to provide a NULL ptr for
* ease of handling. The buffer routines, however, expect a non-NULL ptr
* always. This helper method simply handles NULL input, converting to a
- * git_buf__initbuf.
+ * git_buf__initbuf. If a buffer with a non-NULL ptr is passed in, this method
+ * assures that the buffer is '\0'-terminated.
*/
extern void git_buf_sanitize(git_buf *buf);
extern void git_buf_swap(git_buf *buf_a, git_buf *buf_b);
extern char *git_buf_detach(git_buf *buf);
-extern void git_buf_attach(git_buf *buf, char *ptr, size_t asize);
+extern int git_buf_attach(git_buf *buf, char *ptr, size_t asize);
/* Populates a `git_buf` where the contents are not "owned" by the
* buffer, and calls to `git_buf_free` will not free the given buf.
diff --git a/src/cache.c b/src/cache.c
index ca5173c0d..cdd12979f 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -5,18 +5,16 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "cache.h"
+
#include "repository.h"
#include "commit.h"
#include "thread-utils.h"
#include "util.h"
-#include "cache.h"
#include "odb.h"
#include "object.h"
#include "git2/oid.h"
-GIT__USE_OIDMAP
-
bool git_cache__enabled = true;
ssize_t git_cache__max_storage = (256 * 1024 * 1024);
git_atomic_ssize git_cache__current_storage = {0};
@@ -47,13 +45,13 @@ void git_cache_dump_stats(git_cache *cache)
{
git_cached_obj *object;
- if (kh_size(cache->map) == 0)
+ if (git_cache_size(cache) == 0)
return;
- printf("Cache %p: %d items cached, %"PRIdZ" bytes\n",
- cache, kh_size(cache->map), cache->used_memory);
+ printf("Cache %p: %"PRIuZ" items cached, %"PRIdZ" bytes\n",
+ cache, git_cache_size(cache), cache->used_memory);
- kh_foreach_value(cache->map, object, {
+ git_oidmap_foreach_value(cache->map, object, {
char oid_str[9];
printf(" %s%c %s (%"PRIuZ")\n",
git_object_type2string(object->type),
@@ -70,7 +68,7 @@ int git_cache_init(git_cache *cache)
cache->map = git_oidmap_alloc();
GITERR_CHECK_ALLOC(cache->map);
if (git_rwlock_init(&cache->lock)) {
- giterr_set(GITERR_OS, "Failed to initialize cache rwlock");
+ giterr_set(GITERR_OS, "failed to initialize cache rwlock");
return -1;
}
return 0;
@@ -81,14 +79,14 @@ static void clear_cache(git_cache *cache)
{
git_cached_obj *evict = NULL;
- if (kh_size(cache->map) == 0)
+ if (git_cache_size(cache) == 0)
return;
- kh_foreach_value(cache->map, evict, {
+ git_oidmap_foreach_value(cache->map, evict, {
git_cached_obj_decref(evict);
});
- kh_clear(oid, cache->map);
+ git_oidmap_clear(cache->map);
git_atomic_ssize_add(&git_cache__current_storage, -cache->used_memory);
cache->used_memory = 0;
}
@@ -119,22 +117,22 @@ static void cache_evict_entries(git_cache *cache)
ssize_t evicted_memory = 0;
/* do not infinite loop if there's not enough entries to evict */
- if (evict_count > kh_size(cache->map)) {
+ if (evict_count > git_cache_size(cache)) {
clear_cache(cache);
return;
}
while (evict_count > 0) {
- khiter_t pos = seed++ % kh_end(cache->map);
+ khiter_t pos = seed++ % git_oidmap_end(cache->map);
- if (kh_exist(cache->map, pos)) {
- git_cached_obj *evict = kh_val(cache->map, pos);
+ if (git_oidmap_has_data(cache->map, pos)) {
+ git_cached_obj *evict = git_oidmap_value_at(cache->map, pos);
evict_count--;
evicted_memory += evict->size;
git_cached_obj_decref(evict);
- kh_del(oid, cache->map, pos);
+ git_oidmap_delete_at(cache->map, pos);
}
}
@@ -156,9 +154,9 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0)
return NULL;
- pos = kh_get(oid, cache->map, oid);
- if (pos != kh_end(cache->map)) {
- entry = kh_val(cache->map, pos);
+ pos = git_oidmap_lookup_index(cache->map, oid);
+ if (git_oidmap_valid_index(cache->map, pos)) {
+ entry = git_oidmap_value_at(cache->map, pos);
if (flags && entry->flags != flags) {
entry = NULL;
@@ -193,16 +191,14 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
if (git_cache__current_storage.val > git_cache__max_storage)
cache_evict_entries(cache);
- pos = kh_get(oid, cache->map, &entry->oid);
+ pos = git_oidmap_lookup_index(cache->map, &entry->oid);
/* not found */
- if (pos == kh_end(cache->map)) {
+ if (!git_oidmap_valid_index(cache->map, pos)) {
int rval;
- pos = kh_put(oid, cache->map, &entry->oid, &rval);
+ git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
if (rval >= 0) {
- kh_key(cache->map, pos) = &entry->oid;
- kh_val(cache->map, pos) = entry;
git_cached_obj_incref(entry);
cache->used_memory += entry->size;
git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size);
@@ -210,7 +206,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
}
/* found */
else {
- git_cached_obj *stored_entry = kh_val(cache->map, pos);
+ git_cached_obj *stored_entry = git_oidmap_value_at(cache->map, pos);
if (stored_entry->flags == entry->flags) {
git_cached_obj_decref(entry);
@@ -221,8 +217,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
git_cached_obj_decref(stored_entry);
git_cached_obj_incref(entry);
- kh_key(cache->map, pos) = &entry->oid;
- kh_val(cache->map, pos) = entry;
+ git_oidmap_set_key_at(cache->map, pos, &entry->oid);
+ git_oidmap_set_value_at(cache->map, pos, entry);
} else {
/* NO OP */
}
diff --git a/src/cache.h b/src/cache.h
index 697123739..9c09954ae 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_cache_h__
#define INCLUDE_cache_h__
+#include "common.h"
+
#include "git2/common.h"
#include "git2/oid.h"
#include "git2/odb.h"
@@ -53,7 +55,7 @@ void *git_cache_get_any(git_cache *cache, const git_oid *oid);
GIT_INLINE(size_t) git_cache_size(git_cache *cache)
{
- return (size_t)kh_size(cache->map);
+ return (size_t)git_oidmap_size(cache->map);
}
GIT_INLINE(void) git_cached_obj_incref(void *_obj)
diff --git a/src/checkout.c b/src/checkout.c
index f11102c8b..6c7a94441 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <assert.h>
-
#include "checkout.h"
+#include <assert.h>
+
#include "git2/repository.h"
#include "git2/refs.h"
#include "git2/tree.h"
@@ -35,8 +35,6 @@
#include "pool.h"
#include "strmap.h"
-GIT__USE_STRMAP
-
/* See docs/checkout-internals.md for more information */
enum {
@@ -212,6 +210,10 @@ static bool checkout_is_workdir_modified(
if (baseitem->size && wditem->file_size != baseitem->size)
return true;
+ /* if the workdir item is a directory, it cannot be a modified file */
+ if (S_ISDIR(wditem->mode))
+ return false;
+
if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
return false;
@@ -368,10 +370,8 @@ static int checkout_action_wd_only(
*/
const git_index_entry *e = git_index_get_byindex(data->index, pos);
- if (e != NULL && data->diff->pfxcomp(e->path, wd->path) == 0) {
- notify = GIT_CHECKOUT_NOTIFY_DIRTY;
- remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
- }
+ if (e != NULL && data->diff->pfxcomp(e->path, wd->path) == 0)
+ return git_iterator_advance_into(wditem, workdir);
}
}
@@ -1017,13 +1017,13 @@ static int checkout_conflicts_load_byname_entry(
*theirs_out = NULL;
if (!name_entry->ancestor) {
- giterr_set(GITERR_INDEX, "A NAME entry exists without an ancestor");
+ giterr_set(GITERR_INDEX, "a NAME entry exists without an ancestor");
error = -1;
goto done;
}
if (!name_entry->ours && !name_entry->theirs) {
- giterr_set(GITERR_INDEX, "A NAME entry exists without an ours or theirs");
+ giterr_set(GITERR_INDEX, "a NAME entry exists without an ours or theirs");
error = -1;
goto done;
}
@@ -1031,7 +1031,7 @@ static int checkout_conflicts_load_byname_entry(
if ((ancestor = checkout_conflicts_search_ancestor(data,
name_entry->ancestor)) == NULL) {
giterr_set(GITERR_INDEX,
- "A NAME entry referenced ancestor entry '%s' which does not exist in the main index",
+ "a NAME entry referenced ancestor entry '%s' which does not exist in the main index",
name_entry->ancestor);
error = -1;
goto done;
@@ -1043,7 +1043,7 @@ static int checkout_conflicts_load_byname_entry(
else if ((ours = checkout_conflicts_search_branch(data, name_entry->ours)) == NULL ||
ours->ours == NULL) {
giterr_set(GITERR_INDEX,
- "A NAME entry referenced our entry '%s' which does not exist in the main index",
+ "a NAME entry referenced our entry '%s' which does not exist in the main index",
name_entry->ours);
error = -1;
goto done;
@@ -1058,7 +1058,7 @@ static int checkout_conflicts_load_byname_entry(
else if ((theirs = checkout_conflicts_search_branch(data, name_entry->theirs)) == NULL ||
theirs->theirs == NULL) {
giterr_set(GITERR_INDEX,
- "A NAME entry referenced their entry '%s' which does not exist in the main index",
+ "a NAME entry referenced their entry '%s' which does not exist in the main index",
name_entry->theirs);
error = -1;
goto done;
@@ -1157,7 +1157,7 @@ static int checkout_conflicts_mark_directoryfile(
if ((error = git_index_find(&j, index, path)) < 0) {
if (error == GIT_ENOTFOUND)
giterr_set(GITERR_INDEX,
- "Index inconsistency, could not find entry for expected conflict '%s'", path);
+ "index inconsistency, could not find entry for expected conflict '%s'", path);
goto done;
}
@@ -1165,7 +1165,7 @@ static int checkout_conflicts_mark_directoryfile(
for (; j < len; j++) {
if ((entry = git_index_get_byindex(index, j)) == NULL) {
giterr_set(GITERR_INDEX,
- "Index inconsistency, truncated index while loading expected conflict '%s'", path);
+ "index inconsistency, truncated index while loading expected conflict '%s'", path);
error = -1;
goto done;
}
@@ -1250,14 +1250,14 @@ static int checkout_verify_paths(
if (action & CHECKOUT_ACTION__REMOVE) {
if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
- giterr_set(GITERR_CHECKOUT, "Cannot remove invalid path '%s'", delta->old_file.path);
+ giterr_set(GITERR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
return -1;
}
}
if (action & ~CHECKOUT_ACTION__REMOVE) {
if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
- giterr_set(GITERR_CHECKOUT, "Cannot checkout to invalid path '%s'", delta->new_file.path);
+ giterr_set(GITERR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
return -1;
}
}
@@ -1426,7 +1426,7 @@ static int mkpath2file(
*/
error = git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES);
} else if (errno != ENOENT) {
- giterr_set(GITERR_OS, "Failed to stat file '%s'", path);
+ giterr_set(GITERR_OS, "failed to stat '%s'", path);
return GIT_EEXISTS;
} else {
giterr_clear();
@@ -1450,7 +1450,7 @@ static int checkout_stream_write(
int ret;
if ((ret = p_write(stream->fd, buffer, len)) < 0)
- giterr_set(GITERR_OS, "Could not write to '%s'", stream->path);
+ giterr_set(GITERR_OS, "could not write to '%s'", stream->path);
return ret;
}
@@ -1499,7 +1499,7 @@ static int blob_content_to_file(
mode = GIT_FILEMODE_BLOB;
if ((fd = p_open(path, flags, mode)) < 0) {
- giterr_set(GITERR_OS, "Could not open '%s' for writing", path);
+ giterr_set(GITERR_OS, "could not open '%s' for writing", path);
return fd;
}
@@ -1536,7 +1536,7 @@ static int blob_content_to_file(
data->perfdata.stat_calls++;
if ((error = p_stat(path, st)) < 0) {
- giterr_set(GITERR_OS, "Error statting '%s'", path);
+ giterr_set(GITERR_OS, "failed to stat '%s'", path);
return error;
}
@@ -1563,7 +1563,7 @@ static int blob_content_to_link(
if (data->can_symlink) {
if ((error = p_symlink(git_buf_cstr(&linktarget), path)) < 0)
- giterr_set(GITERR_OS, "Could not create symlink %s", path);
+ giterr_set(GITERR_OS, "could not create symlink %s", path);
} else {
error = git_futils_fake_symlink(git_buf_cstr(&linktarget), path);
}
@@ -1572,7 +1572,7 @@ static int blob_content_to_link(
data->perfdata.stat_calls++;
if ((error = p_lstat(path, st)) < 0)
- giterr_set(GITERR_CHECKOUT, "Could not stat symlink %s", path);
+ giterr_set(GITERR_CHECKOUT, "could not stat symlink %s", path);
st->st_mode = GIT_FILEMODE_LINK;
}
@@ -1617,7 +1617,7 @@ static int checkout_submodule_update_index(
data->perfdata.stat_calls++;
if (p_stat(fullpath->ptr, &st) < 0) {
giterr_set(
- GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path);
+ GITERR_CHECKOUT, "could not stat submodule %s\n", file->path);
return GIT_ENOTFOUND;
}
@@ -1690,7 +1690,7 @@ static int checkout_safe_for_update_only(
return 0;
/* otherwise, stat error and no update */
- giterr_set(GITERR_OS, "Failed to stat file '%s'", path);
+ giterr_set(GITERR_OS, "failed to stat '%s'", path);
return -1;
}
@@ -1962,7 +1962,7 @@ static int checkout_path_suffixed(git_buf *path, const char *suffix)
if (i == INT_MAX) {
git_buf_truncate(path, path_len);
- giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path);
+ giterr_set(GITERR_CHECKOUT, "could not write '%s': working directory file exists", path->ptr);
return GIT_EEXISTS;
}
@@ -2093,7 +2093,7 @@ static int checkout_write_merge(
goto done;
if (result.path == NULL || result.mode == 0) {
- giterr_set(GITERR_CHECKOUT, "Could not merge contents of file");
+ giterr_set(GITERR_CHECKOUT, "could not merge contents of file");
error = GIT_ECONFLICT;
goto done;
}
@@ -2317,8 +2317,6 @@ static void checkout_data_clear(checkout_data *data)
git__free(data->pfx);
data->pfx = NULL;
- git_strmap_free(data->mkdir_map);
-
git_buf_free(&data->target_path);
git_buf_free(&data->tmp);
@@ -2326,6 +2324,7 @@ static void checkout_data_clear(checkout_data *data)
data->index = NULL;
git_strmap_free(data->mkdir_map);
+ data->mkdir_map = NULL;
git_attr_session__free(&data->attr_session);
}
@@ -2341,7 +2340,7 @@ static int checkout_data_init(
memset(data, 0, sizeof(*data));
if (!repo) {
- giterr_set(GITERR_CHECKOUT, "Cannot checkout nothing");
+ giterr_set(GITERR_CHECKOUT, "cannot checkout nothing");
return -1;
}
@@ -2465,7 +2464,7 @@ static int checkout_data_init(
data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
else {
giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
- conflict_style);
+ conflict_style->value);
error = -1;
git_config_entry_free(conflict_style);
goto cleanup;
@@ -2549,6 +2548,10 @@ int git_checkout_iterator(
GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE;
baseline_opts.start = data.pfx;
baseline_opts.end = data.pfx;
+ if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
+ baseline_opts.pathlist.count = opts->paths.count;
+ baseline_opts.pathlist.strings = opts->paths.strings;
+ }
if (data.opts.baseline_index) {
if ((error = git_iterator_for_index(
@@ -2643,7 +2646,7 @@ int git_checkout_index(
if (!index && !repo) {
giterr_set(GITERR_CHECKOUT,
- "Must provide either repository or index to checkout");
+ "must provide either repository or index to checkout");
return -1;
}
@@ -2651,7 +2654,7 @@ int git_checkout_index(
git_index_owner(index) &&
git_index_owner(index) != repo) {
giterr_set(GITERR_CHECKOUT,
- "Index to checkout does not match repository");
+ "index to checkout does not match repository");
return -1;
} else if(index && repo && !git_index_owner(index)) {
GIT_REFCOUNT_OWN(index, repo);
@@ -2690,12 +2693,12 @@ int git_checkout_tree(
if (!treeish && !repo) {
giterr_set(GITERR_CHECKOUT,
- "Must provide either repository or tree to checkout");
+ "must provide either repository or tree to checkout");
return -1;
}
if (treeish && repo && git_object_owner(treeish) != repo) {
giterr_set(GITERR_CHECKOUT,
- "Object to checkout does not match repository");
+ "object to checkout does not match repository");
return -1;
}
@@ -2705,7 +2708,7 @@ int git_checkout_tree(
if (treeish) {
if (git_object_peel((git_object **)&tree, treeish, GIT_OBJ_TREE) < 0) {
giterr_set(
- GITERR_CHECKOUT, "Provided object cannot be peeled to a tree");
+ GITERR_CHECKOUT, "provided object cannot be peeled to a tree");
return -1;
}
}
diff --git a/src/checkout.h b/src/checkout.h
index 60aa29b26..517fbf3b1 100644
--- a/src/checkout.h
+++ b/src/checkout.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_checkout_h__
#define INCLUDE_checkout_h__
+#include "common.h"
+
#include "git2/checkout.h"
#include "iterator.h"
diff --git a/src/cherrypick.c b/src/cherrypick.c
index c92975194..e42b74815 100644
--- a/src/cherrypick.c
+++ b/src/cherrypick.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "repository.h"
#include "filebuf.h"
#include "merge.h"
@@ -28,7 +29,7 @@ static int write_cherrypick_head(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_CHERRYPICK_HEAD_FILE)) >= 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) >= 0 &&
(error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
error = git_filebuf_commit(&file);
@@ -49,7 +50,7 @@ static int write_merge_msg(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) < 0 ||
(error = git_filebuf_printf(&file, "%s", commit_msg)) < 0)
goto cleanup;
@@ -130,13 +131,13 @@ int git_cherrypick_commit(
if (git_commit_parentcount(cherrypick_commit) > 1) {
if (!mainline)
return cherrypick_seterr(cherrypick_commit,
- "Mainline branch is not specified but %s is a merge commit");
+ "mainline branch is not specified but %s is a merge commit");
parent = mainline;
} else {
if (mainline)
return cherrypick_seterr(cherrypick_commit,
- "Mainline branch specified but %s is not a merge commit");
+ "mainline branch specified but %s is not a merge commit");
parent = git_commit_parentcount(cherrypick_commit);
}
diff --git a/src/clone.c b/src/clone.c
index 0d4756e28..8764bb728 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "clone.h"
+
#include <assert.h>
#include "git2/clone.h"
@@ -16,7 +18,6 @@
#include "git2/commit.h"
#include "git2/tree.h"
-#include "common.h"
#include "remote.h"
#include "fileops.h"
#include "refs.h"
@@ -513,9 +514,8 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
return error;
}
- git_buf_joinpath(&src_odb, git_repository_path(src), GIT_OBJECTS_DIR);
- git_buf_joinpath(&dst_odb, git_repository_path(repo), GIT_OBJECTS_DIR);
- if (git_buf_oom(&src_odb) || git_buf_oom(&dst_odb)) {
+ if (git_repository_item_path(&src_odb, src, GIT_REPOSITORY_ITEM_OBJECTS) < 0
+ || git_repository_item_path(&dst_odb, repo, GIT_REPOSITORY_ITEM_OBJECTS) < 0) {
error = -1;
goto cleanup;
}
diff --git a/src/clone.h b/src/clone.h
index 14ca5d44c..864b59029 100644
--- a/src/clone.h
+++ b/src/clone.h
@@ -7,6 +7,10 @@
#ifndef 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);
#endif
diff --git a/src/commit.c b/src/commit.c
index 99a80855c..838688bb8 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -5,13 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "commit.h"
+
#include "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/signature.h"
#include "git2/sys/commit.h"
-#include "common.h"
#include "odb.h"
#include "commit.h"
#include "signature.h"
@@ -159,6 +160,9 @@ static int git_commit__create_internal(
if (git_repository_odb__weakptr(&odb, repo) < 0)
goto cleanup;
+ if (git_odb__freshen(odb, tree) < 0)
+ goto cleanup;
+
if (git_odb_write(id, odb, buf.ptr, buf.size, GIT_OBJ_COMMIT) < 0)
goto cleanup;
@@ -459,15 +463,16 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
buffer = buffer_start + header_len + 1;
/* extract commit message */
- if (buffer <= buffer_end) {
+ if (buffer <= buffer_end)
commit->raw_message = git__strndup(buffer, buffer_end - buffer);
- GITERR_CHECK_ALLOC(commit->raw_message);
- }
+ else
+ commit->raw_message = git__strdup("");
+ GITERR_CHECK_ALLOC(commit->raw_message);
return 0;
bad_buffer:
- giterr_set(GITERR_OBJECT, "Failed to parse bad commit object");
+ giterr_set(GITERR_OBJECT, "failed to parse bad commit object");
return -1;
}
@@ -597,7 +602,7 @@ int git_commit_parent(
parent_id = git_commit_parent_id(commit, n);
if (parent_id == NULL) {
- giterr_set(GITERR_INVALID, "Parent %u does not exist", n);
+ giterr_set(GITERR_INVALID, "parent %u does not exist", n);
return GIT_ENOTFOUND;
}
@@ -641,7 +646,7 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *
{
const char *eol, *buf = commit->raw_header;
- git_buf_sanitize(out);
+ git_buf_clear(out);
while ((eol = strchr(buf, '\n'))) {
/* We can skip continuations here */
@@ -705,8 +710,8 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
const char *h, *eol;
int error;
- git_buf_sanitize(signature);
- git_buf_sanitize(signed_data);
+ git_buf_clear(signature);
+ git_buf_clear(signed_data);
if (!field)
field = "gpgsig";
@@ -765,8 +770,9 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
if (git_buf_oom(signature))
goto oom;
+ error = git_buf_puts(signed_data, eol+1);
git_odb_object_free(obj);
- return git_buf_puts(signed_data, eol+1);
+ return error;
}
giterr_set(GITERR_OBJECT, "this commit is not signed");
diff --git a/src/commit.h b/src/commit.h
index d01ac2b2f..781809d70 100644
--- a/src/commit.h
+++ b/src/commit.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_h__
#define INCLUDE_commit_h__
+#include "common.h"
+
#include "git2/commit.h"
#include "tree.h"
#include "repository.h"
diff --git a/src/commit_list.c b/src/commit_list.c
index 28948c88b..96bd9dc15 100644
--- a/src/commit_list.c
+++ b/src/commit_list.c
@@ -6,17 +6,22 @@
*/
#include "commit_list.h"
-#include "common.h"
+
#include "revwalk.h"
#include "pool.h"
#include "odb.h"
int git_commit_list_time_cmp(const void *a, const void *b)
{
- const git_commit_list_node *commit_a = a;
- const git_commit_list_node *commit_b = b;
+ int64_t time_a = ((git_commit_list_node *) a)->time;
+ int64_t time_b = ((git_commit_list_node *) b)->time;
+
+ if (time_a < time_b)
+ return 1;
+ if (time_a > time_b)
+ return -1;
- return (commit_a->time < commit_b->time);
+ return 0;
}
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
@@ -56,7 +61,7 @@ static int commit_error(git_commit_list_node *commit, const char *msg)
git_oid_fmt(commit_oid, &commit->oid);
commit_oid[GIT_OID_HEXSZ] = '\0';
- giterr_set(GITERR_ODB, "Failed to parse commit %s - %s", commit_oid, msg);
+ giterr_set(GITERR_ODB, "failed to parse commit %s - %s", commit_oid, msg);
return -1;
}
@@ -186,7 +191,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
return error;
if (obj->cached.type != GIT_OBJ_COMMIT) {
- giterr_set(GITERR_INVALID, "Object is no commit object");
+ giterr_set(GITERR_INVALID, "object is no commit object");
error = -1;
} else
error = commit_quick_parse(
diff --git a/src/commit_list.h b/src/commit_list.h
index a6967bcef..a7551a2bc 100644
--- a/src/commit_list.h
+++ b/src/commit_list.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_commit_list_h__
#define INCLUDE_commit_list_h__
+#include "common.h"
+
#include "git2/oid.h"
#define PARENT1 (1 << 0)
@@ -28,6 +30,7 @@ typedef struct git_commit_list_node {
uninteresting:1,
topo_delay:1,
parsed:1,
+ added:1,
flags : FLAG_BITS;
unsigned short in_degree;
diff --git a/src/common.h b/src/common.h
index 51fb9186e..d3622d3eb 100644
--- a/src/common.h
+++ b/src/common.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_common_h__
#define INCLUDE_common_h__
+#ifndef LIBGIT2_NO_FEATURES_H
+# include "git2/sys/features.h"
+#endif
+
#include "git2/common.h"
#include "cc-compat.h"
@@ -47,10 +51,6 @@
# ifdef GIT_THREADS
# include "win32/thread.h"
# endif
-# if defined(GIT_MSVC_CRTDBG)
-# include "win32/w32_stack.h"
-# include "win32/w32_crtdbg_stacktrace.h"
-# endif
#else
@@ -103,7 +103,8 @@
/**
* Set the error message for this thread, formatting as needed.
*/
-void giterr_set(int error_class, const char *string, ...);
+
+void giterr_set(int error_class, const char *string, ...) GIT_FORMAT_PRINTF(2, 3);
/**
* Set the error message for a regex failure, using the internal regex
@@ -187,7 +188,7 @@ GIT_INLINE(int) giterr__check_version(const void *structure, unsigned int expect
if (actual > 0 && actual <= expected_max)
return 0;
- giterr_set(GITERR_INVALID, "Invalid version %d on %s", actual, name);
+ giterr_set(GITERR_INVALID, "invalid version %d on %s", actual, name);
return -1;
}
#define GITERR_CHECK_VERSION(S,V,N) if (giterr__check_version(S,V,N) < 0) return -1
diff --git a/src/config.c b/src/config.c
index f4d4cb2b9..602e0e827 100644
--- a/src/config.c
+++ b/src/config.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "sysdir.h"
#include "config.h"
+
+#include "sysdir.h"
#include "git2/config.h"
#include "git2/sys/config.h"
#include "vector.h"
@@ -109,7 +109,7 @@ int git_config_add_file_ondisk(
res = p_stat(path, &st);
if (res < 0 && errno != ENOENT) {
- giterr_set(GITERR_CONFIG, "Error stat'ing config file '%s'", path);
+ giterr_set(GITERR_CONFIG, "failed to stat '%s'", path);
return -1;
}
@@ -203,7 +203,7 @@ static int find_internal_file_by_level(
if (pos == -1) {
giterr_set(GITERR_CONFIG,
- "No config file exists for the given level '%i'", (int)level);
+ "no config file exists for the given level '%i'", (int)level);
return GIT_ENOTFOUND;
}
@@ -218,7 +218,7 @@ static int duplicate_level(void **old_raw, void *new_raw)
GIT_UNUSED(new_raw);
- giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (int)(*old)->level);
+ giterr_set(GITERR_CONFIG, "a file with the same level (%i) has already been added to the config", (int)(*old)->level);
return GIT_EEXISTS;
}
@@ -478,7 +478,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf
iter = git__calloc(1, sizeof(all_iter));
GITERR_CHECK_ALLOC(iter);
- if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
+ if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&iter->regex, result);
git__free(iter);
return -1;
@@ -512,7 +512,7 @@ int git_config_backend_foreach_match(
int error = 0;
if (regexp != NULL) {
- if ((error = regcomp(&regex, regexp, REG_EXTENDED)) != 0) {
+ if ((error = p_regcomp(&regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&regex, error);
regfree(&regex);
return -1;
@@ -576,22 +576,50 @@ int git_config_foreach_match(
* Setters
**************/
-static int config_error_nofiles(const char *name)
+typedef enum {
+ BACKEND_USE_SET,
+ BACKEND_USE_DELETE
+} backend_use;
+
+static const char *uses[] = {
+ "set",
+ "delete"
+};
+
+static int get_backend_for_use(git_config_backend **out,
+ git_config *cfg, const char *name, backend_use use)
{
+ size_t i;
+ file_internal *f;
+
+ *out = NULL;
+
+ if (git_vector_length(&cfg->files) == 0) {
+ giterr_set(GITERR_CONFIG,
+ "cannot %s value for '%s' when no config files exist",
+ uses[use], name);
+ return GIT_ENOTFOUND;
+ }
+
+ git_vector_foreach(&cfg->files, i, f) {
+ if (!f->file->readonly) {
+ *out = f->file;
+ return 0;
+ }
+ }
+
giterr_set(GITERR_CONFIG,
- "Cannot set value for '%s' when no config files exist", name);
+ "cannot %s value for '%s' when all config files are readonly",
+ uses[use], name);
return GIT_ENOTFOUND;
}
int git_config_delete_entry(git_config *cfg, const char *name)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->del(file, name);
}
@@ -617,17 +645,14 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
{
int error;
git_config_backend *file;
- file_internal *internal;
if (!value) {
- giterr_set(GITERR_CONFIG, "The value to set cannot be NULL");
+ giterr_set(GITERR_CONFIG, "the value to set cannot be NULL");
return -1;
}
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0)
+ return GIT_ENOTFOUND;
error = file->set(file, name, value);
@@ -674,7 +699,7 @@ int git_config__update_entry(
static int config_error_notfound(const char *name)
{
- giterr_set(GITERR_CONFIG, "Config value '%s' was not found", name);
+ giterr_set(GITERR_CONFIG, "config value '%s' was not found", name);
return GIT_ENOTFOUND;
}
@@ -1003,7 +1028,7 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config
goto on_error;
if (regexp != NULL) {
- error = regcomp(&iter->regex, regexp, REG_EXTENDED);
+ error = p_regcomp(&iter->regex, regexp, REG_EXTENDED);
if (error != 0) {
giterr_set_regex(&iter->regex, error);
error = -1;
@@ -1032,12 +1057,9 @@ on_error:
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->set_multivar(file, name, regexp, value);
}
@@ -1045,12 +1067,9 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex
int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->del_multivar(file, name, regexp);
}
@@ -1236,7 +1255,7 @@ int git_config_lookup_map_value(
}
fail_parse:
- giterr_set(GITERR_CONFIG, "Failed to map '%s'", value);
+ giterr_set(GITERR_CONFIG, "failed to map '%s'", value);
return -1;
}
@@ -1270,7 +1289,7 @@ int git_config_parse_bool(int *out, const char *value)
return 0;
}
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
+ giterr_set(GITERR_CONFIG, "failed to parse '%s' as a boolean value", value);
return -1;
}
@@ -1313,7 +1332,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
}
fail_parse:
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value ? value : "(null)");
+ giterr_set(GITERR_CONFIG, "failed to parse '%s' as an integer", value ? value : "(null)");
return -1;
}
@@ -1333,15 +1352,12 @@ int git_config_parse_int32(int32_t *out, const char *value)
return 0;
fail_parse:
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
+ giterr_set(GITERR_CONFIG, "failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
return -1;
}
int git_config_parse_path(git_buf *out, const char *value)
{
- int error = 0;
- const git_buf *home;
-
assert(out && value);
git_buf_sanitize(out);
@@ -1352,16 +1368,7 @@ int git_config_parse_path(git_buf *out, const char *value)
return -1;
}
- if ((error = git_sysdir_get(&home, GIT_SYSDIR_GLOBAL)) < 0)
- return error;
-
- git_buf_sets(out, home->ptr);
- git_buf_puts(out, value + 1);
-
- if (git_buf_oom(out))
- return -1;
-
- return 0;
+ return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
}
return git_buf_sets(out, value);
@@ -1398,7 +1405,7 @@ int git_config__normalize_name(const char *in, char **out)
invalid:
git__free(name);
- giterr_set(GITERR_CONFIG, "Invalid config item name '%s'", in);
+ giterr_set(GITERR_CONFIG, "invalid config item name '%s'", in);
return GIT_EINVALIDSPEC;
}
@@ -1461,7 +1468,7 @@ int git_config_rename_section(
replace.ptr, strchr(replace.ptr, '.'))) < 0)
{
giterr_set(
- GITERR_CONFIG, "Invalid config section '%s'", new_section_name);
+ GITERR_CONFIG, "invalid config section '%s'", new_section_name);
goto cleanup;
}
diff --git a/src/config.h b/src/config.h
index 00c12b50d..a5fcf2e84 100644
--- a/src/config.h
+++ b/src/config.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_config_h__
#define INCLUDE_config_h__
+#include "common.h"
+
#include "git2.h"
#include "git2/config.h"
#include "vector.h"
diff --git a/src/config_cache.c b/src/config_cache.c
index dbea871b9..0efb1a789 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "fileops.h"
#include "repository.h"
#include "config.h"
@@ -78,6 +79,7 @@ static struct map_data _cvar_maps[] = {
{"core.logallrefupdates", NULL, 0, GIT_LOGALLREFUPDATES_DEFAULT },
{"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT },
{"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT },
+ {"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT },
};
int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar)
diff --git a/src/config_file.c b/src/config_file.c
index e33b83738..00d6d9e13 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "config_file.h"
+
#include "config.h"
#include "filebuf.h"
#include "sysdir.h"
@@ -21,8 +22,6 @@
#include <sys/types.h>
#include <regex.h>
-GIT__USE_STRMAP
-
typedef struct cvar_t {
struct cvar_t *next;
git_config_entry *entry;
@@ -76,9 +75,14 @@ typedef struct git_config_file_iter {
(iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
(iter) = (tmp))
-struct reader {
+struct config_file {
git_oid checksum;
- char *file_path;
+ char *path;
+ git_array_t(struct config_file) includes;
+};
+
+struct reader {
+ struct config_file *file;
git_buf buffer;
char *read_ptr;
int line_number;
@@ -102,13 +106,11 @@ typedef struct {
git_config_level_t level;
- git_array_t(struct reader) readers;
-
bool locked;
git_filebuf locked_buf;
git_buf locked_content;
- char *file_path;
+ struct config_file file;
} diskfile_backend;
typedef struct {
@@ -117,7 +119,7 @@ typedef struct {
diskfile_backend *snapshot_from;
} diskfile_readonly_backend;
-static int config_read(git_strmap *values, diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth);
+static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth);
static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value);
static char *escape_value(const char *ptr);
@@ -126,8 +128,8 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in);
static void set_parse_error(struct reader *reader, int col, const char *error_str)
{
- giterr_set(GITERR_CONFIG, "Failed to parse config file: %s (in %s:%d, column %d)",
- error_str, reader->file_path, reader->line_number, col);
+ giterr_set(GITERR_CONFIG, "failed to parse config file: %s (in %s:%d, column %d)",
+ error_str, reader->file->path, reader->line_number, col);
}
static int config_error_readonly(void)
@@ -179,7 +181,7 @@ static int append_entry(git_strmap *values, cvar_t *var)
pos = git_strmap_lookup_index(values, var->entry->name);
if (!git_strmap_valid_index(values, pos)) {
- git_strmap_insert(values, var->entry->name, var, error);
+ git_strmap_insert(values, var->entry->name, var, &error);
} else {
existing = git_strmap_value_at(values, pos);
while (existing->next != NULL) {
@@ -233,7 +235,7 @@ static refcounted_strmap *refcounted_strmap_take(diskfile_header *h)
refcounted_strmap *map;
if (git_mutex_lock(&h->values_mutex) < 0) {
- giterr_set(GITERR_OS, "Failed to lock config backend");
+ giterr_set(GITERR_OS, "failed to lock config backend");
return NULL;
}
@@ -263,10 +265,25 @@ static int refcounted_strmap_alloc(refcounted_strmap **out)
return error;
}
+static void config_file_clear(struct config_file *file)
+{
+ struct config_file *include;
+ uint32_t i;
+
+ if (file == NULL)
+ return;
+
+ git_array_foreach(file->includes, i, include) {
+ config_file_clear(include);
+ }
+ git_array_clear(file->includes);
+
+ git__free(file->path);
+}
+
static int config_open(git_config_backend *cfg, git_config_level_t level)
{
int res;
- struct reader *reader;
diskfile_backend *b = (diskfile_backend *)cfg;
b->level = level;
@@ -274,112 +291,102 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
if ((res = refcounted_strmap_alloc(&b->header.values)) < 0)
return res;
- git_array_init(b->readers);
- reader = git_array_alloc(b->readers);
- if (!reader) {
- refcounted_strmap_free(b->header.values);
- return -1;
- }
- memset(reader, 0, sizeof(struct reader));
-
- reader->file_path = git__strdup(b->file_path);
- GITERR_CHECK_ALLOC(reader->file_path);
-
- git_buf_init(&reader->buffer, 0);
- res = git_futils_readbuffer_updated(
- &reader->buffer, b->file_path, &reader->checksum, NULL);
-
/* It's fine if the file doesn't exist */
- if (res == GIT_ENOTFOUND)
+ if (!git_path_exists(b->file.path))
return 0;
- if (res < 0 || (res = config_read(b->header.values->values, b, reader, level, 0)) < 0) {
+ if (res < 0 || (res = config_read(b->header.values->values, &b->file, level, 0)) < 0) {
refcounted_strmap_free(b->header.values);
b->header.values = NULL;
}
- reader = git_array_get(b->readers, 0);
- git_buf_free(&reader->buffer);
-
return res;
}
-/* The meat of the refresh, as we want to use it in different places */
-static int config__refresh(git_config_backend *cfg)
+static int config_is_modified(int *modified, struct config_file *file)
{
- refcounted_strmap *values = NULL, *tmp;
- diskfile_backend *b = (diskfile_backend *)cfg;
- struct reader *reader = NULL;
- int error = 0;
+ struct config_file *include;
+ git_buf buf = GIT_BUF_INIT;
+ git_oid hash;
+ uint32_t i;
+ int error;
- if ((error = refcounted_strmap_alloc(&values)) < 0)
- goto out;
+ *modified = 0;
- reader = git_array_get(b->readers, git_array_size(b->readers) - 1);
- GITERR_CHECK_ALLOC(reader);
+ if ((error = git_futils_readbuffer(&buf, file->path)) < 0)
+ goto out;
- if ((error = config_read(values->values, b, reader, b->level, 0)) < 0)
+ if ((error = git_hash_buf(&hash, buf.ptr, buf.size)) < 0)
goto out;
- if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) {
- giterr_set(GITERR_OS, "Failed to lock config backend");
+ if (!git_oid_equal(&hash, &file->checksum)) {
+ *modified = 1;
goto out;
}
- tmp = b->header.values;
- b->header.values = values;
- values = tmp;
-
- git_mutex_unlock(&b->header.values_mutex);
+ git_array_foreach(file->includes, i, include) {
+ if ((error = config_is_modified(modified, include)) < 0 || *modified)
+ goto out;
+ }
out:
- refcounted_strmap_free(values);
- if (reader)
- git_buf_free(&reader->buffer);
+ git_buf_free(&buf);
+
return error;
}
static int config_refresh(git_config_backend *cfg)
{
- int error = 0, updated = 0, any_updated = 0;
diskfile_backend *b = (diskfile_backend *)cfg;
- struct reader *reader = NULL;
+ refcounted_strmap *values = NULL, *tmp;
+ struct config_file *include;
+ int error, modified;
uint32_t i;
- for (i = 0; i < git_array_size(b->readers); i++) {
- reader = git_array_get(b->readers, i);
- error = git_futils_readbuffer_updated(
- &reader->buffer, reader->file_path,
- &reader->checksum, &updated);
+ error = config_is_modified(&modified, &b->file);
+ if (error < 0 && error != GIT_ENOTFOUND)
+ goto out;
- if (error < 0 && error != GIT_ENOTFOUND)
- return error;
+ if (!modified)
+ return 0;
- if (updated)
- any_updated = 1;
+ if ((error = refcounted_strmap_alloc(&values)) < 0)
+ goto out;
+
+ /* Reparse the current configuration */
+ git_array_foreach(b->file.includes, i, include) {
+ config_file_clear(include);
}
+ git_array_clear(b->file.includes);
- if (!any_updated)
- return (error == GIT_ENOTFOUND) ? 0 : error;
+ if ((error = config_read(values->values, &b->file, b->level, 0)) < 0)
+ goto out;
- return config__refresh(cfg);
+ if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) {
+ giterr_set(GITERR_OS, "failed to lock config backend");
+ goto out;
+ }
+
+ tmp = b->header.values;
+ b->header.values = values;
+ values = tmp;
+
+ git_mutex_unlock(&b->header.values_mutex);
+
+out:
+ refcounted_strmap_free(values);
+
+ return (error == GIT_ENOTFOUND) ? 0 : error;
}
static void backend_free(git_config_backend *_backend)
{
diskfile_backend *backend = (diskfile_backend *)_backend;
- uint32_t i;
if (backend == NULL)
return;
- for (i = 0; i < git_array_size(backend->readers); i++) {
- struct reader *r = git_array_get(backend->readers, i);
- git__free(r->file_path);
- }
- git_array_clear(backend->readers);
-
- git__free(backend->file_path);
+ config_file_clear(&backend->file);
refcounted_strmap_free(backend->header.values);
git_mutex_free(&backend->header.values_mutex);
git__free(backend);
@@ -479,7 +486,13 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
cvar_t *existing = git_strmap_value_at(values, pos);
if (existing->next != NULL) {
- giterr_set(GITERR_CONFIG, "Multivar incompatible with simple set");
+ giterr_set(GITERR_CONFIG, "multivar incompatible with simple set");
+ ret = -1;
+ goto out;
+ }
+
+ if (existing->included) {
+ giterr_set(GITERR_CONFIG, "modifying included variable is not supported");
ret = -1;
goto out;
}
@@ -570,7 +583,7 @@ static int config_set_multivar(
if ((result = git_config__normalize_name(name, &key)) < 0)
return result;
- result = regcomp(&preg, regexp, REG_EXTENDED);
+ result = p_regcomp(&preg, regexp, REG_EXTENDED);
if (result != 0) {
giterr_set_regex(&preg, result);
result = -1;
@@ -611,15 +624,20 @@ static int config_delete(git_config_backend *cfg, const char *name)
if (!git_strmap_valid_index(values, pos)) {
refcounted_strmap_free(map);
- giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name);
+ giterr_set(GITERR_CONFIG, "could not find key '%s' to delete", name);
return GIT_ENOTFOUND;
}
var = git_strmap_value_at(values, pos);
refcounted_strmap_free(map);
+ if (var->included) {
+ giterr_set(GITERR_CONFIG, "cannot delete included variable");
+ return -1;
+ }
+
if (var->next != NULL) {
- giterr_set(GITERR_CONFIG, "Cannot delete multivar with a single delete");
+ giterr_set(GITERR_CONFIG, "cannot delete multivar with a single delete");
return -1;
}
@@ -651,13 +669,13 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
if (!git_strmap_valid_index(values, pos)) {
refcounted_strmap_free(map);
git__free(key);
- giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name);
+ giterr_set(GITERR_CONFIG, "could not find key '%s' to delete", name);
return GIT_ENOTFOUND;
}
refcounted_strmap_free(map);
- result = regcomp(&preg, regexp, REG_EXTENDED);
+ result = p_regcomp(&preg, regexp, REG_EXTENDED);
if (result != 0) {
giterr_set_regex(&preg, result);
result = -1;
@@ -687,10 +705,10 @@ static int config_lock(git_config_backend *_cfg)
diskfile_backend *cfg = (diskfile_backend *) _cfg;
int error;
- if ((error = git_filebuf_open(&cfg->locked_buf, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0)
+ if ((error = git_filebuf_open(&cfg->locked_buf, cfg->file.path, 0, GIT_CONFIG_FILE_MODE)) < 0)
return error;
- error = git_futils_readbuffer(&cfg->locked_content, cfg->file_path);
+ error = git_futils_readbuffer(&cfg->locked_content, cfg->file.path);
if (error < 0 && error != GIT_ENOTFOUND) {
git_filebuf_cleanup(&cfg->locked_buf);
return error;
@@ -728,8 +746,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;
git_mutex_init(&backend->header.values_mutex);
- backend->file_path = git__strdup(path);
- GITERR_CHECK_ALLOC(backend->file_path);
+ backend->file.path = git__strdup(path);
+ GITERR_CHECK_ALLOC(backend->file.path);
+ git_array_init(backend->file.includes);
backend->header.parent.open = config_open;
backend->header.parent.get = config_get;
@@ -1029,7 +1048,7 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
first_quote = strchr(line, '"');
if (first_quote == NULL) {
set_parse_error(reader, 0, "Missing quotation marks in section header");
- return -1;
+ goto end_error;
}
last_quote = strrchr(line, '"');
@@ -1037,14 +1056,15 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
if (quoted_len == 0) {
set_parse_error(reader, 0, "Missing closing quotation mark in section header");
- return -1;
+ goto end_error;
}
GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
- git_buf_grow(&buf, alloc_len);
- git_buf_printf(&buf, "%s.", base_name);
+ if (git_buf_grow(&buf, alloc_len) < 0 ||
+ git_buf_printf(&buf, "%s.", base_name) < 0)
+ goto end_error;
rpos = 0;
@@ -1060,8 +1080,7 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
switch (c) {
case 0:
set_parse_error(reader, 0, "Unexpected end-of-line in section header");
- git_buf_free(&buf);
- return -1;
+ goto end_error;
case '"':
goto end_parse;
@@ -1071,8 +1090,7 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
if (c == 0) {
set_parse_error(reader, rpos, "Unexpected end-of-line in section header");
- git_buf_free(&buf);
- return -1;
+ goto end_error;
}
default:
@@ -1084,6 +1102,9 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
} 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);
@@ -1092,6 +1113,11 @@ end_parse:
*section_name = git_buf_detach(&buf);
return 0;
+
+end_error:
+ git_buf_free(&buf);
+
+ return -1;
}
static int parse_section_header(struct reader *reader, char **section_out)
@@ -1251,7 +1277,7 @@ static int included_path(git_buf *out, const char *dir, const char *path)
{
/* From the user's home */
if (path[0] == '~' && path[1] == '/')
- return git_sysdir_find_global_file(out, &path[1]);
+ return git_sysdir_expand_global_file(out, &path[1]);
return git_path_join_unrooted(out, path, dir, NULL);
}
@@ -1262,7 +1288,7 @@ static const char *escaped = "\n\t\b\"\\";
/* Escape the values to write them to the file */
static char *escape_value(const char *ptr)
{
- git_buf buf = GIT_BUF_INIT;
+ git_buf buf;
size_t len;
const char *esc;
@@ -1272,7 +1298,8 @@ static char *escape_value(const char *ptr)
if (!len)
return git__calloc(1, sizeof(char));
- git_buf_grow(&buf, len);
+ if (git_buf_init(&buf, len) < 0)
+ return NULL;
while (*ptr != '\0') {
if ((esc = strchr(escaped, *ptr)) != NULL) {
@@ -1325,7 +1352,7 @@ static int unescape_line(
*fixed++ = escaped[esc - escapes];
} else {
git__free(str);
- giterr_set(GITERR_CONFIG, "Invalid escape at %s", ptr);
+ giterr_set(GITERR_CONFIG, "invalid escape at %s", ptr);
return -1;
}
}
@@ -1480,10 +1507,10 @@ on_error:
static int config_parse(
struct reader *reader,
- int (*on_section)(struct reader **reader, const char *current_section, const char *line, size_t line_len, void *data),
- int (*on_variable)(struct reader **reader, const char *current_section, char *var_name, char *var_value, const char *line, size_t line_len, void *data),
- int (*on_comment)(struct reader **reader, const char *line, size_t line_len, void *data),
- int (*on_eof)(struct reader **reader, const char *current_section, void *data),
+ int (*on_section)(struct reader *reader, const char *current_section, const char *line, size_t line_len, void *data),
+ int (*on_variable)(struct reader *reader, const char *current_section, char *var_name, char *var_value, const char *line, size_t line_len, void *data),
+ int (*on_comment)(struct reader *reader, const char *line, size_t line_len, void *data),
+ int (*on_eof)(struct reader *reader, const char *current_section, void *data),
void *data)
{
char *current_section = NULL, *var_name, *var_value, *line_start;
@@ -1509,7 +1536,7 @@ static int config_parse(
if ((result = parse_section_header(reader, &current_section)) == 0 && on_section) {
line_len = reader->read_ptr - line_start;
- result = on_section(&reader, current_section, line_start, line_len, data);
+ result = on_section(reader, current_section, line_start, line_len, data);
}
break;
@@ -1520,21 +1547,21 @@ static int config_parse(
if (on_comment) {
line_len = reader->read_ptr - line_start;
- result = on_comment(&reader, line_start, line_len, data);
+ result = on_comment(reader, line_start, line_len, data);
}
break;
default: /* assume variable declaration */
if ((result = parse_variable(reader, &var_name, &var_value)) == 0 && on_variable) {
line_len = reader->read_ptr - line_start;
- result = on_variable(&reader, current_section, var_name, var_value, line_start, line_len, data);
+ result = on_variable(reader, current_section, var_name, var_value, line_start, line_len, data);
}
break;
}
}
if (on_eof)
- result = on_eof(&reader, current_section, data);
+ result = on_eof(reader, current_section, data);
git__free(current_section);
return result;
@@ -1542,14 +1569,12 @@ static int config_parse(
struct parse_data {
git_strmap *values;
- diskfile_backend *cfg_file;
- uint32_t reader_idx;
git_config_level_t level;
int depth;
};
static int read_on_variable(
- struct reader **reader,
+ struct reader *reader,
const char *current_section,
char *var_name,
char *var_value,
@@ -1591,21 +1616,13 @@ static int read_on_variable(
/* Add or append the new config option */
if (!git__strcmp(var->entry->name, "include.path")) {
- struct reader *r;
+ struct config_file *include;
git_buf path = GIT_BUF_INIT;
char *dir;
- uint32_t index;
- r = git_array_alloc(parse_data->cfg_file->readers);
- /* The reader may have been reallocated */
- *reader = git_array_get(parse_data->cfg_file->readers, parse_data->reader_idx);
- memset(r, 0, sizeof(struct reader));
-
- if ((result = git_path_dirname_r(&path, (*reader)->file_path)) < 0)
+ if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
return result;
- /* We need to know our index in the array, as the next config_parse call may realloc */
- index = git_array_size(parse_data->cfg_file->readers) - 1;
dir = git_buf_detach(&path);
result = included_path(&path, dir, var->entry->value);
git__free(dir);
@@ -1613,51 +1630,60 @@ static int read_on_variable(
if (result < 0)
return result;
- r->file_path = git_buf_detach(&path);
- git_buf_init(&r->buffer, 0);
+ include = git_array_alloc(reader->file->includes);
+ memset(include, 0, sizeof(*include));
+ git_array_init(include->includes);
+ include->path = git_buf_detach(&path);
- result = git_futils_readbuffer_updated(
- &r->buffer, r->file_path, &r->checksum, NULL);
+ result = config_read(parse_data->values, include, parse_data->level, parse_data->depth+1);
- if (result == 0) {
- result = config_read(parse_data->values, parse_data->cfg_file, r, parse_data->level, parse_data->depth+1);
- r = git_array_get(parse_data->cfg_file->readers, index);
- *reader = git_array_get(parse_data->cfg_file->readers, parse_data->reader_idx);
- } else if (result == GIT_ENOTFOUND) {
+ if (result == GIT_ENOTFOUND) {
giterr_clear();
result = 0;
}
-
- git_buf_free(&r->buffer);
}
return result;
}
-static int config_read(git_strmap *values, diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth)
+static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth)
{
struct parse_data parse_data;
+ struct reader reader;
+ int error;
if (depth >= MAX_INCLUDE_DEPTH) {
- giterr_set(GITERR_CONFIG, "Maximum config include depth reached");
+ giterr_set(GITERR_CONFIG, "maximum config include depth reached");
return -1;
}
+ git_buf_init(&reader.buffer, 0);
+
+ if ((error = git_futils_readbuffer(&reader.buffer, file->path)) < 0)
+ goto out;
+
+ if ((error = git_hash_buf(&file->checksum, reader.buffer.ptr, reader.buffer.size)) < 0)
+ goto out;
+
/* Initialize the reading position */
- reader->read_ptr = reader->buffer.ptr;
- reader->eof = 0;
+ reader.file = file;
+ reader.line_number = 0;
+ reader.read_ptr = reader.buffer.ptr;
+ reader.eof = 0;
/* If the file is empty, there's nothing for us to do */
- if (*reader->read_ptr == '\0')
- return 0;
+ if (*reader.read_ptr == '\0')
+ goto out;
parse_data.values = values;
- parse_data.cfg_file = cfg_file;
- parse_data.reader_idx = git_array_size(cfg_file->readers) - 1;
parse_data.level = level;
parse_data.depth = depth;
- return config_parse(reader, NULL, read_on_variable, NULL, NULL, &parse_data);
+ error = config_parse(&reader, NULL, read_on_variable, NULL, NULL, &parse_data);
+
+out:
+ git_buf_free(&reader.buffer);
+ return error;
}
static int write_section(git_buf *fbuf, const char *key)
@@ -1754,7 +1780,7 @@ static int write_value(struct write_data *write_data)
}
static int write_on_section(
- struct reader **reader,
+ struct reader *reader,
const char *current_section,
const char *line,
size_t line_len,
@@ -1790,7 +1816,7 @@ static int write_on_section(
}
static int write_on_variable(
- struct reader **reader,
+ struct reader *reader,
const char *current_section,
char *var_name,
char *var_value,
@@ -1840,7 +1866,7 @@ static int write_on_variable(
return write_value(write_data);
}
-static int write_on_comment(struct reader **reader, const char *line, size_t line_len, void *data)
+static int write_on_comment(struct reader *reader, const char *line, size_t line_len, void *data)
{
struct write_data *write_data;
@@ -1851,7 +1877,7 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin
}
static int write_on_eof(
- struct reader **reader, const char *current_section, void *data)
+ struct reader *reader, const char *current_section, void *data)
{
struct write_data *write_data = (struct write_data *)data;
int result = 0;
@@ -1890,31 +1916,35 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
char *section, *name, *ldot;
git_filebuf file = GIT_FILEBUF_INIT;
git_buf buf = GIT_BUF_INIT;
- struct reader *reader = git_array_get(cfg->readers, 0);
+ struct reader reader;
struct write_data write_data;
+ memset(&reader, 0, sizeof(reader));
+ git_buf_init(&reader.buffer, 0);
+ reader.file = &cfg->file;
+
if (cfg->locked) {
- result = git_buf_puts(&reader->buffer, git_buf_cstr(&cfg->locked_content));
+ result = git_buf_puts(&reader.buffer, git_buf_cstr(&cfg->locked_content));
} else {
/* Lock the file */
if ((result = git_filebuf_open(
- &file, cfg->file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) {
- git_buf_free(&reader->buffer);
+ &file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) {
+ git_buf_free(&reader.buffer);
return result;
}
/* We need to read in our own config file */
- result = git_futils_readbuffer(&reader->buffer, cfg->file_path);
+ result = git_futils_readbuffer(&reader.buffer, cfg->file.path);
}
/* Initialise the reading position */
if (result == GIT_ENOTFOUND) {
- reader->read_ptr = NULL;
- reader->eof = 1;
- git_buf_clear(&reader->buffer);
+ reader.read_ptr = NULL;
+ reader.eof = 1;
+ git_buf_clear(&reader.buffer);
} else if (result == 0) {
- reader->read_ptr = reader->buffer.ptr;
- reader->eof = 0;
+ reader.read_ptr = reader.buffer.ptr;
+ reader.eof = 0;
} else {
git_filebuf_cleanup(&file);
return -1; /* OS error when reading the file */
@@ -1933,7 +1963,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
write_data.preg = preg;
write_data.value = value;
- result = config_parse(reader, write_on_section, write_on_variable, write_on_comment, write_on_eof, &write_data);
+ result = config_parse(&reader, write_on_section, write_on_variable, write_on_comment, write_on_eof, &write_data);
git__free(section);
git_buf_free(&write_data.buffered_comment);
@@ -1954,7 +1984,6 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
done:
git_buf_free(&buf);
- git_buf_free(&reader->buffer);
+ git_buf_free(&reader.buffer);
return result;
}
-
diff --git a/src/config_file.h b/src/config_file.h
index 1c52892c3..11b8118f5 100644
--- a/src/config_file.h
+++ b/src/config_file.h
@@ -7,6 +7,9 @@
#ifndef INCLUDE_config_file_h__
#define INCLUDE_config_file_h__
+#include "common.h"
+
+#include "git2/sys/config.h"
#include "git2/config.h"
GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level)
diff --git a/src/crlf.c b/src/crlf.c
index 11895b19f..9af60076d 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -5,12 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include "git2/attr.h"
#include "git2/blob.h"
#include "git2/index.h"
#include "git2/sys/filter.h"
-#include "common.h"
#include "fileops.h"
#include "hash.h"
#include "filter.h"
@@ -218,7 +219,7 @@ static const char *line_ending(struct crlf_attrs *ca)
return "\r\n";
line_ending_error:
- giterr_set(GITERR_INVALID, "Invalid input to line ending filter");
+ giterr_set(GITERR_INVALID, "invalid input to line ending filter");
return NULL;
}
diff --git a/src/curl_stream.c b/src/curl_stream.c
index 98de187dd..24bf62635 100644
--- a/src/curl_stream.c
+++ b/src/curl_stream.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "curl_stream.h"
+
#ifdef GIT_CURL
#include <curl/curl.h>
@@ -15,6 +17,16 @@
#include "vector.h"
#include "proxy.h"
+/* This is for backwards compatibility with curl<7.45.0. */
+#ifndef CURLINFO_ACTIVESOCKET
+# define CURLINFO_ACTIVESOCKET CURLINFO_LASTSOCKET
+# define GIT_CURL_BADSOCKET -1
+# define git_activesocket_t long
+#else
+# define GIT_CURL_BADSOCKET CURL_SOCKET_BAD
+# define git_activesocket_t curl_socket_t
+#endif
+
typedef struct {
git_stream parent;
CURL *handle;
@@ -87,7 +99,8 @@ static int ask_and_apply_proxy_creds(curl_stream *s)
static int curls_connect(git_stream *stream)
{
curl_stream *s = (curl_stream *) stream;
- long sockextr, connect_last = 0;
+ git_activesocket_t sockextr;
+ long connect_last = 0;
int failed_cert = 0, error;
bool retry_connect;
CURLcode res;
@@ -117,10 +130,15 @@ static int curls_connect(git_stream *stream)
if (res == CURLE_PEER_FAILED_VERIFICATION)
failed_cert = 1;
- if ((res = curl_easy_getinfo(s->handle, CURLINFO_LASTSOCKET, &sockextr)) != CURLE_OK) {
+ if ((res = curl_easy_getinfo(s->handle, CURLINFO_ACTIVESOCKET, &sockextr)) != CURLE_OK) {
return seterr_curl(s);
}
+ if (sockextr == GIT_CURL_BADSOCKET) {
+ giterr_set(GITERR_NET, "curl socket is no longer valid");
+ return -1;
+ }
+
s->socket = sockextr;
if (s->parent.encrypted && failed_cert)
@@ -198,6 +216,7 @@ static int wait_for(curl_socket_t fd, bool reading)
FD_ZERO(&outfd);
FD_ZERO(&errfd);
+ assert(fd >= 0);
FD_SET(fd, &errfd);
if (reading)
FD_SET(fd, &infd);
diff --git a/src/curl_stream.h b/src/curl_stream.h
index 283f0fe40..debade7e2 100644
--- a/src/curl_stream.h
+++ b/src/curl_stream.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_curl_stream_h__
#define INCLUDE_curl_stream_h__
+#include "common.h"
+
#include "git2/sys/stream.h"
extern int git_curl_stream_new(git_stream **out, const char *host, const char *port);
diff --git a/src/delta.c b/src/delta.c
index dc45697b6..073cba7c6 100644
--- a/src/delta.c
+++ b/src/delta.c
@@ -131,7 +131,7 @@ static int lookup_index_alloc(
GITERR_CHECK_ALLOC_ADD(&index_len, index_len, hash_len);
if (!git__is_ulong(index_len)) {
- giterr_set(GITERR_NOMEMORY, "Overly large delta");
+ giterr_set(GITERR_NOMEMORY, "overly large delta");
return -1;
}
@@ -544,12 +544,12 @@ int git_delta_apply(
* base object, resulting in data corruption or segfault.
*/
if ((hdr_sz(&base_sz, &delta, delta_end) < 0) || (base_sz != base_len)) {
- giterr_set(GITERR_INVALID, "Failed to apply delta. Base size does not match given data");
+ giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data");
return -1;
}
if (hdr_sz(&res_sz, &delta, delta_end) < 0) {
- giterr_set(GITERR_INVALID, "Failed to apply delta. Base size does not match given data");
+ giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data");
return -1;
}
@@ -614,6 +614,6 @@ fail:
*out = NULL;
*out_len = 0;
- giterr_set(GITERR_INVALID, "Failed to apply delta");
+ giterr_set(GITERR_INVALID, "failed to apply delta");
return -1;
}
diff --git a/src/delta.h b/src/delta.h
index cc9372922..f61987304 100644
--- a/src/delta.h
+++ b/src/delta.h
@@ -6,6 +6,7 @@
#define INCLUDE_git_delta_h__
#include "common.h"
+
#include "pack.h"
typedef struct git_delta_index git_delta_index;
diff --git a/src/describe.c b/src/describe.c
index fc48fbde4..edf8edfd1 100644
--- a/src/describe.c
+++ b/src/describe.c
@@ -4,12 +4,14 @@
* 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 "common.h"
+
#include "git2/describe.h"
#include "git2/strarray.h"
#include "git2/diff.h"
#include "git2/status.h"
-#include "common.h"
#include "commit.h"
#include "commit_list.h"
#include "oidmap.h"
@@ -19,8 +21,6 @@
#include "vector.h"
#include "repository.h"
-GIT__USE_OIDMAP
-
/* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */
struct commit_name {
@@ -127,7 +127,7 @@ static int add_to_known_names(
if (!found) {
int ret;
- git_oidmap_insert(names, &e->peeled, e, ret);
+ git_oidmap_insert(names, &e->peeled, e, &ret);
if (ret < 0)
return -1;
}
@@ -335,14 +335,14 @@ static int display_name(git_buf *buf, git_repository *repo, struct commit_name *
{
if (n->prio == 2 && !n->tag) {
if (git_tag_lookup(&n->tag, repo, &n->sha1) < 0) {
- giterr_set(GITERR_TAG, "Annotated tag '%s' not available", n->path);
+ giterr_set(GITERR_TAG, "annotated tag '%s' not available", n->path);
return -1;
}
}
if (n->tag && !n->name_checked) {
if (!git_tag_name(n->tag)) {
- giterr_set(GITERR_TAG, "Annotated tag '%s' has no embedded name", n->path);
+ giterr_set(GITERR_TAG, "annotated tag '%s' has no embedded name", n->path);
return -1;
}
@@ -471,7 +471,7 @@ static int describe(
if (!data->opts->max_candidates_tags) {
error = describe_not_found(
git_commit_id(commit),
- "Cannot describe - no tag exactly matches '%s'");
+ "cannot describe - no tag exactly matches '%s'");
goto cleanup;
}
@@ -564,15 +564,15 @@ static int describe(
}
if (unannotated_cnt) {
error = describe_not_found(git_commit_id(commit),
- "Cannot describe - "
- "No annotated tags can describe '%s'."
- "However, there were unannotated tags.");
+ "cannot describe - "
+ "no annotated tags can describe '%s'; "
+ "however, there were unannotated tags.");
goto cleanup;
}
else {
error = describe_not_found(git_commit_id(commit),
- "Cannot describe - "
- "No tags can describe '%s'.");
+ "cannot describe - "
+ "no tags can describe '%s'.");
goto cleanup;
}
}
@@ -695,8 +695,8 @@ int git_describe_commit(
goto cleanup;
if (git_oidmap_size(data.names) == 0 && !opts->show_commit_oid_as_fallback) {
- giterr_set(GITERR_DESCRIBE, "Cannot describe - "
- "No reference found, cannot describe anything.");
+ giterr_set(GITERR_DESCRIBE, "cannot describe - "
+ "no reference found, cannot describe anything.");
error = -1;
goto cleanup;
}
@@ -793,7 +793,7 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g
if (opts.always_use_long_format && opts.abbreviated_size == 0) {
- giterr_set(GITERR_DESCRIBE, "Cannot describe - "
+ giterr_set(GITERR_DESCRIBE, "cannot describe - "
"'always_use_long_format' is incompatible with a zero"
"'abbreviated_size'");
return -1;
diff --git a/src/diff.c b/src/diff.c
index 317d49597..b2a5ff947 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -4,9 +4,10 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "git2/version.h"
-#include "common.h"
+
#include "diff.h"
+
+#include "git2/version.h"
#include "diff_generate.h"
#include "patch.h"
#include "commit.h"
@@ -19,6 +20,12 @@
#define DIFF_FLAG_SET(DIFF,FLAG,VAL) (DIFF)->opts.flags = \
(VAL) ? ((DIFF)->opts.flags | (FLAG)) : ((DIFF)->opts.flags & ~(VAL))
+struct patch_id_args {
+ git_hash_ctx ctx;
+ git_oid result;
+ int first_file;
+};
+
GIT_INLINE(const char *) diff_delta__path(const git_diff_delta *delta)
{
const char *str = delta->old_file.path;
@@ -120,6 +127,41 @@ int git_diff_get_perfdata(git_diff_perfdata *out, const git_diff *diff)
return 0;
}
+int git_diff_foreach(
+ git_diff *diff,
+ git_diff_file_cb file_cb,
+ git_diff_binary_cb binary_cb,
+ git_diff_hunk_cb hunk_cb,
+ git_diff_line_cb data_cb,
+ void *payload)
+{
+ int error = 0;
+ git_diff_delta *delta;
+ size_t idx;
+
+ assert(diff);
+
+ git_vector_foreach(&diff->deltas, idx, delta) {
+ git_patch *patch;
+
+ /* check flags against patch status */
+ if (git_diff_delta__should_skip(&diff->opts, delta))
+ continue;
+
+ if ((error = git_patch_from_diff(&patch, diff, idx)) != 0)
+ break;
+
+ error = git_patch__invoke_callbacks(patch, file_cb, binary_cb,
+ hunk_cb, data_cb, payload);
+ git_patch_free(patch);
+
+ if (error)
+ break;
+ }
+
+ return error;
+}
+
int git_diff_format_email__append_header_tobuf(
git_buf *out,
const git_oid *id,
@@ -339,3 +381,142 @@ int git_diff_format_email_init_options(
return 0;
}
+static int flush_hunk(git_oid *result, git_hash_ctx *ctx)
+{
+ git_oid hash;
+ unsigned short carry = 0;
+ int error, i;
+
+ if ((error = git_hash_final(&hash, ctx)) < 0 ||
+ (error = git_hash_init(ctx)) < 0)
+ return error;
+
+ for (i = 0; i < GIT_OID_RAWSZ; i++) {
+ carry += result->id[i] + hash.id[i];
+ result->id[i] = carry;
+ carry >>= 8;
+ }
+
+ return 0;
+}
+
+static void strip_spaces(git_buf *buf)
+{
+ char *src = buf->ptr, *dst = buf->ptr;
+ char c;
+ size_t len = 0;
+
+ while ((c = *src++) != '\0') {
+ if (!git__isspace(c)) {
+ *dst++ = c;
+ len++;
+ }
+ }
+
+ git_buf_truncate(buf, len);
+}
+
+static int file_cb(
+ const git_diff_delta *delta,
+ float progress,
+ void *payload)
+{
+ struct patch_id_args *args = (struct patch_id_args *) payload;
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ GIT_UNUSED(progress);
+
+ if (!args->first_file &&
+ (error = flush_hunk(&args->result, &args->ctx)) < 0)
+ goto out;
+ args->first_file = 0;
+
+ if ((error = git_buf_printf(&buf,
+ "diff--gita/%sb/%s---a/%s+++b/%s",
+ delta->old_file.path,
+ delta->new_file.path,
+ delta->old_file.path,
+ delta->new_file.path)) < 0)
+ goto out;
+
+ strip_spaces(&buf);
+
+ if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0)
+ goto out;
+
+out:
+ git_buf_free(&buf);
+ return error;
+}
+
+static int line_cb(
+ const git_diff_delta *delta,
+ const git_diff_hunk *hunk,
+ const git_diff_line *line,
+ void *payload)
+{
+ struct patch_id_args *args = (struct patch_id_args *) payload;
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ GIT_UNUSED(delta);
+ GIT_UNUSED(hunk);
+
+ switch (line->origin) {
+ case GIT_DIFF_LINE_ADDITION:
+ git_buf_putc(&buf, '+');
+ break;
+ case GIT_DIFF_LINE_DELETION:
+ git_buf_putc(&buf, '-');
+ break;
+ case GIT_DIFF_LINE_CONTEXT:
+ break;
+ default:
+ giterr_set(GITERR_PATCH, "invalid line origin for patch");
+ return -1;
+ }
+
+ git_buf_put(&buf, line->content, line->content_len);
+ strip_spaces(&buf);
+
+ if ((error = git_hash_update(&args->ctx, buf.ptr, buf.size)) < 0)
+ goto out;
+
+out:
+ git_buf_free(&buf);
+ return error;
+}
+
+int git_diff_patchid_init_options(git_diff_patchid_options *opts, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
+ opts, version, git_diff_patchid_options, GIT_DIFF_PATCHID_OPTIONS_INIT);
+ return 0;
+}
+
+int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opts)
+{
+ struct patch_id_args args;
+ int error;
+
+ GITERR_CHECK_VERSION(
+ opts, GIT_DIFF_PATCHID_OPTIONS_VERSION, "git_diff_patchid_options");
+
+ memset(&args, 0, sizeof(args));
+ args.first_file = 1;
+ if ((error = git_hash_ctx_init(&args.ctx)) < 0)
+ goto out;
+
+ if ((error = git_diff_foreach(diff, file_cb, NULL, NULL, line_cb, &args)) < 0)
+ goto out;
+
+ if ((error = (flush_hunk(&args.result, &args.ctx))) < 0)
+ goto out;
+
+ git_oid_cpy(out, &args.result);
+
+out:
+ git_hash_ctx_cleanup(&args.ctx);
+ return error;
+}
diff --git a/src/diff.h b/src/diff.h
index 5750d2a09..4e5dd93da 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_diff_h__
#define INCLUDE_diff_h__
+#include "common.h"
+
#include "git2/diff.h"
#include "git2/patch.h"
#include "git2/sys/diff.h"
diff --git a/src/diff_driver.c b/src/diff_driver.c
index 14a898c4f..8cd57cdf6 100644
--- a/src/diff_driver.c
+++ b/src/diff_driver.c
@@ -4,20 +4,18 @@
* 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 "common.h"
+
+#include "diff_driver.h"
#include "git2/attr.h"
#include "diff.h"
-#include "diff_driver.h"
#include "strmap.h"
#include "map.h"
#include "buf_text.h"
#include "config.h"
#include "repository.h"
-GIT__USE_STRMAP
-
typedef enum {
DIFF_DRIVER_AUTO = 0,
DIFF_DRIVER_BINARY = 1,
@@ -114,7 +112,7 @@ static int diff_driver_add_patterns(
if (error < 0)
break;
- if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) != 0) {
+ if ((error = p_regcomp(&pat->re, buf.ptr, regex_flags)) != 0) {
/*
* TODO: issue a warning
*/
@@ -151,7 +149,7 @@ static git_diff_driver_registry *git_repository_driver_registry(
}
if (!repo->diff_drivers)
- giterr_set(GITERR_REPOSITORY, "Unable to create diff driver registry");
+ giterr_set(GITERR_REPOSITORY, "unable to create diff driver registry");
return repo->diff_drivers;
}
@@ -210,14 +208,14 @@ static int git_diff_driver_builtin(
goto done;
if (ddef->words &&
- (error = regcomp(
+ (error = p_regcomp(
&drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED)))
{
error = giterr_set_regex(&drv->word_pattern, error);
goto done;
}
- git_strmap_insert(reg->drivers, drv->name, drv, error);
+ git_strmap_insert(reg->drivers, drv->name, drv, &error);
if (error > 0)
error = 0;
@@ -314,7 +312,7 @@ static int git_diff_driver_load(
goto done;
if (!ce || !ce->value)
/* no diff.<driver>.wordregex, so just continue */;
- else if (!(error = regcomp(&drv->word_pattern, ce->value, REG_EXTENDED)))
+ else if (!(error = p_regcomp(&drv->word_pattern, ce->value, REG_EXTENDED)))
found_driver = true;
else {
/* TODO: warn about bad regex instead of failure */
@@ -331,7 +329,7 @@ static int git_diff_driver_load(
goto done;
/* store driver in registry */
- git_strmap_insert(reg->drivers, drv->name, drv, error);
+ git_strmap_insert(reg->drivers, drv->name, drv, &error);
if (error < 0)
goto done;
error = 0;
@@ -519,4 +517,3 @@ void git_diff_find_context_clear(git_diff_find_context_payload *payload)
payload->driver = NULL;
}
}
-
diff --git a/src/diff_driver.h b/src/diff_driver.h
index 0706dcfc5..5691cac30 100644
--- a/src/diff_driver.h
+++ b/src/diff_driver.h
@@ -8,6 +8,7 @@
#define INCLUDE_diff_driver_h__
#include "common.h"
+
#include "buffer.h"
typedef struct git_diff_driver_registry git_diff_driver_registry;
diff --git a/src/diff_file.c b/src/diff_file.c
index cc1029038..270d59bbb 100644
--- a/src/diff_file.c
+++ b/src/diff_file.c
@@ -4,12 +4,13 @@
* 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 "common.h"
+
+#include "diff_file.h"
+
#include "git2/blob.h"
#include "git2/submodule.h"
#include "diff.h"
#include "diff_generate.h"
-#include "diff_file.h"
#include "odb.h"
#include "fileops.h"
#include "filter.h"
@@ -304,7 +305,7 @@ static int diff_file_content_load_workdir_symlink(
read_len = p_readlink(git_buf_cstr(path), fc->map.data, alloc_len);
if (read_len < 0) {
- giterr_set(GITERR_OS, "Failed to read symlink '%s'", fc->file->path);
+ giterr_set(GITERR_OS, "failed to read symlink '%s'", fc->file->path);
return -1;
}
diff --git a/src/diff_file.h b/src/diff_file.h
index 0d54b6d33..5da7a7bb8 100644
--- a/src/diff_file.h
+++ b/src/diff_file.h
@@ -8,6 +8,7 @@
#define INCLUDE_diff_file_h__
#include "common.h"
+
#include "diff.h"
#include "diff_driver.h"
#include "map.h"
diff --git a/src/diff_generate.c b/src/diff_generate.c
index 06f9b19c7..6436ab930 100644
--- a/src/diff_generate.c
+++ b/src/diff_generate.c
@@ -4,9 +4,10 @@
* 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 "common.h"
-#include "diff.h"
+
#include "diff_generate.h"
+
+#include "diff.h"
#include "patch_generate.h"
#include "fileops.h"
#include "config.h"
@@ -624,7 +625,7 @@ int git_diff__oid_for_entry(
error = git_odb__hashlink(out, full_path.ptr);
diff->base.perf.oid_calculations++;
} else if (!git__is_sizet(entry.file_size)) {
- giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'",
+ giterr_set(GITERR_OS, "file size overflow (for 32-bits) on '%s'",
entry.path);
error = -1;
} else if (!(error = git_filter_list_load(&fl,
@@ -1587,7 +1588,7 @@ int git_diff__commit(
char commit_oidstr[GIT_OID_HEXSZ + 1];
error = -1;
- giterr_set(GITERR_INVALID, "Commit %s is a merge commit",
+ giterr_set(GITERR_INVALID, "commit %s is a merge commit",
git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit)));
goto on_error;
}
diff --git a/src/diff_generate.h b/src/diff_generate.h
index 63e7f0532..8de2a0644 100644
--- a/src/diff_generate.h
+++ b/src/diff_generate.h
@@ -7,6 +7,12 @@
#ifndef INCLUDE_diff_generate_h__
#define INCLUDE_diff_generate_h__
+#include "common.h"
+
+#include "diff.h"
+#include "pool.h"
+#include "index.h"
+
enum {
GIT_DIFFCAPS_HAS_SYMLINKS = (1 << 0), /* symlinks on platform? */
GIT_DIFFCAPS_IGNORE_STAT = (1 << 1), /* use stat? */
diff --git a/src/diff_parse.c b/src/diff_parse.c
index e640063af..78da3b675 100644
--- a/src/diff_parse.c
+++ b/src/diff_parse.c
@@ -4,9 +4,10 @@
* 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 "common.h"
-#include "diff.h"
+
#include "diff_parse.h"
+
+#include "diff.h"
#include "patch.h"
#include "patch_parse.h"
@@ -37,7 +38,6 @@ static git_diff_parsed *diff_parsed_alloc(void)
GIT_REFCOUNT_INC(diff);
diff->base.type = GIT_DIFF_TYPE_PARSED;
- diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
diff->base.strcomp = git__strcmp;
diff->base.strncomp = git__strncmp;
diff->base.pfxcomp = git__prefixcmp;
@@ -45,6 +45,13 @@ static git_diff_parsed *diff_parsed_alloc(void)
diff->base.patch_fn = git_patch_parsed_from_diff;
diff->base.free_fn = diff_parsed_free;
+ if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) {
+ git__free(diff);
+ return NULL;
+ }
+
+ diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
+
git_pool_init(&diff->base.pool, 1);
if (git_vector_init(&diff->patches, 0, NULL) < 0 ||
diff --git a/src/diff_parse.h b/src/diff_parse.h
index c47d4cbc9..876782128 100644
--- a/src/diff_parse.h
+++ b/src/diff_parse.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_diff_parse_h__
#define INCLUDE_diff_parse_h__
+#include "common.h"
+
#include "diff.h"
typedef struct {
diff --git a/src/diff_print.c b/src/diff_print.c
index fd1a186c1..28ae38424 100644
--- a/src/diff_print.c
+++ b/src/diff_print.c
@@ -4,7 +4,9 @@
* 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 "common.h"
+
#include "diff.h"
#include "diff_file.h"
#include "patch_generate.h"
@@ -222,7 +224,7 @@ static int diff_print_one_raw(
if (pi->id_strlen > id_abbrev) {
giterr_set(GITERR_PATCH,
- "The patch input contains %d id characters (cannot print %d)",
+ "the patch input contains %d id characters (cannot print %d)",
id_abbrev, pi->id_strlen);
return -1;
}
@@ -273,7 +275,7 @@ static int diff_print_oid_range(
if (delta->old_file.mode &&
id_strlen > delta->old_file.id_abbrev) {
giterr_set(GITERR_PATCH,
- "The patch input contains %d id characters (cannot print %d)",
+ "the patch input contains %d id characters (cannot print %d)",
delta->old_file.id_abbrev, id_strlen);
return -1;
}
@@ -281,7 +283,7 @@ static int diff_print_oid_range(
if ((delta->new_file.mode &&
id_strlen > delta->new_file.id_abbrev)) {
giterr_set(GITERR_PATCH,
- "The patch input contains %d id characters (cannot print %d)",
+ "the patch input contains %d id characters (cannot print %d)",
delta->new_file.id_abbrev, id_strlen);
return -1;
}
@@ -680,7 +682,7 @@ int git_diff_print(
print_file = diff_print_one_name_status;
break;
default:
- giterr_set(GITERR_INVALID, "Unknown diff output format (%d)", format);
+ giterr_set(GITERR_INVALID, "unknown diff output format (%d)", format);
return -1;
}
@@ -708,7 +710,7 @@ int git_diff_print_callback__to_buf(
GIT_UNUSED(delta); GIT_UNUSED(hunk);
if (!output) {
- giterr_set(GITERR_INVALID, "Buffer pointer must be provided");
+ giterr_set(GITERR_INVALID, "buffer pointer must be provided");
return -1;
}
diff --git a/src/diff_stats.c b/src/diff_stats.c
index 9c186d793..583c68459 100644
--- a/src/diff_stats.c
+++ b/src/diff_stats.c
@@ -4,7 +4,9 @@
* 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 "common.h"
+
#include "vector.h"
#include "diff.h"
#include "patch_generate.h"
@@ -300,15 +302,24 @@ int git_diff_stats_to_buf(
}
if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) {
- error = git_buf_printf(
- out, " %" PRIuZ " file%s changed, %" PRIuZ
- " insertion%s(+), %" PRIuZ " deletion%s(-)\n",
- stats->files_changed, stats->files_changed != 1 ? "s" : "",
- stats->insertions, stats->insertions != 1 ? "s" : "",
- stats->deletions, stats->deletions != 1 ? "s" : "");
-
- if (error < 0)
- return error;
+ git_buf_printf(
+ out, " %" PRIuZ " file%s changed",
+ stats->files_changed, stats->files_changed != 1 ? "s" : "");
+
+ if (stats->insertions || stats->deletions == 0)
+ git_buf_printf(
+ out, ", %" PRIuZ " insertion%s(+)",
+ stats->insertions, stats->insertions != 1 ? "s" : "");
+
+ if (stats->deletions || stats->insertions == 0)
+ git_buf_printf(
+ out, ", %" PRIuZ " deletion%s(-)",
+ stats->deletions, stats->deletions != 1 ? "s" : "");
+
+ git_buf_putc(out, '\n');
+
+ if (git_buf_oom(out))
+ return -1;
}
if (format & GIT_DIFF_STATS_INCLUDE_SUMMARY) {
@@ -334,4 +345,3 @@ void git_diff_stats_free(git_diff_stats *stats)
git__free(stats->filestats);
git__free(stats);
}
-
diff --git a/src/diff_tform.c b/src/diff_tform.c
index e8848bd45..c0461a3a3 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -4,7 +4,8 @@
* 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 "common.h"
+
+#include "diff_tform.h"
#include "git2/config.h"
#include "git2/blob.h"
@@ -131,7 +132,7 @@ int git_diff__merge(
if (ignore_case != ((from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) ||
reversed != ((from->opts.flags & GIT_DIFF_REVERSE) != 0)) {
giterr_set(GITERR_INVALID,
- "Attempt to merge diffs created with conflicting options");
+ "attempt to merge diffs created with conflicting options");
return -1;
}
@@ -553,8 +554,8 @@ static int similarity_measure(
*score = -1;
- /* don't try to compare files of different types */
- if (GIT_MODE_TYPE(a_file->mode) != GIT_MODE_TYPE(b_file->mode))
+ /* don't try to compare things that aren't files */
+ if (!GIT_MODE_ISBLOB(a_file->mode) || !GIT_MODE_ISBLOB(b_file->mode))
return 0;
/* if exact match is requested, force calculation of missing OIDs now */
diff --git a/src/diff_tform.h b/src/diff_tform.h
index 5bd9712d9..a31c40f8e 100644
--- a/src/diff_tform.h
+++ b/src/diff_tform.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_diff_tform_h__
#define INCLUDE_diff_tform_h__
+#include "common.h"
+
+#include "diff_file.h"
+
extern int git_diff_find_similar__hashsig_for_file(
void **out, const git_diff_file *f, const char *path, void *p);
diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c
index 5bd6381b5..5e10db13d 100644
--- a/src/diff_xdiff.c
+++ b/src/diff_xdiff.c
@@ -4,11 +4,12 @@
* 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 "diff_xdiff.h"
+
#include "git2/errors.h"
-#include "common.h"
#include "diff.h"
#include "diff_driver.h"
-#include "diff_xdiff.h"
#include "patch_generate.h"
static int git_xdiff_scan_int(const char **str, int *value)
@@ -50,7 +51,7 @@ static int git_xdiff_parse_hunk(git_diff_hunk *hunk, const char *header)
return 0;
fail:
- giterr_set(GITERR_INVALID, "Malformed hunk header from xdiff");
+ giterr_set(GITERR_INVALID, "malformed hunk header from xdiff");
return -1;
}
@@ -99,7 +100,7 @@ static int diff_update_lines(
info->new_lineno += (int)line->num_lines;
break;
default:
- giterr_set(GITERR_INVALID, "Unknown diff line origin %02x",
+ giterr_set(GITERR_INVALID, "unknown diff line origin %02x",
(unsigned int)line->origin);
return -1;
}
diff --git a/src/diff_xdiff.h b/src/diff_xdiff.h
index 88375986b..aca80b131 100644
--- a/src/diff_xdiff.h
+++ b/src/diff_xdiff.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_diff_xdiff_h__
#define INCLUDE_diff_xdiff_h__
+#include "common.h"
+
#include "diff.h"
#include "xdiff/xdiff.h"
#include "patch_generate.h"
diff --git a/src/errors.c b/src/errors.c
index 91acc3541..a874163b0 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -4,7 +4,9 @@
* 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 "common.h"
+
#include "global.h"
#include "posix.h"
#include "buffer.h"
diff --git a/src/features.h.in b/src/features.h.in
new file mode 100644
index 000000000..e03b7a251
--- /dev/null
+++ b/src/features.h.in
@@ -0,0 +1,36 @@
+#ifndef INCLUDE_features_h__
+#define INCLUDE_features_h__
+
+#cmakedefine GIT_DEBUG_POOL 1
+#cmakedefine GIT_TRACE 1
+#cmakedefine GIT_THREADS 1
+#cmakedefine GIT_MSVC_CRTDBG 1
+
+#cmakedefine GIT_ARCH_64 1
+#cmakedefine GIT_ARCH_32 1
+
+#cmakedefine GIT_USE_ICONV 1
+#cmakedefine GIT_USE_NSEC 1
+#cmakedefine GIT_USE_STAT_MTIM 1
+#cmakedefine GIT_USE_STAT_MTIMESPEC 1
+#cmakedefine GIT_USE_STAT_MTIME_NSEC 1
+#cmakedefine GIT_USE_FUTIMENS 1
+#cmakedefine GIT_USE_REGCOMP_L 1
+
+#cmakedefine GIT_SSH 1
+#cmakedefine GIT_SSH_MEMORY_CREDENTIALS 1
+
+#cmakedefine GIT_GSSAPI 1
+#cmakedefine GIT_WINHTTP 1
+#cmakedefine GIT_CURL 1
+
+#cmakedefine GIT_HTTPS 1
+#cmakedefine GIT_OPENSSL 1
+#cmakedefine GIT_SECURE_TRANSPORT 1
+
+#cmakedefine GIT_SHA1_COLLISIONDETECT 1
+#cmakedefine GIT_SHA1_WIN32 1
+#cmakedefine GIT_SHA1_COMMON_CRYPTO 1
+#cmakedefine GIT_SHA1_OPENSSL 1
+
+#endif
diff --git a/src/fetch.c b/src/fetch.c
index 4d895752c..0b22b3673 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -5,16 +5,16 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "fetch.h"
+
#include "git2/oid.h"
#include "git2/refs.h"
#include "git2/revwalk.h"
#include "git2/transport.h"
-#include "common.h"
#include "remote.h"
#include "refspec.h"
#include "pack.h"
-#include "fetch.h"
#include "netops.h"
#include "repository.h"
#include "refs.h"
@@ -113,7 +113,7 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
remote->need_pack = 0;
if (filter_wants(remote, opts) < 0) {
- giterr_set(GITERR_NET, "Failed to filter the reference list for wants");
+ giterr_set(GITERR_NET, "failed to filter the reference list for wants");
return -1;
}
diff --git a/src/fetch.h b/src/fetch.h
index 0412d4e44..1c75af9c3 100644
--- a/src/fetch.h
+++ b/src/fetch.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_fetch_h__
#define INCLUDE_fetch_h__
+#include "common.h"
+
+#include "git2/remote.h"
+
#include "netops.h"
int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts);
diff --git a/src/fetchhead.c b/src/fetchhead.c
index a95ea4ca4..ac25723d3 100644
--- a/src/fetchhead.c
+++ b/src/fetchhead.c
@@ -5,11 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "fetchhead.h"
+
#include "git2/types.h"
#include "git2/oid.h"
-#include "fetchhead.h"
-#include "common.h"
#include "buffer.h"
#include "fileops.h"
#include "filebuf.h"
@@ -115,7 +115,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
assert(repo && fetchhead_refs);
- if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
return -1;
if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) {
@@ -149,7 +149,7 @@ static int fetchhead_ref_parse(
if (!*line) {
giterr_set(GITERR_FETCHHEAD,
- "Empty line in FETCH_HEAD line %d", line_num);
+ "empty line in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
@@ -163,15 +163,15 @@ static int fetchhead_ref_parse(
if (strlen(oid_str) != GIT_OID_HEXSZ) {
giterr_set(GITERR_FETCHHEAD,
- "Invalid object ID in FETCH_HEAD line %d", line_num);
+ "invalid object ID in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
if (git_oid_fromstr(oid, oid_str) < 0) {
const git_error *oid_err = giterr_last();
- const char *err_msg = oid_err ? oid_err->message : "Invalid object ID";
+ const char *err_msg = oid_err ? oid_err->message : "invalid object ID";
- giterr_set(GITERR_FETCHHEAD, "%s in FETCH_HEAD line %d",
+ giterr_set(GITERR_FETCHHEAD, "%s in FETCH_HEAD line %"PRIuZ,
err_msg, line_num);
return -1;
}
@@ -180,7 +180,7 @@ static int fetchhead_ref_parse(
if (*line) {
if ((is_merge_str = git__strsep(&line, "\t")) == NULL) {
giterr_set(GITERR_FETCHHEAD,
- "Invalid description data in FETCH_HEAD line %d", line_num);
+ "invalid description data in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
@@ -190,13 +190,13 @@ static int fetchhead_ref_parse(
*is_merge = 0;
else {
giterr_set(GITERR_FETCHHEAD,
- "Invalid for-merge entry in FETCH_HEAD line %d", line_num);
+ "invalid for-merge entry in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
if ((desc = line) == NULL) {
giterr_set(GITERR_FETCHHEAD,
- "Invalid description in FETCH_HEAD line %d", line_num);
+ "invalid description in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
@@ -213,7 +213,7 @@ static int fetchhead_ref_parse(
if ((desc = strstr(name, "' ")) == NULL ||
git__prefixcmp(desc, "' of ") != 0) {
giterr_set(GITERR_FETCHHEAD,
- "Invalid description in FETCH_HEAD line %d", line_num);
+ "invalid description in FETCH_HEAD line %"PRIuZ, line_num);
return -1;
}
@@ -249,7 +249,7 @@ int git_repository_fetchhead_foreach(git_repository *repo,
assert(repo && cb);
- if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
return -1;
if ((error = git_futils_readbuffer(&file, git_buf_cstr(&path))) < 0)
@@ -277,7 +277,7 @@ int git_repository_fetchhead_foreach(git_repository *repo,
}
if (*buffer) {
- giterr_set(GITERR_FETCHHEAD, "No EOL at line %d", line_num+1);
+ giterr_set(GITERR_FETCHHEAD, "no EOL at line %"PRIuZ, line_num+1);
error = -1;
goto done;
}
diff --git a/src/fetchhead.h b/src/fetchhead.h
index b03bd0f74..9e5171010 100644
--- a/src/fetchhead.h
+++ b/src/fetchhead.h
@@ -7,6 +7,9 @@
#ifndef INCLUDE_fetchhead_h__
#define INCLUDE_fetchhead_h__
+#include "common.h"
+
+#include "oid.h"
#include "vector.h"
typedef struct git_fetchhead_ref {
diff --git a/src/filebuf.c b/src/filebuf.c
index 582399470..8b7e489da 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -4,8 +4,9 @@
* 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 "common.h"
+
#include "filebuf.h"
+
#include "fileops.h"
static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
@@ -23,7 +24,7 @@ static int verify_last_error(git_filebuf *file)
{
switch (file->last_error) {
case BUFERR_WRITE:
- giterr_set(GITERR_OS, "Failed to write out file");
+ giterr_set(GITERR_OS, "failed to write out file");
return -1;
case BUFERR_MEM:
@@ -48,7 +49,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
else {
giterr_clear(); /* actual OS error code just confuses */
giterr_set(GITERR_OS,
- "Failed to lock file '%s' for writing", file->path_lock);
+ "failed to lock file '%s' for writing", file->path_lock);
return GIT_ELOCKED;
}
}
@@ -75,7 +76,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
source = p_open(file->path_original, O_RDONLY);
if (source < 0) {
giterr_set(GITERR_OS,
- "Failed to open file '%s' for reading",
+ "failed to open file '%s' for reading",
file->path_original);
return -1;
}
@@ -90,10 +91,10 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
p_close(source);
if (read_bytes < 0) {
- giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original);
+ giterr_set(GITERR_OS, "failed to read file '%s'", file->path_original);
return -1;
} else if (error < 0) {
- giterr_set(GITERR_OS, "Failed to write file '%s'", file->path_lock);
+ giterr_set(GITERR_OS, "failed to write file '%s'", file->path_lock);
return -1;
}
}
@@ -246,7 +247,7 @@ static int resolve_symlink(git_buf *out, const char *path)
root = git_path_root(target.ptr);
if (root >= 0) {
- if ((error = git_buf_puts(&curpath, target.ptr)) < 0)
+ if ((error = git_buf_sets(&curpath, target.ptr)) < 0)
goto cleanup;
} else {
git_buf dir = GIT_BUF_INIT;
@@ -291,6 +292,9 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
if (flags & GIT_FILEBUF_DO_NOT_BUFFER)
file->do_not_buffer = true;
+ if (flags & GIT_FILEBUF_FSYNC)
+ file->do_fsync = true;
+
file->buf_size = size;
file->buf_pos = 0;
file->fd = -1;
@@ -316,7 +320,7 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
if (compression != 0) {
/* Initialize the ZLib stream */
if (deflateInit(&file->zs, compression) != Z_OK) {
- giterr_set(GITERR_ZLIB, "Failed to initialize zlib");
+ giterr_set(GITERR_ZLIB, "failed to initialize zlib");
goto cleanup;
}
@@ -425,18 +429,26 @@ int git_filebuf_commit(git_filebuf *file)
file->fd_is_open = false;
+ if (file->do_fsync && p_fsync(file->fd) < 0) {
+ giterr_set(GITERR_OS, "failed to fsync '%s'", file->path_lock);
+ goto on_error;
+ }
+
if (p_close(file->fd) < 0) {
- giterr_set(GITERR_OS, "Failed to close file at '%s'", file->path_lock);
+ giterr_set(GITERR_OS, "failed to close file at '%s'", file->path_lock);
goto on_error;
}
file->fd = -1;
if (p_rename(file->path_lock, file->path_original) < 0) {
- giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original);
+ giterr_set(GITERR_OS, "failed to rename lockfile to '%s'", file->path_original);
goto on_error;
}
+ if (file->do_fsync && git_futils_fsync_parent(file->path_original) < 0)
+ goto on_error;
+
file->did_rename = true;
git_filebuf_cleanup(file);
@@ -571,7 +583,7 @@ int git_filebuf_stats(time_t *mtime, size_t *size, git_filebuf *file)
res = p_stat(file->path_original, &st);
if (res < 0) {
- giterr_set(GITERR_OS, "Could not get stat info for '%s'",
+ giterr_set(GITERR_OS, "could not get stat info for '%s'",
file->path_original);
return res;
}
diff --git a/src/filebuf.h b/src/filebuf.h
index 467708d45..f51ff230f 100644
--- a/src/filebuf.h
+++ b/src/filebuf.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_filebuf_h__
#define INCLUDE_filebuf_h__
+#include "common.h"
+
#include "fileops.h"
#include "hash.h"
#include <zlib.h>
@@ -20,7 +22,8 @@
#define GIT_FILEBUF_FORCE (1 << 3)
#define GIT_FILEBUF_TEMPORARY (1 << 4)
#define GIT_FILEBUF_DO_NOT_BUFFER (1 << 5)
-#define GIT_FILEBUF_DEFLATE_SHIFT (6)
+#define GIT_FILEBUF_FSYNC (1 << 6)
+#define GIT_FILEBUF_DEFLATE_SHIFT (7)
#define GIT_FILELOCK_EXTENSION ".lock\0"
#define GIT_FILELOCK_EXTLENGTH 6
@@ -47,6 +50,7 @@ struct git_filebuf {
bool created_lock;
bool did_rename;
bool do_not_buffer;
+ bool do_fsync;
int last_error;
};
diff --git a/src/fileops.c b/src/fileops.c
index fcc0301f9..ad3f67e2b 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -4,8 +4,9 @@
* 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 "common.h"
+
#include "fileops.h"
+
#include "global.h"
#include "strmap.h"
#include <ctype.h>
@@ -13,8 +14,6 @@
#include "win32/findfile.h"
#endif
-GIT__USE_STRMAP
-
int git_futils_mkpath2file(const char *file_path, const mode_t mode)
{
return git_futils_mkdir(
@@ -37,13 +36,13 @@ int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode)
if ((fd = p_mkstemp(path_out->ptr)) < 0) {
giterr_set(GITERR_OS,
- "Failed to create temporary file '%s'", path_out->ptr);
+ "failed to create temporary file '%s'", path_out->ptr);
return -1;
}
if (p_chmod(path_out->ptr, (mode & ~mask))) {
giterr_set(GITERR_OS,
- "Failed to set permissions on file '%s'", path_out->ptr);
+ "failed to set permissions on file '%s'", path_out->ptr);
return -1;
}
@@ -59,7 +58,7 @@ int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode
fd = p_creat(path, mode);
if (fd < 0) {
- giterr_set(GITERR_OS, "Failed to create file '%s'", path);
+ giterr_set(GITERR_OS, "failed to create file '%s'", path);
return -1;
}
@@ -68,12 +67,20 @@ int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode
int git_futils_creat_locked(const char *path, const mode_t mode)
{
- int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC |
- O_EXCL | O_BINARY | O_CLOEXEC, mode);
+ int fd = p_open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC,
+ mode);
if (fd < 0) {
- giterr_set(GITERR_OS, "Failed to create locked file '%s'", path);
- return errno == EEXIST ? GIT_ELOCKED : -1;
+ int error = errno;
+ giterr_set(GITERR_OS, "failed to create locked file '%s'", path);
+ switch (error) {
+ case EEXIST:
+ return GIT_ELOCKED;
+ case ENOENT:
+ return GIT_ENOTFOUND;
+ default:
+ return -1;
+ }
}
return fd;
@@ -100,7 +107,7 @@ git_off_t git_futils_filesize(git_file fd)
struct stat sb;
if (p_fstat(fd, &sb)) {
- giterr_set(GITERR_OS, "Failed to stat file descriptor");
+ giterr_set(GITERR_OS, "failed to stat file descriptor");
return -1;
}
@@ -129,7 +136,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
git_buf_clear(buf);
if (!git__is_ssizet(len)) {
- giterr_set(GITERR_INVALID, "Read too large.");
+ giterr_set(GITERR_INVALID, "read too large");
return -1;
}
@@ -141,7 +148,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
read_size = p_read(fd, buf->ptr, len);
if (read_size != (ssize_t)len) {
- giterr_set(GITERR_OS, "Failed to read descriptor");
+ giterr_set(GITERR_OS, "failed to read descriptor");
git_buf_free(buf);
return -1;
}
@@ -176,7 +183,7 @@ int git_futils_readbuffer_updated(
}
if (!git__is_sizet(st.st_size+1)) {
- giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path);
+ giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path);
return -1;
}
@@ -190,28 +197,29 @@ int git_futils_readbuffer_updated(
p_close(fd);
- if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
- git_buf_free(&buf);
- return error;
- }
+ if (checksum) {
+ if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
+ git_buf_free(&buf);
+ return error;
+ }
- /*
- * If we were given a checksum, we only want to use it if it's different
- */
- if (checksum && !git_oid__cmp(checksum, &checksum_new)) {
- git_buf_free(&buf);
- if (updated)
- *updated = 0;
+ /*
+ * If we were given a checksum, we only want to use it if it's different
+ */
+ if (!git_oid__cmp(checksum, &checksum_new)) {
+ git_buf_free(&buf);
+ if (updated)
+ *updated = 0;
- return 0;
+ return 0;
+ }
+
+ git_oid_cpy(checksum, &checksum_new);
}
/*
* If we're here, the file did change, or the user didn't have an old version
*/
- if (checksum)
- git_oid_cpy(checksum, &checksum_new);
-
if (updated != NULL)
*updated = 1;
@@ -229,26 +237,43 @@ int git_futils_readbuffer(git_buf *buf, const char *path)
int git_futils_writebuffer(
const git_buf *buf, const char *path, int flags, mode_t mode)
{
- int fd, error = 0;
+ int fd, do_fsync = 0, error = 0;
- if (flags <= 0)
+ if (!flags)
flags = O_CREAT | O_TRUNC | O_WRONLY;
+
+ if ((flags & O_FSYNC) != 0)
+ do_fsync = 1;
+
+ flags &= ~O_FSYNC;
+
if (!mode)
mode = GIT_FILEMODE_BLOB;
if ((fd = p_open(path, flags, mode)) < 0) {
- giterr_set(GITERR_OS, "Could not open '%s' for writing", path);
+ giterr_set(GITERR_OS, "could not open '%s' for writing", path);
return fd;
}
if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) {
- giterr_set(GITERR_OS, "Could not write to '%s'", path);
+ giterr_set(GITERR_OS, "could not write to '%s'", path);
(void)p_close(fd);
return error;
}
- if ((error = p_close(fd)) < 0)
- giterr_set(GITERR_OS, "Error while closing '%s'", path);
+ if (do_fsync && (error = p_fsync(fd)) < 0) {
+ giterr_set(GITERR_OS, "could not fsync '%s'", path);
+ p_close(fd);
+ return error;
+ }
+
+ if ((error = p_close(fd)) < 0) {
+ giterr_set(GITERR_OS, "error while closing '%s'", path);
+ return error;
+ }
+
+ if (do_fsync && (flags & O_CREAT))
+ error = git_futils_fsync_parent(path);
return error;
}
@@ -259,7 +284,7 @@ int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmod
return -1;
if (p_rename(from, to) < 0) {
- giterr_set(GITERR_OS, "Failed to rename '%s' to '%s'", from, to);
+ giterr_set(GITERR_OS, "failed to rename '%s' to '%s'", from, to);
return -1;
}
@@ -280,13 +305,19 @@ int git_futils_mmap_ro_file(git_map *out, const char *path)
if (fd < 0)
return fd;
- len = git_futils_filesize(fd);
+ if ((len = git_futils_filesize(fd)) < 0) {
+ result = -1;
+ goto out;
+ }
+
if (!git__is_sizet(len)) {
- giterr_set(GITERR_OS, "File `%s` too large to mmap", path);
- return -1;
+ giterr_set(GITERR_OS, "file `%s` too large to mmap", path);
+ result = -1;
+ goto out;
}
result = git_futils_mmap_ro(out, fd, 0, (size_t)len);
+out:
p_close(fd);
return result;
}
@@ -306,14 +337,14 @@ GIT_INLINE(int) mkdir_validate_dir(
/* with exclusive create, existing dir is an error */
if ((flags & GIT_MKDIR_EXCL) != 0) {
giterr_set(GITERR_FILESYSTEM,
- "Failed to make directory '%s': directory exists", path);
+ "failed to make directory '%s': directory exists", path);
return GIT_EEXISTS;
}
if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) ||
(S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) {
if (p_unlink(path) < 0) {
- giterr_set(GITERR_OS, "Failed to remove %s '%s'",
+ giterr_set(GITERR_OS, "failed to remove %s '%s'",
S_ISLNK(st->st_mode) ? "symlink" : "file", path);
return GIT_EEXISTS;
}
@@ -321,7 +352,7 @@ GIT_INLINE(int) mkdir_validate_dir(
opts->perfdata.mkdir_calls++;
if (p_mkdir(path, mode) < 0) {
- giterr_set(GITERR_OS, "Failed to make directory '%s'", path);
+ giterr_set(GITERR_OS, "failed to make directory '%s'", path);
return GIT_EEXISTS;
}
}
@@ -331,14 +362,14 @@ GIT_INLINE(int) mkdir_validate_dir(
opts->perfdata.stat_calls++;
if (p_stat(path, st) < 0) {
- giterr_set(GITERR_OS, "Failed to make directory '%s'", path);
+ giterr_set(GITERR_OS, "failed to make directory '%s'", path);
return GIT_EEXISTS;
}
}
else if (!S_ISDIR(st->st_mode)) {
giterr_set(GITERR_FILESYSTEM,
- "Failed to make directory '%s': directory exists", path);
+ "failed to make directory '%s': directory exists", path);
return GIT_EEXISTS;
}
@@ -561,7 +592,7 @@ int git_futils_mkdir_relative(
retry_lstat:
if (p_lstat(make_path.ptr, &st) < 0) {
if (mkdir_attempted || errno != ENOENT) {
- giterr_set(GITERR_OS, "Cannot access component in path '%s'", make_path.ptr);
+ giterr_set(GITERR_OS, "cannot access component in path '%s'", make_path.ptr);
error = -1;
goto done;
}
@@ -572,7 +603,7 @@ retry_lstat:
if (p_mkdir(make_path.ptr, mode) < 0) {
if (errno == EEXIST)
goto retry_lstat;
- giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
+ giterr_set(GITERR_OS, "failed to make directory '%s'", make_path.ptr);
error = -1;
goto done;
}
@@ -599,7 +630,7 @@ retry_lstat:
memcpy(cache_path, make_path.ptr, make_path.size + 1);
- git_strmap_insert(opts->dir_map, cache_path, cache_path, error);
+ git_strmap_insert(opts->dir_map, cache_path, cache_path, &error);
if (error < 0)
goto done;
}
@@ -613,7 +644,7 @@ retry_lstat:
opts->perfdata.stat_calls++;
if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) {
- giterr_set(GITERR_OS, "Path is not a directory '%s'",
+ giterr_set(GITERR_OS, "path is not a directory '%s'",
make_path.ptr);
error = GIT_ENOTFOUND;
}
@@ -636,10 +667,10 @@ typedef struct {
static int futils__error_cannot_rmdir(const char *path, const char *filemsg)
{
if (filemsg)
- giterr_set(GITERR_OS, "Could not remove directory. File '%s' %s",
+ giterr_set(GITERR_OS, "could not remove directory '%s': %s",
path, filemsg);
else
- giterr_set(GITERR_OS, "Could not remove directory '%s'", path);
+ giterr_set(GITERR_OS, "could not remove directory '%s'", path);
return -1;
}
@@ -740,6 +771,9 @@ static int futils__rmdir_empty_parent(void *opaque, const char *path)
if (en == ENOENT || en == ENOTDIR) {
/* do nothing */
+ } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0 &&
+ en == EBUSY) {
+ error = git_path_set_error(errno, path, "rmdir");
} else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
error = GIT_ITEROVER;
} else {
@@ -807,7 +841,7 @@ static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done)
error = p_write(ofd, buffer, len);
if (len < 0) {
- giterr_set(GITERR_OS, "Read error while copying file");
+ giterr_set(GITERR_OS, "read error while copying file");
error = (int)len;
}
@@ -863,14 +897,14 @@ static int cp_link(const char *from, const char *to, size_t link_size)
read_len = p_readlink(from, link_data, link_size);
if (read_len != (ssize_t)link_size) {
- giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", from);
+ giterr_set(GITERR_OS, "failed to read symlink data for '%s'", from);
error = -1;
}
else {
link_data[read_len] = '\0';
if (p_symlink(link_data, to) < 0) {
- giterr_set(GITERR_OS, "Could not symlink '%s' as '%s'",
+ giterr_set(GITERR_OS, "could not symlink '%s' as '%s'",
link_data, to);
error = -1;
}
@@ -966,7 +1000,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
return 0;
if (p_unlink(info->to.ptr) < 0) {
- giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'",
+ giterr_set(GITERR_OS, "cannot overwrite existing file '%s'",
info->to.ptr);
return GIT_EEXISTS;
}
@@ -1101,3 +1135,37 @@ void git_futils_filestamp_set_from_stat(
memset(stamp, 0, sizeof(*stamp));
}
}
+
+int git_futils_fsync_dir(const char *path)
+{
+#ifdef GIT_WIN32
+ GIT_UNUSED(path);
+ return 0;
+#else
+ int fd, error = -1;
+
+ if ((fd = p_open(path, O_RDONLY)) < 0) {
+ giterr_set(GITERR_OS, "failed to open directory '%s' for fsync", path);
+ return -1;
+ }
+
+ if ((error = p_fsync(fd)) < 0)
+ giterr_set(GITERR_OS, "failed to fsync directory '%s'", path);
+
+ p_close(fd);
+ return error;
+#endif
+}
+
+int git_futils_fsync_parent(const char *path)
+{
+ char *parent;
+ int error;
+
+ if ((parent = git_path_dirname(path)) == NULL)
+ return -1;
+
+ error = git_futils_fsync_dir(parent);
+ git__free(parent);
+ return error;
+}
diff --git a/src/fileops.h b/src/fileops.h
index 54e3bd4e4..fd5441243 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -8,6 +8,7 @@
#define INCLUDE_fileops_h__
#include "common.h"
+
#include "map.h"
#include "posix.h"
#include "path.h"
@@ -25,6 +26,13 @@ extern int git_futils_readbuffer_updated(
git_buf *obj, const char *path, git_oid *checksum, int *updated);
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
+/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We
+ * support these internally and they will be removed before the `open` call.
+ */
+#ifndef O_FSYNC
+# define O_FSYNC (1 << 31)
+#endif
+
extern int git_futils_writebuffer(
const git_buf *buf, const char *path, int open_flags, mode_t mode);
@@ -45,12 +53,12 @@ extern int git_futils_writebuffer(
extern int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode);
/**
- * Create an open a process-locked file
+ * Create and open a process-locked file
*/
extern int git_futils_creat_locked(const char *path, const mode_t mode);
/**
- * Create an open a process-locked file, while
+ * Create and open a process-locked file, while
* also creating all the folders in its path
*/
extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode);
@@ -356,4 +364,22 @@ extern void git_futils_filestamp_set(
extern void git_futils_filestamp_set_from_stat(
git_futils_filestamp *stamp, struct stat *st);
+/**
+ * `fsync` the parent directory of the given path, if `fsync` is
+ * supported for directories on this platform.
+ *
+ * @param path Path of the directory to sync.
+ * @return 0 on success, -1 on error
+ */
+extern int git_futils_fsync_dir(const char *path);
+
+/**
+ * `fsync` the parent directory of the given path, if `fsync` is
+ * supported for directories on this platform.
+ *
+ * @param path Path of the file whose parent directory should be synced.
+ * @return 0 on success, -1 on error
+ */
+extern int git_futils_fsync_parent(const char *path);
+
#endif /* INCLUDE_fileops_h__ */
diff --git a/src/filter.c b/src/filter.c
index a0628d779..6ab09790b 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -5,10 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "filter.h"
+
#include "common.h"
#include "fileops.h"
#include "hash.h"
-#include "filter.h"
#include "repository.h"
#include "global.h"
#include "git2/sys/filter.h"
@@ -296,7 +297,7 @@ int git_filter_unregister(const char *name)
/* cannot unregister default filters */
if (!strcmp(GIT_FILTER_CRLF, name) || !strcmp(GIT_FILTER_IDENT, name)) {
- giterr_set(GITERR_FILTER, "Cannot unregister filter '%s'", name);
+ giterr_set(GITERR_FILTER, "cannot unregister filter '%s'", name);
return -1;
}
@@ -306,7 +307,7 @@ int git_filter_unregister(const char *name)
}
if ((fdef = filter_registry_lookup(&pos, name)) == NULL) {
- giterr_set(GITERR_FILTER, "Cannot find filter '%s' to unregister", name);
+ giterr_set(GITERR_FILTER, "cannot find filter '%s' to unregister", name);
error = GIT_ENOTFOUND;
goto done;
}
@@ -645,7 +646,7 @@ int git_filter_list_push(
git_rwlock_rdunlock(&filter_registry.lock);
if (fdef == NULL) {
- giterr_set(GITERR_FILTER, "Cannot use an unregistered filter");
+ giterr_set(GITERR_FILTER, "cannot use an unregistered filter");
return -1;
}
@@ -758,7 +759,7 @@ static int buf_from_blob(git_buf *out, git_blob *blob)
git_off_t rawsize = git_blob_rawsize(blob);
if (!git__is_sizet(rawsize)) {
- giterr_set(GITERR_OS, "Blob is too large to filter");
+ giterr_set(GITERR_OS, "blob is too large to filter");
return -1;
}
@@ -895,7 +896,7 @@ static int stream_list_init(
git_array_size(filters->filters) - 1 - i : i;
git_filter_entry *fe = git_array_get(filters->filters, filter_idx);
git_writestream *filter_stream;
-
+
assert(fe->filter->stream || fe->filter->apply);
/* If necessary, create a stream that proxies the traditional
@@ -911,14 +912,19 @@ static int stream_list_init(
last_stream);
if (error < 0)
- return error;
+ goto out;
git_vector_insert(streams, filter_stream);
last_stream = filter_stream;
}
- *out = last_stream;
- return 0;
+out:
+ if (error)
+ last_stream->close(last_stream);
+ else
+ *out = last_stream;
+
+ return error;
}
void stream_list_free(git_vector *streams)
@@ -943,12 +949,13 @@ int git_filter_list_stream_file(
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
ssize_t readlen;
- int fd = -1, error;
+ int fd = -1, error, initialized = 0;
if ((error = stream_list_init(
&stream_start, &filter_streams, filters, target)) < 0 ||
(error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0)
goto done;
+ initialized = 1;
if ((fd = git_futils_open_ro(abspath.ptr)) < 0) {
error = fd;
@@ -960,13 +967,13 @@ int git_filter_list_stream_file(
goto done;
}
- if (!readlen)
- error = stream_start->close(stream_start);
- else if (readlen < 0)
+ if (readlen < 0)
error = readlen;
-
done:
+ if (initialized)
+ error |= stream_start->close(stream_start);
+
if (fd >= 0)
p_close(fd);
stream_list_free(&filter_streams);
@@ -981,20 +988,24 @@ int git_filter_list_stream_data(
{
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
- int error = 0, close_error;
+ int error, initialized = 0;
git_buf_sanitize(data);
if ((error = stream_list_init(&stream_start, &filter_streams, filters, target)) < 0)
goto out;
+ initialized = 1;
- error = stream_start->write(stream_start, data->ptr, data->size);
+ if ((error = stream_start->write(
+ stream_start, data->ptr, data->size)) < 0)
+ goto out;
out:
- close_error = stream_start->close(stream_start);
+ if (initialized)
+ error |= stream_start->close(stream_start);
+
stream_list_free(&filter_streams);
- /* propagate the stream init or write error */
- return error < 0 ? error : close_error;
+ return error;
}
int git_filter_list_stream_blob(
@@ -1012,3 +1023,9 @@ int git_filter_list_stream_blob(
return git_filter_list_stream_data(filters, &in, target);
}
+
+int git_filter_init(git_filter *filter, unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(filter, version, git_filter, GIT_FILTER_INIT);
+ return 0;
+}
diff --git a/src/filter.h b/src/filter.h
index 9bd835f94..b1c403ba9 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -8,6 +8,7 @@
#define INCLUDE_filter_h__
#include "common.h"
+
#include "attr_file.h"
#include "git2/filter.h"
diff --git a/src/fnmatch.c b/src/fnmatch.c
index 33c8a2512..3cc2a27ba 100644
--- a/src/fnmatch.c
+++ b/src/fnmatch.c
@@ -44,12 +44,12 @@
* Compares a filename or pathname to a pattern.
*/
+#include "fnmatch.h"
+
#include <ctype.h>
#include <stdio.h>
#include <string.h>
-#include "fnmatch.h"
-
#define EOS '\0'
#define RANGE_MATCH 1
diff --git a/src/global.c b/src/global.c
index 45b1ab8f6..c6847a4d2 100644
--- a/src/global.c
+++ b/src/global.c
@@ -4,8 +4,9 @@
* 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 "common.h"
+
#include "global.h"
+
#include "hash.h"
#include "sysdir.h"
#include "filter.h"
@@ -22,7 +23,7 @@
git_mutex git__mwindow_mutex;
-#define MAX_SHUTDOWN_CB 8
+#define MAX_SHUTDOWN_CB 9
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
static git_atomic git__n_shutdown_callbacks;
@@ -247,6 +248,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
static pthread_key_t _tls_key;
+static pthread_mutex_t _init_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t _once_init = PTHREAD_ONCE_INIT;
int init_error = 0;
@@ -268,12 +270,19 @@ static void init_once(void)
int git_libgit2_init(void)
{
- int ret;
+ int ret, err;
ret = git_atomic_inc(&git__n_inits);
- pthread_once(&_once_init, init_once);
- return init_error ? init_error : ret;
+ if ((err = pthread_mutex_lock(&_init_mutex)) != 0)
+ return err;
+ err = pthread_once(&_once_init, init_once);
+ err |= pthread_mutex_unlock(&_init_mutex);
+
+ if (err || init_error)
+ return err | init_error;
+
+ return ret;
}
int git_libgit2_shutdown(void)
@@ -285,6 +294,9 @@ int git_libgit2_shutdown(void)
if ((ret = git_atomic_dec(&git__n_inits)) != 0)
return ret;
+ if ((ret = pthread_mutex_lock(&_init_mutex)) != 0)
+ return ret;
+
/* Shut down any subsystems that have global state */
shutdown_common();
@@ -298,6 +310,9 @@ int git_libgit2_shutdown(void)
git_mutex_free(&git__mwindow_mutex);
_once_init = new_once;
+ if ((ret = pthread_mutex_unlock(&_init_mutex)) != 0)
+ return ret;
+
return 0;
}
@@ -327,7 +342,7 @@ int git_libgit2_init(void)
{
int ret;
- /* Only init SSL the first time */
+ /* Only init subsystems the first time */
if ((ret = git_atomic_inc(&git__n_inits)) != 1)
return ret;
@@ -345,6 +360,7 @@ int git_libgit2_shutdown(void)
if ((ret = git_atomic_dec(&git__n_inits)) == 0) {
shutdown_common();
git__global_state_cleanup(&__state);
+ memset(&__state, 0, sizeof(__state));
}
return ret;
diff --git a/src/global.h b/src/global.h
index 219951525..b75ad6f56 100644
--- a/src/global.h
+++ b/src/global.h
@@ -8,6 +8,7 @@
#define INCLUDE_global_h__
#include "common.h"
+
#include "mwindow.h"
#include "hash.h"
@@ -16,6 +17,12 @@ typedef struct {
git_error error_t;
git_buf error_buf;
char oid_fmt[GIT_OID_HEXSZ+1];
+
+ /* On Windows, this is the current child thread that was started by
+ * `git_thread_create`. This is used to set the thread's exit code
+ * when terminated by `git_thread_exit`. It is unused on POSIX.
+ */
+ git_thread *current_thread;
} git_global_st;
#ifdef GIT_OPENSSL
diff --git a/src/graph.c b/src/graph.c
index 8accd808c..df82f0f71 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include "revwalk.h"
#include "merge.h"
#include "git2/graph.h"
@@ -59,7 +61,7 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one,
/* as long as there are non-STALE commits */
while (interesting(&list, roots)) {
git_commit_list_node *commit = git_pqueue_pop(&list);
- int flags;
+ unsigned int flags;
if (commit == NULL)
break;
diff --git a/src/hash.c b/src/hash.c
index f3645a913..cc6676d4d 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -5,7 +5,6 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "hash.h"
int git_hash_buf(git_oid *out, const void *data, size_t len)
diff --git a/src/hash.h b/src/hash.h
index 0bc02a8a9..cce3a7f30 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_hash_h__
#define INCLUDE_hash_h__
+#include "common.h"
+
#include "git2/oid.h"
typedef struct git_hash_prov git_hash_prov;
@@ -16,11 +18,13 @@ int git_hash_global_init(void);
int git_hash_ctx_init(git_hash_ctx *ctx);
void git_hash_ctx_cleanup(git_hash_ctx *ctx);
-#if defined(GIT_COMMON_CRYPTO)
+#if defined(GIT_SHA1_COLLISIONDETECT)
+# include "hash/hash_collisiondetect.h"
+#elif defined(GIT_SHA1_COMMON_CRYPTO)
# include "hash/hash_common_crypto.h"
-#elif defined(OPENSSL_SHA1)
+#elif defined(GIT_SHA1_OPENSSL)
# include "hash/hash_openssl.h"
-#elif defined(WIN32_SHA1)
+#elif defined(GIT_SHA1_WIN32)
# include "hash/hash_win32.h"
#else
# include "hash/hash_generic.h"
diff --git a/src/hash/hash_collisiondetect.h b/src/hash/hash_collisiondetect.h
new file mode 100644
index 000000000..5fdae8df6
--- /dev/null
+++ b/src/hash/hash_collisiondetect.h
@@ -0,0 +1,47 @@
+/*
+ * 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_hash_collisiondetect_h__
+#define INCLUDE_hash_collisiondetect_h__
+
+#include "hash.h"
+#include "sha1dc/sha1.h"
+
+struct git_hash_ctx {
+ SHA1_CTX c;
+};
+
+#define git_hash_global_init() 0
+#define git_hash_ctx_init(ctx) git_hash_init(ctx)
+#define git_hash_ctx_cleanup(ctx)
+
+GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
+{
+ assert(ctx);
+ SHA1DCInit(&ctx->c);
+ return 0;
+}
+
+GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
+{
+ assert(ctx);
+ SHA1DCUpdate(&ctx->c, data, len);
+ return 0;
+}
+
+GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx)
+{
+ assert(ctx);
+ if (SHA1DCFinal(out->id, &ctx->c)) {
+ giterr_set(GITERR_SHA1, "SHA1 collision attack detected");
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* INCLUDE_hash_collisiondetect_h__ */
diff --git a/src/hash/hash_generic.c b/src/hash/hash_generic.c
index 472a7a696..7b33b6194 100644
--- a/src/hash/hash_generic.c
+++ b/src/hash/hash_generic.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "hash_generic.h"
+
#include "hash.h"
-#include "hash/hash_generic.h"
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
diff --git a/src/hash/hash_generic.h b/src/hash/hash_generic.h
index daeb1cda8..114b60781 100644
--- a/src/hash/hash_generic.h
+++ b/src/hash/hash_generic.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_hash_generic_h__
#define INCLUDE_hash_generic_h__
+#include "common.h"
+
#include "hash.h"
struct git_hash_ctx {
diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c
index 6bae53e55..4d53a57bd 100644
--- a/src/hash/hash_win32.c
+++ b/src/hash/hash_win32.c
@@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "hash_win32.h"
+
#include "global.h"
#include "hash.h"
-#include "hash/hash_win32.h"
#include <wincrypt.h>
#include <strsafe.h>
diff --git a/src/hash/hash_win32.h b/src/hash/hash_win32.h
index 2eee5ca79..187c07267 100644
--- a/src/hash/hash_win32.h
+++ b/src/hash/hash_win32.h
@@ -9,6 +9,7 @@
#define INCLUDE_hash_win32_h__
#include "common.h"
+
#include "hash.h"
#include <wincrypt.h>
diff --git a/src/hash/sha1dc/sha1.c b/src/hash/sha1dc/sha1.c
new file mode 100644
index 000000000..facea1bb5
--- /dev/null
+++ b/src/hash/sha1dc/sha1.c
@@ -0,0 +1,1856 @@
+/***
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow (danshu@microsoft.com)
+* Distributed under the MIT Software License.
+* See accompanying file LICENSE.txt or copy at
+* https://opensource.org/licenses/MIT
+***/
+
+#ifndef SHA1DC_NO_STANDARD_INCLUDES
+#include <string.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C
+#include SHA1DC_CUSTOM_INCLUDE_SHA1_C
+#endif
+
+#ifndef SHA1DC_INIT_SAFE_HASH_DEFAULT
+#define SHA1DC_INIT_SAFE_HASH_DEFAULT 1
+#endif
+
+#include "sha1.h"
+#include "ubc_check.h"
+
+
+/*
+ Because Little-Endian architectures are most common,
+ we only set SHA1DC_BIGENDIAN if one of these conditions is met.
+ Note that all MSFT platforms are little endian,
+ so none of these will be defined under the MSC compiler.
+ If you are compiling on a big endian platform and your compiler does not define one of these,
+ you will have to add whatever macros your tool chain defines to indicate Big-Endianness.
+ */
+#ifdef SHA1DC_BIGENDIAN
+#undef SHA1DC_BIGENDIAN
+#endif
+
+#if (defined(_BYTE_ORDER) || defined(__BYTE_ORDER) || defined(__BYTE_ORDER__))
+
+#if ((defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) || \
+ (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
+ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) )
+#define SHA1DC_BIGENDIAN
+#endif
+
+#else
+
+#if (defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN) || defined(__BIG_ENDIAN__) || \
+ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
+ defined(__sparc))
+#define SHA1DC_BIGENDIAN
+#endif
+
+#endif
+
+#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN))
+#undef SHA1DC_BIGENDIAN
+#endif
+#if (defined(SHA1DC_FORCE_BIGENDIAN) && !defined(SHA1DC_BIGENDIAN))
+#define SHA1DC_BIGENDIAN
+#endif
+/*ENDIANNESS SELECTION*/
+
+#if (defined SHA1DC_FORCE_UNALIGNED_ACCESS || \
+ defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
+ defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
+ defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
+ defined(__386) || defined(_M_X64) || defined(_M_AMD64))
+
+#define SHA1DC_ALLOW_UNALIGNED_ACCESS
+
+#endif /*UNALIGNMENT DETECTION*/
+
+
+#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n))))
+#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n))))
+
+#define sha1_bswap32(x) \
+ {x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = (x << 16) | (x >> 16);}
+
+#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1))
+
+#ifdef SHA1DC_BIGENDIAN
+ #define sha1_load(m, t, temp) { temp = m[t]; }
+#else
+ #define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); }
+#endif
+
+#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x
+
+#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d))))
+#define sha1_f2(b,c,d) ((b)^(c)^(d))
+#define sha1_f3(b,c,d) (((b)&(c))+((d)&((b)^(c))))
+#define sha1_f4(b,c,d) ((b)^(c)^(d))
+
+#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \
+ { e += rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; b = rotate_left(b, 30); }
+#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, m, t) \
+ { e += rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; b = rotate_left(b, 30); }
+#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, m, t) \
+ { e += rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; b = rotate_left(b, 30); }
+#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, m, t) \
+ { e += rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; b = rotate_left(b, 30); }
+
+#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, m, t) \
+ { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; }
+#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, m, t) \
+ { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; }
+#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, m, t) \
+ { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; }
+#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \
+ { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; }
+
+#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \
+ {sha1_load(m, t, temp); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30);}
+
+#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6; b = rotate_left(b, 30); }
+
+
+#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e;
+
+#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION
+void sha1_compression(uint32_t ihv[5], const uint32_t m[16])
+{
+ uint32_t W[80];
+ uint32_t a,b,c,d,e;
+ unsigned i;
+
+ memcpy(W, m, 16 * 4);
+ for (i = 16; i < 80; ++i)
+ W[i] = sha1_mix(W, i);
+
+ a = ihv[0]; b = ihv[1]; c = ihv[2]; d = ihv[3]; e = ihv[4];
+
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
+
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
+
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
+
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
+
+ ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
+}
+#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/
+
+
+static void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
+{
+ uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
+
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
+
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
+
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
+
+ ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
+}
+
+
+
+void sha1_compression_states(uint32_t ihv[5], const uint32_t m[16], uint32_t W[80], uint32_t states[80][5])
+{
+ uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+ uint32_t temp;
+
+#ifdef DOSTORESTATE00
+ SHA1_STORE_STATE(0)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp);
+
+#ifdef DOSTORESTATE01
+ SHA1_STORE_STATE(1)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp);
+
+#ifdef DOSTORESTATE02
+ SHA1_STORE_STATE(2)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp);
+
+#ifdef DOSTORESTATE03
+ SHA1_STORE_STATE(3)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp);
+
+#ifdef DOSTORESTATE04
+ SHA1_STORE_STATE(4)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp);
+
+#ifdef DOSTORESTATE05
+ SHA1_STORE_STATE(5)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp);
+
+#ifdef DOSTORESTATE06
+ SHA1_STORE_STATE(6)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp);
+
+#ifdef DOSTORESTATE07
+ SHA1_STORE_STATE(7)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp);
+
+#ifdef DOSTORESTATE08
+ SHA1_STORE_STATE(8)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp);
+
+#ifdef DOSTORESTATE09
+ SHA1_STORE_STATE(9)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp);
+
+#ifdef DOSTORESTATE10
+ SHA1_STORE_STATE(10)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp);
+
+#ifdef DOSTORESTATE11
+ SHA1_STORE_STATE(11)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp);
+
+#ifdef DOSTORESTATE12
+ SHA1_STORE_STATE(12)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp);
+
+#ifdef DOSTORESTATE13
+ SHA1_STORE_STATE(13)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp);
+
+#ifdef DOSTORESTATE14
+ SHA1_STORE_STATE(14)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp);
+
+#ifdef DOSTORESTATE15
+ SHA1_STORE_STATE(15)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp);
+
+#ifdef DOSTORESTATE16
+ SHA1_STORE_STATE(16)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp);
+
+#ifdef DOSTORESTATE17
+ SHA1_STORE_STATE(17)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp);
+
+#ifdef DOSTORESTATE18
+ SHA1_STORE_STATE(18)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp);
+
+#ifdef DOSTORESTATE19
+ SHA1_STORE_STATE(19)
+#endif
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp);
+
+
+
+#ifdef DOSTORESTATE20
+ SHA1_STORE_STATE(20)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp);
+
+#ifdef DOSTORESTATE21
+ SHA1_STORE_STATE(21)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp);
+
+#ifdef DOSTORESTATE22
+ SHA1_STORE_STATE(22)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp);
+
+#ifdef DOSTORESTATE23
+ SHA1_STORE_STATE(23)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp);
+
+#ifdef DOSTORESTATE24
+ SHA1_STORE_STATE(24)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp);
+
+#ifdef DOSTORESTATE25
+ SHA1_STORE_STATE(25)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp);
+
+#ifdef DOSTORESTATE26
+ SHA1_STORE_STATE(26)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp);
+
+#ifdef DOSTORESTATE27
+ SHA1_STORE_STATE(27)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp);
+
+#ifdef DOSTORESTATE28
+ SHA1_STORE_STATE(28)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp);
+
+#ifdef DOSTORESTATE29
+ SHA1_STORE_STATE(29)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp);
+
+#ifdef DOSTORESTATE30
+ SHA1_STORE_STATE(30)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp);
+
+#ifdef DOSTORESTATE31
+ SHA1_STORE_STATE(31)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp);
+
+#ifdef DOSTORESTATE32
+ SHA1_STORE_STATE(32)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp);
+
+#ifdef DOSTORESTATE33
+ SHA1_STORE_STATE(33)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp);
+
+#ifdef DOSTORESTATE34
+ SHA1_STORE_STATE(34)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp);
+
+#ifdef DOSTORESTATE35
+ SHA1_STORE_STATE(35)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp);
+
+#ifdef DOSTORESTATE36
+ SHA1_STORE_STATE(36)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp);
+
+#ifdef DOSTORESTATE37
+ SHA1_STORE_STATE(37)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp);
+
+#ifdef DOSTORESTATE38
+ SHA1_STORE_STATE(38)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp);
+
+#ifdef DOSTORESTATE39
+ SHA1_STORE_STATE(39)
+#endif
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp);
+
+
+
+#ifdef DOSTORESTATE40
+ SHA1_STORE_STATE(40)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp);
+
+#ifdef DOSTORESTATE41
+ SHA1_STORE_STATE(41)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp);
+
+#ifdef DOSTORESTATE42
+ SHA1_STORE_STATE(42)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp);
+
+#ifdef DOSTORESTATE43
+ SHA1_STORE_STATE(43)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp);
+
+#ifdef DOSTORESTATE44
+ SHA1_STORE_STATE(44)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp);
+
+#ifdef DOSTORESTATE45
+ SHA1_STORE_STATE(45)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp);
+
+#ifdef DOSTORESTATE46
+ SHA1_STORE_STATE(46)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp);
+
+#ifdef DOSTORESTATE47
+ SHA1_STORE_STATE(47)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp);
+
+#ifdef DOSTORESTATE48
+ SHA1_STORE_STATE(48)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp);
+
+#ifdef DOSTORESTATE49
+ SHA1_STORE_STATE(49)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp);
+
+#ifdef DOSTORESTATE50
+ SHA1_STORE_STATE(50)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp);
+
+#ifdef DOSTORESTATE51
+ SHA1_STORE_STATE(51)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp);
+
+#ifdef DOSTORESTATE52
+ SHA1_STORE_STATE(52)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp);
+
+#ifdef DOSTORESTATE53
+ SHA1_STORE_STATE(53)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp);
+
+#ifdef DOSTORESTATE54
+ SHA1_STORE_STATE(54)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp);
+
+#ifdef DOSTORESTATE55
+ SHA1_STORE_STATE(55)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp);
+
+#ifdef DOSTORESTATE56
+ SHA1_STORE_STATE(56)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp);
+
+#ifdef DOSTORESTATE57
+ SHA1_STORE_STATE(57)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp);
+
+#ifdef DOSTORESTATE58
+ SHA1_STORE_STATE(58)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp);
+
+#ifdef DOSTORESTATE59
+ SHA1_STORE_STATE(59)
+#endif
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp);
+
+
+
+
+#ifdef DOSTORESTATE60
+ SHA1_STORE_STATE(60)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp);
+
+#ifdef DOSTORESTATE61
+ SHA1_STORE_STATE(61)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp);
+
+#ifdef DOSTORESTATE62
+ SHA1_STORE_STATE(62)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp);
+
+#ifdef DOSTORESTATE63
+ SHA1_STORE_STATE(63)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp);
+
+#ifdef DOSTORESTATE64
+ SHA1_STORE_STATE(64)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp);
+
+#ifdef DOSTORESTATE65
+ SHA1_STORE_STATE(65)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp);
+
+#ifdef DOSTORESTATE66
+ SHA1_STORE_STATE(66)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp);
+
+#ifdef DOSTORESTATE67
+ SHA1_STORE_STATE(67)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp);
+
+#ifdef DOSTORESTATE68
+ SHA1_STORE_STATE(68)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp);
+
+#ifdef DOSTORESTATE69
+ SHA1_STORE_STATE(69)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp);
+
+#ifdef DOSTORESTATE70
+ SHA1_STORE_STATE(70)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp);
+
+#ifdef DOSTORESTATE71
+ SHA1_STORE_STATE(71)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp);
+
+#ifdef DOSTORESTATE72
+ SHA1_STORE_STATE(72)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp);
+
+#ifdef DOSTORESTATE73
+ SHA1_STORE_STATE(73)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp);
+
+#ifdef DOSTORESTATE74
+ SHA1_STORE_STATE(74)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp);
+
+#ifdef DOSTORESTATE75
+ SHA1_STORE_STATE(75)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp);
+
+#ifdef DOSTORESTATE76
+ SHA1_STORE_STATE(76)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp);
+
+#ifdef DOSTORESTATE77
+ SHA1_STORE_STATE(77)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp);
+
+#ifdef DOSTORESTATE78
+ SHA1_STORE_STATE(78)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp);
+
+#ifdef DOSTORESTATE79
+ SHA1_STORE_STATE(79)
+#endif
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp);
+
+
+
+ ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
+}
+
+
+
+
+#define SHA1_RECOMPRESS(t) \
+static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \
+{ \
+ uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \
+ if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \
+ if (t > 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 78); \
+ if (t > 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 77); \
+ if (t > 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 76); \
+ if (t > 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 75); \
+ if (t > 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 74); \
+ if (t > 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 73); \
+ if (t > 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 72); \
+ if (t > 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 71); \
+ if (t > 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 70); \
+ if (t > 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 69); \
+ if (t > 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 68); \
+ if (t > 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 67); \
+ if (t > 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 66); \
+ if (t > 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 65); \
+ if (t > 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 64); \
+ if (t > 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 63); \
+ if (t > 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 62); \
+ if (t > 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 61); \
+ if (t > 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 60); \
+ if (t > 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 59); \
+ if (t > 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 58); \
+ if (t > 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 57); \
+ if (t > 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 56); \
+ if (t > 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 55); \
+ if (t > 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 54); \
+ if (t > 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 53); \
+ if (t > 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 52); \
+ if (t > 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 51); \
+ if (t > 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 50); \
+ if (t > 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 49); \
+ if (t > 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 48); \
+ if (t > 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 47); \
+ if (t > 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 46); \
+ if (t > 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 45); \
+ if (t > 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 44); \
+ if (t > 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 43); \
+ if (t > 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 42); \
+ if (t > 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 41); \
+ if (t > 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 40); \
+ if (t > 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 39); \
+ if (t > 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 38); \
+ if (t > 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 37); \
+ if (t > 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 36); \
+ if (t > 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 35); \
+ if (t > 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 34); \
+ if (t > 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 33); \
+ if (t > 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 32); \
+ if (t > 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 31); \
+ if (t > 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 30); \
+ if (t > 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 29); \
+ if (t > 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 28); \
+ if (t > 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 27); \
+ if (t > 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 26); \
+ if (t > 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 25); \
+ if (t > 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 24); \
+ if (t > 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 23); \
+ if (t > 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 22); \
+ if (t > 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 21); \
+ if (t > 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 20); \
+ if (t > 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 19); \
+ if (t > 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 18); \
+ if (t > 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 17); \
+ if (t > 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 16); \
+ if (t > 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 15); \
+ if (t > 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 14); \
+ if (t > 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 13); \
+ if (t > 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 12); \
+ if (t > 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 11); \
+ if (t > 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 10); \
+ if (t > 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 9); \
+ if (t > 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 8); \
+ if (t > 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 7); \
+ if (t > 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 6); \
+ if (t > 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 5); \
+ if (t > 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 4); \
+ if (t > 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 3); \
+ if (t > 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 2); \
+ if (t > 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 1); \
+ if (t > 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 0); \
+ ihvin[0] = a; ihvin[1] = b; ihvin[2] = c; ihvin[3] = d; ihvin[4] = e; \
+ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; \
+ if (t <= 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 0); \
+ if (t <= 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 1); \
+ if (t <= 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 2); \
+ if (t <= 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 3); \
+ if (t <= 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 4); \
+ if (t <= 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 5); \
+ if (t <= 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 6); \
+ if (t <= 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 7); \
+ if (t <= 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 8); \
+ if (t <= 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 9); \
+ if (t <= 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 10); \
+ if (t <= 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 11); \
+ if (t <= 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 12); \
+ if (t <= 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 13); \
+ if (t <= 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 14); \
+ if (t <= 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 15); \
+ if (t <= 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 16); \
+ if (t <= 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 17); \
+ if (t <= 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 18); \
+ if (t <= 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 19); \
+ if (t <= 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 20); \
+ if (t <= 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 21); \
+ if (t <= 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 22); \
+ if (t <= 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 23); \
+ if (t <= 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 24); \
+ if (t <= 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 25); \
+ if (t <= 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 26); \
+ if (t <= 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 27); \
+ if (t <= 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 28); \
+ if (t <= 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 29); \
+ if (t <= 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 30); \
+ if (t <= 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 31); \
+ if (t <= 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 32); \
+ if (t <= 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 33); \
+ if (t <= 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 34); \
+ if (t <= 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 35); \
+ if (t <= 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 36); \
+ if (t <= 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 37); \
+ if (t <= 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 38); \
+ if (t <= 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 39); \
+ if (t <= 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 40); \
+ if (t <= 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 41); \
+ if (t <= 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 42); \
+ if (t <= 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 43); \
+ if (t <= 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 44); \
+ if (t <= 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 45); \
+ if (t <= 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 46); \
+ if (t <= 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 47); \
+ if (t <= 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 48); \
+ if (t <= 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 49); \
+ if (t <= 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 50); \
+ if (t <= 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 51); \
+ if (t <= 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 52); \
+ if (t <= 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 53); \
+ if (t <= 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 54); \
+ if (t <= 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 55); \
+ if (t <= 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 56); \
+ if (t <= 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 57); \
+ if (t <= 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 58); \
+ if (t <= 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 59); \
+ if (t <= 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 60); \
+ if (t <= 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 61); \
+ if (t <= 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 62); \
+ if (t <= 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 63); \
+ if (t <= 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 64); \
+ if (t <= 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 65); \
+ if (t <= 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 66); \
+ if (t <= 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 67); \
+ if (t <= 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 68); \
+ if (t <= 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 69); \
+ if (t <= 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 70); \
+ if (t <= 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 71); \
+ if (t <= 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 72); \
+ if (t <= 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 73); \
+ if (t <= 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 74); \
+ if (t <= 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 75); \
+ if (t <= 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 76); \
+ if (t <= 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 77); \
+ if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \
+ if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \
+ ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4127) /* Complier complains about the checks in the above macro being constant. */
+#endif
+
+#ifdef DOSTORESTATE0
+SHA1_RECOMPRESS(0)
+#endif
+
+#ifdef DOSTORESTATE1
+SHA1_RECOMPRESS(1)
+#endif
+
+#ifdef DOSTORESTATE2
+SHA1_RECOMPRESS(2)
+#endif
+
+#ifdef DOSTORESTATE3
+SHA1_RECOMPRESS(3)
+#endif
+
+#ifdef DOSTORESTATE4
+SHA1_RECOMPRESS(4)
+#endif
+
+#ifdef DOSTORESTATE5
+SHA1_RECOMPRESS(5)
+#endif
+
+#ifdef DOSTORESTATE6
+SHA1_RECOMPRESS(6)
+#endif
+
+#ifdef DOSTORESTATE7
+SHA1_RECOMPRESS(7)
+#endif
+
+#ifdef DOSTORESTATE8
+SHA1_RECOMPRESS(8)
+#endif
+
+#ifdef DOSTORESTATE9
+SHA1_RECOMPRESS(9)
+#endif
+
+#ifdef DOSTORESTATE10
+SHA1_RECOMPRESS(10)
+#endif
+
+#ifdef DOSTORESTATE11
+SHA1_RECOMPRESS(11)
+#endif
+
+#ifdef DOSTORESTATE12
+SHA1_RECOMPRESS(12)
+#endif
+
+#ifdef DOSTORESTATE13
+SHA1_RECOMPRESS(13)
+#endif
+
+#ifdef DOSTORESTATE14
+SHA1_RECOMPRESS(14)
+#endif
+
+#ifdef DOSTORESTATE15
+SHA1_RECOMPRESS(15)
+#endif
+
+#ifdef DOSTORESTATE16
+SHA1_RECOMPRESS(16)
+#endif
+
+#ifdef DOSTORESTATE17
+SHA1_RECOMPRESS(17)
+#endif
+
+#ifdef DOSTORESTATE18
+SHA1_RECOMPRESS(18)
+#endif
+
+#ifdef DOSTORESTATE19
+SHA1_RECOMPRESS(19)
+#endif
+
+#ifdef DOSTORESTATE20
+SHA1_RECOMPRESS(20)
+#endif
+
+#ifdef DOSTORESTATE21
+SHA1_RECOMPRESS(21)
+#endif
+
+#ifdef DOSTORESTATE22
+SHA1_RECOMPRESS(22)
+#endif
+
+#ifdef DOSTORESTATE23
+SHA1_RECOMPRESS(23)
+#endif
+
+#ifdef DOSTORESTATE24
+SHA1_RECOMPRESS(24)
+#endif
+
+#ifdef DOSTORESTATE25
+SHA1_RECOMPRESS(25)
+#endif
+
+#ifdef DOSTORESTATE26
+SHA1_RECOMPRESS(26)
+#endif
+
+#ifdef DOSTORESTATE27
+SHA1_RECOMPRESS(27)
+#endif
+
+#ifdef DOSTORESTATE28
+SHA1_RECOMPRESS(28)
+#endif
+
+#ifdef DOSTORESTATE29
+SHA1_RECOMPRESS(29)
+#endif
+
+#ifdef DOSTORESTATE30
+SHA1_RECOMPRESS(30)
+#endif
+
+#ifdef DOSTORESTATE31
+SHA1_RECOMPRESS(31)
+#endif
+
+#ifdef DOSTORESTATE32
+SHA1_RECOMPRESS(32)
+#endif
+
+#ifdef DOSTORESTATE33
+SHA1_RECOMPRESS(33)
+#endif
+
+#ifdef DOSTORESTATE34
+SHA1_RECOMPRESS(34)
+#endif
+
+#ifdef DOSTORESTATE35
+SHA1_RECOMPRESS(35)
+#endif
+
+#ifdef DOSTORESTATE36
+SHA1_RECOMPRESS(36)
+#endif
+
+#ifdef DOSTORESTATE37
+SHA1_RECOMPRESS(37)
+#endif
+
+#ifdef DOSTORESTATE38
+SHA1_RECOMPRESS(38)
+#endif
+
+#ifdef DOSTORESTATE39
+SHA1_RECOMPRESS(39)
+#endif
+
+#ifdef DOSTORESTATE40
+SHA1_RECOMPRESS(40)
+#endif
+
+#ifdef DOSTORESTATE41
+SHA1_RECOMPRESS(41)
+#endif
+
+#ifdef DOSTORESTATE42
+SHA1_RECOMPRESS(42)
+#endif
+
+#ifdef DOSTORESTATE43
+SHA1_RECOMPRESS(43)
+#endif
+
+#ifdef DOSTORESTATE44
+SHA1_RECOMPRESS(44)
+#endif
+
+#ifdef DOSTORESTATE45
+SHA1_RECOMPRESS(45)
+#endif
+
+#ifdef DOSTORESTATE46
+SHA1_RECOMPRESS(46)
+#endif
+
+#ifdef DOSTORESTATE47
+SHA1_RECOMPRESS(47)
+#endif
+
+#ifdef DOSTORESTATE48
+SHA1_RECOMPRESS(48)
+#endif
+
+#ifdef DOSTORESTATE49
+SHA1_RECOMPRESS(49)
+#endif
+
+#ifdef DOSTORESTATE50
+SHA1_RECOMPRESS(50)
+#endif
+
+#ifdef DOSTORESTATE51
+SHA1_RECOMPRESS(51)
+#endif
+
+#ifdef DOSTORESTATE52
+SHA1_RECOMPRESS(52)
+#endif
+
+#ifdef DOSTORESTATE53
+SHA1_RECOMPRESS(53)
+#endif
+
+#ifdef DOSTORESTATE54
+SHA1_RECOMPRESS(54)
+#endif
+
+#ifdef DOSTORESTATE55
+SHA1_RECOMPRESS(55)
+#endif
+
+#ifdef DOSTORESTATE56
+SHA1_RECOMPRESS(56)
+#endif
+
+#ifdef DOSTORESTATE57
+SHA1_RECOMPRESS(57)
+#endif
+
+#ifdef DOSTORESTATE58
+SHA1_RECOMPRESS(58)
+#endif
+
+#ifdef DOSTORESTATE59
+SHA1_RECOMPRESS(59)
+#endif
+
+#ifdef DOSTORESTATE60
+SHA1_RECOMPRESS(60)
+#endif
+
+#ifdef DOSTORESTATE61
+SHA1_RECOMPRESS(61)
+#endif
+
+#ifdef DOSTORESTATE62
+SHA1_RECOMPRESS(62)
+#endif
+
+#ifdef DOSTORESTATE63
+SHA1_RECOMPRESS(63)
+#endif
+
+#ifdef DOSTORESTATE64
+SHA1_RECOMPRESS(64)
+#endif
+
+#ifdef DOSTORESTATE65
+SHA1_RECOMPRESS(65)
+#endif
+
+#ifdef DOSTORESTATE66
+SHA1_RECOMPRESS(66)
+#endif
+
+#ifdef DOSTORESTATE67
+SHA1_RECOMPRESS(67)
+#endif
+
+#ifdef DOSTORESTATE68
+SHA1_RECOMPRESS(68)
+#endif
+
+#ifdef DOSTORESTATE69
+SHA1_RECOMPRESS(69)
+#endif
+
+#ifdef DOSTORESTATE70
+SHA1_RECOMPRESS(70)
+#endif
+
+#ifdef DOSTORESTATE71
+SHA1_RECOMPRESS(71)
+#endif
+
+#ifdef DOSTORESTATE72
+SHA1_RECOMPRESS(72)
+#endif
+
+#ifdef DOSTORESTATE73
+SHA1_RECOMPRESS(73)
+#endif
+
+#ifdef DOSTORESTATE74
+SHA1_RECOMPRESS(74)
+#endif
+
+#ifdef DOSTORESTATE75
+SHA1_RECOMPRESS(75)
+#endif
+
+#ifdef DOSTORESTATE76
+SHA1_RECOMPRESS(76)
+#endif
+
+#ifdef DOSTORESTATE77
+SHA1_RECOMPRESS(77)
+#endif
+
+#ifdef DOSTORESTATE78
+SHA1_RECOMPRESS(78)
+#endif
+
+#ifdef DOSTORESTATE79
+SHA1_RECOMPRESS(79)
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
+{
+ switch (step)
+ {
+#ifdef DOSTORESTATE0
+ case 0:
+ sha1recompress_fast_0(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE1
+ case 1:
+ sha1recompress_fast_1(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE2
+ case 2:
+ sha1recompress_fast_2(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE3
+ case 3:
+ sha1recompress_fast_3(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE4
+ case 4:
+ sha1recompress_fast_4(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE5
+ case 5:
+ sha1recompress_fast_5(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE6
+ case 6:
+ sha1recompress_fast_6(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE7
+ case 7:
+ sha1recompress_fast_7(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE8
+ case 8:
+ sha1recompress_fast_8(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE9
+ case 9:
+ sha1recompress_fast_9(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE10
+ case 10:
+ sha1recompress_fast_10(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE11
+ case 11:
+ sha1recompress_fast_11(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE12
+ case 12:
+ sha1recompress_fast_12(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE13
+ case 13:
+ sha1recompress_fast_13(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE14
+ case 14:
+ sha1recompress_fast_14(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE15
+ case 15:
+ sha1recompress_fast_15(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE16
+ case 16:
+ sha1recompress_fast_16(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE17
+ case 17:
+ sha1recompress_fast_17(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE18
+ case 18:
+ sha1recompress_fast_18(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE19
+ case 19:
+ sha1recompress_fast_19(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE20
+ case 20:
+ sha1recompress_fast_20(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE21
+ case 21:
+ sha1recompress_fast_21(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE22
+ case 22:
+ sha1recompress_fast_22(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE23
+ case 23:
+ sha1recompress_fast_23(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE24
+ case 24:
+ sha1recompress_fast_24(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE25
+ case 25:
+ sha1recompress_fast_25(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE26
+ case 26:
+ sha1recompress_fast_26(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE27
+ case 27:
+ sha1recompress_fast_27(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE28
+ case 28:
+ sha1recompress_fast_28(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE29
+ case 29:
+ sha1recompress_fast_29(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE30
+ case 30:
+ sha1recompress_fast_30(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE31
+ case 31:
+ sha1recompress_fast_31(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE32
+ case 32:
+ sha1recompress_fast_32(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE33
+ case 33:
+ sha1recompress_fast_33(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE34
+ case 34:
+ sha1recompress_fast_34(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE35
+ case 35:
+ sha1recompress_fast_35(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE36
+ case 36:
+ sha1recompress_fast_36(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE37
+ case 37:
+ sha1recompress_fast_37(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE38
+ case 38:
+ sha1recompress_fast_38(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE39
+ case 39:
+ sha1recompress_fast_39(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE40
+ case 40:
+ sha1recompress_fast_40(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE41
+ case 41:
+ sha1recompress_fast_41(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE42
+ case 42:
+ sha1recompress_fast_42(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE43
+ case 43:
+ sha1recompress_fast_43(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE44
+ case 44:
+ sha1recompress_fast_44(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE45
+ case 45:
+ sha1recompress_fast_45(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE46
+ case 46:
+ sha1recompress_fast_46(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE47
+ case 47:
+ sha1recompress_fast_47(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE48
+ case 48:
+ sha1recompress_fast_48(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE49
+ case 49:
+ sha1recompress_fast_49(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE50
+ case 50:
+ sha1recompress_fast_50(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE51
+ case 51:
+ sha1recompress_fast_51(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE52
+ case 52:
+ sha1recompress_fast_52(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE53
+ case 53:
+ sha1recompress_fast_53(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE54
+ case 54:
+ sha1recompress_fast_54(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE55
+ case 55:
+ sha1recompress_fast_55(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE56
+ case 56:
+ sha1recompress_fast_56(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE57
+ case 57:
+ sha1recompress_fast_57(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE58
+ case 58:
+ sha1recompress_fast_58(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE59
+ case 59:
+ sha1recompress_fast_59(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE60
+ case 60:
+ sha1recompress_fast_60(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE61
+ case 61:
+ sha1recompress_fast_61(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE62
+ case 62:
+ sha1recompress_fast_62(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE63
+ case 63:
+ sha1recompress_fast_63(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE64
+ case 64:
+ sha1recompress_fast_64(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE65
+ case 65:
+ sha1recompress_fast_65(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE66
+ case 66:
+ sha1recompress_fast_66(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE67
+ case 67:
+ sha1recompress_fast_67(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE68
+ case 68:
+ sha1recompress_fast_68(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE69
+ case 69:
+ sha1recompress_fast_69(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE70
+ case 70:
+ sha1recompress_fast_70(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE71
+ case 71:
+ sha1recompress_fast_71(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE72
+ case 72:
+ sha1recompress_fast_72(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE73
+ case 73:
+ sha1recompress_fast_73(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE74
+ case 74:
+ sha1recompress_fast_74(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE75
+ case 75:
+ sha1recompress_fast_75(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE76
+ case 76:
+ sha1recompress_fast_76(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE77
+ case 77:
+ sha1recompress_fast_77(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE78
+ case 78:
+ sha1recompress_fast_78(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE79
+ case 79:
+ sha1recompress_fast_79(ihvin, ihvout, me2, state);
+ break;
+#endif
+ default:
+ abort();
+ }
+
+}
+
+
+
+static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
+{
+ unsigned i, j;
+ uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF };
+ uint32_t ihvtmp[5];
+
+ ctx->ihv1[0] = ctx->ihv[0];
+ ctx->ihv1[1] = ctx->ihv[1];
+ ctx->ihv1[2] = ctx->ihv[2];
+ ctx->ihv1[3] = ctx->ihv[3];
+ ctx->ihv1[4] = ctx->ihv[4];
+
+ sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states);
+
+ if (ctx->detect_coll)
+ {
+ if (ctx->ubc_check)
+ {
+ ubc_check(ctx->m1, ubc_dv_mask);
+ }
+
+ if (ubc_dv_mask[0] != 0)
+ {
+ for (i = 0; sha1_dvs[i].dvType != 0; ++i)
+ {
+ if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb))
+ {
+ for (j = 0; j < 80; ++j)
+ ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j];
+
+ sha1_recompression_step(sha1_dvs[i].testt, ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]);
+
+ /* to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 */
+ if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | (ihvtmp[4] ^ ctx->ihv[4])))
+ || (ctx->reduced_round_coll && 0==((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | (ctx->ihv1[4] ^ ctx->ihv2[4]))))
+ {
+ ctx->found_collision = 1;
+
+ if (ctx->safe_hash)
+ {
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void SHA1DCInit(SHA1_CTX* ctx)
+{
+ ctx->total = 0;
+ ctx->ihv[0] = 0x67452301;
+ ctx->ihv[1] = 0xEFCDAB89;
+ ctx->ihv[2] = 0x98BADCFE;
+ ctx->ihv[3] = 0x10325476;
+ ctx->ihv[4] = 0xC3D2E1F0;
+ ctx->found_collision = 0;
+ ctx->safe_hash = SHA1DC_INIT_SAFE_HASH_DEFAULT;
+ ctx->ubc_check = 1;
+ ctx->detect_coll = 1;
+ ctx->reduced_round_coll = 0;
+ ctx->callback = NULL;
+}
+
+void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
+{
+ if (safehash)
+ ctx->safe_hash = 1;
+ else
+ ctx->safe_hash = 0;
+}
+
+
+void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check)
+{
+ if (ubc_check)
+ ctx->ubc_check = 1;
+ else
+ ctx->ubc_check = 0;
+}
+
+void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll)
+{
+ if (detect_coll)
+ ctx->detect_coll = 1;
+ else
+ ctx->detect_coll = 0;
+}
+
+void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll)
+{
+ if (reduced_round_coll)
+ ctx->reduced_round_coll = 1;
+ else
+ ctx->reduced_round_coll = 0;
+}
+
+void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
+{
+ ctx->callback = callback;
+}
+
+void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
+{
+ unsigned left, fill;
+
+ if (len == 0)
+ return;
+
+ left = ctx->total & 63;
+ fill = 64 - left;
+
+ if (left && len >= fill)
+ {
+ ctx->total += fill;
+ memcpy(ctx->buffer + left, buf, fill);
+ sha1_process(ctx, (uint32_t*)(ctx->buffer));
+ buf += fill;
+ len -= fill;
+ left = 0;
+ }
+ while (len >= 64)
+ {
+ ctx->total += 64;
+
+#if defined(SHA1DC_ALLOW_UNALIGNED_ACCESS)
+ sha1_process(ctx, (uint32_t*)(buf));
+#else
+ memcpy(ctx->buffer, buf, 64);
+ sha1_process(ctx, (uint32_t*)(ctx->buffer));
+#endif /* defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) */
+ buf += 64;
+ len -= 64;
+ }
+ if (len > 0)
+ {
+ ctx->total += len;
+ memcpy(ctx->buffer + left, buf, len);
+ }
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
+{
+ uint32_t last = ctx->total & 63;
+ uint32_t padn = (last < 56) ? (56 - last) : (120 - last);
+ uint64_t total;
+ SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn);
+
+ total = ctx->total - padn;
+ total <<= 3;
+ ctx->buffer[56] = (unsigned char)(total >> 56);
+ ctx->buffer[57] = (unsigned char)(total >> 48);
+ ctx->buffer[58] = (unsigned char)(total >> 40);
+ ctx->buffer[59] = (unsigned char)(total >> 32);
+ ctx->buffer[60] = (unsigned char)(total >> 24);
+ ctx->buffer[61] = (unsigned char)(total >> 16);
+ ctx->buffer[62] = (unsigned char)(total >> 8);
+ ctx->buffer[63] = (unsigned char)(total);
+ sha1_process(ctx, (uint32_t*)(ctx->buffer));
+ output[0] = (unsigned char)(ctx->ihv[0] >> 24);
+ output[1] = (unsigned char)(ctx->ihv[0] >> 16);
+ output[2] = (unsigned char)(ctx->ihv[0] >> 8);
+ output[3] = (unsigned char)(ctx->ihv[0]);
+ output[4] = (unsigned char)(ctx->ihv[1] >> 24);
+ output[5] = (unsigned char)(ctx->ihv[1] >> 16);
+ output[6] = (unsigned char)(ctx->ihv[1] >> 8);
+ output[7] = (unsigned char)(ctx->ihv[1]);
+ output[8] = (unsigned char)(ctx->ihv[2] >> 24);
+ output[9] = (unsigned char)(ctx->ihv[2] >> 16);
+ output[10] = (unsigned char)(ctx->ihv[2] >> 8);
+ output[11] = (unsigned char)(ctx->ihv[2]);
+ output[12] = (unsigned char)(ctx->ihv[3] >> 24);
+ output[13] = (unsigned char)(ctx->ihv[3] >> 16);
+ output[14] = (unsigned char)(ctx->ihv[3] >> 8);
+ output[15] = (unsigned char)(ctx->ihv[3]);
+ output[16] = (unsigned char)(ctx->ihv[4] >> 24);
+ output[17] = (unsigned char)(ctx->ihv[4] >> 16);
+ output[18] = (unsigned char)(ctx->ihv[4] >> 8);
+ output[19] = (unsigned char)(ctx->ihv[4]);
+ return ctx->found_collision;
+}
+
+#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C
+#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C
+#endif
diff --git a/src/hash/sha1dc/sha1.h b/src/hash/sha1dc/sha1.h
new file mode 100644
index 000000000..1e4e94be5
--- /dev/null
+++ b/src/hash/sha1dc/sha1.h
@@ -0,0 +1,110 @@
+/***
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow <danshu@microsoft.com>
+* Distributed under the MIT Software License.
+* See accompanying file LICENSE.txt or copy at
+* https://opensource.org/licenses/MIT
+***/
+
+#ifndef SHA1DC_SHA1_H
+#define SHA1DC_SHA1_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef SHA1DC_NO_STANDARD_INCLUDES
+#include <stdint.h>
+#endif
+
+/* sha-1 compression function that takes an already expanded message, and additionally store intermediate states */
+/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */
+void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]);
+
+/*
+// Function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]).
+// Where 0 <= T < 80
+// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference.)
+// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block.
+// The function will return:
+// ihvin: The reconstructed input chaining value.
+// ihvout: The reconstructed output chaining value.
+*/
+typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*);
+
+/* A callback function type that can be set to be called when a collision block has been found: */
+/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */
+typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
+
+/* The SHA-1 context. */
+typedef struct {
+ uint64_t total;
+ uint32_t ihv[5];
+ unsigned char buffer[64];
+ int found_collision;
+ int safe_hash;
+ int detect_coll;
+ int ubc_check;
+ int reduced_round_coll;
+ collision_block_callback callback;
+
+ uint32_t ihv1[5];
+ uint32_t ihv2[5];
+ uint32_t m1[80];
+ uint32_t m2[80];
+ uint32_t states[80][5];
+} SHA1_CTX;
+
+/* Initialize SHA-1 context. */
+void SHA1DCInit(SHA1_CTX*);
+
+/*
+ Function to enable safe SHA-1 hashing:
+ Collision attacks are thwarted by hashing a detected near-collision block 3 times.
+ Think of it as extending SHA-1 from 80-steps to 240-steps for such blocks:
+ The best collision attacks against SHA-1 have complexity about 2^60,
+ thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would be 2^180.
+ An attacker would be better off using a generic birthday search of complexity 2^80.
+
+ Enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected,
+ but it will result in a different SHA-1 hash for messages where a collision attack was detected.
+ This will automatically invalidate SHA-1 based digital signature forgeries.
+ Enabled by default.
+*/
+void SHA1DCSetSafeHash(SHA1_CTX*, int);
+
+/*
+ Function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up).
+ Enabled by default
+ */
+void SHA1DCSetUseUBC(SHA1_CTX*, int);
+
+/*
+ Function to disable or enable the use of Collision Detection.
+ Enabled by default.
+ */
+void SHA1DCSetUseDetectColl(SHA1_CTX*, int);
+
+/* function to disable or enable the detection of reduced-round SHA-1 collisions */
+/* disabled by default */
+void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int);
+
+/* function to set a callback function, pass NULL to disable */
+/* by default no callback set */
+void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback);
+
+/* update SHA-1 context with buffer contents */
+void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
+
+/* obtain SHA-1 hash from SHA-1 context */
+/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */
+int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H
+#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H
+#endif
+
+#endif
diff --git a/src/hash/sha1dc/ubc_check.c b/src/hash/sha1dc/ubc_check.c
new file mode 100644
index 000000000..b3beff2af
--- /dev/null
+++ b/src/hash/sha1dc/ubc_check.c
@@ -0,0 +1,372 @@
+/***
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow <danshu@microsoft.com>
+* Distributed under the MIT Software License.
+* See accompanying file LICENSE.txt or copy at
+* https://opensource.org/licenses/MIT
+***/
+
+/*
+// this file was generated by the 'parse_bitrel' program in the tools section
+// using the data files from directory 'tools/data/3565'
+//
+// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check
+// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper)
+// dm[80] is the expanded message block XOR-difference defined by the DV
+// testt is the step to do the recompression from for collision detection
+// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check
+//
+// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
+// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
+// thus one needs to do the recompression check for each DV that has its bit set
+//
+// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded
+// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c
+// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section
+*/
+
+#ifndef SHA1DC_NO_STANDARD_INCLUDES
+#include <stdint.h>
+#endif
+#ifdef SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C
+#include SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C
+#endif
+#include "ubc_check.h"
+
+static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0;
+static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1;
+static const uint32_t DV_I_45_0_bit = (uint32_t)(1) << 2;
+static const uint32_t DV_I_46_0_bit = (uint32_t)(1) << 3;
+static const uint32_t DV_I_46_2_bit = (uint32_t)(1) << 4;
+static const uint32_t DV_I_47_0_bit = (uint32_t)(1) << 5;
+static const uint32_t DV_I_47_2_bit = (uint32_t)(1) << 6;
+static const uint32_t DV_I_48_0_bit = (uint32_t)(1) << 7;
+static const uint32_t DV_I_48_2_bit = (uint32_t)(1) << 8;
+static const uint32_t DV_I_49_0_bit = (uint32_t)(1) << 9;
+static const uint32_t DV_I_49_2_bit = (uint32_t)(1) << 10;
+static const uint32_t DV_I_50_0_bit = (uint32_t)(1) << 11;
+static const uint32_t DV_I_50_2_bit = (uint32_t)(1) << 12;
+static const uint32_t DV_I_51_0_bit = (uint32_t)(1) << 13;
+static const uint32_t DV_I_51_2_bit = (uint32_t)(1) << 14;
+static const uint32_t DV_I_52_0_bit = (uint32_t)(1) << 15;
+static const uint32_t DV_II_45_0_bit = (uint32_t)(1) << 16;
+static const uint32_t DV_II_46_0_bit = (uint32_t)(1) << 17;
+static const uint32_t DV_II_46_2_bit = (uint32_t)(1) << 18;
+static const uint32_t DV_II_47_0_bit = (uint32_t)(1) << 19;
+static const uint32_t DV_II_48_0_bit = (uint32_t)(1) << 20;
+static const uint32_t DV_II_49_0_bit = (uint32_t)(1) << 21;
+static const uint32_t DV_II_49_2_bit = (uint32_t)(1) << 22;
+static const uint32_t DV_II_50_0_bit = (uint32_t)(1) << 23;
+static const uint32_t DV_II_50_2_bit = (uint32_t)(1) << 24;
+static const uint32_t DV_II_51_0_bit = (uint32_t)(1) << 25;
+static const uint32_t DV_II_51_2_bit = (uint32_t)(1) << 26;
+static const uint32_t DV_II_52_0_bit = (uint32_t)(1) << 27;
+static const uint32_t DV_II_53_0_bit = (uint32_t)(1) << 28;
+static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29;
+static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30;
+static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31;
+
+dv_info_t sha1_dvs[] =
+{
+ {1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } }
+, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } }
+, {1,45,0,58,0,2, { 0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803 } }
+, {1,46,0,58,0,3, { 0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c } }
+, {1,46,2,58,0,4, { 0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a,0x00000132 } }
+, {1,47,0,58,0,5, { 0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6 } }
+, {1,47,2,58,0,6, { 0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a } }
+, {1,48,0,58,0,7, { 0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408 } }
+, {1,48,2,58,0,8, { 0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020 } }
+, {1,49,0,58,0,9, { 0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164 } }
+, {1,49,2,58,0,10, { 0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590 } }
+, {1,50,0,65,0,11, { 0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018 } }
+, {1,50,2,65,0,12, { 0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060 } }
+, {1,51,0,65,0,13, { 0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202 } }
+, {1,51,2,65,0,14, { 0xa0000003,0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a } }
+, {1,52,0,65,0,15, { 0x04000010,0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012 } }
+, {2,45,0,58,0,16, { 0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054,0x00000967 } }
+, {2,46,0,58,0,17, { 0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054 } }
+, {2,46,2,58,0,18, { 0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6,0x0000106a,0x00000b90,0x00000152 } }
+, {2,47,0,58,0,19, { 0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4 } }
+, {2,48,0,58,0,20, { 0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a } }
+, {2,49,0,58,0,21, { 0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d } }
+, {2,49,2,58,0,22, { 0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6 } }
+, {2,50,0,65,0,23, { 0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b } }
+, {2,50,2,65,0,24, { 0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c } }
+, {2,51,0,65,0,25, { 0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b } }
+, {2,51,2,65,0,26, { 0x00000043,0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e } }
+, {2,52,0,65,0,27, { 0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014 } }
+, {2,53,0,65,0,28, { 0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089 } }
+, {2,54,0,65,0,29, { 0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107 } }
+, {2,55,0,65,0,30, { 0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b } }
+, {2,56,0,65,0,31, { 0x2600001a,0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046 } }
+, {0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
+};
+void ubc_check(const uint32_t W[80], uint32_t dvmask[1])
+{
+ uint32_t mask = ~((uint32_t)(0));
+ mask &= (((((W[44]^W[45])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_I_51_0_bit|DV_I_52_0_bit|DV_II_45_0_bit|DV_II_46_0_bit|DV_II_50_0_bit|DV_II_51_0_bit));
+ mask &= (((((W[49]^W[50])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_II_45_0_bit|DV_II_50_0_bit|DV_II_51_0_bit|DV_II_55_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[48]^W[49])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_52_0_bit|DV_II_49_0_bit|DV_II_50_0_bit|DV_II_54_0_bit|DV_II_55_0_bit));
+ mask &= ((((W[47]^(W[50]>>25))&(1<<4))-(1<<4)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_51_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[47]^W[48])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_51_0_bit|DV_II_48_0_bit|DV_II_49_0_bit|DV_II_53_0_bit|DV_II_54_0_bit));
+ mask &= (((((W[46]>>4)^(W[49]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_50_0_bit|DV_II_55_0_bit));
+ mask &= (((((W[46]^W[47])>>29)&1)-1) | ~(DV_I_43_0_bit|DV_I_50_0_bit|DV_II_47_0_bit|DV_II_48_0_bit|DV_II_52_0_bit|DV_II_53_0_bit));
+ mask &= (((((W[45]>>4)^(W[48]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_49_0_bit|DV_II_54_0_bit));
+ mask &= (((((W[45]^W[46])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_51_0_bit|DV_II_52_0_bit));
+ mask &= (((((W[44]>>4)^(W[47]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_53_0_bit));
+ mask &= (((((W[43]>>4)^(W[46]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_52_0_bit));
+ mask &= (((((W[43]^W[44])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_I_50_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_49_0_bit|DV_II_50_0_bit));
+ mask &= (((((W[42]>>4)^(W[45]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_51_0_bit));
+ mask &= (((((W[41]>>4)^(W[44]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_50_0_bit));
+ mask &= (((((W[40]^W[41])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_47_0_bit|DV_I_48_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[54]^W[55])>>29)&1)-1) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_50_0_bit|DV_II_55_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[53]^W[54])>>29)&1)-1) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_49_0_bit|DV_II_54_0_bit|DV_II_55_0_bit));
+ mask &= (((((W[52]^W[53])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit|DV_II_53_0_bit|DV_II_54_0_bit));
+ mask &= ((((W[50]^(W[53]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_48_0_bit|DV_II_54_0_bit));
+ mask &= (((((W[50]^W[51])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_II_46_0_bit|DV_II_51_0_bit|DV_II_52_0_bit|DV_II_56_0_bit));
+ mask &= ((((W[49]^(W[52]>>25))&(1<<4))-(1<<4)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_47_0_bit|DV_II_53_0_bit));
+ mask &= ((((W[48]^(W[51]>>25))&(1<<4))-(1<<4)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_52_0_bit));
+ mask &= (((((W[42]^W[43])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_49_0_bit));
+ mask &= (((((W[41]^W[42])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_48_0_bit));
+ mask &= (((((W[40]>>4)^(W[43]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_50_0_bit|DV_II_49_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[39]>>4)^(W[42]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_49_0_bit|DV_II_48_0_bit|DV_II_55_0_bit));
+ if (mask & (DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit))
+ mask &= (((((W[38]>>4)^(W[41]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit));
+ mask &= (((((W[37]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_47_0_bit|DV_II_46_0_bit|DV_II_53_0_bit|DV_II_55_0_bit));
+ if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit))
+ mask &= (((((W[55]^W[56])>>29)&1)-1) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit));
+ if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit))
+ mask &= ((((W[52]^(W[55]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit));
+ if (mask & (DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit))
+ mask &= ((((W[51]^(W[54]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit));
+ if (mask & (DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit))
+ mask &= (((((W[51]^W[52])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit));
+ if (mask & (DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit))
+ mask &= (((((W[36]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit));
+ if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit))
+ mask &= ((0-(((W[53]^W[56])>>29)&1)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit));
+ if (mask & (DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit))
+ mask &= ((0-(((W[51]^W[54])>>29)&1)) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit));
+ if (mask & (DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit))
+ mask &= ((0-(((W[50]^W[52])>>29)&1)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit));
+ if (mask & (DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit))
+ mask &= ((0-(((W[49]^W[51])>>29)&1)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit));
+ if (mask & (DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit))
+ mask &= ((0-(((W[48]^W[50])>>29)&1)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit));
+ if (mask & (DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit))
+ mask &= ((0-(((W[47]^W[49])>>29)&1)) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit));
+ if (mask & (DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit))
+ mask &= ((0-(((W[46]^W[48])>>29)&1)) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit));
+ mask &= ((((W[45]^W[47])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit|DV_I_51_2_bit));
+ if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit))
+ mask &= ((0-(((W[45]^W[47])>>29)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit));
+ mask &= (((((W[44]^W[46])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit|DV_I_50_2_bit));
+ if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit))
+ mask &= ((0-(((W[44]^W[46])>>29)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit));
+ mask &= ((0-((W[41]^(W[42]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_II_46_2_bit|DV_II_51_2_bit));
+ mask &= ((0-((W[40]^(W[41]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_51_2_bit|DV_II_50_2_bit));
+ if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit))
+ mask &= ((0-(((W[40]^W[42])>>4)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit));
+ mask &= ((0-((W[39]^(W[40]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_50_2_bit|DV_II_49_2_bit));
+ if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit))
+ mask &= ((0-(((W[39]^W[41])>>4)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit));
+ if (mask & (DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit))
+ mask &= ((0-(((W[38]^W[40])>>4)&1)) | ~(DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit));
+ if (mask & (DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit))
+ mask &= ((0-(((W[37]^W[39])>>4)&1)) | ~(DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit));
+ mask &= ((0-((W[36]^(W[37]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_50_2_bit|DV_II_46_2_bit));
+ if (mask & (DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit))
+ mask &= (((((W[35]>>4)^(W[39]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit));
+ if (mask & (DV_I_48_0_bit|DV_II_48_0_bit))
+ mask &= ((0-((W[63]^(W[64]>>5))&(1<<0))) | ~(DV_I_48_0_bit|DV_II_48_0_bit));
+ if (mask & (DV_I_45_0_bit|DV_II_45_0_bit))
+ mask &= ((0-((W[63]^(W[64]>>5))&(1<<1))) | ~(DV_I_45_0_bit|DV_II_45_0_bit));
+ if (mask & (DV_I_47_0_bit|DV_II_47_0_bit))
+ mask &= ((0-((W[62]^(W[63]>>5))&(1<<0))) | ~(DV_I_47_0_bit|DV_II_47_0_bit));
+ if (mask & (DV_I_46_0_bit|DV_II_46_0_bit))
+ mask &= ((0-((W[61]^(W[62]>>5))&(1<<0))) | ~(DV_I_46_0_bit|DV_II_46_0_bit));
+ mask &= ((0-((W[61]^(W[62]>>5))&(1<<2))) | ~(DV_I_46_2_bit|DV_II_46_2_bit));
+ if (mask & (DV_I_45_0_bit|DV_II_45_0_bit))
+ mask &= ((0-((W[60]^(W[61]>>5))&(1<<0))) | ~(DV_I_45_0_bit|DV_II_45_0_bit));
+ if (mask & (DV_II_51_0_bit|DV_II_54_0_bit))
+ mask &= (((((W[58]^W[59])>>29)&1)-1) | ~(DV_II_51_0_bit|DV_II_54_0_bit));
+ if (mask & (DV_II_50_0_bit|DV_II_53_0_bit))
+ mask &= (((((W[57]^W[58])>>29)&1)-1) | ~(DV_II_50_0_bit|DV_II_53_0_bit));
+ if (mask & (DV_II_52_0_bit|DV_II_54_0_bit))
+ mask &= ((((W[56]^(W[59]>>25))&(1<<4))-(1<<4)) | ~(DV_II_52_0_bit|DV_II_54_0_bit));
+ if (mask & (DV_II_51_0_bit|DV_II_52_0_bit))
+ mask &= ((0-(((W[56]^W[59])>>29)&1)) | ~(DV_II_51_0_bit|DV_II_52_0_bit));
+ if (mask & (DV_II_49_0_bit|DV_II_52_0_bit))
+ mask &= (((((W[56]^W[57])>>29)&1)-1) | ~(DV_II_49_0_bit|DV_II_52_0_bit));
+ if (mask & (DV_II_51_0_bit|DV_II_53_0_bit))
+ mask &= ((((W[55]^(W[58]>>25))&(1<<4))-(1<<4)) | ~(DV_II_51_0_bit|DV_II_53_0_bit));
+ if (mask & (DV_II_50_0_bit|DV_II_52_0_bit))
+ mask &= ((((W[54]^(W[57]>>25))&(1<<4))-(1<<4)) | ~(DV_II_50_0_bit|DV_II_52_0_bit));
+ if (mask & (DV_II_49_0_bit|DV_II_51_0_bit))
+ mask &= ((((W[53]^(W[56]>>25))&(1<<4))-(1<<4)) | ~(DV_II_49_0_bit|DV_II_51_0_bit));
+ mask &= ((((W[51]^(W[50]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_46_2_bit));
+ mask &= ((((W[48]^W[50])&(1<<6))-(1<<6)) | ~(DV_I_50_2_bit|DV_II_46_2_bit));
+ if (mask & (DV_I_51_0_bit|DV_I_52_0_bit))
+ mask &= ((0-(((W[48]^W[55])>>29)&1)) | ~(DV_I_51_0_bit|DV_I_52_0_bit));
+ mask &= ((((W[47]^W[49])&(1<<6))-(1<<6)) | ~(DV_I_49_2_bit|DV_I_51_2_bit));
+ mask &= ((((W[48]^(W[47]>>5))&(1<<1))-(1<<1)) | ~(DV_I_47_2_bit|DV_II_51_2_bit));
+ mask &= ((((W[46]^W[48])&(1<<6))-(1<<6)) | ~(DV_I_48_2_bit|DV_I_50_2_bit));
+ mask &= ((((W[47]^(W[46]>>5))&(1<<1))-(1<<1)) | ~(DV_I_46_2_bit|DV_II_50_2_bit));
+ mask &= ((0-((W[44]^(W[45]>>5))&(1<<1))) | ~(DV_I_51_2_bit|DV_II_49_2_bit));
+ mask &= ((((W[43]^W[45])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit));
+ mask &= (((((W[42]^W[44])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit));
+ mask &= ((((W[43]^(W[42]>>5))&(1<<1))-(1<<1)) | ~(DV_II_46_2_bit|DV_II_51_2_bit));
+ mask &= ((((W[42]^(W[41]>>5))&(1<<1))-(1<<1)) | ~(DV_I_51_2_bit|DV_II_50_2_bit));
+ mask &= ((((W[41]^(W[40]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_49_2_bit));
+ if (mask & (DV_I_52_0_bit|DV_II_51_0_bit))
+ mask &= ((((W[39]^(W[43]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_51_0_bit));
+ if (mask & (DV_I_51_0_bit|DV_II_50_0_bit))
+ mask &= ((((W[38]^(W[42]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_50_0_bit));
+ if (mask & (DV_I_48_2_bit|DV_I_51_2_bit))
+ mask &= ((0-((W[37]^(W[38]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_I_51_2_bit));
+ if (mask & (DV_I_50_0_bit|DV_II_49_0_bit))
+ mask &= ((((W[37]^(W[41]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_II_49_0_bit));
+ if (mask & (DV_II_52_0_bit|DV_II_54_0_bit))
+ mask &= ((0-((W[36]^W[38])&(1<<4))) | ~(DV_II_52_0_bit|DV_II_54_0_bit));
+ mask &= ((0-((W[35]^(W[36]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_49_2_bit));
+ if (mask & (DV_I_51_0_bit|DV_II_47_0_bit))
+ mask &= ((((W[35]^(W[39]>>25))&(1<<3))-(1<<3)) | ~(DV_I_51_0_bit|DV_II_47_0_bit));
+if (mask) {
+
+ if (mask & DV_I_43_0_bit)
+ if (
+ !((W[61]^(W[62]>>5)) & (1<<1))
+ || !(!((W[59]^(W[63]>>25)) & (1<<5)))
+ || !((W[58]^(W[63]>>30)) & (1<<0))
+ ) mask &= ~DV_I_43_0_bit;
+ if (mask & DV_I_44_0_bit)
+ if (
+ !((W[62]^(W[63]>>5)) & (1<<1))
+ || !(!((W[60]^(W[64]>>25)) & (1<<5)))
+ || !((W[59]^(W[64]>>30)) & (1<<0))
+ ) mask &= ~DV_I_44_0_bit;
+ if (mask & DV_I_46_2_bit)
+ mask &= ((~((W[40]^W[42])>>2)) | ~DV_I_46_2_bit);
+ if (mask & DV_I_47_2_bit)
+ if (
+ !((W[62]^(W[63]>>5)) & (1<<2))
+ || !(!((W[41]^W[43]) & (1<<6)))
+ ) mask &= ~DV_I_47_2_bit;
+ if (mask & DV_I_48_2_bit)
+ if (
+ !((W[63]^(W[64]>>5)) & (1<<2))
+ || !(!((W[48]^(W[49]<<5)) & (1<<6)))
+ ) mask &= ~DV_I_48_2_bit;
+ if (mask & DV_I_49_2_bit)
+ if (
+ !(!((W[49]^(W[50]<<5)) & (1<<6)))
+ || !((W[42]^W[50]) & (1<<1))
+ || !(!((W[39]^(W[40]<<5)) & (1<<6)))
+ || !((W[38]^W[40]) & (1<<1))
+ ) mask &= ~DV_I_49_2_bit;
+ if (mask & DV_I_50_0_bit)
+ mask &= ((((W[36]^W[37])<<7)) | ~DV_I_50_0_bit);
+ if (mask & DV_I_50_2_bit)
+ mask &= ((((W[43]^W[51])<<11)) | ~DV_I_50_2_bit);
+ if (mask & DV_I_51_0_bit)
+ mask &= ((((W[37]^W[38])<<9)) | ~DV_I_51_0_bit);
+ if (mask & DV_I_51_2_bit)
+ if (
+ !(!((W[51]^(W[52]<<5)) & (1<<6)))
+ || !(!((W[49]^W[51]) & (1<<6)))
+ || !(!((W[37]^(W[37]>>5)) & (1<<1)))
+ || !(!((W[35]^(W[39]>>25)) & (1<<5)))
+ ) mask &= ~DV_I_51_2_bit;
+ if (mask & DV_I_52_0_bit)
+ mask &= ((((W[38]^W[39])<<11)) | ~DV_I_52_0_bit);
+ if (mask & DV_II_46_2_bit)
+ mask &= ((((W[47]^W[51])<<17)) | ~DV_II_46_2_bit);
+ if (mask & DV_II_48_0_bit)
+ if (
+ !(!((W[36]^(W[40]>>25)) & (1<<3)))
+ || !((W[35]^(W[40]<<2)) & (1<<30))
+ ) mask &= ~DV_II_48_0_bit;
+ if (mask & DV_II_49_0_bit)
+ if (
+ !(!((W[37]^(W[41]>>25)) & (1<<3)))
+ || !((W[36]^(W[41]<<2)) & (1<<30))
+ ) mask &= ~DV_II_49_0_bit;
+ if (mask & DV_II_49_2_bit)
+ if (
+ !(!((W[53]^(W[54]<<5)) & (1<<6)))
+ || !(!((W[51]^W[53]) & (1<<6)))
+ || !((W[50]^W[54]) & (1<<1))
+ || !(!((W[45]^(W[46]<<5)) & (1<<6)))
+ || !(!((W[37]^(W[41]>>25)) & (1<<5)))
+ || !((W[36]^(W[41]>>30)) & (1<<0))
+ ) mask &= ~DV_II_49_2_bit;
+ if (mask & DV_II_50_0_bit)
+ if (
+ !((W[55]^W[58]) & (1<<29))
+ || !(!((W[38]^(W[42]>>25)) & (1<<3)))
+ || !((W[37]^(W[42]<<2)) & (1<<30))
+ ) mask &= ~DV_II_50_0_bit;
+ if (mask & DV_II_50_2_bit)
+ if (
+ !(!((W[54]^(W[55]<<5)) & (1<<6)))
+ || !(!((W[52]^W[54]) & (1<<6)))
+ || !((W[51]^W[55]) & (1<<1))
+ || !((W[45]^W[47]) & (1<<1))
+ || !(!((W[38]^(W[42]>>25)) & (1<<5)))
+ || !((W[37]^(W[42]>>30)) & (1<<0))
+ ) mask &= ~DV_II_50_2_bit;
+ if (mask & DV_II_51_0_bit)
+ if (
+ !(!((W[39]^(W[43]>>25)) & (1<<3)))
+ || !((W[38]^(W[43]<<2)) & (1<<30))
+ ) mask &= ~DV_II_51_0_bit;
+ if (mask & DV_II_51_2_bit)
+ if (
+ !(!((W[55]^(W[56]<<5)) & (1<<6)))
+ || !(!((W[53]^W[55]) & (1<<6)))
+ || !((W[52]^W[56]) & (1<<1))
+ || !((W[46]^W[48]) & (1<<1))
+ || !(!((W[39]^(W[43]>>25)) & (1<<5)))
+ || !((W[38]^(W[43]>>30)) & (1<<0))
+ ) mask &= ~DV_II_51_2_bit;
+ if (mask & DV_II_52_0_bit)
+ if (
+ !(!((W[59]^W[60]) & (1<<29)))
+ || !(!((W[40]^(W[44]>>25)) & (1<<3)))
+ || !(!((W[40]^(W[44]>>25)) & (1<<4)))
+ || !((W[39]^(W[44]<<2)) & (1<<30))
+ ) mask &= ~DV_II_52_0_bit;
+ if (mask & DV_II_53_0_bit)
+ if (
+ !((W[58]^W[61]) & (1<<29))
+ || !(!((W[57]^(W[61]>>25)) & (1<<4)))
+ || !(!((W[41]^(W[45]>>25)) & (1<<3)))
+ || !(!((W[41]^(W[45]>>25)) & (1<<4)))
+ ) mask &= ~DV_II_53_0_bit;
+ if (mask & DV_II_54_0_bit)
+ if (
+ !(!((W[58]^(W[62]>>25)) & (1<<4)))
+ || !(!((W[42]^(W[46]>>25)) & (1<<3)))
+ || !(!((W[42]^(W[46]>>25)) & (1<<4)))
+ ) mask &= ~DV_II_54_0_bit;
+ if (mask & DV_II_55_0_bit)
+ if (
+ !(!((W[59]^(W[63]>>25)) & (1<<4)))
+ || !(!((W[57]^(W[59]>>25)) & (1<<4)))
+ || !(!((W[43]^(W[47]>>25)) & (1<<3)))
+ || !(!((W[43]^(W[47]>>25)) & (1<<4)))
+ ) mask &= ~DV_II_55_0_bit;
+ if (mask & DV_II_56_0_bit)
+ if (
+ !(!((W[60]^(W[64]>>25)) & (1<<4)))
+ || !(!((W[44]^(W[48]>>25)) & (1<<3)))
+ || !(!((W[44]^(W[48]>>25)) & (1<<4)))
+ ) mask &= ~DV_II_56_0_bit;
+}
+
+ dvmask[0]=mask;
+}
+
+#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C
+#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C
+#endif
diff --git a/src/hash/sha1dc/ubc_check.h b/src/hash/sha1dc/ubc_check.h
new file mode 100644
index 000000000..d7e17dc73
--- /dev/null
+++ b/src/hash/sha1dc/ubc_check.h
@@ -0,0 +1,52 @@
+/***
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow <danshu@microsoft.com>
+* Distributed under the MIT Software License.
+* See accompanying file LICENSE.txt or copy at
+* https://opensource.org/licenses/MIT
+***/
+
+/*
+// this file was generated by the 'parse_bitrel' program in the tools section
+// using the data files from directory 'tools/data/3565'
+//
+// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check
+// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper)
+// dm[80] is the expanded message block XOR-difference defined by the DV
+// testt is the step to do the recompression from for collision detection
+// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check
+//
+// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
+// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
+// thus one needs to do the recompression check for each DV that has its bit set
+*/
+
+#ifndef SHA1DC_UBC_CHECK_H
+#define SHA1DC_UBC_CHECK_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef SHA1DC_NO_STANDARD_INCLUDES
+#include <stdint.h>
+#endif
+
+#define DVMASKSIZE 1
+typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t;
+extern dv_info_t sha1_dvs[];
+void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]);
+
+#define DOSTORESTATE58
+#define DOSTORESTATE65
+
+#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0])
+
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H
+#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H
+#endif
+
+#endif
diff --git a/src/hashsig.c b/src/hashsig.c
index e99637d8b..30d059463 100644
--- a/src/hashsig.c
+++ b/src/hashsig.c
@@ -4,6 +4,9 @@
* 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 "common.h"
+
#include "git2/sys/hashsig.h"
#include "fileops.h"
#include "util.h"
@@ -214,7 +217,7 @@ static int hashsig_finalize_hashes(git_hashsig *sig)
if (sig->mins.size < HASHSIG_HEAP_MIN_SIZE &&
!(sig->opt & GIT_HASHSIG_ALLOW_SMALL_FILES)) {
giterr_set(GITERR_INVALID,
- "File too small for similarity signature calculation");
+ "file too small for similarity signature calculation");
return GIT_EBUFS;
}
@@ -286,7 +289,7 @@ int git_hashsig_create_fromfile(
if ((buflen = p_read(fd, buf, sizeof(buf))) <= 0) {
if ((error = (int)buflen) < 0)
giterr_set(GITERR_OS,
- "Read error on '%s' calculating similarity hashes", path);
+ "read error on '%s' calculating similarity hashes", path);
break;
}
diff --git a/src/ident.c b/src/ident.c
index 4718ed664..7eccf9a43 100644
--- a/src/ident.c
+++ b/src/ident.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include "git2/sys/filter.h"
#include "filter.h"
#include "buffer.h"
diff --git a/src/idxmap.c b/src/idxmap.c
new file mode 100644
index 000000000..45f0c2204
--- /dev/null
+++ b/src/idxmap.c
@@ -0,0 +1,133 @@
+/*
+ * 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 "idxmap.h"
+
+/* This is __ac_X31_hash_string but with tolower and it takes the entry's stage into account */
+static kh_inline khint_t idxentry_hash(const git_index_entry *e)
+{
+ const char *s = e->path;
+ khint_t h = (khint_t)git__tolower(*s);
+ if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)git__tolower(*s);
+ return h + GIT_IDXENTRY_STAGE(e);
+}
+
+#define idxentry_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcmp(a->path, b->path) == 0)
+#define idxentry_icase_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcasecmp(a->path, b->path) == 0)
+
+__KHASH_IMPL(idx, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_equal)
+__KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal)
+
+int git_idxmap_alloc(git_idxmap **map)
+{
+ if ((*map = kh_init(idx)) == NULL) {
+ giterr_set_oom();
+ return -1;
+ }
+
+ return 0;
+}
+
+int git_idxmap_icase_alloc(git_idxmap_icase **map)
+{
+ if ((*map = kh_init(idxicase)) == NULL) {
+ giterr_set_oom();
+ return -1;
+ }
+
+ return 0;
+}
+
+void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval)
+{
+ khiter_t idx = kh_put(idx, map, key, rval);
+
+ if ((*rval) >= 0) {
+ if ((*rval) == 0)
+ kh_key(map, idx) = key;
+ kh_val(map, idx) = value;
+ }
+}
+
+void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval)
+{
+ khiter_t idx = kh_put(idxicase, map, key, rval);
+
+ if ((*rval) >= 0) {
+ if ((*rval) == 0)
+ kh_key(map, idx) = key;
+ kh_val(map, idx) = value;
+ }
+}
+
+size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key)
+{
+ return kh_get(idx, map, key);
+}
+
+size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key)
+{
+ return kh_get(idxicase, map, key);
+}
+
+void *git_idxmap_value_at(git_idxmap *map, size_t idx)
+{
+ return kh_val(map, idx);
+}
+
+int git_idxmap_valid_index(git_idxmap *map, size_t idx)
+{
+ return idx != kh_end(map);
+}
+
+int git_idxmap_has_data(git_idxmap *map, size_t idx)
+{
+ return kh_exist(map, idx);
+}
+
+void git_idxmap_resize(git_idxmap *map, size_t size)
+{
+ kh_resize(idx, map, size);
+}
+
+void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size)
+{
+ kh_resize(idxicase, map, size);
+}
+
+void git_idxmap_free(git_idxmap *map)
+{
+ kh_destroy(idx, map);
+}
+
+void git_idxmap_clear(git_idxmap *map)
+{
+ kh_clear(idx, map);
+}
+
+void git_idxmap_delete_at(git_idxmap *map, size_t idx)
+{
+ kh_del(idx, map, idx);
+}
+
+void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx)
+{
+ kh_del(idxicase, map, idx);
+}
+
+void git_idxmap_delete(git_idxmap *map, const git_index_entry *key)
+{
+ khiter_t idx = git_idxmap_lookup_index(map, key);
+ if (git_idxmap_valid_index(map, idx))
+ git_idxmap_delete_at(map, idx);
+}
+void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key)
+{
+ khiter_t idx = git_idxmap_icase_lookup_index(map, key);
+ if (git_idxmap_valid_index((git_idxmap *)map, idx))
+ git_idxmap_icase_delete_at(map, idx);
+}
diff --git a/src/idxmap.h b/src/idxmap.h
index 4122a89fe..f7e903a61 100644
--- a/src/idxmap.h
+++ b/src/idxmap.h
@@ -7,8 +7,9 @@
#ifndef INCLUDE_idxmap_h__
#define INCLUDE_idxmap_h__
-#include <ctype.h>
#include "common.h"
+
+#include <ctype.h>
#include "git2/index.h"
#define kmalloc git__malloc
@@ -26,66 +27,27 @@ typedef khash_t(idxicase) git_idxmap_icase;
typedef khiter_t git_idxmap_iter;
-/* This is __ac_X31_hash_string but with tolower and it takes the entry's stage into account */
-static kh_inline khint_t idxentry_hash(const git_index_entry *e)
-{
- const char *s = e->path;
- khint_t h = (khint_t)git__tolower(*s);
- if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)git__tolower(*s);
- return h + GIT_IDXENTRY_STAGE(e);
-}
-
-#define idxentry_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcmp(a->path, b->path) == 0)
-#define idxentry_icase_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcasecmp(a->path, b->path) == 0)
-
-#define GIT__USE_IDXMAP \
- __KHASH_IMPL(idx, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_equal)
-
-#define GIT__USE_IDXMAP_ICASE \
- __KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal)
-
-#define git_idxmap_alloc(hp) \
- ((*(hp) = kh_init(idx)) == NULL) ? giterr_set_oom(), -1 : 0
-
-#define git_idxmap_icase_alloc(hp) \
- ((*(hp) = kh_init(idxicase)) == NULL) ? giterr_set_oom(), -1 : 0
-
-#define git_idxmap_insert(h, key, val, rval) do { \
- khiter_t __pos = kh_put(idx, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) kh_key(h, __pos) = key; \
- kh_val(h, __pos) = val; \
- } } while (0)
-
-#define git_idxmap_icase_insert(h, key, val, rval) do { \
- khiter_t __pos = kh_put(idxicase, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) kh_key(h, __pos) = key; \
- kh_val(h, __pos) = val; \
- } } while (0)
-
-#define git_idxmap_lookup_index(h, k) kh_get(idx, h, k)
-#define git_idxmap_icase_lookup_index(h, k) kh_get(idxicase, h, k)
-#define git_idxmap_value_at(h, idx) kh_val(h, idx)
-#define git_idxmap_valid_index(h, idx) (idx != kh_end(h))
-#define git_idxmap_has_data(h, idx) kh_exist(h, idx)
+int git_idxmap_alloc(git_idxmap **map);
+int git_idxmap_icase_alloc(git_idxmap_icase **map);
+void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval);
+void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval);
-#define git_idxmap_resize(h,s) kh_resize(idx, h, s)
-#define git_idxmap_free(h) kh_destroy(idx, h), h = NULL
-#define git_idxmap_clear(h) kh_clear(idx, h)
+size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key);
+size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key);
+void *git_idxmap_value_at(git_idxmap *map, size_t idx);
+int git_idxmap_valid_index(git_idxmap *map, size_t idx);
+int git_idxmap_has_data(git_idxmap *map, size_t idx);
-#define git_idxmap_delete_at(h, id) kh_del(idx, h, id)
-#define git_idxmap_icase_delete_at(h, id) kh_del(idxicase, h, id)
+void git_idxmap_resize(git_idxmap *map, size_t size);
+void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size);
+void git_idxmap_free(git_idxmap *map);
+void git_idxmap_clear(git_idxmap *map);
-#define git_idxmap_delete(h, key) do { \
- khiter_t __pos = git_idxmap_lookup_index(h, key); \
- if (git_idxmap_valid_index(h, __pos)) \
- git_idxmap_delete_at(h, __pos); } while (0)
+void git_idxmap_delete_at(git_idxmap *map, size_t idx);
+void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx);
-#define git_idxmap_icase_delete(h, key) do { \
- khiter_t __pos = git_idxmap_icase_lookup_index(h, key); \
- if (git_idxmap_valid_index(h, __pos)) \
- git_idxmap_icase_delete_at(h, __pos); } while (0)
+void git_idxmap_delete(git_idxmap *map, const git_index_entry *key);
+void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key);
#define git_idxmap_begin kh_begin
#define git_idxmap_end kh_end
diff --git a/src/ignore.c b/src/ignore.c
index dcbd5c1ca..f089dbeb5 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -1,6 +1,14 @@
+/*
+ * 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 "ignore.h"
+
#include "git2/ignore.h"
#include "common.h"
-#include "ignore.h"
#include "attrcache.h"
#include "path.h"
#include "config.h"
@@ -40,38 +48,42 @@
*/
static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
{
+ int (*cmp)(const char *, const char *, size_t);
git_attr_fnmatch *longer, *shorter;
char *p;
- if ((rule->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0
- && (neg->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0) {
-
- /* If lengths match we need to have an exact match */
- if (rule->length == neg->length) {
- return strcmp(rule->pattern, neg->pattern) == 0;
- } else if (rule->length < neg->length) {
- shorter = rule;
- longer = neg;
- } else {
- shorter = neg;
- longer = rule;
- }
-
- /* Otherwise, we need to check if the shorter
- * rule is a basename only (that is, it contains
- * no path separator) and, if so, if it
- * matches the tail of the longer rule */
- p = longer->pattern + longer->length - shorter->length;
+ if ((rule->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0
+ || (neg->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0)
+ return false;
+
+ if (neg->flags & GIT_ATTR_FNMATCH_ICASE)
+ cmp = git__strncasecmp;
+ else
+ cmp = strncmp;
+
+ /* If lengths match we need to have an exact match */
+ if (rule->length == neg->length) {
+ return cmp(rule->pattern, neg->pattern, rule->length) == 0;
+ } else if (rule->length < neg->length) {
+ shorter = rule;
+ longer = neg;
+ } else {
+ shorter = neg;
+ longer = rule;
+ }
- if (p[-1] != '/')
- return false;
- if (memchr(shorter->pattern, '/', shorter->length) != NULL)
- return false;
+ /* Otherwise, we need to check if the shorter
+ * rule is a basename only (that is, it contains
+ * no path separator) and, if so, if it
+ * matches the tail of the longer rule */
+ p = longer->pattern + longer->length - shorter->length;
- return memcmp(p, shorter->pattern, shorter->length) == 0;
- }
+ if (p[-1] != '/')
+ return false;
+ if (memchr(shorter->pattern, '/', shorter->length) != NULL)
+ return false;
- return false;
+ return cmp(p, shorter->pattern, shorter->length) == 0;
}
/**
@@ -89,7 +101,7 @@ static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
*/
static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match)
{
- int error = 0;
+ int error = 0, fnflags;
size_t i;
git_attr_fnmatch *rule;
char *path;
@@ -97,6 +109,10 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
*out = 0;
+ fnflags = FNM_PATHNAME;
+ if (match->flags & GIT_ATTR_FNMATCH_ICASE)
+ fnflags |= FNM_IGNORECASE;
+
/* path of the file relative to the workdir, so we match the rules in subdirs */
if (match->containing_dir) {
git_buf_puts(&buf, match->containing_dir);
@@ -117,12 +133,12 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
continue;
}
- /*
- * When dealing with a directory, we add '/<star>' so
- * p_fnmatch() honours FNM_PATHNAME. Checking for LEADINGDIR
- * alone isn't enough as that's also set for nagations, so we
- * need to check that NEGATIVE is off.
- */
+ /*
+ * When dealing with a directory, we add '/<star>' so
+ * p_fnmatch() honours FNM_PATHNAME. Checking for LEADINGDIR
+ * alone isn't enough as that's also set for nagations, so we
+ * need to check that NEGATIVE is off.
+ */
git_buf_clear(&buf);
if (rule->containing_dir) {
git_buf_puts(&buf, rule->containing_dir);
@@ -136,7 +152,7 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
if (error < 0)
goto out;
- if ((error = p_fnmatch(git_buf_cstr(&buf), path, FNM_PATHNAME)) < 0) {
+ if ((error = p_fnmatch(git_buf_cstr(&buf), path, fnflags)) < 0) {
giterr_set(GITERR_INVALID, "error matching pattern");
goto out;
}
@@ -175,7 +191,7 @@ static int parse_ignore_file(
context = attrs->entry->path;
if (git_mutex_lock(&attrs->lock) < 0) {
- giterr_set(GITERR_OS, "Failed to lock ignore file");
+ giterr_set(GITERR_OS, "failed to lock ignore file");
return -1;
}
@@ -199,8 +215,14 @@ static int parse_ignore_file(
scan = git__next_line(scan);
- /* if a negative match doesn't actually do anything, throw it away */
- if (match->flags & GIT_ATTR_FNMATCH_NEGATIVE)
+ /*
+ * If a negative match doesn't actually do anything,
+ * throw it away. As we cannot always verify whether a
+ * rule containing wildcards negates another rule, we
+ * do not optimize away these rules, though.
+ * */
+ if (match->flags & GIT_ATTR_FNMATCH_NEGATIVE
+ && !(match->flags & GIT_ATTR_FNMATCH_HASWILD))
error = does_negate_rule(&valid_rule, &attrs->rules, match);
if (!error && valid_rule)
@@ -277,8 +299,9 @@ int git_ignore__for_path(
{
int error = 0;
const char *workdir = git_repository_workdir(repo);
+ git_buf infopath = GIT_BUF_INIT;
- assert(ignores && path);
+ assert(repo && ignores && path);
memset(ignores, 0, sizeof(*ignores));
ignores->repo = repo;
@@ -322,10 +345,14 @@ int git_ignore__for_path(
goto cleanup;
}
+ if ((error = git_repository_item_path(&infopath,
+ repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
+ goto cleanup;
+
/* load .git/info/exclude */
error = push_ignore_file(
ignores, &ignores->ign_global,
- git_repository_path(repo), GIT_IGNORE_FILE_INREPO);
+ infopath.ptr, GIT_IGNORE_FILE_INREPO);
if (error < 0)
goto cleanup;
@@ -336,6 +363,7 @@ int git_ignore__for_path(
git_repository_attr_cache(repo)->cfg_excl_file);
cleanup:
+ git_buf_free(&infopath);
if (error < 0)
git_ignore__free(ignores);
@@ -503,9 +531,9 @@ int git_ignore_path_is_ignored(
unsigned int i;
git_attr_file *file;
- assert(ignored && pathname);
+ assert(repo && ignored && pathname);
- workdir = repo ? git_repository_workdir(repo) : NULL;
+ workdir = git_repository_workdir(repo);
memset(&path, 0, sizeof(path));
memset(&ignores, 0, sizeof(ignores));
diff --git a/src/ignore.h b/src/ignore.h
index d40bd60f9..5895d3faa 100644
--- a/src/ignore.h
+++ b/src/ignore.h
@@ -7,12 +7,14 @@
#ifndef INCLUDE_ignore_h__
#define INCLUDE_ignore_h__
+#include "common.h"
+
#include "repository.h"
#include "vector.h"
#include "attr_file.h"
#define GIT_IGNORE_FILE ".gitignore"
-#define GIT_IGNORE_FILE_INREPO "info/exclude"
+#define GIT_IGNORE_FILE_INREPO "exclude"
#define GIT_IGNORE_FILE_XDG "ignore"
/* The git_ignores structure maintains three sets of ignores:
diff --git a/src/index.c b/src/index.c
index bc15959a8..b7602fb44 100644
--- a/src/index.c
+++ b/src/index.c
@@ -5,11 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "index.h"
+
#include <stddef.h>
-#include "common.h"
#include "repository.h"
-#include "index.h"
#include "tree.h"
#include "tree-cache.h"
#include "hash.h"
@@ -27,9 +27,6 @@
#include "git2/config.h"
#include "git2/sys/index.h"
-GIT__USE_IDXMAP
-GIT__USE_IDXMAP_ICASE
-
#define INSERT_IN_MAP_EX(idx, map, e, err) do { \
if ((idx)->ignore_case) \
git_idxmap_icase_insert((khash_t(idxicase) *) (map), (e), (e), (err)); \
@@ -57,10 +54,6 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
unsigned int flags,
git_index_matched_path_cb cb, void *payload);
-#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
-#define short_entry_size(len) entry_size(struct entry_short, len)
-#define long_entry_size(len) entry_size(struct entry_long, len)
-
#define minimal_entry_size (offsetof(struct entry_short, path))
static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
@@ -552,7 +545,7 @@ int git_index_clear(git_index *index)
static int create_index_error(int error, const char *msg)
{
- giterr_set(GITERR_INDEX, msg);
+ giterr_set_str(GITERR_INDEX, msg);
return error;
}
@@ -570,7 +563,7 @@ int git_index_set_caps(git_index *index, int caps)
if (!repo)
return create_index_error(
- -1, "Cannot access repository to set index caps");
+ -1, "cannot access repository to set index caps");
if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORECASE))
index->ignore_case = (val != 0);
@@ -639,7 +632,7 @@ int git_index_read(git_index *index, int force)
if (!index->index_file_path)
return create_index_error(-1,
- "Failed to read index: The index is in-memory only");
+ "failed to read index: The index is in-memory only");
index->on_disk = git_path_exists(index->index_file_path);
@@ -653,7 +646,7 @@ int git_index_read(git_index *index, int force)
((updated = compare_checksum(index)) < 0)) {
giterr_set(
GITERR_INDEX,
- "Failed to read index: '%s' no longer exists",
+ "failed to read index: '%s' no longer exists",
index->index_file_path);
return updated;
}
@@ -765,7 +758,7 @@ int git_index_set_version(git_index *index, unsigned int version)
if (version < INDEX_VERSION_NUMBER_LB ||
version > INDEX_VERSION_NUMBER_UB) {
- giterr_set(GITERR_INDEX, "Invalid version number");
+ giterr_set(GITERR_INDEX, "invalid version number");
return -1;
}
@@ -805,7 +798,7 @@ int git_index_write_tree(git_oid *oid, git_index *index)
if (repo == NULL)
return create_index_error(-1, "Failed to write tree. "
- "The index file is not backed up by an existing repository");
+ "the index file is not backed up by an existing repository");
return git_tree__write_index(oid, index, repo);
}
@@ -847,7 +840,7 @@ const git_index_entry *git_index_get_bypath(
if (git_idxmap_valid_index(index->entries_map, pos))
return git_idxmap_value_at(index->entries_map, pos);
- giterr_set(GITERR_INDEX, "Index does not contain %s", path);
+ giterr_set(GITERR_INDEX, "index does not contain '%s'", path);
return NULL;
}
@@ -934,7 +927,7 @@ static int index_entry_init(
if (INDEX_OWNER(index) == NULL)
return create_index_error(-1,
- "Could not initialize index entry. "
+ "could not initialize index entry. "
"Index is not backed up by an existing repository.");
if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, true) < 0)
@@ -1365,7 +1358,7 @@ static int index_insert(
error = git_vector_insert_sorted(&index->entries, entry, index_no_dups);
if (error == 0) {
- INSERT_IN_MAP(index, entry, error);
+ INSERT_IN_MAP(index, entry, &error);
}
}
@@ -1423,7 +1416,7 @@ int git_index_add_frombuffer(
if (INDEX_OWNER(index) == NULL)
return create_index_error(-1,
- "Could not initialize index entry. "
+ "could not initialize index entry. "
"Index is not backed up by an existing repository.");
if (!valid_filemode(source_entry->mode)) {
@@ -1592,7 +1585,7 @@ int git_index__fill(git_index *index, const git_vector *source_entries)
if ((ret = git_vector_insert(&index->entries, entry)) < 0)
break;
- INSERT_IN_MAP(index, entry, ret);
+ INSERT_IN_MAP(index, entry, &ret);
if (ret < 0)
break;
}
@@ -1637,7 +1630,7 @@ int git_index_remove(git_index *index, const char *path, int stage)
if (index_find(&position, index, path, 0, stage) < 0) {
giterr_set(
- GITERR_INDEX, "Index does not contain %s at stage %d", path, stage);
+ GITERR_INDEX, "index does not contain %s at stage %d", path, stage);
error = GIT_ENOTFOUND;
} else {
error = index_remove_entry(index, position);
@@ -1709,7 +1702,7 @@ int git_index_find(size_t *at_pos, git_index *index, const char *path)
if (git_vector_bsearch2(
&pos, &index->entries, index->entries_search_path, path) < 0) {
- giterr_set(GITERR_INDEX, "Index does not contain %s", path);
+ giterr_set(GITERR_INDEX, "index does not contain %s", path);
return GIT_ENOTFOUND;
}
@@ -2153,7 +2146,7 @@ void git_index_reuc_clear(git_index *index)
static int index_error_invalid(const char *message)
{
- giterr_set(GITERR_INDEX, "Invalid data in index - %s", message);
+ giterr_set(GITERR_INDEX, "invalid data in index - %s", message);
return -1;
}
@@ -2285,12 +2278,29 @@ out_err:
return 0;
}
+static size_t index_entry_size(size_t path_len, size_t varint_len, uint32_t flags)
+{
+ if (varint_len) {
+ if (flags & GIT_IDXENTRY_EXTENDED)
+ return offsetof(struct entry_long, path) + path_len + 1 + varint_len;
+ else
+ return offsetof(struct entry_short, path) + path_len + 1 + varint_len;
+ } else {
+#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
+ if (flags & GIT_IDXENTRY_EXTENDED)
+ return entry_size(struct entry_long, path_len);
+ else
+ return entry_size(struct entry_short, path_len);
+#undef entry_size
+ }
+}
+
static size_t read_entry(
git_index_entry **out,
git_index *index,
const void *buffer,
size_t buffer_size,
- const char **last)
+ const char *last)
{
size_t path_length, entry_size;
const char *path_ptr;
@@ -2347,35 +2357,34 @@ static size_t read_entry(
path_length = path_end - path_ptr;
}
- if (entry.flags & GIT_IDXENTRY_EXTENDED)
- entry_size = long_entry_size(path_length);
- else
- entry_size = short_entry_size(path_length);
-
- if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
- return 0;
-
+ entry_size = index_entry_size(path_length, 0, entry.flags);
entry.path = (char *)path_ptr;
} else {
size_t varint_len;
- size_t shared = git_decode_varint((const unsigned char *)path_ptr,
- &varint_len);
- size_t len = strlen(path_ptr + varint_len);
- size_t last_len = strlen(*last);
- size_t tmp_path_len;
+ size_t strip_len = git_decode_varint((const unsigned char *)path_ptr,
+ &varint_len);
+ size_t last_len = strlen(last);
+ size_t prefix_len = last_len - strip_len;
+ size_t suffix_len = strlen(path_ptr + varint_len);
+ size_t path_len;
if (varint_len == 0)
return index_error_invalid("incorrect prefix length");
- GITERR_CHECK_ALLOC_ADD(&tmp_path_len, shared, len + 1);
- tmp_path = git__malloc(tmp_path_len);
+ GITERR_CHECK_ALLOC_ADD(&path_len, prefix_len, suffix_len);
+ GITERR_CHECK_ALLOC_ADD(&path_len, path_len, 1);
+ tmp_path = git__malloc(path_len);
GITERR_CHECK_ALLOC(tmp_path);
- memcpy(tmp_path, last, last_len);
- memcpy(tmp_path + last_len, path_ptr + varint_len, len);
- entry_size = long_entry_size(shared + len);
+
+ memcpy(tmp_path, last, prefix_len);
+ memcpy(tmp_path + prefix_len, path_ptr + varint_len, suffix_len + 1);
+ entry_size = index_entry_size(suffix_len, varint_len, entry.flags);
entry.path = tmp_path;
}
+ if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
+ return 0;
+
if (index_entry_dup(out, index, &entry) < 0) {
git__free(tmp_path);
return 0;
@@ -2448,7 +2457,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
unsigned int i;
struct index_header header = { 0 };
git_oid checksum_calculated, checksum_expected;
- const char **last = NULL;
+ const char *last = NULL;
const char *empty = "";
#define seek_forward(_increase) { \
@@ -2472,16 +2481,16 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
index->version = header.version;
if (index->version >= INDEX_VERSION_NUMBER_COMP)
- last = &empty;
+ last = empty;
seek_forward(INDEX_HEADER_SIZE);
assert(!index->entries.length);
if (index->ignore_case)
- kh_resize(idxicase, (khash_t(idxicase) *) index->entries_map, header.entry_count);
+ git_idxmap_icase_resize((khash_t(idxicase) *) index->entries_map, header.entry_count);
else
- kh_resize(idx, index->entries_map, header.entry_count);
+ git_idxmap_resize(index->entries_map, header.entry_count);
/* Parse all the entries */
for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
@@ -2499,7 +2508,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
goto done;
}
- INSERT_IN_MAP(index, entry, error);
+ INSERT_IN_MAP(index, entry, &error);
if (error < 0) {
index_entry_free(entry);
@@ -2507,6 +2516,9 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
}
error = 0;
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
+ last = entry->path;
+
seek_forward(entry_size);
}
@@ -2577,11 +2589,12 @@ static bool is_index_extended(git_index *index)
return (extended > 0);
}
-static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char **last)
+static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char *last)
{
void *mem = NULL;
struct entry_short *ondisk;
size_t path_len, disk_size;
+ int varint_len = 0;
char *path;
const char *path_start = entry->path;
size_t same_len = 0;
@@ -2589,7 +2602,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
path_len = ((struct entry_internal *)entry)->pathlen;
if (last) {
- const char *last_c = *last;
+ const char *last_c = last;
while (*path_start == *last_c) {
if (!*path_start || !*last_c)
@@ -2599,13 +2612,10 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
++same_len;
}
path_len -= same_len;
- *last = entry->path;
+ varint_len = git_encode_varint(NULL, 0, same_len);
}
- if (entry->flags & GIT_IDXENTRY_EXTENDED)
- disk_size = long_entry_size(path_len);
- else
- disk_size = short_entry_size(path_len);
+ disk_size = index_entry_size(path_len, varint_len, entry->flags);
if (git_filebuf_reserve(file, &mem, disk_size) < 0)
return -1;
@@ -2645,16 +2655,34 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
ondisk_ext->flags_extended = htons(entry->flags_extended &
GIT_IDXENTRY_EXTENDED_FLAGS);
path = ondisk_ext->path;
- }
- else
+ disk_size -= offsetof(struct entry_long, path);
+ } else {
path = ondisk->path;
+ disk_size -= offsetof(struct entry_short, path);
+ }
if (last) {
- path += git_encode_varint((unsigned char *) path,
- disk_size,
- path_len - same_len);
+ varint_len = git_encode_varint((unsigned char *) path,
+ disk_size, same_len);
+ assert(varint_len > 0);
+ path += varint_len;
+ disk_size -= varint_len;
+
+ /*
+ * If using path compression, we are not allowed
+ * to have additional trailing NULs.
+ */
+ assert(disk_size == path_len + 1);
+ } else {
+ /*
+ * If no path compression is used, we do have
+ * NULs as padding. As such, simply assert that
+ * we have enough space left to write the path.
+ */
+ assert(disk_size > path_len);
}
- memcpy(path, path_start, path_len);
+
+ memcpy(path, path_start, path_len + 1);
return 0;
}
@@ -2665,8 +2693,7 @@ static int write_entries(git_index *index, git_filebuf *file)
size_t i;
git_vector case_sorted, *entries;
git_index_entry *entry;
- const char **last = NULL;
- const char *empty = "";
+ const char *last = NULL;
/* If index->entries is sorted case-insensitively, then we need
* to re-sort it case-sensitively before writing */
@@ -2679,11 +2706,14 @@ static int write_entries(git_index *index, git_filebuf *file)
}
if (index->version >= INDEX_VERSION_NUMBER_COMP)
- last = &empty;
+ last = "";
- git_vector_foreach(entries, i, entry)
+ git_vector_foreach(entries, i, entry) {
if ((error = write_disk_entry(file, entry, last)) < 0)
break;
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
+ last = entry->path;
+ }
if (index->ignore_case)
git_vector_free(&case_sorted);
@@ -2979,12 +3009,12 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
goto cleanup;
if (index->ignore_case)
- kh_resize(idxicase, (khash_t(idxicase) *) entries_map, entries.length);
+ git_idxmap_icase_resize((khash_t(idxicase) *) entries_map, entries.length);
else
- kh_resize(idx, entries_map, entries.length);
+ git_idxmap_resize(entries_map, entries.length);
git_vector_foreach(&entries, i, e) {
- INSERT_IN_MAP_EX(index, entries_map, e, error);
+ INSERT_IN_MAP_EX(index, entries_map, e, &error);
if (error < 0) {
giterr_set(GITERR_INDEX, "failed to insert entry into map");
@@ -3037,9 +3067,9 @@ static int git_index_read_iterator(
goto done;
if (index->ignore_case && new_length_hint)
- kh_resize(idxicase, (khash_t(idxicase) *) new_entries_map, new_length_hint);
+ git_idxmap_icase_resize((khash_t(idxicase) *) new_entries_map, new_length_hint);
else if (new_length_hint)
- kh_resize(idx, new_entries_map, new_length_hint);
+ git_idxmap_resize(new_entries_map, new_length_hint);
opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
GIT_ITERATOR_INCLUDE_CONFLICTS;
@@ -3103,7 +3133,7 @@ static int git_index_read_iterator(
if (add_entry) {
if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
- INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error);
+ INSERT_IN_MAP_EX(index, new_entries_map, add_entry, &error);
}
if (remove_entry && error >= 0)
@@ -3390,7 +3420,7 @@ static int index_apply_to_all(
i--; /* back up foreach if we removed this */
break;
default:
- giterr_set(GITERR_INVALID, "Unknown index action %d", action);
+ giterr_set(GITERR_INVALID, "unknown index action %d", action);
error = -1;
break;
}
@@ -3475,13 +3505,13 @@ int git_indexwriter_init(
if (!index->index_file_path)
return create_index_error(-1,
- "Failed to write index: The index is in-memory only");
+ "failed to write index: The index is in-memory only");
if ((error = git_filebuf_open(
&writer->file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) {
if (error == GIT_ELOCKED)
- giterr_set(GITERR_INDEX, "The index is locked. This might be due to a concurrent or crashed process");
+ giterr_set(GITERR_INDEX, "the index is locked; this might be due to a concurrent or crashed process");
return error;
}
@@ -3530,7 +3560,7 @@ int git_indexwriter_commit(git_indexwriter *writer)
if ((error = git_futils_filestamp_check(
&writer->index->stamp, writer->index->index_file_path)) < 0) {
- giterr_set(GITERR_OS, "Could not read index timestamp");
+ giterr_set(GITERR_OS, "could not read index timestamp");
return -1;
}
diff --git a/src/index.h b/src/index.h
index 9918f140d..0f1c0956c 100644
--- a/src/index.h
+++ b/src/index.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_index_h__
#define INCLUDE_index_h__
+#include "common.h"
+
#include "fileops.h"
#include "filebuf.h"
#include "vector.h"
diff --git a/src/indexer.c b/src/indexer.c
index a3a866989..766bbc3c3 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -5,10 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "indexer.h"
+
#include "git2/indexer.h"
#include "git2/object.h"
-#include "common.h"
#include "pack.h"
#include "mwindow.h"
#include "posix.h"
@@ -17,8 +18,7 @@
#include "oid.h"
#include "oidmap.h"
#include "zstream.h"
-
-GIT__USE_OIDMAP
+#include "object.h"
extern git_mutex git__mwindow_mutex;
@@ -33,9 +33,10 @@ struct entry {
struct git_indexer {
unsigned int parsed_header :1,
- opened_pack :1,
+ pack_committed :1,
have_stream :1,
- have_delta :1;
+ have_delta :1,
+ do_fsync :1;
struct git_pack_header hdr;
struct git_pack_file *pack;
unsigned int mode;
@@ -83,12 +84,12 @@ static int parse_header(struct git_pack_header *hdr, struct git_pack_file *pack)
/* Verify we recognize this pack file format. */
if (hdr->hdr_signature != ntohl(PACK_SIGNATURE)) {
- giterr_set(GITERR_INDEXER, "Wrong pack signature");
+ giterr_set(GITERR_INDEXER, "wrong pack signature");
return -1;
}
if (!pack_version_ok(hdr->hdr_version)) {
- giterr_set(GITERR_INDEXER, "Wrong pack version");
+ giterr_set(GITERR_INDEXER, "wrong pack version");
return -1;
}
@@ -125,6 +126,9 @@ int git_indexer_new(
git_hash_ctx_init(&idx->hash_ctx);
git_hash_ctx_init(&idx->trailer);
+ if (git_repository__fsync_gitdir)
+ idx->do_fsync = 1;
+
error = git_buf_joinpath(&path, prefix, suff);
if (error < 0)
goto cleanup;
@@ -151,12 +155,23 @@ cleanup:
if (fd != -1)
p_close(fd);
+ if (git_buf_len(&tmp_path) > 0)
+ p_unlink(git_buf_cstr(&tmp_path));
+
+ if (idx->pack != NULL)
+ p_unlink(idx->pack->pack_name);
+
git_buf_free(&path);
git_buf_free(&tmp_path);
git__free(idx);
return -1;
}
+void git_indexer__set_fsync(git_indexer *idx, int do_fsync)
+{
+ idx->do_fsync = !!do_fsync;
+}
+
/* Try to store the delta so we can try to resolve it later */
static int store_delta(git_indexer *idx)
{
@@ -288,7 +303,7 @@ static int store_object(git_indexer *idx)
git_oid_cpy(&pentry->sha1, &oid);
pentry->offset = entry_start;
- k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
+ k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
if (error == -1) {
git__free(pentry);
giterr_set_oom();
@@ -302,7 +317,7 @@ static int store_object(git_indexer *idx)
}
- kh_value(idx->pack->idx_cache, k) = pentry;
+ git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
git_oid_cpy(&entry->oid, &oid);
@@ -327,9 +342,7 @@ on_error:
GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id)
{
- khiter_t k;
- k = kh_get(oid, idx->pack->idx_cache, id);
- return (k != kh_end(idx->pack->idx_cache));
+ return git_oidmap_exists(idx->pack->idx_cache, id);
}
static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start)
@@ -345,14 +358,14 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent
}
pentry->offset = entry_start;
- k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error);
+ k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
if (error <= 0) {
giterr_set(GITERR_INDEXER, "cannot insert object into pack");
return -1;
}
- kh_value(idx->pack->idx_cache, k) = pentry;
+ git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
/* Add the object to the list */
if (git_vector_insert(&idx->objects, entry) < 0)
@@ -376,7 +389,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_star
GITERR_CHECK_ALLOC(entry);
if (git_odb__hashobj(&oid, obj) < 0) {
- giterr_set(GITERR_INDEXER, "Failed to hash object");
+ giterr_set(GITERR_INDEXER, "failed to hash object");
goto on_error;
}
@@ -477,13 +490,29 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
static int append_to_pack(git_indexer *idx, const void *data, size_t size)
{
+ git_off_t new_size;
+ size_t mmap_alignment;
+ size_t page_offset;
+ git_off_t page_start;
git_off_t current_size = idx->pack->mwf.size;
int fd = idx->pack->mwf.fd;
+ int error;
if (!size)
return 0;
- if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 ||
+ if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
+ return error;
+
+ /* Write a single byte to force the file system to allocate space now or
+ * report an error, since we can't report errors when writing using mmap.
+ * Round the size up to the nearest page so that we only need to perform file
+ * I/O when we add a page, instead of whenever we write even a single byte. */
+ new_size = current_size + size;
+ page_offset = new_size % mmap_alignment;
+ page_start = new_size - page_offset;
+
+ if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 ||
p_write(idx->pack->mwf.fd, data, 1) < 0) {
giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
return -1;
@@ -909,7 +938,6 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
git_buf filename = GIT_BUF_INIT;
struct entry *entry;
git_oid trailer_hash, file_hash;
- git_hash_ctx ctx;
git_filebuf index_file = {0};
void *packfile_trailer;
@@ -918,9 +946,6 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
return -1;
}
- if (git_hash_ctx_init(&ctx) < 0)
- return -1;
-
/* Test for this before resolve_deltas(), as it plays with idx->off */
if (idx->off + 20 < idx->pack->mwf.size) {
giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack");
@@ -964,6 +989,10 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
git_vector_sort(&idx->objects);
+ /* Use the trailer hash as the pack file name to ensure
+ * files with different contents have different names */
+ git_oid_cpy(&idx->hash, &trailer_hash);
+
git_buf_sets(&filename, idx->pack->pack_name);
git_buf_shorten(&filename, strlen("pack"));
git_buf_puts(&filename, "idx");
@@ -971,7 +1000,9 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
return -1;
if (git_filebuf_open(&index_file, filename.ptr,
- GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0)
+ GIT_FILEBUF_HASH_CONTENTS |
+ (idx->do_fsync ? GIT_FILEBUF_FSYNC : 0),
+ idx->mode) < 0)
goto on_error;
/* Write out the header */
@@ -988,9 +1019,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
/* Write out the object names (SHA-1 hashes) */
git_vector_foreach(&idx->objects, i, entry) {
git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
- git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ);
}
- git_hash_final(&idx->hash, &ctx);
/* Write out the CRC32 values */
git_vector_foreach(&idx->objects, i, entry) {
@@ -1041,6 +1070,18 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
goto on_error;
git_mwindow_free_all(&idx->pack->mwf);
+
+ /* Truncate file to undo rounding up to next page_size in append_to_pack */
+ if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
+ giterr_set(GITERR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
+ return -1;
+ }
+
+ if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
+ giterr_set(GITERR_OS, "failed to fsync packfile");
+ goto on_error;
+ }
+
/* We need to close the descriptor here so Windows doesn't choke on commit_at */
if (p_close(idx->pack->mwf.fd) < 0) {
giterr_set(GITERR_OS, "failed to close packfile");
@@ -1053,17 +1094,23 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
goto on_error;
/* And don't forget to rename the packfile to its new place. */
- p_rename(idx->pack->pack_name, git_buf_cstr(&filename));
+ if (p_rename(idx->pack->pack_name, git_buf_cstr(&filename)) < 0)
+ goto on_error;
+
+ /* And fsync the parent directory if we're asked to. */
+ if (idx->do_fsync &&
+ git_futils_fsync_parent(git_buf_cstr(&filename)) < 0)
+ goto on_error;
+
+ idx->pack_committed = 1;
git_buf_free(&filename);
- git_hash_ctx_cleanup(&ctx);
return 0;
on_error:
git_mwindow_free_all(&idx->pack->mwf);
git_filebuf_cleanup(&index_file);
git_buf_free(&filename);
- git_hash_ctx_cleanup(&ctx);
return -1;
}
@@ -1074,10 +1121,11 @@ void git_indexer_free(git_indexer *idx)
git_vector_free_deep(&idx->objects);
- if (idx->pack && idx->pack->idx_cache) {
+ if (idx->pack->idx_cache) {
struct git_pack_entry *pentry;
- kh_foreach_value(
- idx->pack->idx_cache, pentry, { git__free(pentry); });
+ git_oidmap_foreach_value(idx->pack->idx_cache, pentry, {
+ git__free(pentry);
+ });
git_oidmap_free(idx->pack->idx_cache);
}
@@ -1085,6 +1133,9 @@ void git_indexer_free(git_indexer *idx)
git_vector_free_deep(&idx->deltas);
if (!git_mutex_lock(&git__mwindow_mutex)) {
+ if (!idx->pack_committed)
+ git_packfile_close(idx->pack, true);
+
git_packfile_free(idx->pack);
git_mutex_unlock(&git__mwindow_mutex);
}
diff --git a/src/indexer.h b/src/indexer.h
new file mode 100644
index 000000000..8ee6115a6
--- /dev/null
+++ b/src/indexer.h
@@ -0,0 +1,16 @@
+/*
+ * 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_indexer_h__
+#define INCLUDE_indexer_h__
+
+#include "common.h"
+
+#include "git2/indexer.h"
+
+extern void git_indexer__set_fsync(git_indexer *idx, int do_fsync);
+
+#endif
diff --git a/src/integer.h b/src/integer.h
index b08094c2f..61712cebf 100644
--- a/src/integer.h
+++ b/src/integer.h
@@ -55,16 +55,16 @@ GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t
}
/* Use clang/gcc compiler intrinsics whenever possible */
-#if (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow)
-# define git__add_sizet_overflow(out, one, two) \
- __builtin_uadd_overflow(one, two, out)
-# define git__multiply_sizet_overflow(out, one, two) \
- __builtin_umul_overflow(one, two, out)
-#elif (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow)
+#if (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow)
# define git__add_sizet_overflow(out, one, two) \
__builtin_uaddl_overflow(one, two, out)
# define git__multiply_sizet_overflow(out, one, two) \
__builtin_umull_overflow(one, two, out)
+#elif (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow)
+# define git__add_sizet_overflow(out, one, two) \
+ __builtin_uadd_overflow(one, two, out)
+# define git__multiply_sizet_overflow(out, one, two) \
+ __builtin_umul_overflow(one, two, out)
#else
/**
diff --git a/src/iterator.c b/src/iterator.c
index 598c69c83..960031233 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -6,6 +6,7 @@
*/
#include "iterator.h"
+
#include "tree.h"
#include "index.h"
@@ -1311,7 +1312,7 @@ static int filesystem_iterator_frame_push(
if (iter->frames.size == FILESYSTEM_MAX_DEPTH) {
giterr_set(GITERR_REPOSITORY,
- "directory nesting too deep (%d)", iter->frames.size);
+ "directory nesting too deep (%"PRIuZ")", iter->frames.size);
return -1;
}
diff --git a/src/iterator.h b/src/iterator.h
index 0b239a5bd..0bcb128d9 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -8,6 +8,7 @@
#define INCLUDE_iterator_h__
#include "common.h"
+
#include "git2/index.h"
#include "vector.h"
#include "buffer.h"
diff --git a/src/merge.c b/src/merge.c
index 6934aa731..72cfa464d 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -5,13 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "merge.h"
+
#include "posix.h"
#include "buffer.h"
#include "repository.h"
#include "revwalk.h"
#include "commit_list.h"
-#include "merge.h"
#include "path.h"
#include "refs.h"
#include "object.h"
@@ -32,6 +32,8 @@
#include "commit.h"
#include "oidarray.h"
#include "merge_driver.h"
+#include "oidmap.h"
+#include "array.h"
#include "git2/types.h"
#include "git2/repository.h"
@@ -78,7 +80,7 @@ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_reposito
unsigned int i;
if (length < 2) {
- giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length);
+ giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor");
return -1;
}
@@ -104,7 +106,7 @@ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_reposito
goto on_error;
if (!result) {
- giterr_set(GITERR_MERGE, "No merge base found");
+ giterr_set(GITERR_MERGE, "no merge base found");
error = GIT_ENOTFOUND;
goto on_error;
}
@@ -184,7 +186,7 @@ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, co
assert(out && repo && input_array);
if (length < 2) {
- giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length);
+ giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor");
return -1;
}
@@ -230,7 +232,7 @@ static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_reposi
if (!result) {
git_revwalk_free(walk);
- giterr_set(GITERR_MERGE, "No merge base found");
+ giterr_set(GITERR_MERGE, "no merge base found");
return GIT_ENOTFOUND;
}
@@ -562,7 +564,7 @@ int git_repository_mergehead_foreach(
assert(repo && cb);
- if ((error = git_buf_joinpath(&merge_head_path, repo->path_repository,
+ if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
GIT_MERGE_HEAD_FILE)) < 0)
return error;
@@ -574,7 +576,7 @@ int git_repository_mergehead_foreach(
while ((line = git__strsep(&buffer, "\n")) != NULL) {
if (strlen(line) != GIT_OID_HEXSZ) {
- giterr_set(GITERR_INVALID, "Unable to parse OID - invalid length");
+ giterr_set(GITERR_INVALID, "unable to parse OID - invalid length");
error = -1;
goto cleanup;
}
@@ -591,7 +593,7 @@ int git_repository_mergehead_foreach(
}
if (*buffer) {
- giterr_set(GITERR_MERGE, "No EOL at line %d", line_num);
+ giterr_set(GITERR_MERGE, "no EOL at line %"PRIuZ, line_num);
error = -1;
goto cleanup;
}
@@ -1005,27 +1007,6 @@ struct merge_diff_similarity {
size_t other_idx;
};
-static int index_entry_similarity_exact(
- git_repository *repo,
- git_index_entry *a,
- size_t a_idx,
- git_index_entry *b,
- size_t b_idx,
- void **cache,
- const git_merge_options *opts)
-{
- GIT_UNUSED(repo);
- GIT_UNUSED(a_idx);
- GIT_UNUSED(b_idx);
- GIT_UNUSED(cache);
- GIT_UNUSED(opts);
-
- if (git_oid__cmp(&a->id, &b->id) == 0)
- return 100;
-
- return 0;
-}
-
static int index_entry_similarity_calc(
void **out,
git_repository *repo,
@@ -1075,7 +1056,7 @@ static int index_entry_similarity_inexact(
int score = 0;
int error = 0;
- if (GIT_MODE_TYPE(a->mode) != GIT_MODE_TYPE(b->mode))
+ if (!GIT_MODE_ISBLOB(a->mode) || !GIT_MODE_ISBLOB(b->mode))
return 0;
/* update signature cache if needed */
@@ -1102,12 +1083,154 @@ static int index_entry_similarity_inexact(
return score;
}
-static int merge_diff_mark_similarity(
+/* Tracks deletes by oid for merge_diff_mark_similarity_exact(). This is a
+* non-shrinking queue where next_pos is the next position to dequeue.
+*/
+typedef struct {
+ git_array_t(size_t) arr;
+ size_t next_pos;
+ size_t first_entry;
+} deletes_by_oid_queue;
+
+static void deletes_by_oid_free(git_oidmap *map) {
+ deletes_by_oid_queue *queue;
+
+ if (!map)
+ return;
+
+ git_oidmap_foreach_value(map, queue, {
+ git_array_clear(queue->arr);
+ });
+ git_oidmap_free(map);
+}
+
+static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx) {
+ khint_t pos;
+ deletes_by_oid_queue *queue;
+ size_t *array_entry;
+ int error;
+
+ pos = git_oidmap_lookup_index(map, id);
+ if (!git_oidmap_valid_index(map, pos)) {
+ queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue));
+ GITERR_CHECK_ALLOC(queue);
+
+ git_array_init(queue->arr);
+ queue->next_pos = 0;
+ queue->first_entry = idx;
+
+ git_oidmap_insert(map, id, queue, &error);
+ if (error < 0)
+ return -1;
+ } else {
+ queue = git_oidmap_value_at(map, pos);
+ array_entry = git_array_alloc(queue->arr);
+ GITERR_CHECK_ALLOC(array_entry);
+ *array_entry = idx;
+ }
+
+ return 0;
+}
+
+static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id) {
+ khint_t pos;
+ deletes_by_oid_queue *queue;
+ size_t *array_entry;
+
+ pos = git_oidmap_lookup_index(map, id);
+
+ if (!git_oidmap_valid_index(map, pos))
+ return GIT_ENOTFOUND;
+
+ queue = git_oidmap_value_at(map, pos);
+
+ if (queue->next_pos == 0) {
+ *idx = queue->first_entry;
+ } else {
+ array_entry = git_array_get(queue->arr, queue->next_pos - 1);
+ if (array_entry == NULL)
+ return GIT_ENOTFOUND;
+
+ *idx = *array_entry;
+ }
+
+ queue->next_pos++;
+ return 0;
+}
+
+static int merge_diff_mark_similarity_exact(
+ git_merge_diff_list *diff_list,
+ struct merge_diff_similarity *similarity_ours,
+ struct merge_diff_similarity *similarity_theirs)
+{
+ size_t i, j;
+ git_merge_diff *conflict_src, *conflict_tgt;
+ git_oidmap *ours_deletes_by_oid = NULL, *theirs_deletes_by_oid = NULL;
+ int error = 0;
+
+ if (!(ours_deletes_by_oid = git_oidmap_alloc()) ||
+ !(theirs_deletes_by_oid = git_oidmap_alloc())) {
+ error = -1;
+ goto done;
+ }
+
+ /* Build a map of object ids to conflicts */
+ git_vector_foreach(&diff_list->conflicts, i, conflict_src) {
+ /* Items can be the source of a rename iff they have an item in the
+ * ancestor slot and lack an item in the ours or theirs slot. */
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->ancestor_entry))
+ continue;
+
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
+ error = deletes_by_oid_enqueue(ours_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
+ if (error < 0)
+ goto done;
+ }
+
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
+ error = deletes_by_oid_enqueue(theirs_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
+ if (error < 0)
+ goto done;
+ }
+ }
+
+ git_vector_foreach(&diff_list->conflicts, j, conflict_tgt) {
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->ancestor_entry))
+ continue;
+
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry)) {
+ if (deletes_by_oid_dequeue(&i, ours_deletes_by_oid, &conflict_tgt->our_entry.id) == 0) {
+ similarity_ours[i].similarity = 100;
+ similarity_ours[i].other_idx = j;
+
+ similarity_ours[j].similarity = 100;
+ similarity_ours[j].other_idx = i;
+ }
+ }
+
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry)) {
+ if (deletes_by_oid_dequeue(&i, theirs_deletes_by_oid, &conflict_tgt->their_entry.id) == 0) {
+ similarity_theirs[i].similarity = 100;
+ similarity_theirs[i].other_idx = j;
+
+ similarity_theirs[j].similarity = 100;
+ similarity_theirs[j].other_idx = i;
+ }
+ }
+ }
+
+done:
+ deletes_by_oid_free(ours_deletes_by_oid);
+ deletes_by_oid_free(theirs_deletes_by_oid);
+
+ return error;
+}
+
+static int merge_diff_mark_similarity_inexact(
git_repository *repo,
git_merge_diff_list *diff_list,
struct merge_diff_similarity *similarity_ours,
struct merge_diff_similarity *similarity_theirs,
- int (*similarity_fn)(git_repository *, git_index_entry *, size_t, git_index_entry *, size_t, void **, const git_merge_options *),
void **cache,
const git_merge_options *opts)
{
@@ -1132,7 +1255,7 @@ static int merge_diff_mark_similarity(
if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry) &&
!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
- similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
+ similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
if (similarity == GIT_EBUFS)
continue;
@@ -1158,7 +1281,7 @@ static int merge_diff_mark_similarity(
if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry) &&
!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
- similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
+ similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
if (similarity > similarity_theirs[i].similarity &&
similarity > similarity_theirs[j].similarity) {
@@ -1396,11 +1519,10 @@ int git_merge_diff_list__find_renames(
/* Calculate similarity between items that were deleted from the ancestor
* and added in the other branch.
*/
- if ((error = merge_diff_mark_similarity(repo, diff_list, similarity_ours,
- similarity_theirs, index_entry_similarity_exact, NULL, opts)) < 0)
+ if ((error = merge_diff_mark_similarity_exact(diff_list, similarity_ours, similarity_theirs)) < 0)
goto done;
- if (diff_list->conflicts.length <= opts->target_limit) {
+ if (opts->rename_threshold < 100 && diff_list->conflicts.length <= opts->target_limit) {
GITERR_CHECK_ALLOC_MULTIPLY(&cache_size, diff_list->conflicts.length, 3);
cache = git__calloc(cache_size, sizeof(void *));
GITERR_CHECK_ALLOC(cache);
@@ -1410,9 +1532,8 @@ int git_merge_diff_list__find_renames(
if (src_count > opts->target_limit || tgt_count > opts->target_limit) {
/* TODO: report! */
} else {
- if ((error = merge_diff_mark_similarity(
- repo, diff_list, similarity_ours, similarity_theirs,
- index_entry_similarity_inexact, cache, opts)) < 0)
+ if ((error = merge_diff_mark_similarity_inexact(
+ repo, diff_list, similarity_ours, similarity_theirs, cache, opts)) < 0)
goto done;
}
}
@@ -1713,15 +1834,15 @@ static int merge_normalize_opts(
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
return error;
- if (given != NULL)
+ if (given != NULL) {
memcpy(opts, given, sizeof(git_merge_options));
- else {
+ } else {
git_merge_options init = GIT_MERGE_OPTIONS_INIT;
memcpy(opts, &init, sizeof(init));
+ }
- opts->flags = GIT_MERGE_FIND_RENAMES;
+ if ((opts->flags & GIT_MERGE_FIND_RENAMES) && !opts->rename_threshold)
opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
- }
if (given && given->default_driver) {
opts->default_driver = git__strdup(given->default_driver);
@@ -2018,6 +2139,26 @@ int git_merge_trees(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error;
+ assert(out && repo);
+
+ /* if one side is treesame to the ancestor, take the other side */
+ if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
+ const git_tree *result = NULL;
+ const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree);
+
+ if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree)))
+ result = their_tree;
+ else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree)))
+ result = our_tree;
+
+ if (result) {
+ if ((error = git_index_new(out)) == 0)
+ error = git_index_read_tree(*out, result);
+
+ return error;
+ }
+ }
+
iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
if ((error = git_iterator_for_tree(
@@ -2277,7 +2418,7 @@ static int write_merge_head(
assert(repo && heads);
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_HEAD_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
goto cleanup;
@@ -2305,7 +2446,7 @@ static int write_merge_mode(git_repository *repo)
assert(repo);
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
goto cleanup;
@@ -2536,7 +2677,7 @@ static int write_merge_msg(
for (i = 0; i < heads_len; i++)
entries[i].merge_head = heads[i];
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0 ||
(error = git_filebuf_write(&file, "Merge ", 6)) < 0)
goto cleanup;
@@ -2914,7 +3055,7 @@ int git_merge__append_conflicts_to_merge_msg(
if (!git_index_has_conflicts(index))
return 0;
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0)
goto cleanup;
@@ -3043,7 +3184,7 @@ int git_merge_analysis(
assert(analysis_out && preference_out && repo && their_heads);
if (their_heads_len != 1) {
- giterr_set(GITERR_MERGE, "Can only merge a single branch");
+ giterr_set(GITERR_MERGE, "can only merge a single branch");
error = -1;
goto done;
}
@@ -3099,7 +3240,7 @@ int git_merge(
assert(repo && their_heads);
if (their_heads_len != 1) {
- giterr_set(GITERR_MERGE, "Can only merge a single branch");
+ giterr_set(GITERR_MERGE, "can only merge a single branch");
return -1;
}
diff --git a/src/merge.h b/src/merge.h
index f8cac161f..173a1b435 100644
--- a/src/merge.h
+++ b/src/merge.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_merge_h__
#define INCLUDE_merge_h__
+#include "common.h"
+
#include "vector.h"
#include "commit_list.h"
#include "pool.h"
diff --git a/src/merge_driver.c b/src/merge_driver.c
index 88a53ecdb..ea4bd2787 100644
--- a/src/merge_driver.c
+++ b/src/merge_driver.c
@@ -5,11 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "merge_driver.h"
+
#include "vector.h"
#include "global.h"
#include "merge.h"
-#include "merge_driver.h"
#include "git2/merge.h"
#include "git2/sys/merge.h"
@@ -32,6 +32,35 @@ static struct merge_driver_registry merge_driver_registry;
static void git_merge_driver_global_shutdown(void);
+const git_repository* git_merge_driver_source_repo(const git_merge_driver_source *src)
+{
+ assert(src);
+ return src->repo;
+}
+
+const git_index_entry* git_merge_driver_source_ancestor(const git_merge_driver_source *src)
+{
+ assert(src);
+ return src->ancestor;
+}
+
+const git_index_entry* git_merge_driver_source_ours(const git_merge_driver_source *src)
+{
+ assert(src);
+ return src->ours;
+}
+
+const git_index_entry* git_merge_driver_source_theirs(const git_merge_driver_source *src)
+{
+ assert(src);
+ return src->theirs;
+}
+
+const git_merge_file_options* git_merge_driver_source_file_options(const git_merge_driver_source *src)
+{
+ assert(src);
+ return src->file_opts;
+}
int git_merge_driver__builtin_apply(
git_merge_driver *self,
diff --git a/src/merge_driver.h b/src/merge_driver.h
index bde27502c..6b7da5287 100644
--- a/src/merge_driver.h
+++ b/src/merge_driver.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_merge_driver_h__
#define INCLUDE_merge_driver_h__
+#include "common.h"
+
#include "git2/merge.h"
#include "git2/index.h"
#include "git2/sys/merge.h"
diff --git a/src/merge_file.c b/src/merge_file.c
index 3f14a4f63..a54d6bd57 100644
--- a/src/merge_file.c
+++ b/src/merge_file.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "repository.h"
#include "posix.h"
#include "fileops.h"
@@ -127,7 +128,7 @@ static int merge_file__xdiff(
if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile,
&their_mmfile, &xmparam, &mmbuffer)) < 0) {
- giterr_set(GITERR_MERGE, "Failed to merge files.");
+ giterr_set(GITERR_MERGE, "failed to merge files");
error = -1;
goto done;
}
diff --git a/src/message.h b/src/message.h
index 3c4b8dc45..88fc7884c 100644
--- a/src/message.h
+++ b/src/message.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_message_h__
#define INCLUDE_message_h__
+#include "common.h"
+
#include "git2/message.h"
#include "buffer.h"
diff --git a/src/mwindow.c b/src/mwindow.c
index 8a5b5caee..38d0352b4 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "mwindow.h"
+
#include "vector.h"
#include "fileops.h"
#include "map.h"
@@ -14,8 +14,6 @@
#include "strmap.h"
#include "pack.h"
-GIT__USE_STRMAP
-
#define DEFAULT_WINDOW_SIZE \
(sizeof(void*) >= 8 \
? 1 * 1024 * 1024 * 1024 \
@@ -84,7 +82,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path)
git_atomic_inc(&pack->refcount);
- git_strmap_insert(git__pack_cache, pack->pack_name, pack, error);
+ git_strmap_insert(git__pack_cache, pack->pack_name, pack, &error);
git_mutex_unlock(&git__mwindow_mutex);
if (error < 0) {
@@ -231,7 +229,7 @@ static int git_mwindow_close_lru(git_mwindow_file *mwf)
}
if (!lru_w) {
- giterr_set(GITERR_OS, "Failed to close memory window. Couldn't find LRU");
+ giterr_set(GITERR_OS, "failed to close memory window; couldn't find LRU");
return -1;
}
diff --git a/src/mwindow.h b/src/mwindow.h
index bdde9e0a4..ea962d1b6 100644
--- a/src/mwindow.h
+++ b/src/mwindow.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_mwindow__
#define INCLUDE_mwindow__
+#include "common.h"
+
#include "map.h"
#include "vector.h"
diff --git a/src/netops.c b/src/netops.c
index 90326ea59..68f404d2c 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -5,11 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "netops.h"
+
#include <ctype.h>
#include "git2/errors.h"
-#include "common.h"
-#include "netops.h"
#include "posix.h"
#include "buffer.h"
#include "http_parser.h"
@@ -144,7 +144,7 @@ int gitno_connection_data_from_url(
default_port = "80";
if (data->use_ssl) {
- giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed");
+ giterr_set(GITERR_NET, "redirect from HTTPS to HTTP is not allowed");
goto cleanup;
}
} else if (!git__prefixcmp(url, prefix_https)) {
@@ -155,7 +155,7 @@ int gitno_connection_data_from_url(
default_port = data->use_ssl ? "443" : "80";
if (!default_port) {
- giterr_set(GITERR_NET, "Unrecognized URL prefix");
+ giterr_set(GITERR_NET, "unrecognized URL prefix");
goto cleanup;
}
@@ -187,7 +187,7 @@ int gitno_connection_data_from_url(
/* Check for errors in the resulting data */
if (original_host && url[0] != '/' && strcmp(original_host, data->host)) {
- giterr_set(GITERR_NET, "Cross host redirect not allowed");
+ giterr_set(GITERR_NET, "cross host redirect not allowed");
error = -1;
}
}
@@ -237,7 +237,7 @@ int gitno_extract_url_parts(
const char *_host, *_port, *_path, *_userinfo;
if (http_parser_parse_url(url, strlen(url), false, &u)) {
- giterr_set(GITERR_NET, "Malformed URL '%s'", url);
+ giterr_set(GITERR_NET, "malformed URL '%s'", url);
return GIT_EINVALIDSPEC;
}
diff --git a/src/netops.h b/src/netops.h
index b7170a0f2..75fd9a512 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -7,8 +7,9 @@
#ifndef INCLUDE_netops_h__
#define INCLUDE_netops_h__
-#include "posix.h"
#include "common.h"
+
+#include "posix.h"
#include "stream.h"
#ifdef GIT_OPENSSL
diff --git a/src/notes.c b/src/notes.c
index fe8d2164f..75108b9c9 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -15,7 +15,7 @@
static int note_error_notfound(void)
{
- giterr_set(GITERR_INVALID, "Note could not be found");
+ giterr_set(GITERR_INVALID, "note could not be found");
return GIT_ENOTFOUND;
}
@@ -226,7 +226,7 @@ static int remove_note_in_tree_enotfound_cb(
GIT_UNUSED(note_oid);
GIT_UNUSED(fanout);
- giterr_set(GITERR_REPOSITORY, "Object '%s' has no note", annotated_object_sha);
+ giterr_set(GITERR_REPOSITORY, "object '%s' has no note", annotated_object_sha);
return current_error;
}
@@ -244,7 +244,7 @@ static int insert_note_in_tree_eexists_cb(git_tree **out,
GIT_UNUSED(note_oid);
GIT_UNUSED(fanout);
- giterr_set(GITERR_REPOSITORY, "Note for '%s' exists already", annotated_object_sha);
+ giterr_set(GITERR_REPOSITORY, "note for '%s' exists already", annotated_object_sha);
return current_error;
}
diff --git a/src/object.c b/src/object.c
index 1d45f9f1b..4d069a34c 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,9 +4,11 @@
* 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 "object.h"
+
#include "git2/object.h"
-#include "common.h"
#include "repository.h"
#include "commit.h"
@@ -66,12 +68,12 @@ int git_object__from_odb_object(
/* Validate type match */
if (type != GIT_OBJ_ANY && type != odb_obj->cached.type) {
giterr_set(GITERR_INVALID,
- "The requested type does not match the type in the ODB");
+ "the requested type does not match the type in the ODB");
return GIT_ENOTFOUND;
}
if ((object_size = git_object__size(odb_obj->cached.type)) == 0) {
- giterr_set(GITERR_INVALID, "The requested type is invalid");
+ giterr_set(GITERR_INVALID, "the requested type is invalid");
return GIT_ENOTFOUND;
}
@@ -122,7 +124,7 @@ int git_object_lookup_prefix(
assert(repo && object_out && id);
if (len < GIT_OID_MINPREFIXLEN) {
- giterr_set(GITERR_OBJECT, "Ambiguous lookup - OID prefix is too short");
+ giterr_set(GITERR_OBJECT, "ambiguous lookup - OID prefix is too short");
return GIT_EAMBIGUOUS;
}
@@ -147,7 +149,7 @@ int git_object_lookup_prefix(
if (type != GIT_OBJ_ANY && type != object->cached.type) {
git_object_free(object);
giterr_set(GITERR_INVALID,
- "The requested type does not match the type in ODB");
+ "the requested type does not match the type in ODB");
return GIT_ENOTFOUND;
}
@@ -292,7 +294,7 @@ static int peel_error(int error, const git_oid *oid, git_otype type)
git_oid_fmt(hex_oid, oid);
hex_oid[GIT_OID_HEXSZ] = '\0';
- giterr_set(GITERR_OBJECT, "The git_object of id '%s' can not be "
+ giterr_set(GITERR_OBJECT, "the git_object of id '%s' can not be "
"successfully peeled into a %s (git_otype=%i).", hex_oid, type_name, type);
return error;
diff --git a/src/object.h b/src/object.h
index dd227d16d..ff61c1d33 100644
--- a/src/object.h
+++ b/src/object.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_object_h__
#define INCLUDE_object_h__
+#include "common.h"
+
#include "repository.h"
extern bool git_object__strict_input_validation;
diff --git a/src/object_api.c b/src/object_api.c
index e0d8760e7..75efa4d10 100644
--- a/src/object_api.c
+++ b/src/object_api.c
@@ -4,11 +4,12 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "git2/object.h"
#include "common.h"
-#include "repository.h"
+#include "git2/object.h"
+
+#include "repository.h"
#include "commit.h"
#include "tree.h"
#include "blob.h"
diff --git a/src/odb.c b/src/odb.c
index acf4dea71..7da391bff 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -5,13 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "odb.h"
+
#include <zlib.h>
#include "git2/object.h"
#include "git2/sys/odb_backend.h"
#include "fileops.h"
#include "hash.h"
-#include "odb.h"
#include "delta.h"
#include "filter.h"
#include "repository.h"
@@ -31,6 +31,8 @@
#define GIT_ALTERNATES_MAX_DEPTH 5
+bool git_odb__strict_hash_verification = true;
+
typedef struct
{
git_odb_backend *backend;
@@ -176,7 +178,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
int error = 0;
if (!git_object_typeisloose(type)) {
- giterr_set(GITERR_INVALID, "Invalid object type for hash");
+ giterr_set(GITERR_INVALID, "invalid object type for hash");
return -1;
}
@@ -199,7 +201,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type)
* If size is not zero, the file was truncated after we originally
* stat'd it, so we consider this a read failure too */
if (read_len < 0 || size > 0) {
- giterr_set(GITERR_OS, "Error reading file for hashing");
+ giterr_set(GITERR_OS, "error reading file for hashing");
error = -1;
goto done;
@@ -251,7 +253,7 @@ int git_odb__hashlink(git_oid *out, const char *path)
return -1;
if (!git__is_int(st.st_size) || (int)st.st_size < 0) {
- giterr_set(GITERR_FILESYSTEM, "File size overflow for 32-bit systems");
+ giterr_set(GITERR_FILESYSTEM, "file size overflow for 32-bit systems");
return -1;
}
@@ -269,7 +271,7 @@ int git_odb__hashlink(git_oid *out, const char *path)
read_len = p_readlink(path, link_data, size);
link_data[size] = '\0';
if (read_len != size) {
- giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path);
+ giterr_set(GITERR_OS, "failed to read symlink data for '%s'", path);
git__free(link_data);
return -1;
}
@@ -295,7 +297,7 @@ int git_odb_hashfile(git_oid *out, const char *path, git_otype type)
return fd;
if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) {
- giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
+ giterr_set(GITERR_OS, "file size overflow for 32-bit systems");
p_close(fd);
return -1;
}
@@ -475,7 +477,7 @@ size_t git_odb_num_backends(git_odb *odb)
static int git_odb__error_unsupported_in_backend(const char *action)
{
giterr_set(GITERR_ODB,
- "Cannot %s - unsupported in the loaded odb backends", action);
+ "cannot %s - unsupported in the loaded odb backends", action);
return -1;
}
@@ -492,11 +494,11 @@ int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
return 0;
}
- giterr_set(GITERR_ODB, "No ODB backend loaded at index %" PRIuZ, pos);
+ giterr_set(GITERR_ODB, "no ODB backend loaded at index %" PRIuZ, pos);
return GIT_ENOTFOUND;
}
-static int add_default_backends(
+int git_odb__add_default_backends(
git_odb *db, const char *objects_dir,
bool as_alternates, int alternate_depth)
{
@@ -517,7 +519,7 @@ static int add_default_backends(
if (as_alternates)
return 0;
- giterr_set(GITERR_ODB, "Failed to load object database in '%s'", objects_dir);
+ giterr_set(GITERR_ODB, "failed to load object database in '%s'", objects_dir);
return -1;
}
@@ -531,7 +533,7 @@ static int add_default_backends(
#endif
/* add the loose object backend */
- if (git_odb_backend_loose(&loose, objects_dir, -1, 0, 0, 0) < 0 ||
+ if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0)
return -1;
@@ -586,7 +588,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
alternate = git_buf_cstr(&alternates_path);
}
- if ((result = add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
+ if ((result = git_odb__add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
break;
}
@@ -598,7 +600,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
int git_odb_add_disk_alternate(git_odb *odb, const char *path)
{
- return add_default_backends(odb, path, true, 0);
+ return git_odb__add_default_backends(odb, path, true, 0);
}
int git_odb_open(git_odb **out, const char *objects_dir)
@@ -612,7 +614,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
if (git_odb_new(&db) < 0)
return -1;
- if (add_default_backends(db, objects_dir, 0, 0) < 0) {
+ if (git_odb__add_default_backends(db, objects_dir, 0, 0) < 0) {
git_odb_free(db);
return -1;
}
@@ -621,6 +623,24 @@ int git_odb_open(git_odb **out, const char *objects_dir)
return 0;
}
+int git_odb__set_caps(git_odb *odb, int caps)
+{
+ if (caps == GIT_ODB_CAP_FROM_OWNER) {
+ git_repository *repo = odb->rc.owner;
+ int val;
+
+ if (!repo) {
+ giterr_set(GITERR_ODB, "cannot access repository to set odb caps");
+ return -1;
+ }
+
+ if (!git_repository__cvar(&val, repo, GIT_CVAR_FSYNCOBJECTFILES))
+ odb->do_fsync = !!val;
+ }
+
+ return 0;
+}
+
static void odb_free(git_odb *db)
{
size_t i;
@@ -695,7 +715,7 @@ static int odb_freshen_1(
return (int)found;
}
-static int odb_freshen(git_odb *db, const git_oid *id)
+int git_odb__freshen(git_odb *db, const git_oid *id)
{
assert(db && id);
@@ -980,7 +1000,9 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
size_t i;
git_rawobj raw;
git_odb_object *object;
+ git_oid hashed;
bool found = false;
+ int error = 0;
if (!only_refreshed && odb_read_hardcoded(&raw, id) == 0)
found = true;
@@ -993,7 +1015,7 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
continue;
if (b->read != NULL) {
- int error = b->read(&raw.data, &raw.len, &raw.type, b, id);
+ error = b->read(&raw.data, &raw.len, &raw.type, b, id);
if (error == GIT_PASSTHROUGH || error == GIT_ENOTFOUND)
continue;
@@ -1007,12 +1029,26 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
if (!found)
return GIT_ENOTFOUND;
+ if (git_odb__strict_hash_verification) {
+ if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
+ goto out;
+
+ if (!git_oid_equal(id, &hashed)) {
+ error = git_odb__error_mismatch(id, &hashed);
+ goto out;
+ }
+ }
+
giterr_clear();
if ((object = odb_object__alloc(id, &raw)) == NULL)
- return -1;
+ goto out;
*out = git_cache_store_raw(odb_cache(db), object);
- return 0;
+
+out:
+ if (error)
+ git__free(raw.data);
+ return error;
}
int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
@@ -1063,9 +1099,9 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
const git_oid *key, size_t len, bool only_refreshed)
{
size_t i;
- int error = GIT_ENOTFOUND;
+ int error = 0;
git_oid found_full_oid = {{0}};
- git_rawobj raw;
+ git_rawobj raw = {0};
void *data = NULL;
bool found = false;
git_odb_object *object;
@@ -1080,18 +1116,29 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
if (b->read_prefix != NULL) {
git_oid full_oid;
error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, key, len);
- if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
+
+ if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) {
+ error = 0;
continue;
+ }
if (error)
- return error;
+ goto out;
git__free(data);
data = raw.data;
if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
- git__free(raw.data);
- return git_odb__error_ambiguous("multiple matches for prefix");
+ git_buf buf = GIT_BUF_INIT;
+
+ git_buf_printf(&buf, "multiple matches for prefix: %s",
+ git_oid_tostr_s(&full_oid));
+ git_buf_printf(&buf, " %s",
+ git_oid_tostr_s(&found_full_oid));
+
+ error = git_odb__error_ambiguous(buf.ptr);
+ git_buf_free(&buf);
+ goto out;
}
found_full_oid = full_oid;
@@ -1102,11 +1149,28 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
if (!found)
return GIT_ENOTFOUND;
+ if (git_odb__strict_hash_verification) {
+ git_oid hash;
+
+ if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type)) < 0)
+ goto out;
+
+ if (!git_oid_equal(&found_full_oid, &hash)) {
+ error = git_odb__error_mismatch(&found_full_oid, &hash);
+ goto out;
+ }
+ }
+
if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
- return -1;
+ goto out;
*out = git_cache_store_raw(odb_cache(db), object);
- return 0;
+
+out:
+ if (error)
+ git__free(raw.data);
+
+ return error;
}
int git_odb_read_prefix(
@@ -1167,7 +1231,7 @@ int git_odb_write(
assert(oid && db);
git_odb_hash(oid, data, len, type);
- if (odb_freshen(db, oid))
+ if (git_odb__freshen(db, oid))
return 0;
for (i = 0; i < db->backends.length && error < 0; ++i) {
@@ -1264,10 +1328,10 @@ static int git_odb_stream__invalid_length(
const char *action)
{
giterr_set(GITERR_ODB,
- "Cannot %s - "
- "Invalid length. %"PRIuZ" was expected. The "
- "total size of the received chunks amounts to %"PRIuZ".",
- action, stream->declared_size, stream->received_bytes);
+ "cannot %s - "
+ "Invalid length. %"PRIdZ" was expected. The "
+ "total size of the received chunks amounts to %"PRIdZ".",
+ action, stream->declared_size, stream->received_bytes);
return -1;
}
@@ -1293,7 +1357,7 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
git_hash_final(out, stream->hash_ctx);
- if (odb_freshen(stream->backend->odb, out))
+ if (git_odb__freshen(stream->backend->odb, out))
return 0;
return stream->finalize_write(stream, out);
@@ -1393,23 +1457,36 @@ int git_odb_refresh(struct git_odb *db)
return 0;
}
+int git_odb__error_mismatch(const git_oid *expected, const git_oid *actual)
+{
+ char expected_oid[GIT_OID_HEXSZ + 1], actual_oid[GIT_OID_HEXSZ + 1];
+
+ git_oid_tostr(expected_oid, sizeof(expected_oid), expected);
+ git_oid_tostr(actual_oid, sizeof(actual_oid), actual);
+
+ giterr_set(GITERR_ODB, "object hash mismatch - expected %s but got %s",
+ expected_oid, actual_oid);
+
+ return GIT_EMISMATCH;
+}
+
int git_odb__error_notfound(
const char *message, const git_oid *oid, size_t oid_len)
{
if (oid != NULL) {
char oid_str[GIT_OID_HEXSZ + 1];
git_oid_tostr(oid_str, oid_len+1, oid);
- giterr_set(GITERR_ODB, "Object not found - %s (%.*s)",
- message, oid_len, oid_str);
+ giterr_set(GITERR_ODB, "object not found - %s (%.*s)",
+ message, (int) oid_len, oid_str);
} else
- giterr_set(GITERR_ODB, "Object not found - %s", message);
+ giterr_set(GITERR_ODB, "object not found - %s", message);
return GIT_ENOTFOUND;
}
int git_odb__error_ambiguous(const char *message)
{
- giterr_set(GITERR_ODB, "Ambiguous SHA1 prefix - %s", message);
+ giterr_set(GITERR_ODB, "ambiguous SHA1 prefix - %s", message);
return GIT_EAMBIGUOUS;
}
diff --git a/src/odb.h b/src/odb.h
index 31a9fd1b9..6845b22f1 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_odb_h__
#define INCLUDE_odb_h__
+#include "common.h"
+
#include "git2/odb.h"
#include "git2/oid.h"
#include "git2/types.h"
@@ -20,6 +22,8 @@
#define GIT_OBJECT_DIR_MODE 0777
#define GIT_OBJECT_FILE_MODE 0444
+extern bool git_odb__strict_hash_verification;
+
/* DO NOT EXPORT */
typedef struct {
void *data; /**< Raw, decompressed object data. */
@@ -38,8 +42,25 @@ struct git_odb {
git_refcount rc;
git_vector backends;
git_cache own_cache;
+ unsigned int do_fsync :1;
};
+typedef enum {
+ GIT_ODB_CAP_FROM_OWNER = -1,
+} git_odb_cap_t;
+
+/*
+ * Set the capabilities for the object database.
+ */
+int git_odb__set_caps(git_odb *odb, int caps);
+
+/*
+ * Add the default loose and packed backends for a database.
+ */
+int git_odb__add_default_backends(
+ git_odb *db, const char *objects_dir,
+ bool as_alternates, int alternate_depth);
+
/*
* Hash a git_rawobj internally.
* The `git_rawobj` is supposed to be previously initialized
@@ -79,6 +100,12 @@ int git_odb__hashfd_filtered(
*/
int git_odb__hashlink(git_oid *out, const char *path);
+/**
+ * Generate a GIT_EMISMATCH error for the ODB.
+ */
+int git_odb__error_mismatch(
+ const git_oid *expected, const git_oid *actual);
+
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
@@ -98,6 +125,9 @@ int git_odb__read_header_or_object(
git_odb_object **out, size_t *len_p, git_otype *type_p,
git_odb *db, const git_oid *id);
+/* freshen an entry in the object database */
+int git_odb__freshen(git_odb *db, const git_oid *id);
+
/* fully free the object; internal method, DO NOT EXPORT */
void git_odb_object__free(void *object);
diff --git a/src/odb_loose.c b/src/odb_loose.c
index f312b9c9c..72b47f091 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include <zlib.h>
#include "git2/object.h"
#include "git2/sys/odb_backend.h"
@@ -14,6 +15,7 @@
#include "odb.h"
#include "delta.h"
#include "filebuf.h"
+#include "object.h"
#include "git2/odb_backend.h"
#include "git2/types.h"
@@ -204,6 +206,11 @@ static int start_inflate(z_stream *s, git_buf *obj, void *out, size_t len)
return inflate(s, 0);
}
+static void abort_inflate(z_stream *s)
+{
+ inflateEnd(s);
+}
+
static int finish_inflate(z_stream *s)
{
int status = Z_OK;
@@ -214,7 +221,7 @@ static int finish_inflate(z_stream *s)
inflateEnd(s);
if ((status != Z_STREAM_END) || (s->avail_in != 0)) {
- giterr_set(GITERR_ZLIB, "Failed to finish ZLib inflation. Stream aborted prematurely");
+ giterr_set(GITERR_ZLIB, "failed to finish zlib inflation; stream aborted prematurely");
return -1;
}
@@ -243,7 +250,7 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
zs.avail_in = (uInt)inlen;
if (inflateInit(&zs) < Z_OK) {
- giterr_set(GITERR_ZLIB, "Failed to inflate buffer");
+ giterr_set(GITERR_ZLIB, "failed to inflate buffer");
return -1;
}
@@ -255,7 +262,7 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
if (status != Z_STREAM_END /* || zs.avail_in != 0 */ ||
zs.total_out != outlen)
{
- giterr_set(GITERR_ZLIB, "Failed to inflate buffer. Stream aborted prematurely");
+ giterr_set(GITERR_ZLIB, "failed to inflate buffer; stream aborted prematurely");
return -1;
}
@@ -319,7 +326,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
*/
if ((used = get_binary_object_header(&hdr, obj)) == 0 ||
!git_object_typeisloose(hdr.type)) {
- giterr_set(GITERR_ODB, "Failed to inflate loose object.");
+ giterr_set(GITERR_ODB, "failed to inflate loose object");
return -1;
}
@@ -366,7 +373,8 @@ static int inflate_disk_obj(git_rawobj *out, git_buf *obj)
(used = get_object_header(&hdr, head)) == 0 ||
!git_object_typeisloose(hdr.type))
{
- giterr_set(GITERR_ODB, "Failed to inflate disk object.");
+ abort_inflate(&zs);
+ giterr_set(GITERR_ODB, "failed to inflate disk object");
return -1;
}
@@ -455,7 +463,7 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
|| get_object_header(&header_obj, inflated_buffer) == 0
|| git_object_typeisloose(header_obj.type) == 0)
{
- giterr_set(GITERR_ZLIB, "Failed to read loose object header");
+ giterr_set(GITERR_ZLIB, "failed to read loose object header");
error = -1;
} else {
out->len = header_obj.size;
@@ -838,6 +846,17 @@ static void loose_backend__stream_free(git_odb_stream *_stream)
git__free(stream);
}
+static int filebuf_flags(loose_backend *backend)
+{
+ int flags = GIT_FILEBUF_TEMPORARY |
+ (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT);
+
+ if (backend->fsync_object_files || git_repository__fsync_gitdir)
+ flags |= GIT_FILEBUF_FSYNC;
+
+ return flags;
+}
+
static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type)
{
loose_backend *backend;
@@ -864,9 +883,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
stream->stream.mode = GIT_STREAM_WRONLY;
if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
- git_filebuf_open(&stream->fbuf, tmp_path.ptr,
- GIT_FILEBUF_TEMPORARY |
- (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT),
+ git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0 ||
stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
{
@@ -894,9 +911,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
header_len = git_odb__format_object_header(header, sizeof(header), len, type);
if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
- git_filebuf_open(&fbuf, final_path.ptr,
- GIT_FILEBUF_TEMPORARY |
- (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT),
+ git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0)
{
error = -1;
diff --git a/src/odb_mempack.c b/src/odb_mempack.c
index 594a2784c..0c05f0566 100644
--- a/src/odb_mempack.c
+++ b/src/odb_mempack.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "git2/object.h"
#include "git2/sys/odb_backend.h"
#include "fileops.h"
@@ -18,13 +19,11 @@
#include "git2/types.h"
#include "git2/pack.h"
-GIT__USE_OIDMAP
-
struct memobject {
git_oid oid;
size_t len;
git_otype type;
- char data[];
+ char data[GIT_FLEX_ARRAY];
};
struct memory_packer_db {
@@ -41,7 +40,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
size_t alloc_len;
int rval;
- pos = kh_put(oid, db->objects, oid, &rval);
+ pos = git_oidmap_put(db->objects, oid, &rval);
if (rval < 0)
return -1;
@@ -57,8 +56,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
obj->len = len;
obj->type = type;
- kh_key(db->objects, pos) = &obj->oid;
- kh_val(db->objects, pos) = obj;
+ git_oidmap_set_key_at(db->objects, pos, &obj->oid);
+ git_oidmap_set_value_at(db->objects, pos, obj);
if (type == GIT_OBJ_COMMIT) {
struct memobject **store = git_array_alloc(db->commits);
@@ -72,13 +71,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
static int impl__exists(git_odb_backend *backend, const git_oid *oid)
{
struct memory_packer_db *db = (struct memory_packer_db *)backend;
- khiter_t pos;
- pos = kh_get(oid, db->objects, oid);
- if (pos != kh_end(db->objects))
- return 1;
-
- return 0;
+ return git_oidmap_exists(db->objects, oid);
}
static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
@@ -87,11 +81,11 @@ static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb
struct memobject *obj = NULL;
khiter_t pos;
- pos = kh_get(oid, db->objects, oid);
- if (pos == kh_end(db->objects))
+ pos = git_oidmap_lookup_index(db->objects, oid);
+ if (!git_oidmap_valid_index(db->objects, pos))
return GIT_ENOTFOUND;
- obj = kh_val(db->objects, pos);
+ obj = git_oidmap_value_at(db->objects, pos);
*len_p = obj->len;
*type_p = obj->type;
@@ -108,11 +102,11 @@ static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *
struct memobject *obj = NULL;
khiter_t pos;
- pos = kh_get(oid, db->objects, oid);
- if (pos == kh_end(db->objects))
+ pos = git_oidmap_lookup_index(db->objects, oid);
+ if (!git_oidmap_valid_index(db->objects, pos))
return GIT_ENOTFOUND;
- obj = kh_val(db->objects, pos);
+ obj = git_oidmap_value_at(db->objects, pos);
*len_p = obj->len;
*type_p = obj->type;
@@ -149,7 +143,7 @@ void git_mempack_reset(git_odb_backend *_backend)
struct memory_packer_db *db = (struct memory_packer_db *)_backend;
struct memobject *object = NULL;
- kh_foreach_value(db->objects, object, {
+ git_oidmap_foreach_value(db->objects, object, {
git__free(object);
});
@@ -177,6 +171,7 @@ int git_mempack_new(git_odb_backend **out)
db->objects = git_oidmap_alloc();
+ db->parent.version = GIT_ODB_BACKEND_VERSION;
db->parent.read = &impl__read;
db->parent.write = &impl__write;
db->parent.read_header = &impl__read_header;
diff --git a/src/odb_pack.c b/src/odb_pack.c
index b80d0337a..20aff5386 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include <zlib.h>
#include "git2/repository.h"
#include "git2/indexer.h"
@@ -428,7 +429,7 @@ static int pack_backend__read_prefix(
git_oid_cpy(out_oid, short_oid);
} else {
struct git_pack_entry e;
- git_rawobj raw;
+ git_rawobj raw = {NULL};
if ((error = pack_entry_find_prefix(
&e, (struct pack_backend *)backend, short_oid, len)) == 0 &&
diff --git a/src/offmap.c b/src/offmap.c
new file mode 100644
index 000000000..ab6649697
--- /dev/null
+++ b/src/offmap.c
@@ -0,0 +1,83 @@
+/*
+ * 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 "offmap.h"
+
+__KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal)
+
+git_offmap *git_offmap_alloc(void)
+{
+ return kh_init(off);
+}
+
+void git_offmap_free(git_offmap *map)
+{
+ kh_destroy(off, map);
+}
+
+void git_offmap_clear(git_offmap *map)
+{
+ kh_clear(off, map);
+}
+
+size_t git_offmap_num_entries(git_offmap *map)
+{
+ return kh_size(map);
+}
+
+size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key)
+{
+ return kh_get(off, map, key);
+}
+
+int git_offmap_valid_index(git_offmap *map, size_t idx)
+{
+ return idx != kh_end(map);
+}
+
+int git_offmap_exists(git_offmap *map, const git_off_t key)
+{
+ return kh_get(off, map, key) != kh_end(map);
+}
+
+void *git_offmap_value_at(git_offmap *map, size_t idx)
+{
+ return kh_val(map, idx);
+}
+
+void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value)
+{
+ kh_val(map, idx) = value;
+}
+
+void git_offmap_delete_at(git_offmap *map, size_t idx)
+{
+ kh_del(off, map, idx);
+}
+
+int git_offmap_put(git_offmap *map, const git_off_t key, int *err)
+{
+ return kh_put(off, map, key, err);
+}
+
+void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval)
+{
+ khiter_t idx = kh_put(off, map, key, rval);
+
+ if ((*rval) >= 0) {
+ if ((*rval) == 0)
+ kh_key(map, idx) = key;
+ kh_val(map, idx) = value;
+ }
+}
+
+void git_offmap_delete(git_offmap *map, const git_off_t key)
+{
+ khiter_t idx = git_offmap_lookup_index(map, key);
+ if (git_offmap_valid_index(map, idx))
+ git_offmap_delete_at(map, idx);
+}
diff --git a/src/offmap.h b/src/offmap.h
index 0d0e51272..0b0896b8f 100644
--- a/src/offmap.h
+++ b/src/offmap.h
@@ -8,6 +8,7 @@
#define INCLUDE_offmap_h__
#include "common.h"
+
#include "git2/types.h"
#define kmalloc git__malloc
@@ -20,45 +21,24 @@
__KHASH_TYPE(off, git_off_t, void *)
typedef khash_t(off) git_offmap;
-#define GIT__USE_OFFMAP \
- __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal)
-
-#define git_offmap_alloc() kh_init(off)
-#define git_offmap_free(h) kh_destroy(off, h), h = NULL
-#define git_offmap_clear(h) kh_clear(off, h)
-
-#define git_offmap_num_entries(h) kh_size(h)
-
-#define git_offmap_lookup_index(h, k) kh_get(off, h, k)
-#define git_offmap_valid_index(h, idx) (idx != kh_end(h))
+git_offmap *git_offmap_alloc(void);
+void git_offmap_free(git_offmap *map);
+void git_offmap_clear(git_offmap *map);
-#define git_offmap_exists(h, k) (kh_get(off, h, k) != kh_end(h))
+size_t git_offmap_num_entries(git_offmap *map);
-#define git_offmap_value_at(h, idx) kh_val(h, idx)
-#define git_offmap_set_value_at(h, idx, v) kh_val(h, idx) = v
-#define git_offmap_delete_at(h, idx) kh_del(off, h, idx)
+size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key);
+int git_offmap_valid_index(git_offmap *map, size_t idx);
-#define git_offmap_insert(h, key, val, rval) do { \
- khiter_t __pos = kh_put(off, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) kh_key(h, __pos) = key; \
- kh_val(h, __pos) = val; \
- } } while (0)
+int git_offmap_exists(git_offmap *map, const git_off_t key);
-#define git_offmap_insert2(h, key, val, oldv, rval) do { \
- khiter_t __pos = kh_put(off, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) { \
- oldv = kh_val(h, __pos); \
- kh_key(h, __pos) = key; \
- } else { oldv = NULL; } \
- kh_val(h, __pos) = val; \
- } } while (0)
+void *git_offmap_value_at(git_offmap *map, size_t idx);
+void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value);
+void git_offmap_delete_at(git_offmap *map, size_t idx);
-#define git_offmap_delete(h, key) do { \
- khiter_t __pos = git_offmap_lookup_index(h, key); \
- if (git_offmap_valid_index(h, __pos)) \
- git_offmap_delete_at(h, __pos); } while (0)
+int git_offmap_put(git_offmap *map, const git_off_t key, int *err);
+void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval);
+void git_offmap_delete(git_offmap *map, const git_off_t key);
#define git_offmap_foreach kh_foreach
#define git_offmap_foreach_value kh_foreach_value
diff --git a/src/oid.c b/src/oid.c
index 9fe2ebb65..0c63abb2e 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "oid.h"
+
#include "git2/oid.h"
#include "repository.h"
#include "global.h"
@@ -16,7 +17,7 @@ static char to_hex[] = "0123456789abcdef";
static int oid_error_invalid(const char *msg)
{
- giterr_set(GITERR_INVALID, "Unable to parse OID - %s", msg);
+ giterr_set(GITERR_INVALID, "unable to parse OID - %s", msg);
return -1;
}
@@ -380,7 +381,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
node_index idx;
if (os->full) {
- giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
+ giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full");
return -1;
}
@@ -395,7 +396,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
trie_node *node;
if (c == -1) {
- giterr_set(GITERR_INVALID, "Unable to shorten OID - invalid hex value");
+ giterr_set(GITERR_INVALID, "unable to shorten OID - invalid hex value");
return -1;
}
@@ -410,7 +411,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]);
if (node == NULL) {
if (os->full)
- giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
+ giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full");
return -1;
}
}
@@ -418,7 +419,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
if (node->children[c] == 0) {
if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL) {
if (os->full)
- giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full");
+ giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full");
return -1;
}
break;
diff --git a/src/oid.h b/src/oid.h
index 922a2a347..84231ffca 100644
--- a/src/oid.h
+++ b/src/oid.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_oid_h__
#define INCLUDE_oid_h__
+#include "common.h"
+
#include "git2/oid.h"
/**
@@ -22,14 +24,7 @@ char *git_oid_allocfmt(const git_oid *id);
GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
{
- int i;
-
- for (i = 0; i < GIT_OID_RAWSZ; i++, sha1++, sha2++) {
- if (*sha1 != *sha2)
- return *sha1 - *sha2;
- }
-
- return 0;
+ return memcmp(sha1, sha2, GIT_OID_RAWSZ);
}
/*
diff --git a/src/oidarray.c b/src/oidarray.c
index 1d51a2958..fda3b638d 100644
--- a/src/oidarray.c
+++ b/src/oidarray.c
@@ -5,8 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "git2/oidarray.h"
#include "oidarray.h"
+
+#include "git2/oidarray.h"
#include "array.h"
void git_oidarray_free(git_oidarray *arr)
diff --git a/src/oidarray.h b/src/oidarray.h
index a7215ae6c..f051a0ec4 100644
--- a/src/oidarray.h
+++ b/src/oidarray.h
@@ -8,6 +8,7 @@
#define INCLUDE_oidarray_h__
#include "common.h"
+
#include "git2/oidarray.h"
#include "array.h"
diff --git a/src/oidmap.c b/src/oidmap.c
new file mode 100644
index 000000000..5f156a18e
--- /dev/null
+++ b/src/oidmap.c
@@ -0,0 +1,105 @@
+/*
+ * 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 "oidmap.h"
+
+GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
+{
+ khint_t h;
+ memcpy(&h, oid, sizeof(khint_t));
+ return h;
+}
+
+__KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal)
+
+git_oidmap *git_oidmap_alloc()
+{
+ return kh_init(oid);
+}
+
+void git_oidmap_free(git_oidmap *map)
+{
+ kh_destroy(oid, map);
+}
+
+void git_oidmap_clear(git_oidmap *map)
+{
+ kh_clear(oid, map);
+}
+
+size_t git_oidmap_size(git_oidmap *map)
+{
+ return kh_size(map);
+}
+
+size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key)
+{
+ return kh_get(oid, map, key);
+}
+
+int git_oidmap_valid_index(git_oidmap *map, size_t idx)
+{
+ return idx != kh_end(map);
+}
+
+int git_oidmap_exists(git_oidmap *map, const git_oid *key)
+{
+ return kh_get(oid, map, key) != kh_end(map);
+}
+
+int git_oidmap_has_data(git_oidmap *map, size_t idx)
+{
+ return kh_exist(map, idx);
+}
+
+const git_oid *git_oidmap_key(git_oidmap *map, size_t idx)
+{
+ return kh_key(map, idx);
+}
+
+void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key)
+{
+ kh_key(map, idx) = key;
+}
+
+void *git_oidmap_value_at(git_oidmap *map, size_t idx)
+{
+ return kh_val(map, idx);
+}
+
+void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value)
+{
+ kh_val(map, idx) = value;
+}
+
+void git_oidmap_delete_at(git_oidmap *map, size_t idx)
+{
+ kh_del(oid, map, idx);
+}
+
+int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err)
+{
+ return kh_put(oid, map, key, err);
+}
+
+void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval)
+{
+ khiter_t idx = kh_put(oid, map, key, rval);
+
+ if ((*rval) >= 0) {
+ if ((*rval) == 0)
+ kh_key(map, idx) = key;
+ kh_val(map, idx) = value;
+ }
+}
+
+void git_oidmap_delete(git_oidmap *map, const git_oid *key)
+{
+ khiter_t idx = git_oidmap_lookup_index(map, key);
+ if (git_oidmap_valid_index(map, idx))
+ git_oidmap_delete_at(map, idx);
+}
diff --git a/src/oidmap.h b/src/oidmap.h
index 2cf208f53..49f129e93 100644
--- a/src/oidmap.h
+++ b/src/oidmap.h
@@ -8,6 +8,7 @@
#define INCLUDE_oidmap_h__
#include "common.h"
+
#include "git2/oid.h"
#define kmalloc git__malloc
@@ -20,35 +21,31 @@
__KHASH_TYPE(oid, const git_oid *, void *)
typedef khash_t(oid) git_oidmap;
-GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
-{
- khint_t h;
- memcpy(&h, oid, sizeof(khint_t));
- return h;
-}
+git_oidmap *git_oidmap_alloc(void);
+void git_oidmap_free(git_oidmap *map);
+void git_oidmap_clear(git_oidmap *map);
-#define GIT__USE_OIDMAP \
- __KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal)
+size_t git_oidmap_size(git_oidmap *map);
-#define git_oidmap_alloc() kh_init(oid)
-#define git_oidmap_free(h) kh_destroy(oid,h), h = NULL
+size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key);
+int git_oidmap_valid_index(git_oidmap *map, size_t idx);
-#define git_oidmap_lookup_index(h, k) kh_get(oid, h, k)
-#define git_oidmap_valid_index(h, idx) (idx != kh_end(h))
+int git_oidmap_exists(git_oidmap *map, const git_oid *key);
+int git_oidmap_has_data(git_oidmap *map, size_t idx);
-#define git_oidmap_value_at(h, idx) kh_val(h, idx)
+const git_oid *git_oidmap_key(git_oidmap *map, size_t idx);
+void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key);
+void *git_oidmap_value_at(git_oidmap *map, size_t idx);
+void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value);
+void git_oidmap_delete_at(git_oidmap *map, size_t idx);
-#define git_oidmap_insert(h, key, val, rval) do { \
- khiter_t __pos = kh_put(oid, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) kh_key(h, __pos) = key; \
- kh_val(h, __pos) = val; \
- } } while (0)
+int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err);
+void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval);
+void git_oidmap_delete(git_oidmap *map, const git_oid *key);
#define git_oidmap_foreach_value kh_foreach_value
-#define git_oidmap_size(h) kh_size(h)
-
-#define git_oidmap_clear(h) kh_clear(oid, h)
+#define git_oidmap_begin kh_begin
+#define git_oidmap_end kh_end
#endif
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index b8ab21fef..3860c4f3c 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "openssl_stream.h"
+
#ifdef GIT_OPENSSL
#include <ctype.h>
@@ -36,7 +38,7 @@ SSL_CTX *git__ssl_ctx;
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
-#ifdef GIT_THREADS
+#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
static git_mutex *openssl_locks;
@@ -65,11 +67,14 @@ static void shutdown_ssl_locking(void)
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
- git_mutex_free(openssl_locks);
+ git_mutex_free(&openssl_locks[i]);
git__free(openssl_locks);
}
-#endif /* GIT_THREADS */
+#endif /* GIT_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
+
+static BIO_METHOD *git_stream_bio_method;
+static int init_bio_method(void);
/**
* This function aims to clean-up the SSL context which
@@ -77,6 +82,11 @@ static void shutdown_ssl_locking(void)
*/
static void shutdown_ssl(void)
{
+ if (git_stream_bio_method) {
+ BIO_meth_free(git_stream_bio_method);
+ git_stream_bio_method = NULL;
+ }
+
if (git__ssl_ctx) {
SSL_CTX_free(git__ssl_ctx);
git__ssl_ctx = NULL;
@@ -94,8 +104,13 @@ int git_openssl_stream_global_init(void)
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
+#else
+ OPENSSL_init_ssl(0, NULL);
+#endif
+
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
@@ -121,6 +136,13 @@ int git_openssl_stream_global_init(void)
git__ssl_ctx = NULL;
return -1;
}
+
+ if (init_bio_method() < 0) {
+ SSL_CTX_free(git__ssl_ctx);
+ git__ssl_ctx = NULL;
+ return -1;
+ }
+
#endif
git__on_shutdown(shutdown_ssl);
@@ -130,7 +152,7 @@ int git_openssl_stream_global_init(void)
int git_openssl_set_locking(void)
{
-#ifdef GIT_THREADS
+#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
int num_locks, i;
num_locks = CRYPTO_num_locks();
@@ -147,8 +169,10 @@ int git_openssl_set_locking(void)
CRYPTO_set_locking_callback(openssl_locking_function);
git__on_shutdown(shutdown_ssl_locking);
return 0;
+#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
+ return 0;
#else
- giterr_set(GITERR_THREAD, "libgit2 as not built with threads");
+ giterr_set(GITERR_THREAD, "libgit2 was not built with threads");
return -1;
#endif
}
@@ -156,10 +180,8 @@ int git_openssl_set_locking(void)
static int bio_create(BIO *b)
{
- b->init = 1;
- b->num = 0;
- b->ptr = NULL;
- b->flags = 0;
+ BIO_set_init(b, 1);
+ BIO_set_data(b, NULL);
return 1;
}
@@ -169,23 +191,22 @@ static int bio_destroy(BIO *b)
if (!b)
return 0;
- b->init = 0;
- b->num = 0;
- b->ptr = NULL;
- b->flags = 0;
+ BIO_set_data(b, NULL);
return 1;
}
static int bio_read(BIO *b, char *buf, int len)
{
- git_stream *io = (git_stream *) b->ptr;
+ git_stream *io = (git_stream *) BIO_get_data(b);
+
return (int) git_stream_read(io, buf, len);
}
static int bio_write(BIO *b, const char *buf, int len)
{
- git_stream *io = (git_stream *) b->ptr;
+ git_stream *io = (git_stream *) BIO_get_data(b);
+
return (int) git_stream_write(io, buf, len, 0);
}
@@ -214,17 +235,22 @@ static int bio_puts(BIO *b, const char *str)
return bio_write(b, str, strlen(str));
}
-static BIO_METHOD git_stream_bio_method = {
- BIO_TYPE_SOURCE_SINK,
- "git_stream",
- bio_write,
- bio_read,
- bio_puts,
- bio_gets,
- bio_ctrl,
- bio_create,
- bio_destroy
-};
+static int init_bio_method(void)
+{
+ /* Set up the BIO_METHOD we use for wrapping our own stream implementations */
+ git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
+ GITERR_CHECK_ALLOC(git_stream_bio_method);
+
+ BIO_meth_set_write(git_stream_bio_method, bio_write);
+ BIO_meth_set_read(git_stream_bio_method, bio_read);
+ BIO_meth_set_puts(git_stream_bio_method, bio_puts);
+ BIO_meth_set_gets(git_stream_bio_method, bio_gets);
+ BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
+ BIO_meth_set_create(git_stream_bio_method, bio_create);
+ BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
+
+ return 0;
+}
static int ssl_set_error(SSL *ssl, int error)
{
@@ -239,10 +265,10 @@ static int ssl_set_error(SSL *ssl, int error)
switch (err) {
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
- giterr_set(GITERR_NET, "SSL error: connection failure\n");
+ giterr_set(GITERR_NET, "SSL error: connection failure");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
- giterr_set(GITERR_NET, "SSL error: x509 error\n");
+ giterr_set(GITERR_NET, "SSL error: x509 error");
break;
case SSL_ERROR_SYSCALL:
e = ERR_get_error();
@@ -309,7 +335,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
int i = -1,j;
if (SSL_get_verify_result(ssl) != X509_V_OK) {
- giterr_set(GITERR_SSL, "The SSL certificate is invalid");
+ giterr_set(GITERR_SSL, "the SSL certificate is invalid");
return GIT_ECERTIFICATE;
}
@@ -339,7 +365,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
num = sk_GENERAL_NAME_num(alts);
for (i = 0; i < num && matched != 1; i++) {
const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i);
- const char *name = (char *) ASN1_STRING_data(gn->d.ia5);
+ const char *name = (char *) ASN1_STRING_get0_data(gn->d.ia5);
size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5);
/* Skip any names of a type we're not looking for */
@@ -394,7 +420,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
if (size > 0) {
peer_cn = OPENSSL_malloc(size + 1);
GITERR_CHECK_ALLOC(peer_cn);
- memcpy(peer_cn, ASN1_STRING_data(str), size);
+ memcpy(peer_cn, ASN1_STRING_get0_data(str), size);
peer_cn[size] = '\0';
} else {
goto cert_fail_name;
@@ -445,11 +471,12 @@ int openssl_connect(git_stream *stream)
st->connected = true;
- bio = BIO_new(&git_stream_bio_method);
+ bio = BIO_new(git_stream_bio_method);
GITERR_CHECK_ALLOC(bio);
- bio->ptr = st->io;
+ BIO_set_data(bio, st->io);
SSL_set_bio(st->ssl, bio, bio);
+
/* specify the host in case SNI is needed */
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_set_tlsext_host_name(st->ssl, st->host);
diff --git a/src/openssl_stream.h b/src/openssl_stream.h
index 82b5110c4..2dcfcc929 100644
--- a/src/openssl_stream.h
+++ b/src/openssl_stream.h
@@ -7,10 +7,118 @@
#ifndef INCLUDE_openssl_stream_h__
#define INCLUDE_openssl_stream_h__
+#include "common.h"
+
#include "git2/sys/stream.h"
extern int git_openssl_stream_global_init(void);
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
+/*
+ * OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
+ * which do not exist in previous versions. We define these inline functions so
+ * we can program against the interface instead of littering the implementation
+ * with ifdefs.
+ */
+#ifdef GIT_OPENSSL
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+
+
+
+# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
+{
+ BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
+ if (!meth) {
+ return NULL;
+ }
+
+ meth->type = type;
+ meth->name = name;
+
+ return meth;
+}
+
+GIT_INLINE(void) BIO_meth_free(BIO_METHOD *biom)
+{
+ git__free(biom);
+}
+
+GIT_INLINE(int) BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
+{
+ biom->bwrite = write;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
+{
+ biom->bread = read;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
+{
+ biom->bputs = puts;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
+
+{
+ biom->bgets = gets;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
+{
+ biom->ctrl = ctrl;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
+{
+ biom->create = create;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
+{
+ biom->destroy = destroy;
+ return 1;
+}
+
+GIT_INLINE(int) BIO_get_new_index(void)
+{
+ /* This exists as of 1.1 so before we'd just have 0 */
+ return 0;
+}
+
+GIT_INLINE(void) BIO_set_init(BIO *b, int init)
+{
+ b->init = init;
+}
+
+GIT_INLINE(void) BIO_set_data(BIO *a, void *ptr)
+{
+ a->ptr = ptr;
+}
+
+GIT_INLINE(void*) BIO_get_data(BIO *a)
+{
+ return a->ptr;
+}
+
+GIT_INLINE(const unsigned char *) ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+ return ASN1_STRING_data((ASN1_STRING *)x);
+}
+
+# endif // OpenSSL < 1.1
+#endif // GIT_OPENSSL
+
#endif
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 9f62322f7..ef272e8f5 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -41,8 +41,6 @@ struct pack_write_context {
git_transfer_progress *stats;
};
-GIT__USE_OIDMAP
-
#ifdef GIT_THREADS
#define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \
@@ -162,7 +160,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
git_mutex_init(&pb->progress_mutex) ||
git_cond_init(&pb->progress_cond))
{
- giterr_set(GITERR_OS, "Failed to initialize packbuilder mutex");
+ giterr_set(GITERR_OS, "failed to initialize packbuilder mutex");
goto on_error;
}
@@ -197,10 +195,10 @@ static void rehash(git_packbuilder *pb)
size_t i;
int ret;
- kh_clear(oid, pb->object_ix);
+ git_oidmap_clear(pb->object_ix);
for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) {
- pos = kh_put(oid, pb->object_ix, &po->id, &ret);
- kh_value(pb->object_ix, pos) = po;
+ pos = git_oidmap_put(pb->object_ix, &po->id, &ret);
+ git_oidmap_set_value_at(pb->object_ix, pos, po);
}
}
@@ -216,8 +214,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
/* If the object already exists in the hash table, then we don't
* have any work to do */
- pos = kh_get(oid, pb->object_ix, oid);
- if (pos != kh_end(pb->object_ix))
+ if (git_oidmap_exists(pb->object_ix, oid))
return 0;
if (pb->nr_objects >= pb->nr_alloc) {
@@ -225,7 +222,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
GITERR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2);
if (!git__is_uint32(newsize)) {
- giterr_set(GITERR_NOMEMORY, "Packfile too large to fit in memory.");
+ giterr_set(GITERR_NOMEMORY, "packfile too large to fit in memory.");
return -1;
}
@@ -247,13 +244,13 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
git_oid_cpy(&po->id, oid);
po->hash = name_hash(name);
- pos = kh_put(oid, pb->object_ix, &po->id, &ret);
+ pos = git_oidmap_put(pb->object_ix, &po->id, &ret);
if (ret < 0) {
giterr_set_oom();
return ret;
}
assert(ret != 0);
- kh_value(pb->object_ix, pos) = po;
+ git_oidmap_set_value_at(pb->object_ix, pos, po);
pb->done = false;
@@ -298,7 +295,7 @@ static int get_delta(void **out, git_odb *odb, git_pobject *po)
goto on_error;
if (error == GIT_EBUFS || delta_size != po->delta_size) {
- giterr_set(GITERR_INVALID, "Delta size changed");
+ giterr_set(GITERR_INVALID, "delta size changed");
goto on_error;
}
@@ -517,11 +514,11 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
GIT_UNUSED(name);
- pos = kh_get(oid, pb->object_ix, oid);
- if (pos == kh_end(pb->object_ix))
+ pos = git_oidmap_lookup_index(pb->object_ix, oid);
+ if (!git_oidmap_valid_index(pb->object_ix, pos))
return 0;
- po = kh_value(pb->object_ix, pos);
+ po = git_oidmap_value_at(pb->object_ix, pos);
po->tagged = 1;
/* TODO: peel objects */
@@ -808,7 +805,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
if (sz != trg_size) {
giterr_set(GITERR_INVALID,
- "Inconsistent target object length");
+ "inconsistent target object length");
return -1;
}
@@ -830,7 +827,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
if (sz != src_size) {
giterr_set(GITERR_INVALID,
- "Inconsistent source object length");
+ "inconsistent source object length");
return -1;
}
@@ -1388,6 +1385,7 @@ int git_packbuilder_write(
git_indexer *indexer;
git_transfer_progress stats;
struct pack_write_context ctx;
+ int t;
PREPARE_PACK;
@@ -1395,6 +1393,9 @@ int git_packbuilder_write(
&indexer, path, mode, pb->odb, progress_cb, progress_cb_payload) < 0)
return -1;
+ if (!git_repository__cvar(&t, pb->repo, GIT_CVAR_FSYNCOBJECTFILES) && t)
+ git_indexer__set_fsync(indexer, 1);
+
ctx.indexer = indexer;
ctx.stats = &stats;
@@ -1541,7 +1542,7 @@ static int retrieve_object(git_walk_object **out, git_packbuilder *pb, const git
if ((error = lookup_walk_object(&obj, pb, id)) < 0)
return error;
- git_oidmap_insert(pb->walk_objects, &obj->id, obj, error);
+ git_oidmap_insert(pb->walk_objects, &obj->id, obj, &error);
}
*out = obj;
@@ -1738,7 +1739,7 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
if (error == GIT_ITEROVER)
error = 0;
- return 0;
+ return error;
}
int git_packbuilder_set_callbacks(git_packbuilder *pb, git_packbuilder_progress progress_cb, void *progress_cb_payload)
diff --git a/src/pack-objects.h b/src/pack-objects.h
index 5a84f4158..e1e0ee3c8 100644
--- a/src/pack-objects.h
+++ b/src/pack-objects.h
@@ -16,6 +16,7 @@
#include "netops.h"
#include "zstream.h"
#include "pool.h"
+#include "indexer.h"
#include "git2/oid.h"
#include "git2/pack.h"
diff --git a/src/pack.c b/src/pack.c
index 310f00fa3..7fd95c905 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "odb.h"
#include "pack.h"
+
+#include "odb.h"
#include "delta.h"
#include "sha1_lookup.h"
#include "mwindow.h"
@@ -16,9 +16,6 @@
#include <zlib.h>
-GIT__USE_OFFMAP
-GIT__USE_OIDMAP
-
static int packfile_open(struct git_pack_file *p);
static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n);
static int packfile_unpack_compressed(
@@ -45,7 +42,7 @@ static int pack_entry_find_offset(
static int packfile_error(const char *message)
{
- giterr_set(GITERR_ODB, "Invalid pack file - %s", message);
+ giterr_set(GITERR_ODB, "invalid pack file - %s", message);
return -1;
}
@@ -78,13 +75,12 @@ static void free_cache_object(void *o)
static void cache_free(git_pack_cache *cache)
{
- khiter_t k;
+ git_pack_cache_entry *entry;
if (cache->entries) {
- for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
- if (kh_exist(cache->entries, k))
- free_cache_object(kh_value(cache->entries, k));
- }
+ git_offmap_foreach_value(cache->entries, entry, {
+ free_cache_object(entry);
+ });
git_offmap_free(cache->entries);
cache->entries = NULL;
@@ -99,7 +95,7 @@ static int cache_init(git_pack_cache *cache)
cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT;
if (git_mutex_init(&cache->lock)) {
- giterr_set(GITERR_OS, "Failed to initialize pack cache mutex");
+ giterr_set(GITERR_OS, "failed to initialize pack cache mutex");
git__free(cache->entries);
cache->entries = NULL;
@@ -118,9 +114,9 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset)
if (git_mutex_lock(&cache->lock) < 0)
return NULL;
- k = kh_get(off, cache->entries, offset);
- if (k != kh_end(cache->entries)) { /* found it */
- entry = kh_value(cache->entries, k);
+ k = git_offmap_lookup_index(cache->entries, offset);
+ if (git_offmap_valid_index(cache->entries, k)) { /* found it */
+ entry = git_offmap_value_at(cache->entries, k);
git_atomic_inc(&entry->refcount);
entry->last_usage = cache->use_ctr++;
}
@@ -132,21 +128,16 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset)
/* Run with the cache lock held */
static void free_lowest_entry(git_pack_cache *cache)
{
+ git_off_t offset;
git_pack_cache_entry *entry;
- khiter_t k;
-
- for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) {
- if (!kh_exist(cache->entries, k))
- continue;
-
- entry = kh_value(cache->entries, k);
+ git_offmap_foreach(cache->entries, offset, entry, {
if (entry && entry->refcount.val == 0) {
cache->memory_used -= entry->raw.len;
- kh_del(off, cache->entries, k);
+ git_offmap_delete(cache->entries, offset);
free_cache_object(entry);
}
- }
+ });
}
static int cache_add(
@@ -170,14 +161,14 @@ static int cache_add(
return -1;
}
/* Add it to the cache if nobody else has */
- exists = kh_get(off, cache->entries, offset) != kh_end(cache->entries);
+ exists = git_offmap_exists(cache->entries, offset);
if (!exists) {
while (cache->memory_used + base->len > cache->memory_limit)
free_lowest_entry(cache);
- k = kh_put(off, cache->entries, offset, &error);
+ k = git_offmap_put(cache->entries, offset, &error);
assert(error != 0);
- kh_value(cache->entries, k) = entry;
+ git_offmap_set_value_at(cache->entries, k, entry);
cache->memory_used += entry->raw.len;
*cached_out = entry;
@@ -226,7 +217,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
if (p_fstat(fd, &st) < 0) {
p_close(fd);
- giterr_set(GITERR_OS, "Unable to stat pack index '%s'", path);
+ giterr_set(GITERR_OS, "unable to stat pack index '%s'", path);
return -1;
}
@@ -235,7 +226,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p)
(idx_size = (size_t)st.st_size) < 4 * 256 + 20 + 20)
{
p_close(fd);
- giterr_set(GITERR_ODB, "Invalid pack index '%s'", path);
+ giterr_set(GITERR_ODB, "invalid pack index '%s'", path);
return -1;
}
@@ -321,7 +312,7 @@ static int pack_index_open(struct git_pack_file *p)
{
int error = 0;
size_t name_len;
- git_buf idx_name = GIT_BUF_INIT;
+ git_buf idx_name;
if (p->index_version > -1)
return 0;
@@ -329,11 +320,13 @@ static int pack_index_open(struct git_pack_file *p)
name_len = strlen(p->pack_name);
assert(name_len > strlen(".pack")); /* checked by git_pack_file alloc */
- git_buf_grow(&idx_name, name_len);
+ if (git_buf_init(&idx_name, name_len) < 0)
+ return -1;
+
git_buf_put(&idx_name, p->pack_name, name_len - strlen(".pack"));
git_buf_puts(&idx_name, ".idx");
if (git_buf_oom(&idx_name)) {
- giterr_set_oom();
+ git_buf_free(&idx_name);
return -1;
}
@@ -509,8 +502,10 @@ int git_packfile_resolve_header(
git_packfile_stream_free(&stream);
if (error < 0)
return error;
- } else
+ } else {
*size_p = size;
+ base_offset = 0;
+ }
while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
curpos = base_offset;
@@ -757,8 +752,11 @@ int git_packfile_unpack(
}
cleanup:
- if (error < 0)
+ if (error < 0) {
git__free(obj->data);
+ if (cached)
+ git_atomic_dec(&cached->refcount);
+ }
if (elem)
*obj_offset = curpos;
@@ -957,10 +955,10 @@ git_off_t get_delta_base(
git_oid oid;
git_oid_fromraw(&oid, base_info);
- k = kh_get(oid, p->idx_cache, &oid);
- if (k != kh_end(p->idx_cache)) {
+ k = git_oidmap_lookup_index(p->idx_cache, &oid);
+ if (git_oidmap_valid_index(p->idx_cache, k)) {
*curpos += 20;
- return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset;
+ return ((struct git_pack_entry *)git_oidmap_value_at(p->idx_cache, k))->offset;
} else {
/* If we're building an index, don't try to find the pack
* entry; we just haven't seen it yet. We'll make
@@ -986,6 +984,18 @@ git_off_t get_delta_base(
*
***********************************************************/
+void git_packfile_close(struct git_pack_file *p, bool unlink_packfile)
+{
+ if (p->mwf.fd >= 0) {
+ git_mwindow_free_all_locked(&p->mwf);
+ p_close(p->mwf.fd);
+ p->mwf.fd = -1;
+ }
+
+ if (unlink_packfile)
+ p_unlink(p->pack_name);
+}
+
void git_packfile_free(struct git_pack_file *p)
{
if (!p)
@@ -993,10 +1003,7 @@ void git_packfile_free(struct git_pack_file *p)
cache_free(&p->bases);
- if (p->mwf.fd >= 0) {
- git_mwindow_free_all_locked(&p->mwf);
- p_close(p->mwf.fd);
- }
+ git_packfile_close(p, false);
pack_index_free(p);
@@ -1077,7 +1084,7 @@ static int packfile_open(struct git_pack_file *p)
return 0;
cleanup:
- giterr_set(GITERR_OS, "Invalid packfile '%s'", p->pack_name);
+ giterr_set(GITERR_OS, "invalid packfile '%s'", p->pack_name);
if (p->mwf.fd >= 0)
p_close(p->mwf.fd);
@@ -1153,7 +1160,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
p->index_version = -1;
if (git_mutex_init(&p->lock)) {
- giterr_set(GITERR_OS, "Failed to initialize packfile mutex");
+ giterr_set(GITERR_OS, "failed to initialize packfile mutex");
git__free(p);
return -1;
}
@@ -1268,8 +1275,8 @@ static int pack_entry_find_offset(
const git_oid *short_oid,
size_t len)
{
- const uint32_t *level1_ofs = p->index_map.data;
- const unsigned char *index = p->index_map.data;
+ const uint32_t *level1_ofs;
+ const unsigned char *index;
unsigned hi, lo, stride;
int pos, found = 0;
git_off_t offset;
@@ -1283,11 +1290,11 @@ static int pack_entry_find_offset(
if ((error = pack_index_open(p)) < 0)
return error;
assert(p->index_map.data);
-
- index = p->index_map.data;
- level1_ofs = p->index_map.data;
}
+ index = p->index_map.data;
+ level1_ofs = p->index_map.data;
+
if (p->index_version > 1) {
level1_ofs += 2;
index += 8;
@@ -1309,11 +1316,7 @@ static int pack_entry_find_offset(
short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects);
#endif
-#ifdef GIT_USE_LOOKUP
- pos = sha1_entry_pos(index, stride, 0, lo, hi, p->num_objects, short_oid->id);
-#else
pos = sha1_position(index, stride, lo, hi, short_oid->id);
-#endif
if (pos >= 0) {
/* An object matching exactly the oid was found */
diff --git a/src/pack.h b/src/pack.h
index 5302db5b7..c0ca74f14 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -8,11 +8,12 @@
#ifndef INCLUDE_pack_h__
#define INCLUDE_pack_h__
+#include "common.h"
+
#include <zlib.h>
#include "git2/oid.h"
-#include "common.h"
#include "map.h"
#include "mwindow.h"
#include "odb.h"
@@ -149,6 +150,7 @@ git_off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
git_off_t *curpos, git_otype type,
git_off_t delta_obj_offset);
+void git_packfile_close(struct git_pack_file *p, bool unlink_packfile);
void git_packfile_free(struct git_pack_file *p);
int git_packfile_alloc(struct git_pack_file **pack_out, const char *path);
diff --git a/src/patch.c b/src/patch.c
index 9b7c9c64c..5e329518d 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -1,7 +1,14 @@
-#include "git2/patch.h"
-#include "diff.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 "patch.h"
+#include "git2/patch.h"
+#include "diff.h"
int git_patch__invoke_callbacks(
git_patch *patch,
diff --git a/src/patch.h b/src/patch.h
index 525ae7007..156d1310e 100644
--- a/src/patch.h
+++ b/src/patch.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_patch_h__
#define INCLUDE_patch_h__
+#include "common.h"
+
#include "git2/patch.h"
#include "array.h"
diff --git a/src/patch_generate.c b/src/patch_generate.c
index a13f2ff5d..3995c56be 100644
--- a/src/patch_generate.c
+++ b/src/patch_generate.c
@@ -4,13 +4,14 @@
* 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 "common.h"
+
+#include "patch_generate.h"
+
#include "git2/blob.h"
#include "diff.h"
#include "diff_generate.h"
#include "diff_file.h"
#include "diff_driver.h"
-#include "patch_generate.h"
#include "diff_xdiff.h"
#include "delta.h"
#include "zstream.h"
@@ -206,35 +207,14 @@ static int patch_generated_load(git_patch_generated *patch, git_patch_generated_
((patch->nfile.flags & GIT_DIFF_FLAG__NO_DATA) != 0 ||
(patch->nfile.file->flags & GIT_DIFF_FLAG_VALID_ID) != 0));
- /* always try to load workdir content first because filtering may
- * need 2x data size and this minimizes peak memory footprint
- */
- if (patch->ofile.src == GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->ofile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->ofile.file))
- goto cleanup;
- }
- if (patch->nfile.src == GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->nfile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->nfile.file))
- goto cleanup;
- }
-
- /* once workdir has been tried, load other data as needed */
- if (patch->ofile.src != GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->ofile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->ofile.file))
- goto cleanup;
- }
- if (patch->nfile.src != GIT_ITERATOR_TYPE_WORKDIR) {
- if ((error = git_diff_file_content__load(
- &patch->nfile, &patch->base.diff_opts)) < 0 ||
- should_skip_binary(patch, patch->nfile.file))
- goto cleanup;
- }
+ if ((error = git_diff_file_content__load(
+ &patch->ofile, &patch->base.diff_opts)) < 0 ||
+ should_skip_binary(patch, patch->ofile.file))
+ goto cleanup;
+ if ((error = git_diff_file_content__load(
+ &patch->nfile, &patch->base.diff_opts)) < 0 ||
+ should_skip_binary(patch, patch->nfile.file))
+ goto cleanup;
/* if previously missing an oid, and now that we have it the two sides
* are the same (and not submodules), update MODIFIED -> UNMODIFIED
@@ -284,7 +264,7 @@ static int create_binary(
size_t b_datalen)
{
git_buf deflate = GIT_BUF_INIT, delta = GIT_BUF_INIT;
- size_t delta_data_len;
+ size_t delta_data_len = 0;
int error;
/* The git_delta function accepts unsigned long only */
@@ -417,58 +397,10 @@ static int diff_required(git_diff *diff, const char *action)
{
if (diff)
return 0;
- giterr_set(GITERR_INVALID, "Must provide valid diff to %s", action);
+ giterr_set(GITERR_INVALID, "must provide valid diff to %s", action);
return -1;
}
-int git_diff_foreach(
- git_diff *diff,
- git_diff_file_cb file_cb,
- git_diff_binary_cb binary_cb,
- git_diff_hunk_cb hunk_cb,
- git_diff_line_cb data_cb,
- void *payload)
-{
- int error = 0;
- git_xdiff_output xo;
- size_t idx;
- git_patch_generated patch;
-
- if ((error = diff_required(diff, "git_diff_foreach")) < 0)
- return error;
-
- memset(&xo, 0, sizeof(xo));
- memset(&patch, 0, sizeof(patch));
- diff_output_init(
- &xo.output, &diff->opts, file_cb, binary_cb, hunk_cb, data_cb, payload);
- git_xdiff_init(&xo, &diff->opts);
-
- git_vector_foreach(&diff->deltas, idx, patch.base.delta) {
-
- /* check flags against patch status */
- if (git_diff_delta__should_skip(&diff->opts, patch.base.delta))
- continue;
-
- if (binary_cb || hunk_cb || data_cb) {
- if ((error = patch_generated_init(&patch, diff, idx)) != 0 ||
- (error = patch_generated_load(&patch, &xo.output)) != 0)
- return error;
- }
-
- if ((error = patch_generated_invoke_file_callback(&patch, &xo.output)) == 0) {
- if (binary_cb || hunk_cb || data_cb)
- error = patch_generated_create(&patch, &xo.output);
- }
-
- git_patch_free(&patch.base);
-
- if (error)
- break;
- }
-
- return error;
-}
-
typedef struct {
git_patch_generated patch;
git_diff_delta delta;
@@ -710,7 +642,7 @@ int git_patch_from_blob_and_buffer(
git_patch **out,
const git_blob *old_blob,
const char *old_path,
- const char *buf,
+ const void *buf,
size_t buflen,
const char *buf_path,
const git_diff_options *opts)
@@ -749,7 +681,7 @@ int git_patch_from_buffers(
const void *old_buf,
size_t old_len,
const char *old_path,
- const char *new_buf,
+ const void *new_buf,
size_t new_len,
const char *new_path,
const git_diff_options *opts)
@@ -776,7 +708,7 @@ int git_patch_generated_from_diff(
delta = git_vector_get(&diff->deltas, idx);
if (!delta) {
- giterr_set(GITERR_INVALID, "Index out of range for delta in diff");
+ giterr_set(GITERR_INVALID, "index out of range for delta in diff");
return GIT_ENOTFOUND;
}
diff --git a/src/patch_generate.h b/src/patch_generate.h
index 2e89b5c4d..20f78cbfa 100644
--- a/src/patch_generate.h
+++ b/src/patch_generate.h
@@ -8,6 +8,7 @@
#define INCLUDE_patch_generate_h__
#include "common.h"
+
#include "diff.h"
#include "diff_file.h"
#include "patch.h"
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 5ee09ee27..a531eec4d 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -4,9 +4,11 @@
* 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 "patch_parse.h"
+
#include "git2/patch.h"
#include "patch.h"
-#include "patch_parse.h"
#include "diff_parse.h"
#include "path.h"
@@ -176,7 +178,7 @@ static int parse_header_mode(uint16_t *mode, git_patch_parse_ctx *ctx)
int ret;
if (ctx->line_len < 1 || !git__isdigit(ctx->line[0]))
- return parse_err("invalid file mode at line %d", ctx->line_num);
+ return parse_err("invalid file mode at line %"PRIuZ, ctx->line_num);
if ((ret = git__strntol32(&m, ctx->line, ctx->line_len, &end, 8)) < 0)
return ret;
@@ -205,7 +207,7 @@ static int parse_header_oid(
if (len < GIT_OID_MINPREFIXLEN || len > GIT_OID_HEXSZ ||
git_oid_fromstrn(oid, ctx->line, len) < 0)
- return parse_err("invalid hex formatted object id at line %d",
+ return parse_err("invalid hex formatted object id at line %"PRIuZ,
ctx->line_num);
parse_advance_chars(ctx, len);
@@ -350,7 +352,7 @@ static int parse_header_similarity(
git_patch_parsed *patch, git_patch_parse_ctx *ctx)
{
if (parse_header_percent(&patch->base.delta->similarity, ctx) < 0)
- return parse_err("invalid similarity percentage at line %d",
+ return parse_err("invalid similarity percentage at line %"PRIuZ,
ctx->line_num);
return 0;
@@ -362,7 +364,7 @@ static int parse_header_dissimilarity(
uint16_t dissimilarity;
if (parse_header_percent(&dissimilarity, ctx) < 0)
- return parse_err("invalid similarity percentage at line %d",
+ return parse_err("invalid similarity percentage at line %"PRIuZ,
ctx->line_num);
patch->base.delta->similarity = 100 - dissimilarity;
@@ -406,15 +408,15 @@ static int parse_header_git(
/* Parse the diff --git line */
if (parse_advance_expected_str(ctx, "diff --git ") < 0)
- return parse_err("corrupt git diff header at line %d", ctx->line_num);
+ return parse_err("corrupt git diff header at line %"PRIuZ, ctx->line_num);
if (parse_header_path(&patch->header_old_path, ctx) < 0)
- return parse_err("corrupt old path in git diff header at line %d",
+ return parse_err("corrupt old path in git diff header at line %"PRIuZ,
ctx->line_num);
if (parse_advance_ws(ctx) < 0 ||
parse_header_path(&patch->header_new_path, ctx) < 0)
- return parse_err("corrupt new path in git diff header at line %d",
+ return parse_err("corrupt new path in git diff header at line %"PRIuZ,
ctx->line_num);
/* Parse remaining header lines */
@@ -444,10 +446,10 @@ static int parse_header_git(
goto done;
parse_advance_ws(ctx);
- parse_advance_expected_str(ctx, "\n");
- if (ctx->line_len > 0) {
- error = parse_err("trailing data at line %d", ctx->line_num);
+ if (parse_advance_expected_str(ctx, "\n") < 0 ||
+ ctx->line_len > 0) {
+ error = parse_err("trailing data at line %"PRIuZ, ctx->line_num);
goto done;
}
@@ -456,7 +458,7 @@ static int parse_header_git(
}
if (!found) {
- error = parse_err("invalid patch header at line %d",
+ error = parse_err("invalid patch header at line %"PRIuZ,
ctx->line_num);
goto done;
}
@@ -536,7 +538,7 @@ static int parse_hunk_header(
hunk->hunk.header_len = ctx->line - header_start;
if (hunk->hunk.header_len > (GIT_DIFF_HUNK_HEADER_SIZE - 1))
- return parse_err("oversized patch hunk header at line %d",
+ return parse_err("oversized patch hunk header at line %"PRIuZ,
ctx->line_num);
memcpy(hunk->hunk.header, header_start, hunk->hunk.header_len);
@@ -545,7 +547,7 @@ static int parse_hunk_header(
return 0;
fail:
- giterr_set(GITERR_PATCH, "invalid patch hunk header at line %d",
+ giterr_set(GITERR_PATCH, "invalid patch hunk header at line %"PRIuZ,
ctx->line_num);
return -1;
}
@@ -562,15 +564,16 @@ static int parse_hunk_body(
int newlines = hunk->hunk.new_lines;
for (;
- ctx->remain_len > 4 && (oldlines || newlines) &&
- memcmp(ctx->line, "@@ -", 4) != 0;
+ ctx->remain_len > 1 &&
+ (oldlines || newlines) &&
+ (ctx->remain_len <= 4 || memcmp(ctx->line, "@@ -", 4) != 0);
parse_advance_line(ctx)) {
int origin;
int prefix = 1;
if (ctx->line_len == 0 || ctx->line[ctx->line_len - 1] != '\n') {
- error = parse_err("invalid patch instruction at line %d",
+ error = parse_err("invalid patch instruction at line %"PRIuZ,
ctx->line_num);
goto done;
}
@@ -596,7 +599,7 @@ static int parse_hunk_body(
break;
default:
- error = parse_err("invalid patch hunk at line %d", ctx->line_num);
+ error = parse_err("invalid patch hunk at line %"PRIuZ, ctx->line_num);
goto done;
}
@@ -672,7 +675,7 @@ static int parse_patch_header(
continue;
}
- error = parse_err("invalid hunk header outside patch at line %d",
+ error = parse_err("invalid hunk header outside patch at line %"PRIuZ,
line_num);
goto done;
}
@@ -715,12 +718,12 @@ static int parse_patch_binary_side(
parse_advance_chars(ctx, 6);
} else {
error = parse_err(
- "unknown binary delta type at line %d", ctx->line_num);
+ "unknown binary delta type at line %"PRIuZ, ctx->line_num);
goto done;
}
if (parse_number(&len, ctx) < 0 || parse_advance_nl(ctx) < 0 || len < 0) {
- error = parse_err("invalid binary size at line %d", ctx->line_num);
+ error = parse_err("invalid binary size at line %"PRIuZ, ctx->line_num);
goto done;
}
@@ -736,7 +739,7 @@ static int parse_patch_binary_side(
decoded_len = c - 'a' + (('z' - 'a') + 1) + 1;
if (!decoded_len) {
- error = parse_err("invalid binary length at line %d", ctx->line_num);
+ error = parse_err("invalid binary length at line %"PRIuZ, ctx->line_num);
goto done;
}
@@ -745,7 +748,7 @@ static int parse_patch_binary_side(
encoded_len = ((decoded_len / 4) + !!(decoded_len % 4)) * 5;
if (encoded_len > ctx->line_len - 1) {
- error = parse_err("truncated binary data at line %d", ctx->line_num);
+ error = parse_err("truncated binary data at line %"PRIuZ, ctx->line_num);
goto done;
}
@@ -754,14 +757,14 @@ static int parse_patch_binary_side(
goto done;
if (decoded.size - decoded_orig != decoded_len) {
- error = parse_err("truncated binary data at line %d", ctx->line_num);
+ error = parse_err("truncated binary data at line %"PRIuZ, ctx->line_num);
goto done;
}
parse_advance_chars(ctx, encoded_len);
if (parse_advance_nl(ctx) < 0) {
- error = parse_err("trailing data at line %d", ctx->line_num);
+ error = parse_err("trailing data at line %"PRIuZ, ctx->line_num);
goto done;
}
}
@@ -785,7 +788,7 @@ static int parse_patch_binary(
if (parse_advance_expected_str(ctx, "GIT binary patch") < 0 ||
parse_advance_nl(ctx) < 0)
- return parse_err("corrupt git binary header at line %d", ctx->line_num);
+ return parse_err("corrupt git binary header at line %"PRIuZ, ctx->line_num);
/* parse old->new binary diff */
if ((error = parse_patch_binary_side(
@@ -793,7 +796,7 @@ static int parse_patch_binary(
return error;
if (parse_advance_nl(ctx) < 0)
- return parse_err("corrupt git binary separator at line %d",
+ return parse_err("corrupt git binary separator at line %"PRIuZ,
ctx->line_num);
/* parse new->old binary diff */
@@ -802,7 +805,7 @@ static int parse_patch_binary(
return error;
if (parse_advance_nl(ctx) < 0)
- return parse_err("corrupt git binary patch separator at line %d",
+ return parse_err("corrupt git binary patch separator at line %"PRIuZ,
ctx->line_num);
patch->base.binary.contains_data = 1;
@@ -820,7 +823,7 @@ static int parse_patch_binary_nodata(
parse_advance_expected_str(ctx, patch->header_new_path) < 0 ||
parse_advance_expected_str(ctx, " differ") < 0 ||
parse_advance_nl(ctx) < 0)
- return parse_err("corrupt git binary header at line %d", ctx->line_num);
+ return parse_err("corrupt git binary header at line %"PRIuZ, ctx->line_num);
patch->base.binary.contains_data = 0;
patch->base.delta->flags |= GIT_DIFF_FLAG_BINARY;
@@ -912,7 +915,7 @@ static int check_prefix(
if (remain_len || !*path)
return parse_err(
- "header filename does not contain %d path components",
+ "header filename does not contain %"PRIuZ" path components",
prefix_len);
done:
@@ -1014,8 +1017,10 @@ git_patch_parse_ctx *git_patch_parse_ctx_init(
return NULL;
if (content_len) {
- if ((ctx->content = git__malloc(content_len)) == NULL)
+ if ((ctx->content = git__malloc(content_len)) == NULL) {
+ git__free(ctx);
return NULL;
+ }
memcpy((char *)ctx->content, content, content_len);
}
diff --git a/src/patch_parse.h b/src/patch_parse.h
index 99eb4587b..f27651e39 100644
--- a/src/patch_parse.h
+++ b/src/patch_parse.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_patch_parse_h__
#define INCLUDE_patch_parse_h__
+#include "common.h"
+
+#include "patch.h"
+
typedef struct {
git_refcount rc;
diff --git a/src/path.c b/src/path.c
index e5f04a56a..ea0a3c3f6 100644
--- a/src/path.c
+++ b/src/path.c
@@ -4,8 +4,9 @@
* 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 "common.h"
+
#include "path.h"
+
#include "posix.h"
#include "repository.h"
#ifdef GIT_WIN32
@@ -111,13 +112,41 @@ Exit:
}
/*
+ * Determine if the path is a Windows prefix and, if so, returns
+ * its actual lentgh. If it is not a prefix, returns -1.
+ */
+static int win32_prefix_length(const char *path, int len)
+{
+#ifndef GIT_WIN32
+ GIT_UNUSED(path);
+ GIT_UNUSED(len);
+#else
+ /*
+ * Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
+ * 'C:/' here
+ */
+ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path))
+ return 2;
+
+ /*
+ * Similarly checks if we're dealing with a network computer name
+ * '//computername/.git' will return '//computername/'
+ */
+ if (looks_like_network_computer_name(path, len))
+ return len;
+#endif
+
+ return -1;
+}
+
+/*
* Based on the Android implementation, BSD licensed.
* Check http://android.git.kernel.org/
*/
int git_path_dirname_r(git_buf *buffer, const char *path)
{
const char *endp;
- int result, len;
+ int is_prefix = 0, len;
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
@@ -131,6 +160,11 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
while (endp > path && *endp == '/')
endp--;
+ if ((len = win32_prefix_length(path, endp - path + 1)) > 0) {
+ is_prefix = 1;
+ goto Exit;
+ }
+
/* Find the start of the dir */
while (endp > path && *endp != '/')
endp--;
@@ -146,35 +180,23 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
endp--;
} while (endp > path && *endp == '/');
- /* Cast is safe because max path < max int */
- len = (int)(endp - path + 1);
-
-#ifdef GIT_WIN32
- /* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
- 'C:/' here */
-
- if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) {
- len = 3;
- goto Exit;
- }
-
- /* Similarly checks if we're dealing with a network computer name
- '//computername/.git' will return '//computername/' */
-
- if (looks_like_network_computer_name(path, len)) {
- len++;
+ if ((len = win32_prefix_length(path, endp - path + 1)) > 0) {
+ is_prefix = 1;
goto Exit;
}
-#endif
+ /* Cast is safe because max path < max int */
+ len = (int)(endp - path + 1);
Exit:
- result = len;
-
- if (buffer != NULL && git_buf_set(buffer, path, len) < 0)
- return -1;
+ if (buffer) {
+ if (git_buf_set(buffer, path, len) < 0)
+ return -1;
+ if (is_prefix && git_buf_putc(buffer, '/') < 0)
+ return -1;
+ }
- return result;
+ return len;
}
@@ -341,7 +363,7 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
if (p_realpath(path, buf) == NULL) {
/* giterr_set resets the errno when dealing with a GITERR_OS kind of error */
int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1;
- giterr_set(GITERR_OS, "Failed to resolve path '%s'", path);
+ giterr_set(GITERR_OS, "failed to resolve path '%s'", path);
git_buf_clear(path_out);
@@ -632,20 +654,24 @@ int git_path_set_error(int errno_value, const char *path, const char *action)
switch (errno_value) {
case ENOENT:
case ENOTDIR:
- giterr_set(GITERR_OS, "Could not find '%s' to %s", path, action);
+ giterr_set(GITERR_OS, "could not find '%s' to %s", path, action);
return GIT_ENOTFOUND;
case EINVAL:
case ENAMETOOLONG:
- giterr_set(GITERR_OS, "Invalid path for filesystem '%s'", path);
+ giterr_set(GITERR_OS, "invalid path for filesystem '%s'", path);
return GIT_EINVALIDSPEC;
case EEXIST:
- giterr_set(GITERR_OS, "Failed %s - '%s' already exists", action, path);
+ giterr_set(GITERR_OS, "failed %s - '%s' already exists", action, path);
return GIT_EEXISTS;
+ case EACCES:
+ giterr_set(GITERR_OS, "failed %s - '%s' is locked", action, path);
+ return GIT_ELOCKED;
+
default:
- giterr_set(GITERR_OS, "Could not %s '%s'", action, path);
+ giterr_set(GITERR_OS, "could not %s '%s'", action, path);
return -1;
}
}
@@ -675,7 +701,8 @@ static bool _check_dir_contents(
return false;
/* save excursion */
- git_buf_joinpath(dir, dir->ptr, sub);
+ if (git_buf_joinpath(dir, dir->ptr, sub) < 0)
+ return false;
result = predicate(dir->ptr);
@@ -754,7 +781,7 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling)
/* error out if trying to up one from a hard base */
if (to == base && ceiling != 0) {
giterr_set(GITERR_INVALID,
- "Cannot strip root component off url");
+ "cannot strip root component off url");
return -1;
}
@@ -800,8 +827,8 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling)
int git_path_apply_relative(git_buf *target, const char *relpath)
{
- git_buf_joinpath(target, git_buf_cstr(target), relpath);
- return git_path_resolve_relative(target, 0);
+ return git_buf_joinpath(target, git_buf_cstr(target), relpath) ||
+ git_path_resolve_relative(target, 0);
}
int git_path_cmp(
@@ -983,7 +1010,7 @@ int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen)
return 0;
fail:
- giterr_set(GITERR_OS, "Unable to convert unicode path data");
+ giterr_set(GITERR_OS, "unable to convert unicode path data");
return -1;
}
@@ -1076,7 +1103,7 @@ int git_path_direach(
wd_len = git_buf_len(path);
if ((dir = opendir(path->ptr)) == NULL) {
- giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr);
+ giterr_set(GITERR_OS, "failed to open directory '%s'", path->ptr);
if (errno == ENOENT)
return GIT_ENOTFOUND;
@@ -1141,7 +1168,6 @@ int git_path_diriter_init(
unsigned int flags)
{
git_win32_path path_filter;
- git_buf hack = {0};
static int is_win7_or_later = -1;
if (is_win7_or_later < 0)
@@ -1158,13 +1184,13 @@ int git_path_diriter_init(
git_path_trim_slashes(&diriter->path_utf8);
if (diriter->path_utf8.size == 0) {
- giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path);
+ giterr_set(GITERR_FILESYSTEM, "could not open directory '%s'", path);
return -1;
}
if ((diriter->parent_len = git_win32_path_from_utf8(diriter->path, diriter->path_utf8.ptr)) < 0 ||
!git_win32__findfirstfile_filter(path_filter, diriter->path_utf8.ptr)) {
- giterr_set(GITERR_OS, "Could not parse the directory path '%s'", path);
+ giterr_set(GITERR_OS, "could not parse the directory path '%s'", path);
return -1;
}
@@ -1177,7 +1203,7 @@ int git_path_diriter_init(
is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0);
if (diriter->handle == INVALID_HANDLE_VALUE) {
- giterr_set(GITERR_OS, "Could not open directory '%s'", path);
+ giterr_set(GITERR_OS, "could not open directory '%s'", path);
return -1;
}
@@ -1307,14 +1333,14 @@ int git_path_diriter_init(
git_path_trim_slashes(&diriter->path);
if (diriter->path.size == 0) {
- giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path);
+ giterr_set(GITERR_FILESYSTEM, "could not open directory '%s'", path);
return -1;
}
if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) {
git_buf_free(&diriter->path);
- giterr_set(GITERR_OS, "Failed to open directory '%s'", path);
+ giterr_set(GITERR_OS, "failed to open directory '%s'", path);
return -1;
}
@@ -1347,7 +1373,7 @@ int git_path_diriter_next(git_path_diriter *diriter)
return GIT_ITEROVER;
giterr_set(GITERR_OS,
- "Could not read directory '%s'", diriter->path);
+ "could not read directory '%s'", diriter->path.ptr);
return -1;
}
} while (skip_dot && git_path_is_dot_or_dotdot(de->d_name));
@@ -1683,6 +1709,7 @@ GIT_INLINE(unsigned int) dotgit_flags(
unsigned int flags)
{
int protectHFS = 0, protectNTFS = 0;
+ int error = 0;
flags |= GIT_PATH_REJECT_DOT_GIT_LITERAL;
@@ -1695,13 +1722,13 @@ GIT_INLINE(unsigned int) dotgit_flags(
#endif
if (repo && !protectHFS)
- git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS);
- if (protectHFS)
+ error = git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS);
+ if (!error && protectHFS)
flags |= GIT_PATH_REJECT_DOT_GIT_HFS;
if (repo && !protectNTFS)
- git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS);
- if (protectNTFS)
+ error = git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS);
+ if (!error && protectNTFS)
flags |= GIT_PATH_REJECT_DOT_GIT_NTFS;
return flags;
diff --git a/src/path.h b/src/path.h
index fb45a6534..360372cfb 100644
--- a/src/path.h
+++ b/src/path.h
@@ -8,6 +8,7 @@
#define INCLUDE_path_h__
#include "common.h"
+
#include "posix.h"
#include "buffer.h"
#include "vector.h"
diff --git a/src/pathspec.c b/src/pathspec.c
index 361b398b8..998b6fb36 100644
--- a/src/pathspec.c
+++ b/src/pathspec.c
@@ -5,9 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "pathspec.h"
+
#include "git2/pathspec.h"
#include "git2/diff.h"
-#include "pathspec.h"
#include "buf_text.h"
#include "attr_file.h"
#include "iterator.h"
@@ -487,7 +488,7 @@ static int pathspec_match_from_iterator(
/* if every pattern failed to match, then we have failed */
if ((flags & GIT_PATHSPEC_NO_MATCH_ERROR) != 0 && !found_files) {
- giterr_set(GITERR_INVALID, "No matching files were found");
+ giterr_set(GITERR_INVALID, "no matching files were found");
error = GIT_ENOTFOUND;
}
@@ -658,7 +659,7 @@ int git_pathspec_match_diff(
/* if every pattern failed to match, then we have failed */
if ((flags & GIT_PATHSPEC_NO_MATCH_ERROR) != 0 && !found_deltas) {
- giterr_set(GITERR_INVALID, "No matching deltas were found");
+ giterr_set(GITERR_INVALID, "no matching deltas were found");
error = GIT_ENOTFOUND;
}
diff --git a/src/pathspec.h b/src/pathspec.h
index 40cd21c3f..c4d1a83d3 100644
--- a/src/pathspec.h
+++ b/src/pathspec.h
@@ -8,7 +8,8 @@
#define INCLUDE_pathspec_h__
#include "common.h"
-#include <git2/pathspec.h>
+
+#include "git2/pathspec.h"
#include "buffer.h"
#include "vector.h"
#include "pool.h"
diff --git a/src/pool.c b/src/pool.c
index b4fc50fca..c0efe9c9d 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -1,4 +1,12 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
#include "pool.h"
+
#include "posix.h"
#ifndef GIT_WIN32
#include <unistd.h>
diff --git a/src/pool.h b/src/pool.h
index f61f16944..92ddf994a 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -8,6 +8,7 @@
#define INCLUDE_pool_h__
#include "common.h"
+
#include "vector.h"
typedef struct git_pool_page git_pool_page;
diff --git a/src/posix.c b/src/posix.c
index b3f1a1cd3..6e7985ece 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -4,12 +4,15 @@
* 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 "common.h"
+
#include "posix.h"
+
#include "path.h"
#include <stdio.h>
#include <ctype.h>
+size_t p_fsync__cnt = 0;
+
#ifndef GIT_WIN32
#ifdef NO_ADDRINFO
@@ -38,7 +41,7 @@ int p_getaddrinfo(
if (ainfo->ai_servent)
ainfo->ai_port = ainfo->ai_servent->s_port;
else
- ainfo->ai_port = atol(port);
+ ainfo->ai_port = htons(atol(port));
memcpy(&ainfo->ai_addr_in.sin_addr,
ainfo->ai_hostent->h_addr_list[0],
@@ -240,7 +243,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
out->len = 0;
if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
- giterr_set(GITERR_OS, "Trying to map shared-writeable");
+ giterr_set(GITERR_OS, "trying to map shared-writeable");
return -1;
}
diff --git a/src/posix.h b/src/posix.h
index f204751cf..3e3bcb287 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -8,6 +8,7 @@
#define INCLUDE_posix_h__
#include "common.h"
+
#include <fcntl.h>
#include <time.h>
#include "fnmatch.h"
@@ -24,6 +25,10 @@
#define _S_IFLNK S_IFLNK
#endif
+#ifndef S_IWUSR
+#define S_IWUSR 00200
+#endif
+
#ifndef S_IXUSR
#define S_IXUSR 00100
#endif
@@ -111,6 +116,12 @@ extern int p_rename(const char *from, const char *to);
extern int git__page_size(size_t *page_size);
extern int git__mmap_alignment(size_t *page_size);
+/* The number of times `p_fsync` has been called. Note that this is for
+ * test code only; it it not necessarily thread-safe and should not be
+ * relied upon in production.
+ */
+extern size_t p_fsync__cnt;
+
/**
* Platform-dependent methods
*/
diff --git a/src/pqueue.c b/src/pqueue.c
index 54a60ca04..3820e999c 100644
--- a/src/pqueue.c
+++ b/src/pqueue.c
@@ -6,6 +6,7 @@
*/
#include "pqueue.h"
+
#include "util.h"
#define PQUEUE_LCHILD_OF(I) (((I)<<1)+1)
@@ -86,14 +87,15 @@ int git_pqueue_insert(git_pqueue *pq, void *item)
if ((pq->flags & GIT_PQUEUE_FIXED_SIZE) != 0 &&
pq->length >= pq->_alloc_size)
{
- /* skip this item if below min item in heap */
- if (pq->_cmp(item, git_vector_get(pq, 0)) <= 0)
+ /* skip this item if below min item in heap or if
+ * we do not have a comparison function */
+ if (!pq->_cmp || pq->_cmp(item, git_vector_get(pq, 0)) <= 0)
return 0;
/* otherwise remove the min item before inserting new */
(void)git_pqueue_pop(pq);
}
- if (!(error = git_vector_insert(pq, item)))
+ if (!(error = git_vector_insert(pq, item)) && pq->_cmp)
pqueue_up(pq, pq->length - 1);
return error;
@@ -101,9 +103,15 @@ int git_pqueue_insert(git_pqueue *pq, void *item)
void *git_pqueue_pop(git_pqueue *pq)
{
- void *rval = git_pqueue_get(pq, 0);
+ void *rval;
+
+ if (!pq->_cmp) {
+ rval = git_vector_last(pq);
+ } else {
+ rval = git_pqueue_get(pq, 0);
+ }
- if (git_pqueue_size(pq) > 1) {
+ if (git_pqueue_size(pq) > 1 && pq->_cmp) {
/* move last item to top of heap, shrink, and push item down */
pq->contents[0] = git_vector_last(pq);
git_vector_pop(pq);
diff --git a/src/pqueue.h b/src/pqueue.h
index da7b74edf..c0a6cd49e 100644
--- a/src/pqueue.h
+++ b/src/pqueue.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_pqueue_h__
#define INCLUDE_pqueue_h__
+#include "common.h"
+
#include "vector.h"
typedef git_vector git_pqueue;
@@ -35,6 +37,7 @@ extern int git_pqueue_init(
#define git_pqueue_clear git_vector_clear
#define git_pqueue_size git_vector_length
#define git_pqueue_get git_vector_get
+#define git_pqueue_reverse git_vector_reverse
/**
* Insert a new item into the queue
diff --git a/src/proxy.c b/src/proxy.c
index f53ac1151..b07371d48 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "proxy.h"
+
#include "git2/proxy.h"
int git_proxy_init_options(git_proxy_options *opts, unsigned int version)
diff --git a/src/proxy.h b/src/proxy.h
index bf9382737..7582301c9 100644
--- a/src/proxy.h
+++ b/src/proxy.h
@@ -7,8 +7,10 @@
#ifndef INCLUDE_proxy_h__
#define INCLUDE_proxy_h__
+#include "common.h"
+
#include "git2/proxy.h"
extern int git_proxy_options_dup(git_proxy_options *tgt, const git_proxy_options *src);
-#endif \ No newline at end of file
+#endif
diff --git a/src/push.c b/src/push.c
index b4901388b..41b66df06 100644
--- a/src/push.c
+++ b/src/push.c
@@ -5,14 +5,14 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "push.h"
+
#include "git2.h"
-#include "common.h"
#include "pack.h"
#include "pack-objects.h"
#include "remote.h"
#include "vector.h"
-#include "push.h"
#include "tree.h"
static int push_spec_rref_cmp(const void *a, const void *b)
@@ -90,7 +90,7 @@ static void free_refspec(push_spec *spec)
static int check_rref(char *ref)
{
if (git__prefixcmp(ref, "refs/")) {
- giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
+ giterr_set(GITERR_INVALID, "not a valid reference '%s'", ref);
return -1;
}
@@ -111,7 +111,7 @@ static int check_lref(git_push *push, char *ref)
giterr_set(GITERR_REFERENCE,
"src refspec '%s' does not match any existing object", ref);
else
- giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
+ giterr_set(GITERR_INVALID, "not a valid reference '%s'", ref);
return -1;
}
@@ -178,6 +178,9 @@ int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks)
if (!fetch_spec)
continue;
+ /* Clear the buffer which can be dirty from previous iteration */
+ git_buf_clear(&remote_ref_name);
+
if ((error = git_refspec_transform(&remote_ref_name, fetch_spec, status->ref)) < 0)
goto on_error;
@@ -321,7 +324,7 @@ static int revwalk(git_vector *commits, git_push *push)
if (!git_odb_exists(push->repo->_odb, &spec->roid)) {
giterr_set(GITERR_REFERENCE,
- "Cannot push because a reference that you are trying to update on the remote contains commits that are not present locally.");
+ "cannot push because a reference that you are trying to update on the remote contains commits that are not present locally.");
error = GIT_ENONFASTFORWARD;
goto on_error;
}
@@ -332,7 +335,7 @@ static int revwalk(git_vector *commits, git_push *push)
if (error == GIT_ENOTFOUND ||
(!error && !git_oid_equal(&base, &spec->roid))) {
giterr_set(GITERR_REFERENCE,
- "Cannot push non-fastforwardable reference");
+ "cannot push non-fastforwardable reference");
error = GIT_ENONFASTFORWARD;
goto on_error;
}
@@ -553,7 +556,7 @@ static int calculate_work(git_push *push)
/* This is a create or update. Local ref must exist. */
if (git_reference_name_to_id(
&spec->loid, push->repo, spec->refspec.src) < 0) {
- giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->refspec.src);
+ giterr_set(GITERR_REFERENCE, "no such reference '%s'", spec->refspec.src);
return -1;
}
}
@@ -579,7 +582,7 @@ static int do_push(git_push *push, const git_remote_callbacks *callbacks)
git_transport *transport = push->remote->transport;
if (!transport->push) {
- giterr_set(GITERR_NET, "Remote transport doesn't support push");
+ giterr_set(GITERR_NET, "remote transport doesn't support push");
error = -1;
goto on_error;
}
diff --git a/src/push.h b/src/push.h
index e32ad2f4d..31ac43609 100644
--- a/src/push.h
+++ b/src/push.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_push_h__
#define INCLUDE_push_h__
+#include "common.h"
+
#include "git2.h"
#include "refspec.h"
diff --git a/src/rebase.c b/src/rebase.c
index 470e62a23..3be751254 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "buffer.h"
#include "repository.h"
#include "posix.h"
@@ -92,7 +93,7 @@ static int rebase_state_type(
git_buf path = GIT_BUF_INIT;
git_rebase_type_t type = GIT_REBASE_TYPE_NONE;
- if (git_buf_joinpath(&path, repo->path_repository, REBASE_APPLY_DIR) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0)
return -1;
if (git_path_isdir(git_buf_cstr(&path))) {
@@ -101,7 +102,7 @@ static int rebase_state_type(
}
git_buf_clear(&path);
- if (git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0)
return -1;
if (git_path_isdir(git_buf_cstr(&path))) {
@@ -152,7 +153,7 @@ GIT_INLINE(int) rebase_readint(
return error;
if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
- giterr_set(GITERR_REBASE, "The file '%s' contains an invalid numeric value", filename);
+ giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
return -1;
}
@@ -170,7 +171,7 @@ GIT_INLINE(int) rebase_readoid(
return error;
if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) {
- giterr_set(GITERR_REBASE, "The file '%s' contains an invalid object ID", filename);
+ giterr_set(GITERR_REBASE, "the file '%s' contains an invalid object ID", filename);
return -1;
}
@@ -316,7 +317,7 @@ int git_rebase_open(
goto done;
if (rebase->type == GIT_REBASE_TYPE_NONE) {
- giterr_set(GITERR_REBASE, "There is no rebase in progress");
+ giterr_set(GITERR_REBASE, "there is no rebase in progress");
error = GIT_ENOTFOUND;
goto done;
}
@@ -372,14 +373,14 @@ int git_rebase_open(
switch (rebase->type) {
case GIT_REBASE_TYPE_INTERACTIVE:
- giterr_set(GITERR_REBASE, "Interactive rebase is not supported");
+ giterr_set(GITERR_REBASE, "interactive rebase is not supported");
error = -1;
break;
case GIT_REBASE_TYPE_MERGE:
error = rebase_open_merge(rebase);
break;
case GIT_REBASE_TYPE_APPLY:
- giterr_set(GITERR_REBASE, "Patch application rebase is not supported");
+ giterr_set(GITERR_REBASE, "patch application rebase is not supported");
error = -1;
break;
default:
@@ -447,8 +448,8 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
size_t i;
int error = 0;
- if ((error = rebase_setupfile(rebase, END_FILE, -1, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
- (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0)
+ if ((error = rebase_setupfile(rebase, END_FILE, 0, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
+ (error = rebase_setupfile(rebase, ONTO_NAME_FILE, 0, "%s\n", rebase->onto_name)) < 0)
goto done;
for (i = 0; i < git_array_size(rebase->operations); i++) {
@@ -459,7 +460,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
git_oid_fmt(id_str, &operation->id);
- if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1,
+ if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0,
"%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
goto done;
}
@@ -478,7 +479,7 @@ static int rebase_setupfiles(git_rebase *rebase)
git_oid_fmt(orig_head, &rebase->orig_head_id);
if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) {
- giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", rebase->state_path);
+ giterr_set(GITERR_OS, "failed to create rebase directory '%s'", rebase->state_path);
return -1;
}
@@ -486,10 +487,10 @@ static int rebase_setupfiles(git_rebase *rebase)
rebase->orig_head_name;
if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
- rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", orig_head_name) < 0 ||
- rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
- rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
- rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0)
+ rebase_setupfile(rebase, HEAD_NAME_FILE, 0, "%s\n", orig_head_name) < 0 ||
+ rebase_setupfile(rebase, ONTO_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
+ rebase_setupfile(rebase, ORIG_HEAD_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
+ rebase_setupfile(rebase, QUIET_FILE, 0, rebase->quiet ? "t\n" : "\n") < 0)
return -1;
return rebase_setupfiles_merge(rebase);
@@ -511,7 +512,7 @@ static int rebase_ensure_not_in_progress(git_repository *repo)
return error;
if (type != GIT_REBASE_TYPE_NONE) {
- giterr_set(GITERR_REBASE, "There is an existing rebase in progress");
+ giterr_set(GITERR_REBASE, "there is an existing rebase in progress");
return -1;
}
@@ -536,7 +537,7 @@ static int rebase_ensure_not_dirty(
goto done;
if (git_diff_num_deltas(diff) > 0) {
- giterr_set(GITERR_REBASE, "Uncommitted changes exist in index");
+ giterr_set(GITERR_REBASE, "uncommitted changes exist in index");
error = fail_with;
goto done;
}
@@ -546,11 +547,13 @@ static int rebase_ensure_not_dirty(
}
if (check_workdir) {
- if ((error = git_diff_index_to_workdir(&diff, repo, index, NULL)) < 0)
+ git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
+ diff_opts.ignore_submodules = GIT_SUBMODULE_IGNORE_UNTRACKED;
+ if ((error = git_diff_index_to_workdir(&diff, repo, index, &diff_opts)) < 0)
goto done;
if (git_diff_num_deltas(diff) > 0) {
- giterr_set(GITERR_REBASE, "Unstaged changes exist in workdir");
+ giterr_set(GITERR_REBASE, "unstaged changes exist in workdir");
error = fail_with;
goto done;
}
@@ -586,7 +589,7 @@ static int rebase_init_operations(
(error = git_revwalk_hide(revwalk, git_annotated_commit_id(upstream))) < 0)
goto done;
- git_revwalk_sorting(revwalk, GIT_SORT_REVERSE | GIT_SORT_TIME);
+ git_revwalk_sorting(revwalk, GIT_SORT_REVERSE);
while ((error = git_revwalk_next(&id, revwalk)) == 0) {
if ((error = git_commit_lookup(&commit, repo, &id)) < 0)
@@ -624,13 +627,13 @@ static int rebase_init_merge(
GIT_UNUSED(upstream);
- if ((error = git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR)) < 0)
+ if ((error = git_buf_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0)
goto done;
rebase->state_path = git_buf_detach(&state_path);
GITERR_CHECK_ALLOC(rebase->state_path);
- if (branch->ref_name) {
+ if (branch->ref_name && strcmp(branch->ref_name, "HEAD")) {
rebase->orig_head_name = git__strdup(branch->ref_name);
GITERR_CHECK_ALLOC(rebase->orig_head_name);
} else {
@@ -731,7 +734,7 @@ int git_rebase_init(
if (inmemory)
error = rebase_init_inmemory(rebase, repo, branch, upstream, onto);
else
- rebase_init_merge(rebase, repo, branch ,upstream, onto);
+ error = rebase_init_merge(rebase, repo, branch ,upstream, onto);
if (error == 0)
*out = rebase;
@@ -807,7 +810,7 @@ static int rebase_next_merge(
goto done;
if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
- giterr_set(GITERR_REBASE, "Cannot rebase a merge commit");
+ giterr_set(GITERR_REBASE, "cannot rebase a merge commit");
error = -1;
goto done;
} else if (parent_count) {
@@ -821,8 +824,8 @@ static int rebase_next_merge(
normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit);
if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 ||
- (error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
- (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
+ (error = rebase_setupfile(rebase, MSGNUM_FILE, 0, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
+ (error = rebase_setupfile(rebase, CURRENT_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
(error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 ||
(error = git_merge__check_result(rebase->repo, index)) < 0 ||
(error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 ||
@@ -864,7 +867,7 @@ static int rebase_next_inmemory(
goto done;
if ((parent_count = git_commit_parentcount(current_commit)) > 1) {
- giterr_set(GITERR_REBASE, "Cannot rebase a merge commit");
+ giterr_set(GITERR_REBASE, "cannot rebase a merge commit");
error = -1;
goto done;
} else if (parent_count) {
@@ -1259,7 +1262,7 @@ static int rebase_copy_notes(
goto done;
on_error:
- giterr_set(GITERR_REBASE, "Invalid rewritten file at line %d", linenum);
+ giterr_set(GITERR_REBASE, "invalid rewritten file at line %d", linenum);
error = -1;
done:
diff --git a/src/refdb.c b/src/refdb.c
index debba1276..c162a153f 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -5,8 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "posix.h"
+#include "refdb.h"
#include "git2/object.h"
#include "git2/refs.h"
@@ -14,9 +13,9 @@
#include "git2/sys/refdb_backend.h"
#include "hash.h"
-#include "refdb.h"
#include "refs.h"
#include "reflog.h"
+#include "posix.h"
int git_refdb_new(git_refdb **out, git_repository *repo)
{
@@ -125,13 +124,15 @@ int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char *glob)
{
+ int error;
+
if (!db->backend || !db->backend->iterator) {
- giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators");
+ giterr_set(GITERR_REFERENCE, "this backend doesn't support iterators");
return -1;
}
- if (db->backend->iterator(out, db->backend, glob) < 0)
- return -1;
+ if ((error = db->backend->iterator(out, db->backend, glob)) < 0)
+ return error;
GIT_REFCOUNT_INC(db);
(*out)->db = db;
diff --git a/src/refdb.h b/src/refdb.h
index 4ee3b8065..2d4ec753a 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_refdb_h__
#define INCLUDE_refdb_h__
+#include "common.h"
+
#include "git2/refdb.h"
#include "repository.h"
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index f978038e6..ade734c6a 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "refdb_fs.h"
+
#include "refs.h"
#include "hash.h"
#include "repository.h"
@@ -13,7 +15,6 @@
#include "pack.h"
#include "reflog.h"
#include "refdb.h"
-#include "refdb_fs.h"
#include "iterator.h"
#include "sortedcache.h"
#include "signature.h"
@@ -26,8 +27,6 @@
#include <git2/sys/refs.h>
#include <git2/sys/reflog.h>
-GIT__USE_STRMAP
-
#define DEFAULT_NESTING_LEVEL 5
#define MAX_NESTING_LEVEL 10
@@ -55,12 +54,16 @@ typedef struct refdb_fs_backend {
git_refdb_backend parent;
git_repository *repo;
- char *path;
+ /* path to git directory */
+ char *gitpath;
+ /* path to common objects' directory */
+ char *commonpath;
git_sortedcache *refcache;
int peeling_mode;
git_iterator_flag_t iterator_flags;
uint32_t direach_flags;
+ int fsync;
} refdb_fs_backend;
static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
@@ -77,7 +80,7 @@ static int packed_reload(refdb_fs_backend *backend)
git_buf packedrefs = GIT_BUF_INIT;
char *scan, *eof, *eol;
- if (!backend->path)
+ if (!backend->gitpath)
return 0;
error = git_sortedcache_lockandload(backend->refcache, &packedrefs);
@@ -185,7 +188,7 @@ static int packed_reload(refdb_fs_backend *backend)
return 0;
parse_failed:
- giterr_set(GITERR_REFERENCE, "Corrupted packed references file");
+ giterr_set(GITERR_REFERENCE, "corrupted packed references file");
git_sortedcache_clear(backend->refcache, false);
git_sortedcache_wunlock(backend->refcache);
@@ -212,7 +215,7 @@ static int loose_parse_oid(
return 0;
corrupted:
- giterr_set(GITERR_REFERENCE, "Corrupted loose reference file: %s", filename);
+ giterr_set(GITERR_REFERENCE, "corrupted loose reference file: %s", filename);
return -1;
}
@@ -238,7 +241,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name)
/* if we fail to load the loose reference, assume someone changed
* the filesystem under us and skip it...
*/
- if (loose_readbuffer(&ref_file, backend->path, name) < 0) {
+ if (loose_readbuffer(&ref_file, backend->gitpath, name) < 0) {
giterr_clear();
goto done;
}
@@ -287,7 +290,7 @@ static int _dirent_loose_load(void *payload, git_buf *full_path)
return error;
}
- file_path = full_path->ptr + strlen(backend->path);
+ file_path = full_path->ptr + strlen(backend->gitpath);
return loose_lookup_to_packfile(backend, file_path);
}
@@ -303,7 +306,7 @@ static int packed_loadloose(refdb_fs_backend *backend)
int error;
git_buf refs_path = GIT_BUF_INIT;
- if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0)
+ if (git_buf_joinpath(&refs_path, backend->gitpath, GIT_REFS_DIR) < 0)
return -1;
/*
@@ -326,12 +329,13 @@ static int refdb_fs_backend__exists(
{
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
git_buf ref_path = GIT_BUF_INIT;
+ int error;
assert(backend);
- if (packed_reload(backend) < 0 ||
- git_buf_joinpath(&ref_path, backend->path, ref_name) < 0)
- return -1;
+ if ((error = packed_reload(backend)) < 0 ||
+ (error = git_buf_joinpath(&ref_path, backend->gitpath, ref_name)) < 0)
+ return error;
*exists = git_path_isfile(ref_path.ptr) ||
(git_sortedcache_lookup(backend->refcache, ref_name) != NULL);
@@ -348,7 +352,7 @@ static const char *loose_parse_symbolic(git_buf *file_content)
refname_start = (const char *)file_content->ptr;
if (git_buf_len(file_content) < header_len + 1) {
- giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
+ giterr_set(GITERR_REFERENCE, "corrupted loose reference file");
return NULL;
}
@@ -361,6 +365,19 @@ static const char *loose_parse_symbolic(git_buf *file_content)
return refname_start;
}
+/*
+ * Returns whether a reference is stored per worktree or not.
+ * Per-worktree references are:
+ *
+ * - all pseudorefs, e.g. HEAD and MERGE_HEAD
+ * - all references stored inside of "refs/bisect/"
+ */
+static bool is_per_worktree_ref(const char *ref_name)
+{
+ return git__prefixcmp(ref_name, "refs/") != 0 ||
+ git__prefixcmp(ref_name, "refs/bisect/") == 0;
+}
+
static int loose_lookup(
git_reference **out,
refdb_fs_backend *backend,
@@ -368,11 +385,17 @@ static int loose_lookup(
{
git_buf ref_file = GIT_BUF_INIT;
int error = 0;
+ const char *ref_dir;
if (out)
*out = NULL;
- if ((error = loose_readbuffer(&ref_file, backend->path, ref_name)) < 0)
+ if (is_per_worktree_ref(ref_name))
+ ref_dir = backend->gitpath;
+ else
+ ref_dir = backend->commonpath;
+
+ if ((error = loose_readbuffer(&ref_file, ref_dir, ref_name)) < 0)
/* cannot read loose ref file - gah */;
else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) {
const char *target;
@@ -397,7 +420,7 @@ static int loose_lookup(
static int ref_error_notfound(const char *name)
{
- giterr_set(GITERR_REFERENCE, "Reference '%s' not found", name);
+ giterr_set(GITERR_REFERENCE, "reference '%s' not found", name);
return GIT_ENOTFOUND;
}
@@ -409,8 +432,8 @@ static int packed_lookup(
int error = 0;
struct packref *entry;
- if (packed_reload(backend) < 0)
- return -1;
+ if ((error = packed_reload(backend)) < 0)
+ return error;
if (git_sortedcache_rlock(backend->refcache) < 0)
return -1;
@@ -483,12 +506,12 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter)
git_iterator_options fsit_opts = GIT_ITERATOR_OPTIONS_INIT;
const git_index_entry *entry = NULL;
- if (!backend->path) /* do nothing if no path for loose refs */
+ if (!backend->commonpath) /* do nothing if no commonpath for loose refs */
return 0;
fsit_opts.flags = backend->iterator_flags;
- if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 ||
+ if ((error = git_buf_printf(&path, "%s/refs", backend->commonpath)) < 0 ||
(error = git_iterator_for_filesystem(&fsit, path.ptr, &fsit_opts)) < 0) {
git_buf_free(&path);
return error;
@@ -615,13 +638,14 @@ static int refdb_fs_backend__iterator_next_name(
static int refdb_fs_backend__iterator(
git_reference_iterator **out, git_refdb_backend *_backend, const char *glob)
{
+ int error;
refdb_fs_iter *iter;
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
assert(backend);
- if (packed_reload(backend) < 0)
- return -1;
+ if ((error = packed_reload(backend)) < 0)
+ return error;
iter = git__calloc(1, sizeof(refdb_fs_iter));
GITERR_CHECK_ALLOC(iter);
@@ -674,20 +698,22 @@ static int reference_path_available(
int force)
{
size_t i;
+ int error;
- if (packed_reload(backend) < 0)
- return -1;
+ if ((error = packed_reload(backend)) < 0)
+ return error;
if (!force) {
int exists;
- if (refdb_fs_backend__exists(
- &exists, (git_refdb_backend *)backend, new_ref) < 0)
- return -1;
+ if ((error = refdb_fs_backend__exists(
+ &exists, (git_refdb_backend *)backend, new_ref)) < 0) {
+ return error;
+ }
if (exists) {
giterr_set(GITERR_REFERENCE,
- "Failed to write reference '%s': a reference with "
+ "failed to write reference '%s': a reference with "
"that name already exists.", new_ref);
return GIT_EEXISTS;
}
@@ -701,7 +727,7 @@ static int reference_path_available(
if (ref && !ref_is_available(old_ref, new_ref, ref->name)) {
git_sortedcache_runlock(backend->refcache);
giterr_set(GITERR_REFERENCE,
- "Path to reference '%s' collides with existing one", new_ref);
+ "path to reference '%s' collides with existing one", new_ref);
return -1;
}
}
@@ -712,26 +738,36 @@ static int reference_path_available(
static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
{
- int error;
+ int error, filebuf_flags;
git_buf ref_path = GIT_BUF_INIT;
+ const char *basedir;
assert(file && backend && name);
if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
- giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", name);
+ giterr_set(GITERR_INVALID, "invalid reference name '%s'", name);
return GIT_EINVALIDSPEC;
}
+ if (is_per_worktree_ref(name))
+ basedir = backend->gitpath;
+ else
+ basedir = backend->commonpath;
+
/* Remove a possibly existing empty directory hierarchy
* which name would collide with the reference name
*/
- if (git_futils_rmdir_r(name, backend->path, GIT_RMDIR_SKIP_NONEMPTY) < 0)
- return -1;
+ if ((error = git_futils_rmdir_r(name, basedir, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
+ return error;
- if (git_buf_joinpath(&ref_path, backend->path, name) < 0)
+ if (git_buf_joinpath(&ref_path, basedir, name) < 0)
return -1;
- error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE);
+ filebuf_flags = GIT_FILEBUF_FORCE;
+ if (backend->fsync)
+ filebuf_flags |= GIT_FILEBUF_FSYNC;
+
+ error = git_filebuf_open(file, ref_path.ptr, filebuf_flags, GIT_REFS_FILE_MODE);
if (error == GIT_EDIRECTORY)
giterr_set(GITERR_REFERENCE, "cannot lock ref '%s', there are refs beneath that folder", name);
@@ -901,40 +937,62 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file)
static int packed_remove_loose(refdb_fs_backend *backend)
{
size_t i;
- git_buf full_path = GIT_BUF_INIT;
- int failed = 0;
+ git_filebuf lock = GIT_FILEBUF_INIT;
+ git_buf ref_content = GIT_BUF_INIT;
+ int error = 0;
/* backend->refcache is already locked when this is called */
for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) {
struct packref *ref = git_sortedcache_entry(backend->refcache, i);
+ git_oid current_id;
if (!ref || !(ref->flags & PACKREF_WAS_LOOSE))
continue;
- if (git_buf_joinpath(&full_path, backend->path, ref->name) < 0)
- return -1; /* critical; do not try to recover on oom */
+ git_filebuf_cleanup(&lock);
- if (git_path_exists(full_path.ptr) && p_unlink(full_path.ptr) < 0) {
- if (failed)
- continue;
+ /* We need to stop anybody from updating the ref while we try to do a safe delete */
+ error = loose_lock(&lock, backend, ref->name);
+ /* If someone else is updating it, let them do it */
+ if (error == GIT_EEXISTS || error == GIT_ENOTFOUND)
+ continue;
- giterr_set(GITERR_REFERENCE,
- "Failed to remove loose reference '%s' after packing: %s",
- full_path.ptr, strerror(errno));
- failed = 1;
+ if (error < 0) {
+ git_buf_free(&ref_content);
+ giterr_set(GITERR_REFERENCE, "failed to lock loose reference '%s'", ref->name);
+ return error;
}
+ error = git_futils_readbuffer(&ref_content, lock.path_original);
+ /* Someone else beat us to cleaning up the ref, let's simply continue */
+ if (error == GIT_ENOTFOUND)
+ continue;
+
+ /* This became a symref between us packing and trying to delete it, so ignore it */
+ if (!git__prefixcmp(ref_content.ptr, GIT_SYMREF))
+ continue;
+
+ /* Figure out the current id; if we find a bad ref file, skip it so we can do the rest */
+ if (loose_parse_oid(&current_id, lock.path_original, &ref_content) < 0)
+ continue;
+
+ /* If the ref moved since we packed it, we must not delete it */
+ if (!git_oid_equal(&current_id, &ref->oid))
+ continue;
+
/*
* if we fail to remove a single file, this is *not* good,
* but we should keep going and remove as many as possible.
- * After we've removed as many files as possible, we return
- * the error code anyway.
+ * If we fail to remove, the ref is still in the old state, so
+ * we haven't lost information.
*/
+ p_unlink(lock.path_original);
}
- git_buf_free(&full_path);
- return failed ? -1 : 0;
+ git_buf_free(&ref_content);
+ git_filebuf_cleanup(&lock);
+ return 0;
}
/*
@@ -944,41 +1002,45 @@ static int packed_write(refdb_fs_backend *backend)
{
git_sortedcache *refcache = backend->refcache;
git_filebuf pack_file = GIT_FILEBUF_INIT;
+ int error, open_flags = 0;
size_t i;
/* lock the cache to updates while we do this */
- if (git_sortedcache_wlock(refcache) < 0)
- return -1;
+ if ((error = git_sortedcache_wlock(refcache)) < 0)
+ return error;
+
+ if (backend->fsync)
+ open_flags = GIT_FILEBUF_FSYNC;
/* Open the file! */
- if (git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0, GIT_PACKEDREFS_FILE_MODE) < 0)
+ if ((error = git_filebuf_open(&pack_file, git_sortedcache_path(refcache), open_flags, GIT_PACKEDREFS_FILE_MODE)) < 0)
goto fail;
/* Packfiles have a header... apparently
* This is in fact not required, but we might as well print it
* just for kicks */
- if (git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER) < 0)
+ if ((error = git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < 0)
goto fail;
for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) {
struct packref *ref = git_sortedcache_entry(refcache, i);
assert(ref);
- if (packed_find_peel(backend, ref) < 0)
+ if ((error = packed_find_peel(backend, ref)) < 0)
goto fail;
- if (packed_write_ref(ref, &pack_file) < 0)
+ if ((error = packed_write_ref(ref, &pack_file)) < 0)
goto fail;
}
/* if we've written all the references properly, we can commit
* the packfile to make the changes effective */
- if (git_filebuf_commit(&pack_file) < 0)
+ if ((error = git_filebuf_commit(&pack_file)) < 0)
goto fail;
/* when and only when the packfile has been properly written,
* we can go ahead and remove the loose refs */
- if (packed_remove_loose(backend) < 0)
+ if ((error = packed_remove_loose(backend)) < 0)
goto fail;
git_sortedcache_updated(refcache);
@@ -991,7 +1053,7 @@ fail:
git_filebuf_cleanup(&pack_file);
git_sortedcache_wunlock(refcache);
- return -1;
+ return error;
}
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *author, const char *message);
@@ -1079,7 +1141,7 @@ out:
static int maybe_append_head(refdb_fs_backend *backend, const git_reference *ref, const git_signature *who, const char *message)
{
int error;
- git_oid old_id = {{0}};
+ git_oid old_id;
git_reference *tmp = NULL, *head = NULL, *peeled = NULL;
const char *name;
@@ -1087,7 +1149,8 @@ static int maybe_append_head(refdb_fs_backend *backend, const git_reference *ref
return 0;
/* if we can't resolve, we use {0}*40 as old id */
- git_reference_name_to_id(&old_id, backend->repo, ref->name);
+ if (git_reference_name_to_id(&old_id, backend->repo, ref->name) < 0)
+ memset(&old_id, 0, sizeof(old_id));
if ((error = git_reference_lookup(&head, backend->repo, GIT_HEAD_FILE)) < 0)
return error;
@@ -1143,8 +1206,7 @@ static int refdb_fs_backend__write(
assert(backend);
- error = reference_path_available(backend, ref->name, NULL, force);
- if (error < 0)
+ if ((error = reference_path_available(backend, ref->name, NULL, force)) < 0)
return error;
/* We need to perform the reflog append and old value check under the ref's lock */
@@ -1257,18 +1319,17 @@ static int refdb_fs_backend__delete_tail(
}
/* If a loose reference exists, remove it from the filesystem */
- if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0)
+ if (git_buf_joinpath(&loose_path, backend->gitpath, ref_name) < 0)
return -1;
- if (git_path_isfile(loose_path.ptr)) {
- error = p_unlink(loose_path.ptr);
- loose_deleted = 1;
- }
-
- git_buf_free(&loose_path);
- if (error != 0)
+ error = p_unlink(loose_path.ptr);
+ if (error < 0 && errno == ENOENT)
+ error = 0;
+ else if (error < 0)
goto cleanup;
+ else if (error == 0)
+ loose_deleted = 1;
if ((error = packed_reload(backend)) < 0)
goto cleanup;
@@ -1291,6 +1352,7 @@ static int refdb_fs_backend__delete_tail(
error = packed_write(backend);
cleanup:
+ git_buf_free(&loose_path);
git_filebuf_cleanup(file);
return error;
@@ -1362,14 +1424,15 @@ static int refdb_fs_backend__rename(
static int refdb_fs_backend__compress(git_refdb_backend *_backend)
{
+ int error;
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
assert(backend);
- if (packed_reload(backend) < 0 || /* load the existing packfile */
- packed_loadloose(backend) < 0 || /* add all the loose refs */
- packed_write(backend) < 0) /* write back to disk */
- return -1;
+ if ((error = packed_reload(backend)) < 0 || /* load the existing packfile */
+ (error = packed_loadloose(backend)) < 0 || /* add all the loose refs */
+ (error = packed_write(backend)) < 0) /* write back to disk */
+ return error;
return 0;
}
@@ -1381,28 +1444,30 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
assert(backend);
git_sortedcache_free(backend->refcache);
- git__free(backend->path);
+ git__free(backend->gitpath);
+ git__free(backend->commonpath);
git__free(backend);
}
-static int setup_namespace(git_buf *path, git_repository *repo)
+static char *setup_namespace(git_repository *repo, const char *in)
{
- char *parts, *start, *end;
+ git_buf path = GIT_BUF_INIT;
+ char *parts, *start, *end, *out = NULL;
- /* Not all repositories have a path */
- if (repo->path_repository == NULL)
- return 0;
+ if (!in)
+ goto done;
- /* Load the path to the repo first */
- git_buf_puts(path, repo->path_repository);
+ git_buf_puts(&path, in);
/* if the repo is not namespaced, nothing else to do */
- if (repo->namespace == NULL)
- return 0;
+ if (repo->namespace == NULL) {
+ out = git_buf_detach(&path);
+ goto done;
+ }
parts = end = git__strdup(repo->namespace);
if (parts == NULL)
- return -1;
+ goto done;
/*
* From `man gitnamespaces`:
@@ -1410,21 +1475,24 @@ static int setup_namespace(git_buf *path, git_repository *repo)
* of namespaces; for example, GIT_NAMESPACE=foo/bar will store
* refs under refs/namespaces/foo/refs/namespaces/bar/
*/
- while ((start = git__strsep(&end, "/")) != NULL) {
- git_buf_printf(path, "refs/namespaces/%s/", start);
- }
+ while ((start = git__strsep(&end, "/")) != NULL)
+ git_buf_printf(&path, "refs/namespaces/%s/", start);
- git_buf_printf(path, "refs/namespaces/%s/refs", end);
+ git_buf_printf(&path, "refs/namespaces/%s/refs", end);
git__free(parts);
/* Make sure that the folder with the namespace exists */
- if (git_futils_mkdir_relative(git_buf_cstr(path), repo->path_repository,
- 0777, GIT_MKDIR_PATH, NULL) < 0)
- return -1;
+ if (git_futils_mkdir_relative(git_buf_cstr(&path), in, 0777,
+ GIT_MKDIR_PATH, NULL) < 0)
+ goto done;
- /* Return root of the namespaced path, i.e. without the trailing '/refs' */
- git_buf_rtruncate_at_char(path, '/');
- return 0;
+ /* Return root of the namespaced gitpath, i.e. without the trailing '/refs' */
+ git_buf_rtruncate_at_char(&path, '/');
+ out = git_buf_detach(&path);
+
+done:
+ git_buf_free(&path);
+ return out;
}
static int reflog_alloc(git_reflog **reflog, const char *name)
@@ -1457,7 +1525,7 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size)
#define seek_forward(_increase) do { \
if (_increase >= buf_size) { \
- giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \
+ giterr_set(GITERR_INVALID, "ran out of data while parsing reflog"); \
goto fail; \
} \
buf += _increase; \
@@ -1535,7 +1603,7 @@ static int create_new_reflog_file(const char *filepath)
GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const char *name)
{
- return git_buf_join3(path, '/', repo->path_repository, GIT_REFLOG_DIR, name);
+ return git_buf_join3(path, '/', repo->commondir, GIT_REFLOG_DIR, name);
}
static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *name)
@@ -1673,7 +1741,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
repo = backend->repo;
if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
- giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", refname);
+ giterr_set(GITERR_INVALID, "invalid reference name '%s'", refname);
return GIT_EINVALIDSPEC;
}
@@ -1682,7 +1750,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
if (!git_path_isfile(git_buf_cstr(&log_path))) {
giterr_set(GITERR_INVALID,
- "Log file for reference '%s' doesn't exist.", refname);
+ "log file for reference '%s' doesn't exist", refname);
error = -1;
goto cleanup;
}
@@ -1734,7 +1802,7 @@ success:
/* Append to the reflog, must be called under reference lock */
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *who, const char *message)
{
- int error, is_symbolic;
+ int error, is_symbolic, open_flags;
git_oid old_id = {{0}}, new_id = {{0}};
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
git_repository *repo = backend->repo;
@@ -1789,9 +1857,10 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
* there maybe an obsolete/unused directory (or directory hierarchy) in the way.
*/
if (git_path_isdir(git_buf_cstr(&path))) {
- if ((git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0))
- error = -1;
- else if (git_path_isdir(git_buf_cstr(&path))) {
+ if ((error = git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_SKIP_NONEMPTY)) < 0) {
+ if (error == GIT_ENOTFOUND)
+ error = 0;
+ } else if (git_path_isdir(git_buf_cstr(&path))) {
giterr_set(GITERR_REFERENCE, "cannot create reflog at '%s', there are reflogs beneath that folder",
ref->name);
error = GIT_EDIRECTORY;
@@ -1801,7 +1870,12 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
goto cleanup;
}
- error = git_futils_writebuffer(&buf, git_buf_cstr(&path), O_WRONLY|O_CREAT|O_APPEND, GIT_REFLOG_FILE_MODE);
+ open_flags = O_WRONLY | O_CREAT | O_APPEND;
+
+ if (backend->fsync)
+ open_flags |= O_FSYNC;
+
+ error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE);
cleanup:
git_buf_free(&buf);
@@ -1829,7 +1903,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
&normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0)
return error;
- if (git_buf_joinpath(&temp_path, repo->path_repository, GIT_REFLOG_DIR) < 0)
+ if (git_buf_joinpath(&temp_path, repo->gitdir, GIT_REFLOG_DIR) < 0)
return -1;
if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), old_name) < 0)
@@ -1861,7 +1935,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
p_close(fd);
if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0) {
- giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name);
+ giterr_set(GITERR_OS, "failed to rename reflog for %s", new_name);
error = -1;
goto cleanup;
}
@@ -1878,7 +1952,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
}
if (p_rename(git_buf_cstr(&temp_path), git_buf_cstr(&new_path)) < 0) {
- giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name);
+ giterr_set(GITERR_OS, "failed to rename reflog for %s", new_name);
error = -1;
}
@@ -1920,7 +1994,7 @@ int git_refdb_backend_fs(
git_repository *repository)
{
int t = 0;
- git_buf path = GIT_BUF_INIT;
+ git_buf gitpath = GIT_BUF_INIT;
refdb_fs_backend *backend;
backend = git__calloc(1, sizeof(refdb_fs_backend));
@@ -1928,18 +2002,27 @@ int git_refdb_backend_fs(
backend->repo = repository;
- if (setup_namespace(&path, repository) < 0)
- goto fail;
+ if (repository->gitdir) {
+ backend->gitpath = setup_namespace(repository, repository->gitdir);
+
+ if (backend->gitpath == NULL)
+ goto fail;
+ }
- backend->path = git_buf_detach(&path);
+ if (repository->commondir) {
+ backend->commonpath = setup_namespace(repository, repository->commondir);
- if (git_buf_joinpath(&path, backend->path, GIT_PACKEDREFS_FILE) < 0 ||
+ if (backend->commonpath == NULL)
+ goto fail;
+ }
+
+ if (git_buf_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 ||
git_sortedcache_new(
&backend->refcache, offsetof(struct packref, name),
- NULL, NULL, packref_cmp, git_buf_cstr(&path)) < 0)
+ NULL, NULL, packref_cmp, git_buf_cstr(&gitpath)) < 0)
goto fail;
- git_buf_free(&path);
+ git_buf_free(&gitpath);
if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) {
backend->iterator_flags |= GIT_ITERATOR_IGNORE_CASE;
@@ -1949,6 +2032,9 @@ int git_refdb_backend_fs(
backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE;
backend->direach_flags |= GIT_PATH_DIR_PRECOMPOSE_UNICODE;
}
+ if ((!git_repository__cvar(&t, backend->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) ||
+ git_repository__fsync_gitdir)
+ backend->fsync = 1;
backend->parent.exists = &refdb_fs_backend__exists;
backend->parent.lookup = &refdb_fs_backend__lookup;
@@ -1971,8 +2057,9 @@ int git_refdb_backend_fs(
return 0;
fail:
- git_buf_free(&path);
- git__free(backend->path);
+ git_buf_free(&gitpath);
+ git__free(backend->gitpath);
+ git__free(backend->commonpath);
git__free(backend);
return -1;
}
diff --git a/src/refdb_fs.h b/src/refdb_fs.h
index 79e296833..0c84814df 100644
--- a/src/refdb_fs.h
+++ b/src/refdb_fs.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_refdb_fs_h__
#define INCLUDE_refdb_fs_h__
+#include "common.h"
+
+#include "strmap.h"
+
typedef struct {
git_strmap *packfile;
time_t packfile_time;
diff --git a/src/reflog.c b/src/reflog.c
index 9ce9aee6f..938999218 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -6,6 +6,7 @@
*/
#include "reflog.h"
+
#include "repository.h"
#include "filebuf.h"
#include "signature.h"
@@ -93,7 +94,7 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign
if (newline) {
if (newline[1] != '\0') {
- giterr_set(GITERR_INVALID, "Reflog message cannot contain newline");
+ giterr_set(GITERR_INVALID, "reflog message cannot contain newline");
goto cleanup;
}
@@ -193,7 +194,7 @@ int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry)
entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx);
if (entry == NULL) {
- giterr_set(GITERR_REFERENCE, "No reflog entry at index %"PRIuZ, idx);
+ giterr_set(GITERR_REFERENCE, "no reflog entry at index %"PRIuZ, idx);
return GIT_ENOTFOUND;
}
diff --git a/src/reflog.h b/src/reflog.h
index 2d31ae47d..d54b4cde8 100644
--- a/src/reflog.h
+++ b/src/reflog.h
@@ -8,6 +8,7 @@
#define INCLUDE_reflog_h__
#include "common.h"
+
#include "git2/reflog.h"
#include "vector.h"
diff --git a/src/refs.c b/src/refs.c
index bff443ac9..942054001 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -6,6 +6,7 @@
*/
#include "refs.h"
+
#include "hash.h"
#include "repository.h"
#include "fileops.h"
@@ -24,7 +25,7 @@
#include <git2/signature.h>
#include <git2/commit.h>
-GIT__USE_STRMAP
+bool git_reference__enable_symbolic_ref_target_validation = true;
#define DEFAULT_NESTING_LEVEL 5
#define MAX_NESTING_LEVEL 10
@@ -178,7 +179,8 @@ int git_reference_name_to_id(
static int reference_normalize_for_repo(
git_refname_t out,
git_repository *repo,
- const char *name)
+ const char *name,
+ bool validate)
{
int precompose;
unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL;
@@ -187,6 +189,9 @@ static int reference_normalize_for_repo(
precompose)
flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE;
+ if (!validate)
+ flags |= GIT_REF_FORMAT__VALIDATION_DISABLE;
+
return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags);
}
@@ -213,7 +218,7 @@ int git_reference_lookup_resolved(
scan_type = GIT_REF_SYMBOLIC;
- if ((error = reference_normalize_for_repo(scan_name, repo, name)) < 0)
+ if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0)
return error;
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
@@ -236,7 +241,7 @@ int git_reference_lookup_resolved(
if (scan_type != GIT_REF_OID && max_nesting != 0) {
giterr_set(GITERR_REFERENCE,
- "Cannot resolve reference (>%u levels deep)", max_nesting);
+ "cannot resolve reference (>%u levels deep)", max_nesting);
git_reference_free(ref);
return -1;
}
@@ -245,6 +250,40 @@ int git_reference_lookup_resolved(
return 0;
}
+int git_reference__read_head(
+ git_reference **out,
+ git_repository *repo,
+ const char *path)
+{
+ git_buf reference = GIT_BUF_INIT;
+ char *name = NULL;
+ int error;
+
+ if ((error = git_futils_readbuffer(&reference, path)) < 0)
+ goto out;
+ git_buf_rtrim(&reference);
+
+ if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) {
+ git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
+
+ name = git_path_basename(path);
+
+ if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) {
+ error = -1;
+ goto out;
+ }
+ } else {
+ if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0)
+ goto out;
+ }
+
+out:
+ git__free(name);
+ git_buf_free(&reference);
+
+ return error;
+}
+
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
{
int error = 0, i;
@@ -298,7 +337,7 @@ cleanup:
if (error && !foundvalid) {
/* never found a valid reference name */
giterr_set(GITERR_REFERENCE,
- "Could not use '%s' as valid reference name", git_buf_cstr(&name));
+ "could not use '%s' as valid reference name", git_buf_cstr(&name));
}
if (error == GIT_ENOTFOUND)
@@ -383,7 +422,7 @@ static int reference__create(
if (ref_out)
*ref_out = NULL;
- error = reference_normalize_for_repo(normalized, repo, name);
+ error = reference_normalize_for_repo(normalized, repo, name, true);
if (error < 0)
return error;
@@ -396,7 +435,7 @@ static int reference__create(
if (!git_object__is_valid(repo, oid, GIT_OBJ_ANY)) {
giterr_set(GITERR_REFERENCE,
- "Target OID for the reference doesn't exist on the repository");
+ "target OID for the reference doesn't exist on the repository");
return -1;
}
@@ -404,7 +443,10 @@ static int reference__create(
} else {
git_refname_t normalized_target;
- if ((error = reference_normalize_for_repo(normalized_target, repo, symbolic)) < 0)
+ error = reference_normalize_for_repo(normalized_target, repo,
+ symbolic, git_reference__enable_symbolic_ref_target_validation);
+
+ if (error < 0)
return error;
ref = git_reference__alloc_symbolic(normalized, normalized_target);
@@ -524,7 +566,7 @@ static int ensure_is_an_updatable_direct_reference(git_reference *ref)
if (ref->type == GIT_REF_OID)
return 0;
- giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference");
+ giterr_set(GITERR_REFERENCE, "cannot set OID on symbolic reference");
return -1;
}
@@ -552,7 +594,7 @@ static int ensure_is_an_updatable_symbolic_reference(git_reference *ref)
if (ref->type == GIT_REF_SYMBOLIC)
return 0;
- giterr_set(GITERR_REFERENCE, "Cannot set symbolic target on a direct reference");
+ giterr_set(GITERR_REFERENCE, "cannot set symbolic target on a direct reference");
return -1;
}
@@ -573,20 +615,63 @@ int git_reference_symbolic_set_target(
out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, log_message);
}
+typedef struct {
+ const char *old_name;
+ git_refname_t new_name;
+} rename_cb_data;
+
+static int update_wt_heads(git_repository *repo, const char *path, void *payload)
+{
+ rename_cb_data *data = (rename_cb_data *) payload;
+ git_reference *head = NULL;
+ char *gitdir = NULL;
+ int error;
+
+ if ((error = git_reference__read_head(&head, repo, path)) < 0) {
+ giterr_set(GITERR_REFERENCE, "could not read HEAD when renaming references");
+ goto out;
+ }
+
+ if ((gitdir = git_path_dirname(path)) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if (git_reference_type(head) != GIT_REF_SYMBOLIC ||
+ git__strcmp(head->target.symbolic, data->old_name) != 0) {
+ error = 0;
+ goto out;
+ }
+
+ /* Update HEAD it was pointing to the reference being renamed */
+ if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) {
+ giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference");
+ goto out;
+ }
+
+out:
+ git_reference_free(head);
+ git__free(gitdir);
+
+ return error;
+}
+
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
const git_signature *signature, const char *message)
{
+ git_repository *repo;
git_refname_t normalized;
bool should_head_be_updated = false;
int error = 0;
assert(ref && new_name && signature);
+ repo = git_reference_owner(ref);
+
if ((error = reference_normalize_for_repo(
- normalized, git_reference_owner(ref), new_name)) < 0)
+ normalized, repo, new_name, true)) < 0)
return error;
-
/* Check if we have to update HEAD. */
if ((error = git_branch_is_head(ref)) < 0)
return error;
@@ -596,14 +681,18 @@ static int reference__rename(git_reference **out, git_reference *ref, const char
if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0)
return error;
- /* Update HEAD it was pointing to the reference being renamed */
- if (should_head_be_updated &&
- (error = git_repository_set_head(ref->db->repo, normalized)) < 0) {
- giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
- return error;
+ /* Update HEAD if it was pointing to the reference being renamed */
+ if (should_head_be_updated) {
+ error = git_repository_set_head(ref->db->repo, normalized);
+ } else {
+ rename_cb_data payload;
+ payload.old_name = ref->name;
+ memcpy(&payload.new_name, &normalized, sizeof(normalized));
+
+ error = git_repository_foreach_head(repo, update_wt_heads, &payload);
}
- return 0;
+ return error;
}
@@ -636,7 +725,7 @@ int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1);
default:
- giterr_set(GITERR_REFERENCE, "Invalid reference");
+ giterr_set(GITERR_REFERENCE, "invalid reference");
return -1;
}
}
@@ -876,6 +965,7 @@ int git_reference__normalize_name(
int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
unsigned int process_flags;
bool normalize = (buf != NULL);
+ bool validate = (flags & GIT_REF_FORMAT__VALIDATION_DISABLE) == 0;
#ifdef GIT_USE_ICONV
git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -886,7 +976,7 @@ int git_reference__normalize_name(
process_flags = flags;
current = (char *)name;
- if (*current == '/')
+ if (validate && *current == '/')
goto cleanup;
if (normalize)
@@ -902,6 +992,13 @@ int git_reference__normalize_name(
}
#endif
+ if (!validate) {
+ git_buf_sets(buf, current);
+
+ error = git_buf_oom(buf) ? -1 : 0;
+ goto cleanup;
+ }
+
while (true) {
segment_len = ensure_segment_validity(current);
if (segment_len < 0) {
@@ -973,7 +1070,7 @@ cleanup:
if (error == GIT_EINVALIDSPEC)
giterr_set(
GITERR_REFERENCE,
- "The given reference name '%s' is not valid", name);
+ "the given reference name '%s' is not valid", name);
if (error && normalize)
git_buf_free(buf);
@@ -1000,7 +1097,7 @@ int git_reference_normalize_name(
if (git_buf_len(&buf) > buffer_size - 1) {
giterr_set(
GITERR_REFERENCE,
- "The provided buffer is too short to hold the normalization of '%s'", name);
+ "the provided buffer is too short to hold the normalization of '%s'", name);
error = GIT_EBUFS;
goto cleanup;
}
@@ -1046,7 +1143,7 @@ static int get_terminal(git_reference **out, git_repository *repo, const char *r
int error = 0;
if (nesting > MAX_NESTING_LEVEL) {
- giterr_set(GITERR_REFERENCE, "Reference chain too deep (%d)", nesting);
+ giterr_set(GITERR_REFERENCE, "reference chain too deep (%d)", nesting);
return GIT_ENOTFOUND;
}
@@ -1115,6 +1212,18 @@ int git_reference__update_terminal(
return error;
}
+static const char *commit_type(const git_commit *commit)
+{
+ unsigned int count = git_commit_parentcount(commit);
+
+ if (count >= 2)
+ return " (merge)";
+ else if (count == 0)
+ return " (initial)";
+ else
+ return "";
+}
+
int git_reference__update_for_commit(
git_repository *repo,
git_reference *ref,
@@ -1131,7 +1240,7 @@ int git_reference__update_for_commit(
if ((error = git_commit_lookup(&commit, repo, id)) < 0 ||
(error = git_buf_printf(&reflog_msg, "%s%s: %s",
operation ? operation : "commit",
- git_commit_parentcount(commit) == 0 ? " (initial)" : "",
+ commit_type(commit),
git_commit_summary(commit))) < 0)
goto done;
@@ -1229,7 +1338,7 @@ static int peel_error(int error, git_reference *ref, const char* msg)
{
giterr_set(
GITERR_INVALID,
- "The reference '%s' cannot be peeled - %s", git_reference_name(ref), msg);
+ "the reference '%s' cannot be peeled - %s", git_reference_name(ref), msg);
return error;
}
diff --git a/src/refs.h b/src/refs.h
index fda9532de..7a1a9aed1 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -8,6 +8,7 @@
#define INCLUDE_refs_h__
#include "common.h"
+
#include "git2/oid.h"
#include "git2/refs.h"
#include "git2/refdb.h"
@@ -15,6 +16,8 @@
#include "buffer.h"
#include "oid.h"
+extern bool git_reference__enable_symbolic_ref_target_validation;
+
#define GIT_REFS_DIR "refs/"
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
@@ -53,6 +56,7 @@
#define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE
#define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16)
+#define GIT_REF_FORMAT__VALIDATION_DISABLE (1u << 15)
#define GIT_REFNAME_MAX 1024
@@ -104,6 +108,20 @@ int git_reference_lookup_resolved(
const char *name,
int max_deref);
+/**
+ * Read reference from a file.
+ *
+ * This function will read in the file at `path`. If it is a
+ * symref, it will return a new unresolved symbolic reference
+ * with the given name pointing to the reference pointed to by
+ * the file. If it is not a symbolic reference, it will return
+ * the resolved reference.
+ */
+int git_reference__read_head(
+ git_reference **out,
+ git_repository *repo,
+ const char *path);
+
int git_reference__log_signature(git_signature **out, git_repository *repo);
/** Update a reference after a commit. */
diff --git a/src/refspec.c b/src/refspec.c
index d200e5609..01a77c97f 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "refspec.h"
+
#include "git2/errors.h"
-#include "common.h"
-#include "refspec.h"
#include "util.h"
#include "posix.h"
#include "refs.h"
diff --git a/src/refspec.h b/src/refspec.h
index 9a87c97a5..fd2d8b312 100644
--- a/src/refspec.h
+++ b/src/refspec.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_refspec_h__
#define INCLUDE_refspec_h__
+#include "common.h"
+
#include "git2/refspec.h"
#include "buffer.h"
#include "vector.h"
diff --git a/src/remote.c b/src/remote.c
index c1d7d59ea..303911760 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -5,15 +5,15 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "remote.h"
+
#include "git2/config.h"
#include "git2/types.h"
#include "git2/oid.h"
#include "git2/net.h"
-#include "common.h"
#include "config.h"
#include "repository.h"
-#include "remote.h"
#include "fetch.h"
#include "refs.h"
#include "refspec.h"
@@ -192,15 +192,15 @@ static int canonicalize_url(git_buf *out, const char *in)
static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
{
git_remote *remote;
- git_config *config = NULL;
+ git_config *config_ro = NULL, *config_rw;
git_buf canonical_url = GIT_BUF_INIT;
git_buf var = GIT_BUF_INIT;
int error = -1;
- /* name is optional */
- assert(out && repo && url);
+ /* repo, name, and fetch are optional */
+ assert(out && url);
- if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ if (repo && (error = git_repository_config_snapshot(&config_ro, repo)) < 0)
return error;
remote = git__calloc(1, sizeof(git_remote));
@@ -212,7 +212,12 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
(error = canonicalize_url(&canonical_url, url)) < 0)
goto on_error;
- remote->url = apply_insteadof(repo->_config, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ if (repo) {
+ remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ } else {
+ remote->url = git__strdup(canonical_url.ptr);
+ }
+ GITERR_CHECK_ALLOC(remote->url);
if (name != NULL) {
remote->name = git__strdup(name);
@@ -221,7 +226,9 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
if ((error = git_buf_printf(&var, CONFIG_URL_FMT, name)) < 0)
goto on_error;
- if ((error = git_config_set_string(config, var.ptr, canonical_url.ptr)) < 0)
+ if (repo &&
+ ((error = git_repository_config__weakptr(&config_rw, repo)) < 0 ||
+ (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
goto on_error;
}
@@ -233,10 +240,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
if (name && (error = write_add_refspec(repo, name, fetch, true)) < 0)
goto on_error;
- if ((error = git_repository_config_snapshot(&config, repo)) < 0)
- goto on_error;
-
- if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
+ if (repo && (error = lookup_remote_prune_config(remote, config_ro, name)) < 0)
goto on_error;
/* Move the data over to where the matching functions can find them */
@@ -260,7 +264,7 @@ on_error:
if (error)
git_remote_free(remote);
- git_config_free(config);
+ git_config_free(config_ro);
git_buf_free(&canonical_url);
git_buf_free(&var);
return error;
@@ -283,7 +287,7 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
giterr_set(
GITERR_CONFIG,
- "Remote '%s' already exists.", name);
+ "remote '%s' already exists", name);
return GIT_EEXISTS;
}
@@ -331,6 +335,11 @@ int git_remote_create_anonymous(git_remote **out, git_repository *repo, const ch
return create_internal(out, repo, NULL, url, NULL);
}
+int git_remote_create_detached(git_remote **out, const char *url)
+{
+ return create_internal(out, NULL, NULL, url, NULL);
+}
+
int git_remote_dup(git_remote **dest, git_remote *source)
{
size_t i;
@@ -476,7 +485,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
if (!optional_setting_found) {
error = GIT_ENOTFOUND;
- giterr_set(GITERR_CONFIG, "Remote '%s' does not exist.", name);
+ giterr_set(GITERR_CONFIG, "remote '%s' does not exist", name);
goto cleanup;
}
@@ -675,7 +684,9 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re
url = git_remote__urlfordirection(remote, direction);
if (url == NULL) {
giterr_set(GITERR_INVALID,
- "Malformed remote '%s' - missing URL", remote->name);
+ "Malformed remote '%s' - missing %s URL",
+ remote->name ? remote->name : "(anonymous)",
+ direction == GIT_DIRECTION_FETCH ? "fetch" : "push");
return -1;
}
@@ -770,8 +781,12 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur
goto found;
}
- /* HTTP_PROXY / HTTPS_PROXY environment variables */
- error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
+ /* http_proxy / https_proxy environment variables */
+ error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy");
+
+ /* try uppercase environment variables */
+ if (error == GIT_ENOTFOUND)
+ error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
if (error < 0) {
if (error == GIT_ENOTFOUND) {
@@ -856,6 +871,11 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
assert(remote);
+ if (!remote->repo) {
+ giterr_set(GITERR_INVALID, "cannot download detached remote");
+ return -1;
+ }
+
if (opts) {
GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
cbs = &opts->callbacks;
@@ -1718,7 +1738,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_
error = 0;
break;
default:
- giterr_set(GITERR_INVALID, "Invalid value for the tagopt setting");
+ giterr_set(GITERR_INVALID, "invalid value for the tagopt setting");
error = -1;
}
@@ -2341,6 +2361,11 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
assert(remote);
+ if (!remote->repo) {
+ giterr_set(GITERR_INVALID, "cannot download detached remote");
+ return -1;
+ }
+
if (opts) {
cbs = &opts->callbacks;
custom_headers = &opts->custom_headers;
@@ -2400,6 +2425,13 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
const git_strarray *custom_headers = NULL;
const git_proxy_options *proxy = NULL;
+ assert(remote);
+
+ if (!remote->repo) {
+ giterr_set(GITERR_INVALID, "cannot download detached remote");
+ return -1;
+ }
+
if (opts) {
GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
cbs = &opts->callbacks;
@@ -2408,7 +2440,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
proxy = &opts->proxy_opts;
}
- assert(remote && refspecs);
+ assert(remote);
if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
return error;
diff --git a/src/remote.h b/src/remote.h
index e696997f4..a94481f25 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_remote_h__
#define INCLUDE_remote_h__
+#include "common.h"
+
#include "git2/remote.h"
#include "git2/transport.h"
#include "git2/sys/transport.h"
diff --git a/src/repository.c b/src/repository.c
index cf3d18a2d..fe549e6e8 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -4,6 +4,9 @@
* 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 "repository.h"
+
#include <ctype.h>
#include "git2/object.h"
@@ -11,7 +14,6 @@
#include "git2/sys/repository.h"
#include "common.h"
-#include "repository.h"
#include "commit.h"
#include "tag.h"
#include "blob.h"
@@ -27,13 +29,43 @@
#include "merge.h"
#include "diff_driver.h"
#include "annotated_commit.h"
+#include "submodule.h"
+#include "worktree.h"
+
+#include "strmap.h"
#ifdef GIT_WIN32
# include "win32/w32_util.h"
#endif
+bool git_repository__fsync_gitdir = false;
+
+static const struct {
+ git_repository_item_t parent;
+ const char *name;
+ bool directory;
+} items[] = {
+ { GIT_REPOSITORY_ITEM_GITDIR, NULL, true },
+ { GIT_REPOSITORY_ITEM_WORKDIR, NULL, true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true },
+ { GIT_REPOSITORY_ITEM_GITDIR, "index", false },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "config", false },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "info", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true },
+ { GIT_REPOSITORY_ITEM_GITDIR, "modules", true },
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true }
+};
+
static int check_repositoryformatversion(git_config *config);
+#define GIT_COMMONDIR_FILE "commondir"
+#define GIT_GITDIR_FILE "gitdir"
+
#define GIT_FILE_CONTENT_PREFIX "gitdir:"
#define GIT_BRANCH_MASTER "master"
@@ -109,6 +141,7 @@ void git_repository__cleanup(git_repository *repo)
{
assert(repo);
+ git_repository_submodule_cache_clear(repo);
git_cache_clear(&repo->objects);
git_attr_cache_flush(repo);
@@ -136,8 +169,9 @@ void git_repository_free(git_repository *repo)
git_buf_free(git_array_get(repo->reserved_names, i));
git_array_clear(repo->reserved_names);
- git__free(repo->path_gitlink);
- git__free(repo->path_repository);
+ git__free(repo->gitlink);
+ git__free(repo->gitdir);
+ git__free(repo->commondir);
git__free(repo->workdir);
git__free(repo->namespace);
git__free(repo->ident_name);
@@ -152,17 +186,41 @@ void git_repository_free(git_repository *repo)
*
* Open a repository object from its path
*/
-static bool valid_repository_path(git_buf *repository_path)
+static bool valid_repository_path(git_buf *repository_path, git_buf *common_path)
{
- /* Check OBJECTS_DIR first, since it will generate the longest path name */
- if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
- return false;
+ /* Check if we have a separate commondir (e.g. we have a
+ * worktree) */
+ if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
+ git_buf common_link = GIT_BUF_INIT;
+ git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE);
+
+ git_futils_readbuffer(&common_link, common_link.ptr);
+ git_buf_rtrim(&common_link);
+
+ if (git_path_is_relative(common_link.ptr)) {
+ git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr);
+ } else {
+ git_buf_swap(common_path, &common_link);
+ }
+
+ git_buf_free(&common_link);
+ }
+ else {
+ git_buf_set(common_path, repository_path->ptr, repository_path->size);
+ }
+
+ /* Make sure the commondir path always has a trailing * slash */
+ if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1)
+ git_buf_putc(common_path, '/');
/* Ensure HEAD file exists */
if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
return false;
- if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
+ /* Check files in common dir */
+ if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
+ return false;
+ if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false)
return false;
return true;
@@ -201,6 +259,7 @@ int git_repository_new(git_repository **out)
GITERR_CHECK_ALLOC(repo);
repo->is_bare = 1;
+ repo->is_worktree = 0;
return 0;
}
@@ -220,9 +279,10 @@ static int load_config_data(git_repository *repo, const git_config *config)
static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path)
{
- int error;
+ int error;
git_config_entry *ce;
- git_buf worktree = GIT_BUF_INIT;
+ git_buf worktree = GIT_BUF_INIT;
+ git_buf path = GIT_BUF_INIT;
if (repo->is_bare)
return 0;
@@ -231,9 +291,26 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren
&ce, config, "core.worktree", false)) < 0)
return error;
- if (ce && ce->value) {
+ if (repo->is_worktree) {
+ char *gitlink = git_worktree__read_link(repo->gitdir, GIT_GITDIR_FILE);
+ if (!gitlink) {
+ error = -1;
+ goto cleanup;
+ }
+
+ git_buf_attach(&worktree, gitlink, 0);
+
+ if ((git_path_dirname_r(&worktree, worktree.ptr)) < 0 ||
+ git_path_to_dir(&worktree) < 0) {
+ error = -1;
+ goto cleanup;
+ }
+
+ repo->workdir = git_buf_detach(&worktree);
+ }
+ else if (ce && ce->value) {
if ((error = git_path_prettify_dir(
- &worktree, ce->value, repo->path_repository)) < 0)
+ &worktree, ce->value, repo->gitdir)) < 0)
goto cleanup;
repo->workdir = git_buf_detach(&worktree);
@@ -241,7 +318,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren
else if (parent_path && git_path_isdir(parent_path->ptr))
repo->workdir = git_buf_detach(parent_path);
else {
- if (git_path_dirname_r(&worktree, repo->path_repository) < 0 ||
+ if (git_path_dirname_r(&worktree, repo->gitdir) < 0 ||
git_path_to_dir(&worktree) < 0) {
error = -1;
goto cleanup;
@@ -252,6 +329,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren
GITERR_CHECK_ALLOC(repo->workdir);
cleanup:
+ git_buf_free(&path);
git_config_entry_free(ce);
return error;
}
@@ -332,7 +410,7 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
{
giterr_set(GITERR_REPOSITORY,
- "The `.git` file at '%s' is malformed", file_path);
+ "the `.git` file at '%s' is malformed", file_path);
error = -1;
}
else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
@@ -348,9 +426,10 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
}
static int find_repo(
- git_buf *repo_path,
- git_buf *parent_path,
- git_buf *link_path,
+ git_buf *gitdir_path,
+ git_buf *workdir_path,
+ git_buf *gitlink_path,
+ git_buf *commondir_path,
const char *start_path,
uint32_t flags,
const char *ceiling_dirs)
@@ -358,13 +437,14 @@ static int find_repo(
int error;
git_buf path = GIT_BUF_INIT;
git_buf repo_link = GIT_BUF_INIT;
+ git_buf common_link = GIT_BUF_INIT;
struct stat st;
dev_t initial_device = 0;
int min_iterations;
bool in_dot_git;
size_t ceiling_offset = 0;
- git_buf_free(repo_path);
+ git_buf_clear(gitdir_path);
error = git_path_prettify(&path, start_path, NULL);
if (error < 0)
@@ -404,21 +484,30 @@ static int find_repo(
break;
if (S_ISDIR(st.st_mode)) {
- if (valid_repository_path(&path)) {
+ if (valid_repository_path(&path, &common_link)) {
git_path_to_dir(&path);
- git_buf_set(repo_path, path.ptr, path.size);
+ git_buf_set(gitdir_path, path.ptr, path.size);
+
+ if (gitlink_path)
+ git_buf_attach(gitlink_path,
+ git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0);
+ if (commondir_path)
+ git_buf_swap(&common_link, commondir_path);
+
break;
}
}
- else if (S_ISREG(st.st_mode)) {
+ else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
error = read_gitfile(&repo_link, path.ptr);
if (error < 0)
break;
- if (valid_repository_path(&repo_link)) {
- git_buf_swap(repo_path, &repo_link);
+ if (valid_repository_path(&repo_link, &common_link)) {
+ git_buf_swap(gitdir_path, &repo_link);
- if (link_path)
- error = git_buf_put(link_path, path.ptr, path.size);
+ if (gitlink_path)
+ error = git_buf_put(gitlink_path, path.ptr, path.size);
+ if (commondir_path)
+ git_buf_swap(&common_link, commondir_path);
}
break;
}
@@ -444,27 +533,28 @@ static int find_repo(
break;
}
- if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
- if (!git_buf_len(repo_path))
- git_buf_clear(parent_path);
+ if (!error && workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
+ if (!git_buf_len(gitdir_path))
+ git_buf_clear(workdir_path);
else {
- git_path_dirname_r(parent_path, path.ptr);
- git_path_to_dir(parent_path);
+ git_path_dirname_r(workdir_path, path.ptr);
+ git_path_to_dir(workdir_path);
}
- if (git_buf_oom(parent_path))
+ if (git_buf_oom(workdir_path))
return -1;
}
/* If we didn't find the repository, and we don't have any other error
* to report, report that. */
- if (!git_buf_len(repo_path) && !error) {
+ if (!git_buf_len(gitdir_path) && !error) {
giterr_set(GITERR_REPOSITORY,
- "Could not find repository from '%s'", start_path);
+ "could not find repository from '%s'", start_path);
error = GIT_ENOTFOUND;
}
git_buf_free(&path);
git_buf_free(&repo_link);
+ git_buf_free(&common_link);
return error;
}
@@ -473,26 +563,30 @@ int git_repository_open_bare(
const char *bare_path)
{
int error;
- git_buf path = GIT_BUF_INIT;
+ git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT;
git_repository *repo = NULL;
if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0)
return error;
- if (!valid_repository_path(&path)) {
+ if (!valid_repository_path(&path, &common_path)) {
git_buf_free(&path);
- giterr_set(GITERR_REPOSITORY, "Path is not a repository: %s", bare_path);
+ git_buf_free(&common_path);
+ giterr_set(GITERR_REPOSITORY, "path is not a repository: %s", bare_path);
return GIT_ENOTFOUND;
}
repo = repository_alloc();
GITERR_CHECK_ALLOC(repo);
- repo->path_repository = git_buf_detach(&path);
- GITERR_CHECK_ALLOC(repo->path_repository);
+ repo->gitdir = git_buf_detach(&path);
+ GITERR_CHECK_ALLOC(repo->gitdir);
+ repo->commondir = git_buf_detach(&common_path);
+ GITERR_CHECK_ALLOC(repo->commondir);
/* of course we're bare! */
repo->is_bare = 1;
+ repo->is_worktree = 0;
repo->workdir = NULL;
*repo_ptr = repo;
@@ -613,9 +707,10 @@ static int _git_repository_open_ext_from_env(
git_repository_set_odb(repo, odb);
error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
- if (error == GIT_ENOTFOUND)
+ if (error == GIT_ENOTFOUND) {
giterr_clear();
- else if (error < 0)
+ error = 0;
+ } else if (error < 0)
goto error;
else {
const char *end;
@@ -638,9 +733,11 @@ static int _git_repository_open_ext_from_env(
}
}
- error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
- if (error < 0)
- goto error;
+ if (git_buf_len(&namespace_buf)) {
+ error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
+ if (error < 0)
+ goto error;
+ }
git_repository_set_index(repo, index);
@@ -665,6 +762,29 @@ success:
return error;
}
+static int repo_is_worktree(unsigned *out, const git_repository *repo)
+{
+ git_buf gitdir_link = GIT_BUF_INIT;
+ int error;
+
+ /* Worktrees cannot have the same commondir and gitdir */
+ if (repo->commondir && repo->gitdir
+ && !strcmp(repo->commondir, repo->gitdir)) {
+ *out = 0;
+ return 0;
+ }
+
+ if ((error = git_buf_joinpath(&gitdir_link, repo->gitdir, "gitdir")) < 0)
+ return -1;
+
+ /* A 'gitdir' file inside a git directory is currently
+ * only used when the repository is a working tree. */
+ *out = !!git_path_exists(gitdir_link.ptr);
+
+ git_buf_free(&gitdir_link);
+ return error;
+}
+
int git_repository_open_ext(
git_repository **repo_ptr,
const char *start_path,
@@ -672,8 +792,9 @@ int git_repository_open_ext(
const char *ceiling_dirs)
{
int error;
- git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT,
- link_path = GIT_BUF_INIT;
+ unsigned is_worktree;
+ git_buf gitdir = GIT_BUF_INIT, workdir = GIT_BUF_INIT,
+ gitlink = GIT_BUF_INIT, commondir = GIT_BUF_INIT;
git_repository *repo;
git_config *config = NULL;
@@ -684,7 +805,7 @@ int git_repository_open_ext(
*repo_ptr = NULL;
error = find_repo(
- &path, &parent, &link_path, start_path, flags, ceiling_dirs);
+ &gitdir, &workdir, &gitlink, &commondir, start_path, flags, ceiling_dirs);
if (error < 0 || !repo_ptr)
return error;
@@ -692,14 +813,22 @@ int git_repository_open_ext(
repo = repository_alloc();
GITERR_CHECK_ALLOC(repo);
- repo->path_repository = git_buf_detach(&path);
- GITERR_CHECK_ALLOC(repo->path_repository);
+ repo->gitdir = git_buf_detach(&gitdir);
+ GITERR_CHECK_ALLOC(repo->gitdir);
- if (link_path.size) {
- repo->path_gitlink = git_buf_detach(&link_path);
- GITERR_CHECK_ALLOC(repo->path_gitlink);
+ if (gitlink.size) {
+ repo->gitlink = git_buf_detach(&gitlink);
+ GITERR_CHECK_ALLOC(repo->gitlink);
+ }
+ if (commondir.size) {
+ repo->commondir = git_buf_detach(&commondir);
+ GITERR_CHECK_ALLOC(repo->commondir);
}
+ if ((error = repo_is_worktree(&is_worktree, repo)) < 0)
+ goto cleanup;
+ repo->is_worktree = is_worktree;
+
/*
* We'd like to have the config, but git doesn't particularly
* care if it's not there, so we need to deal with that.
@@ -718,12 +847,13 @@ int git_repository_open_ext(
if (config &&
((error = load_config_data(repo, config)) < 0 ||
- (error = load_workdir(repo, config, &parent)) < 0))
+ (error = load_workdir(repo, config, &workdir)) < 0))
goto cleanup;
}
cleanup:
- git_buf_free(&parent);
+ git_buf_free(&gitdir);
+ git_buf_free(&workdir);
git_config_free(config);
if (error < 0)
@@ -740,6 +870,36 @@ int git_repository_open(git_repository **repo_out, const char *path)
repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL);
}
+int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *wt)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_repository *repo = NULL;
+ int len, err;
+
+ assert(repo_out && wt);
+
+ *repo_out = NULL;
+ len = strlen(wt->gitlink_path);
+
+ if (len <= 4 || strcasecmp(wt->gitlink_path + len - 4, ".git")) {
+ err = -1;
+ goto out;
+ }
+
+ if ((err = git_buf_set(&path, wt->gitlink_path, len - 4)) < 0)
+ goto out;
+
+ if ((err = git_repository_open(&repo, path.ptr)) < 0)
+ goto out;
+
+ *repo_out = repo;
+
+out:
+ git_buf_free(&path);
+
+ return err;
+}
+
int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
{
git_repository *repo;
@@ -765,7 +925,7 @@ int git_repository_discover(
git_buf_sanitize(out);
- return find_repo(out, NULL, NULL, start_path, flags, ceiling_dirs);
+ return find_repo(out, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
}
static int load_config(
@@ -785,14 +945,10 @@ static int load_config(
if ((error = git_config_new(&cfg)) < 0)
return error;
- error = git_buf_joinpath(
- &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
- if (error < 0)
- goto on_error;
+ if ((error = git_repository_item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG)) == 0)
+ error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0);
- if ((error = git_config_add_file_ondisk(
- cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0 &&
- error != GIT_ENOTFOUND)
+ if (error && error != GIT_ENOTFOUND)
goto on_error;
git_buf_free(&config_path);
@@ -920,18 +1076,23 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
git_buf odb_path = GIT_BUF_INIT;
git_odb *odb;
- if ((error = git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR)) < 0)
+ if ((error = git_repository_item_path(&odb_path, repo,
+ GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
+ (error = git_odb_new(&odb)) < 0)
return error;
- error = git_odb_open(&odb, odb_path.ptr);
- if (!error) {
- GIT_REFCOUNT_OWN(odb, repo);
+ GIT_REFCOUNT_OWN(odb, repo);
- odb = git__compare_and_swap(&repo->_odb, NULL, odb);
- if (odb != NULL) {
- GIT_REFCOUNT_OWN(odb, NULL);
- git_odb_free(odb);
- }
+ if ((error = git_odb__set_caps(odb, GIT_ODB_CAP_FROM_OWNER)) < 0 ||
+ (error = git_odb__add_default_backends(odb, odb_path.ptr, 0, 0)) < 0) {
+ git_odb_free(odb);
+ return error;
+ }
+
+ odb = git__compare_and_swap(&repo->_odb, NULL, odb);
+ if (odb != NULL) {
+ GIT_REFCOUNT_OWN(odb, NULL);
+ git_odb_free(odb);
}
git_buf_free(&odb_path);
@@ -1006,7 +1167,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
git_buf index_path = GIT_BUF_INIT;
git_index *index;
- if ((error = git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE)) < 0)
+ if ((error = git_buf_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0)
return error;
error = git_index_open(&index, index_path.ptr);
@@ -1076,7 +1237,7 @@ static int reserved_names_add8dot3(git_repository *repo, const char *path)
name_len = strlen(name);
- if ((name_len == def_len && memcmp(name, def, def_len) == 0) ||
+ if ((name_len == def_len && memcmp(name, def, def_len) == 0) ||
(name_len == def_dot_git_len && memcmp(name, def_dot_git, def_dot_git_len) == 0)) {
git__free(name);
return 0;
@@ -1122,13 +1283,13 @@ bool git_repository__reserved_names(
prefixcmp = (error || ignorecase) ? git__prefixcmp_icase :
git__prefixcmp;
- if (repo->path_gitlink &&
- reserved_names_add8dot3(repo, repo->path_gitlink) < 0)
+ if (repo->gitlink &&
+ reserved_names_add8dot3(repo, repo->gitlink) < 0)
goto on_error;
- if (repo->path_repository &&
- prefixcmp(repo->path_repository, repo->workdir) == 0 &&
- reserved_names_add8dot3(repo, repo->path_repository) < 0)
+ if (repo->gitdir &&
+ prefixcmp(repo->gitdir, repo->workdir) == 0 &&
+ reserved_names_add8dot3(repo, repo->gitdir) < 0)
goto on_error;
}
}
@@ -1177,7 +1338,7 @@ static int check_repositoryformatversion(git_config *config)
if (GIT_REPO_VERSION < version) {
giterr_set(GITERR_REPOSITORY,
- "Unsupported repository version %d. Only versions up to %d are supported.",
+ "unsupported repository version %d. Only versions up to %d are supported.",
version, GIT_REPO_VERSION);
return -1;
}
@@ -1185,7 +1346,7 @@ static int check_repositoryformatversion(git_config *config)
return 0;
}
-static int repo_init_create_head(const char *git_dir, const char *ref_name)
+int git_repository_create_head(const char *git_dir, const char *ref_name)
{
git_buf ref_path = GIT_BUF_INIT;
git_filebuf ref = GIT_FILEBUF_INIT;
@@ -1271,12 +1432,12 @@ static int create_empty_file(const char *path, mode_t mode)
int fd;
if ((fd = p_creat(path, mode)) < 0) {
- giterr_set(GITERR_OS, "Error while creating '%s'", path);
+ giterr_set(GITERR_OS, "error while creating '%s'", path);
return -1;
}
if (p_close(fd) < 0) {
- giterr_set(GITERR_OS, "Error while closing '%s'", path);
+ giterr_set(GITERR_OS, "error while closing '%s'", path);
return -1;
}
@@ -1505,7 +1666,7 @@ static int repo_write_template(
if (error)
giterr_set(GITERR_OS,
- "Failed to initialize repository with template '%s'", file);
+ "failed to initialize repository with template '%s'", file);
return error;
}
@@ -1536,7 +1697,7 @@ static int repo_write_gitlink(
if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
giterr_set(GITERR_REPOSITORY,
- "Cannot overwrite gitlink file into path '%s'", in_dir);
+ "cannot overwrite gitlink file into path '%s'", in_dir);
error = GIT_EEXISTS;
goto cleanup;
}
@@ -1590,7 +1751,7 @@ static int repo_init_structure(
if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) {
if (git_win32__set_hidden(repo_dir, true) < 0) {
giterr_set(GITERR_OS,
- "Failed to mark Git repository folder as hidden");
+ "failed to mark Git repository folder as hidden");
return -1;
}
}
@@ -1625,7 +1786,13 @@ static int repo_init_structure(
default_template = true;
}
- if (tdir) {
+ /*
+ * If tdir was the empty string, treat it like tdir was a path to an
+ * empty directory (so, don't do any copying). This is the behavior
+ * that git(1) exhibits, although it doesn't seem to be officially
+ * documented.
+ */
+ if (tdir && git__strcmp(tdir, "") != 0) {
uint32_t cpflags = GIT_CPDIR_COPY_SYMLINKS |
GIT_CPDIR_SIMPLE_TO_MODE |
GIT_CPDIR_COPY_DOTFILES;
@@ -1744,7 +1911,7 @@ static int repo_init_directories(
if (git_path_dirname_r(wd_path, repo_path->ptr) < 0)
return -1;
} else {
- giterr_set(GITERR_REPOSITORY, "Cannot pick working directory"
+ giterr_set(GITERR_REPOSITORY, "cannot pick working directory"
" for non-bare repository that isn't a '.git' directory");
return -1;
}
@@ -1848,7 +2015,8 @@ int git_repository_init_ext(
git_repository_init_options *opts)
{
int error;
- git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT;
+ git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
+ common_path = GIT_BUF_INIT;
const char *wd;
assert(out && given_repo && opts);
@@ -1860,11 +2028,11 @@ int git_repository_init_ext(
goto cleanup;
wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
- if (valid_repository_path(&repo_path)) {
+ if (valid_repository_path(&repo_path, &common_path)) {
if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
giterr_set(GITERR_REPOSITORY,
- "Attempt to reinitialize '%s'", given_repo);
+ "attempt to reinitialize '%s'", given_repo);
error = GIT_EEXISTS;
goto cleanup;
}
@@ -1881,7 +2049,7 @@ int git_repository_init_ext(
repo_path.ptr, wd, opts)) &&
!(error = repo_init_config(
repo_path.ptr, wd, opts->flags, opts->mode)))
- error = repo_init_create_head(
+ error = git_repository_create_head(
repo_path.ptr, opts->initial_head);
}
if (error < 0)
@@ -1893,6 +2061,7 @@ int git_repository_init_ext(
error = repo_init_create_origin(*out, opts->origin_url);
cleanup:
+ git_buf_free(&common_path);
git_buf_free(&repo_path);
git_buf_free(&wd_path);
@@ -1922,6 +2091,29 @@ int git_repository_head_detached(git_repository *repo)
return exists;
}
+static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file)
+{
+ git_buf_clear(out);
+ return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file);
+}
+
+int git_repository_head_detached_for_worktree(git_repository *repo, const char *name)
+{
+ git_reference *ref = NULL;
+ int error;
+
+ assert(repo && name);
+
+ if ((error = git_repository_head_for_worktree(&ref, repo, name)) < 0)
+ goto out;
+
+ error = (git_reference_type(ref) != GIT_REF_SYMBOLIC);
+out:
+ git_reference_free(ref);
+
+ return error;
+}
+
int git_repository_head(git_reference **head_out, git_repository *repo)
{
git_reference *head;
@@ -1941,6 +2133,71 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
return error == GIT_ENOTFOUND ? GIT_EUNBORNBRANCH : error;
}
+int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_reference *head = NULL;
+ int error;
+
+ assert(out && repo && name);
+
+ *out = NULL;
+
+ if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 ||
+ (error = git_reference__read_head(&head, repo, path.ptr)) < 0)
+ goto out;
+
+ if (git_reference_type(head) != GIT_REF_OID) {
+ git_reference *resolved;
+
+ error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1);
+ git_reference_free(head);
+ head = resolved;
+ }
+
+ *out = head;
+
+out:
+ if (error)
+ git_reference_free(head);
+
+ git_buf_free(&path);
+
+ return error;
+}
+
+int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload)
+{
+ git_strarray worktrees = GIT_VECTOR_INIT;
+ git_buf path = GIT_BUF_INIT;
+ int error;
+ size_t i;
+
+ /* Execute callback for HEAD of commondir */
+ if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 ||
+ (error = cb(repo, path.ptr, payload) != 0))
+ goto out;
+
+ if ((error = git_worktree_list(&worktrees, repo)) < 0) {
+ error = 0;
+ goto out;
+ }
+
+ /* Execute callback for all worktree HEADs */
+ for (i = 0; i < worktrees.count; i++) {
+ if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0)
+ continue;
+
+ if ((error = cb(repo, path.ptr, payload)) != 0)
+ goto out;
+ }
+
+out:
+ git_buf_free(&path);
+ git_strarray_free(&worktrees);
+ return error;
+}
+
int git_repository_head_unborn(git_repository *repo)
{
git_reference *ref = NULL;
@@ -1999,10 +2256,50 @@ int git_repository_is_empty(git_repository *repo)
return is_empty;
}
+int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item)
+{
+ const char *parent;
+
+ switch (items[item].parent) {
+ case GIT_REPOSITORY_ITEM_GITDIR:
+ parent = git_repository_path(repo);
+ break;
+ case GIT_REPOSITORY_ITEM_WORKDIR:
+ parent = git_repository_workdir(repo);
+ break;
+ case GIT_REPOSITORY_ITEM_COMMONDIR:
+ parent = git_repository_commondir(repo);
+ break;
+ default:
+ giterr_set(GITERR_INVALID, "invalid item directory");
+ return -1;
+ }
+
+ if (parent == NULL) {
+ giterr_set(GITERR_INVALID, "path cannot exist in repository");
+ return GIT_ENOTFOUND;
+ }
+
+ if (git_buf_sets(out, parent) < 0)
+ return -1;
+
+ if (items[item].name) {
+ if (git_buf_joinpath(out, parent, items[item].name) < 0)
+ return -1;
+ }
+
+ if (items[item].directory) {
+ if (git_path_to_dir(out) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
const char *git_repository_path(git_repository *repo)
{
assert(repo);
- return repo->path_repository;
+ return repo->gitdir;
}
const char *git_repository_workdir(git_repository *repo)
@@ -2015,6 +2312,12 @@ const char *git_repository_workdir(git_repository *repo)
return repo->workdir;
}
+const char *git_repository_commondir(git_repository *repo)
+{
+ assert(repo);
+ return repo->commondir;
+}
+
int git_repository_set_workdir(
git_repository *repo, const char *workdir, int update_gitlink)
{
@@ -2065,6 +2368,12 @@ int git_repository_is_bare(git_repository *repo)
return repo->is_bare;
}
+int git_repository_is_worktree(git_repository *repo)
+{
+ assert(repo);
+ return repo->is_worktree;
+}
+
int git_repository_set_bare(git_repository *repo)
{
int error;
@@ -2119,7 +2428,7 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head
git_oid_fmt(orig_head_str, orig_head);
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 &&
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 &&
(error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0)
error = git_filebuf_commit(&file);
@@ -2140,13 +2449,13 @@ int git_repository_message(git_buf *out, git_repository *repo)
git_buf_sanitize(out);
- if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
return -1;
if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) {
if (errno == ENOENT)
error = GIT_ENOTFOUND;
- giterr_set(GITERR_OS, "Could not access message file");
+ giterr_set(GITERR_OS, "could not access message file");
} else {
error = git_futils_readbuffer(out, git_buf_cstr(&path));
}
@@ -2161,7 +2470,7 @@ int git_repository_message_remove(git_repository *repo)
git_buf path = GIT_BUF_INIT;
int error;
- if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
return -1;
error = p_unlink(git_buf_cstr(&path));
@@ -2224,7 +2533,7 @@ int git_repository_hashfile(
}
if (!git__is_sizet(len)) {
- giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
+ giterr_set(GITERR_OS, "file size overflow for 32-bit systems");
error = -1;
goto cleanup;
}
@@ -2251,7 +2560,9 @@ static int checkout_message(git_buf *out, git_reference *old, const char *new)
git_buf_puts(out, " to ");
- if (git_reference__is_branch(new))
+ if (git_reference__is_branch(new) ||
+ git_reference__is_tag(new) ||
+ git_reference__is_remote(new))
git_buf_puts(out, git_reference__shorthand(new));
else
git_buf_puts(out, new);
@@ -2262,77 +2573,86 @@ static int checkout_message(git_buf *out, git_reference *old, const char *new)
return 0;
}
-int git_repository_set_head(
- git_repository* repo,
- const char* refname)
+static int detach(git_repository *repo, const git_oid *id, const char *new)
{
- git_reference *ref = NULL, *current = NULL, *new_head = NULL;
- git_buf log_message = GIT_BUF_INIT;
int error;
+ git_buf log_message = GIT_BUF_INIT;
+ git_object *object = NULL, *peeled = NULL;
+ git_reference *new_head = NULL, *current = NULL;
- assert(repo && refname);
+ assert(repo && id);
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
return error;
- if ((error = checkout_message(&log_message, current, refname)) < 0)
+ if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
goto cleanup;
- error = git_reference_lookup(&ref, repo, refname);
- if (error < 0 && error != GIT_ENOTFOUND)
+ if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
goto cleanup;
- if (!error) {
- if (git_reference_is_branch(ref)) {
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
- git_reference_name(ref), true, git_buf_cstr(&log_message));
- } else {
- error = git_repository_set_head_detached(repo, git_reference_target(ref));
- }
- } else if (git_reference__is_branch(refname)) {
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
- true, git_buf_cstr(&log_message));
- }
+ if (new == NULL)
+ new = git_oid_tostr_s(git_object_id(peeled));
+
+ if ((error = checkout_message(&log_message, current, new)) < 0)
+ goto cleanup;
+
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
cleanup:
git_buf_free(&log_message);
+ git_object_free(object);
+ git_object_free(peeled);
git_reference_free(current);
- git_reference_free(ref);
git_reference_free(new_head);
return error;
}
-static int detach(git_repository *repo, const git_oid *id, const char *from)
+int git_repository_set_head(
+ git_repository* repo,
+ const char* refname)
{
- int error;
+ git_reference *ref = NULL, *current = NULL, *new_head = NULL;
git_buf log_message = GIT_BUF_INIT;
- git_object *object = NULL, *peeled = NULL;
- git_reference *new_head = NULL, *current = NULL;
+ int error;
- assert(repo && id);
+ assert(repo && refname);
if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
return error;
- if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
+ if ((error = checkout_message(&log_message, current, refname)) < 0)
goto cleanup;
- if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
+ error = git_reference_lookup(&ref, repo, refname);
+ if (error < 0 && error != GIT_ENOTFOUND)
goto cleanup;
- if (from == NULL)
- from = git_oid_tostr_s(git_object_id(peeled));
-
- if ((error = checkout_message(&log_message, current, from)) < 0)
+ if (ref && current->type == GIT_REF_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) &&
+ git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) {
+ giterr_set(GITERR_REPOSITORY, "cannot set HEAD to reference '%s' as it is the current HEAD "
+ "of a linked repository.", git_reference_name(ref));
+ error = -1;
goto cleanup;
+ }
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
+ if (!error) {
+ if (git_reference_is_branch(ref)) {
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
+ git_reference_name(ref), true, git_buf_cstr(&log_message));
+ } else {
+ error = detach(repo, git_reference_target(ref),
+ git_reference_is_tag(ref) || git_reference_is_remote(ref) ? refname : NULL);
+ }
+ } else if (git_reference__is_branch(refname)) {
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
+ true, git_buf_cstr(&log_message));
+ }
cleanup:
git_buf_free(&log_message);
- git_object_free(object);
- git_object_free(peeled);
git_reference_free(current);
+ git_reference_free(ref);
git_reference_free(new_head);
return error;
}
@@ -2397,7 +2717,7 @@ int git_repository_state(git_repository *repo)
assert(repo);
- if (git_buf_puts(&repo_path, repo->path_repository) < 0)
+ if (git_buf_puts(&repo_path, repo->gitdir) < 0)
return -1;
if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE))
@@ -2439,7 +2759,7 @@ int git_repository__cleanup_files(
for (error = 0, i = 0; !error && i < files_len; ++i) {
const char *path;
- if (git_buf_joinpath(&buf, repo->path_repository, files[i]) < 0)
+ if (git_buf_joinpath(&buf, repo->gitdir, files[i]) < 0)
return -1;
path = git_buf_cstr(&buf);
@@ -2450,7 +2770,7 @@ int git_repository__cleanup_files(
error = git_futils_rmdir_r(path, NULL,
GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS);
}
-
+
git_buf_clear(&buf);
}
@@ -2483,7 +2803,7 @@ int git_repository_is_shallow(git_repository *repo)
struct stat st;
int error;
- if ((error = git_buf_joinpath(&path, repo->path_repository, "shallow")) < 0)
+ if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
return error;
error = git_path_lstat(path.ptr, &st);
@@ -2538,3 +2858,31 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char
return 0;
}
+
+int git_repository_submodule_cache_all(git_repository *repo)
+{
+ int error;
+
+ assert(repo);
+
+ if ((error = git_strmap_alloc(&repo->submodule_cache)))
+ return error;
+
+ error = git_submodule__map(repo, repo->submodule_cache);
+ return error;
+}
+
+int git_repository_submodule_cache_clear(git_repository *repo)
+{
+ git_submodule *sm;
+ assert(repo);
+ if (repo->submodule_cache == NULL) {
+ return 0;
+ }
+ git_strmap_foreach_value(repo->submodule_cache, sm, {
+ git_submodule_free(sm);
+ });
+ git_strmap_free(repo->submodule_cache);
+ repo->submodule_cache = 0;
+ return 0;
+}
diff --git a/src/repository.h b/src/repository.h
index fd679b483..fd6400cc1 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_repository_h__
#define INCLUDE_repository_h__
+#include "common.h"
+
#include "git2/common.h"
#include "git2/oid.h"
#include "git2/odb.h"
@@ -31,6 +33,8 @@
/* Default DOS-compatible 8.3 "short name" for a git repository, "GIT~1" */
#define GIT_DIR_SHORTNAME "GIT~1"
+extern bool git_repository__fsync_gitdir;
+
/** Cvar cache identifiers */
typedef enum {
GIT_CVAR_AUTO_CRLF = 0, /* core.autocrlf */
@@ -46,6 +50,7 @@ typedef enum {
GIT_CVAR_LOGALLREFUPDATES, /* core.logallrefupdates */
GIT_CVAR_PROTECTHFS, /* core.protectHFS */
GIT_CVAR_PROTECTNTFS, /* core.protectNTFS */
+ GIT_CVAR_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */
GIT_CVAR_CACHE_MAX
} git_cvar_cached;
@@ -106,6 +111,8 @@ typedef enum {
GIT_PROTECTHFS_DEFAULT = GIT_CVAR_FALSE,
/* core.protectNTFS */
GIT_PROTECTNTFS_DEFAULT = GIT_CVAR_FALSE,
+ /* core.fsyncObjectFiles */
+ GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CVAR_FALSE,
} git_cvar_value;
/* internal repository init flags */
@@ -126,8 +133,9 @@ struct git_repository {
git_attr_cache *attrcache;
git_diff_driver_registry *diff_drivers;
- char *path_repository;
- char *path_gitlink;
+ char *gitlink;
+ char *gitdir;
+ char *commondir;
char *workdir;
char *namespace;
@@ -137,12 +145,14 @@ struct git_repository {
git_array_t(git_buf) reserved_names;
unsigned is_bare:1;
+ unsigned is_worktree:1;
unsigned int lru_counter;
git_atomic attr_session_key;
git_cvar_value cvar_cache[GIT_CVAR_CACHE_MAX];
+ git_strmap *submodule_cache;
};
GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
@@ -151,6 +161,27 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
}
int git_repository_head_tree(git_tree **tree, git_repository *repo);
+int git_repository_create_head(const char *git_dir, const char *ref_name);
+
+/*
+ * Called for each HEAD.
+ *
+ * Can return either 0, causing the iteration over HEADs to
+ * continue, or a non-0 value causing the iteration to abort. The
+ * return value is passed back to the caller of
+ * `git_repository_foreach_head`
+ */
+typedef int (*git_repository_foreach_head_cb)(git_repository *repo, const char *path, void *payload);
+
+/*
+ * Iterate over repository and all worktree HEADs.
+ *
+ * This function will be called for the repository HEAD and for
+ * all HEADS of linked worktrees. For each HEAD, the callback is
+ * executed with the given payload. The return value equals the
+ * return value of the last executed callback function.
+ */
+int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload);
/*
* Weak pointers to repository internals.
@@ -182,7 +213,7 @@ GIT_INLINE(int) git_repository__ensure_not_bare(
giterr_set(
GITERR_REPOSITORY,
- "Cannot %s. This operation is not allowed against bare repositories.",
+ "cannot %s. This operation is not allowed against bare repositories.",
operation_name);
return GIT_EBAREREPO;
diff --git a/src/reset.c b/src/reset.c
index db0bfb373..21596812f 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "commit.h"
#include "tag.h"
#include "merge.h"
@@ -20,8 +21,8 @@
int git_reset_default(
git_repository *repo,
- git_object *target,
- git_strarray* pathspecs)
+ const git_object *target,
+ const git_strarray* pathspecs)
{
git_object *commit = NULL;
git_tree *tree = NULL;
@@ -100,7 +101,7 @@ cleanup:
static int reset(
git_repository *repo,
- git_object *target,
+ const git_object *target,
const char *to,
git_reset_t reset_type,
const git_checkout_options *checkout_opts)
@@ -137,7 +138,7 @@ static int reset(
(git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE ||
git_index_has_conflicts(index)))
{
- giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge.", ERROR_MSG);
+ giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG);
error = GIT_EUNMERGED;
goto cleanup;
}
@@ -182,7 +183,7 @@ cleanup:
int git_reset(
git_repository *repo,
- git_object *target,
+ const git_object *target,
git_reset_t reset_type,
const git_checkout_options *checkout_opts)
{
@@ -191,7 +192,7 @@ int git_reset(
int git_reset_from_annotated(
git_repository *repo,
- git_annotated_commit *commit,
+ const git_annotated_commit *commit,
git_reset_t reset_type,
const git_checkout_options *checkout_opts)
{
diff --git a/src/revert.c b/src/revert.c
index c481e7dea..54f6d48e4 100644
--- a/src/revert.c
+++ b/src/revert.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "repository.h"
#include "filebuf.h"
#include "merge.h"
@@ -27,7 +28,7 @@ static int write_revert_head(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_REVERT_HEAD_FILE)) >= 0 &&
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_REVERT_HEAD_FILE)) >= 0 &&
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_REVERT_FILE_MODE)) >= 0 &&
(error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0)
error = git_filebuf_commit(&file);
@@ -49,7 +50,7 @@ static int write_merge_msg(
git_buf file_path = GIT_BUF_INIT;
int error = 0;
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_REVERT_FILE_MODE)) < 0 ||
(error = git_filebuf_printf(&file, "Revert \"%s\"\n\nThis reverts commit %s.\n",
commit_msgline, commit_oidstr)) < 0)
@@ -133,13 +134,13 @@ int git_revert_commit(
if (git_commit_parentcount(revert_commit) > 1) {
if (!mainline)
return revert_seterr(revert_commit,
- "Mainline branch is not specified but %s is a merge commit");
+ "mainline branch is not specified but %s is a merge commit");
parent = mainline;
} else {
if (mainline)
return revert_seterr(revert_commit,
- "Mainline branch specified but %s is not a merge commit");
+ "mainline branch specified but %s is not a merge commit");
parent = git_commit_parentcount(revert_commit);
}
diff --git a/src/revparse.c b/src/revparse.c
index e0ec3941d..4ab4fb96d 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -5,9 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include <assert.h>
-#include "common.h"
#include "buffer.h"
#include "tree.h"
#include "refdb.h"
@@ -46,11 +47,11 @@ static int build_regex(regex_t *regex, const char *pattern)
int error;
if (*pattern == '\0') {
- giterr_set(GITERR_REGEX, "Empty pattern");
+ giterr_set(GITERR_REGEX, "empty pattern");
return GIT_EINVALIDSPEC;
}
- error = regcomp(regex, pattern, REG_EXTENDED);
+ error = p_regcomp(regex, pattern, REG_EXTENDED);
if (!error)
return 0;
@@ -118,7 +119,7 @@ static int revparse_lookup_object(
if ((error = maybe_describe(object_out, repo, spec)) != GIT_ENOTFOUND)
return error;
- giterr_set(GITERR_REFERENCE, "Revspec '%s' not found.", spec);
+ giterr_set(GITERR_REFERENCE, "revspec '%s' not found", spec);
return GIT_ENOTFOUND;
}
@@ -245,7 +246,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide
notfound:
giterr_set(
GITERR_REFERENCE,
- "Reflog for '%s' has only %"PRIuZ" entries, asked for %"PRIuZ,
+ "reflog for '%s' has only %"PRIuZ" entries, asked for %"PRIuZ,
git_reference_name(ref), numentries, identifier);
git_reflog_free(reflog);
@@ -757,7 +758,7 @@ int revparse__ext(
* TODO: support merge-stage path lookup (":2:Makefile")
* and plain index blob lookup (:i-am/a/blob)
*/
- giterr_set(GITERR_INVALID, "Unimplemented");
+ giterr_set(GITERR_INVALID, "unimplemented");
error = GIT_ERROR;
goto cleanup;
}
@@ -816,7 +817,7 @@ cleanup:
if (error) {
if (error == GIT_EINVALIDSPEC)
giterr_set(GITERR_INVALID,
- "Failed to parse revision specifier - Invalid pattern '%s'", spec);
+ "failed to parse revision specifier - Invalid pattern '%s'", spec);
git_object_free(base_rev);
git_reference_free(reference);
@@ -892,6 +893,17 @@ int git_revparse(
const char *rstr;
revspec->flags = GIT_REVPARSE_RANGE;
+ /*
+ * Following git.git, don't allow '..' because it makes command line
+ * arguments which can be either paths or revisions ambiguous when the
+ * path is almost certainly intended. The empty range '...' is still
+ * allowed.
+ */
+ if (!git__strcmp(spec, "..")) {
+ giterr_set(GITERR_INVALID, "Invalid pattern '..'");
+ return GIT_EINVALIDSPEC;
+ }
+
lstr = git__substrdup(spec, dotdot - spec);
rstr = dotdot + 2;
if (dotdot[2] == '.') {
@@ -899,9 +911,17 @@ int git_revparse(
rstr++;
}
- error = git_revparse_single(&revspec->from, repo, lstr);
- if (!error)
- error = git_revparse_single(&revspec->to, repo, rstr);
+ error = git_revparse_single(
+ &revspec->from,
+ repo,
+ *lstr == '\0' ? "HEAD" : lstr);
+
+ if (!error) {
+ error = git_revparse_single(
+ &revspec->to,
+ repo,
+ *rstr == '\0' ? "HEAD" : rstr);
+ }
git__free((void*)lstr);
} else {
diff --git a/src/revwalk.c b/src/revwalk.c
index 4815a1089..b1aa8f91a 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -5,16 +5,15 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "revwalk.h"
+
#include "commit.h"
#include "odb.h"
#include "pool.h"
-#include "revwalk.h"
#include "git2/revparse.h"
#include "merge.h"
-
-GIT__USE_OIDMAP
+#include "vector.h"
git_commit_list_node *git_revwalk__commit_lookup(
git_revwalk *walk, const git_oid *oid)
@@ -24,9 +23,9 @@ git_commit_list_node *git_revwalk__commit_lookup(
int ret;
/* lookup and reserve space if not already present */
- pos = kh_get(oid, walk->commits, oid);
- if (pos != kh_end(walk->commits))
- return kh_value(walk->commits, pos);
+ pos = git_oidmap_lookup_index(walk->commits, oid);
+ if (git_oidmap_valid_index(walk->commits, pos))
+ return git_oidmap_value_at(walk->commits, pos);
commit = git_commit_list_alloc_node(walk);
if (commit == NULL)
@@ -34,104 +33,13 @@ git_commit_list_node *git_revwalk__commit_lookup(
git_oid_cpy(&commit->oid, oid);
- pos = kh_put(oid, walk->commits, &commit->oid, &ret);
+ pos = git_oidmap_put(walk->commits, &commit->oid, &ret);
assert(ret != 0);
- kh_value(walk->commits, pos) = commit;
+ git_oidmap_set_value_at(walk->commits, pos, commit);
return commit;
}
-typedef git_array_t(git_commit_list_node*) commit_list_node_array;
-
-static bool interesting_arr(commit_list_node_array arr)
-{
- git_commit_list_node **n;
- size_t i = 0, size;
-
- size = git_array_size(arr);
- for (i = 0; i < size; i++) {
- n = git_array_get(arr, i);
- if (!*n)
- break;
-
- if (!(*n)->uninteresting)
- return true;
- }
-
- return false;
-}
-
-static int mark_uninteresting(git_revwalk *walk, git_commit_list_node *commit)
-{
- int error;
- unsigned short i;
- commit_list_node_array pending = GIT_ARRAY_INIT;
- git_commit_list_node **tmp;
-
- assert(commit);
-
- do {
- commit->uninteresting = 1;
-
- if ((error = git_commit_list_parse(walk, commit)) < 0)
- return error;
-
- for (i = 0; i < commit->out_degree; ++i)
- if (!commit->parents[i]->uninteresting) {
- git_commit_list_node **node = git_array_alloc(pending);
- GITERR_CHECK_ALLOC(node);
- *node = commit->parents[i];
- }
-
- tmp = git_array_pop(pending);
- commit = tmp ? *tmp : NULL;
-
- } while (commit != NULL && !interesting_arr(pending));
-
- git_array_clear(pending);
-
- return 0;
-}
-
-static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int hide)
-{
- int error;
-
- if (!hide && walk->hide_cb)
- hide = walk->hide_cb(&commit->oid, walk->hide_cb_payload);
-
- if (hide && mark_uninteresting(walk, commit) < 0)
- return -1;
-
- if (commit->seen)
- return 0;
-
- commit->seen = 1;
-
- if ((error = git_commit_list_parse(walk, commit)) < 0)
- return error;
-
- if (!hide)
- return walk->enqueue(walk, commit);
-
- return 0;
-}
-
-static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commit)
-{
- unsigned short i, max;
- int error = 0;
-
- max = commit->out_degree;
- if (walk->first_parent && commit->out_degree)
- max = 1;
-
- for (i = 0; i < max && !error; ++i)
- error = process_commit(walk, commit->parents[i], commit->uninteresting);
-
- return error;
-}
-
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
{
git_oid commit_id;
@@ -151,7 +59,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
if (from_glob)
return 0;
- giterr_set(GITERR_INVALID, "Object is not a committish");
+ giterr_set(GITERR_INVALID, "object is not a committish");
return -1;
}
if (error < 0)
@@ -288,7 +196,7 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
/* TODO: support "<commit>...<commit>" */
- giterr_set(GITERR_INVALID, "Symmetric differences not implemented in revwalk");
+ giterr_set(GITERR_INVALID, "symmetric differences not implemented in revwalk");
return GIT_EINVALIDSPEC;
}
@@ -321,17 +229,15 @@ static int revwalk_enqueue_unsorted(git_revwalk *walk, git_commit_list_node *com
static int revwalk_next_timesort(git_commit_list_node **object_out, git_revwalk *walk)
{
- int error;
git_commit_list_node *next;
- while ((next = git_pqueue_pop(&walk->iterator_time)) != NULL)
+ while ((next = git_pqueue_pop(&walk->iterator_time)) != NULL) {
+ /* Some commits might become uninteresting after being added to the list */
if (!next->uninteresting) {
- if ((error = process_commit_parents(walk, next)) < 0)
- return error;
-
*object_out = next;
return 0;
}
+ }
giterr_clear();
return GIT_ITEROVER;
@@ -339,17 +245,15 @@ static int revwalk_next_timesort(git_commit_list_node **object_out, git_revwalk
static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk *walk)
{
- int error;
git_commit_list_node *next;
- while ((next = git_commit_list_pop(&walk->iterator_rand)) != NULL)
+ while ((next = git_commit_list_pop(&walk->iterator_rand)) != NULL) {
+ /* Some commits might become uninteresting after being added to the list */
if (!next->uninteresting) {
- if ((error = process_commit_parents(walk, next)) < 0)
- return error;
-
*object_out = next;
return 0;
}
+ }
giterr_clear();
return GIT_ITEROVER;
@@ -358,121 +262,283 @@ static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk
static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk *walk)
{
git_commit_list_node *next;
- unsigned short i, max;
- for (;;) {
- next = git_commit_list_pop(&walk->iterator_topo);
- if (next == NULL) {
- giterr_clear();
- return GIT_ITEROVER;
+ while ((next = git_commit_list_pop(&walk->iterator_topo)) != NULL) {
+ /* Some commits might become uninteresting after being added to the list */
+ if (!next->uninteresting) {
+ *object_out = next;
+ return 0;
}
+ }
- if (next->in_degree > 0) {
- next->topo_delay = 1;
- continue;
+ giterr_clear();
+ return GIT_ITEROVER;
+}
+
+static int revwalk_next_reverse(git_commit_list_node **object_out, git_revwalk *walk)
+{
+ *object_out = git_commit_list_pop(&walk->iterator_reverse);
+ return *object_out ? 0 : GIT_ITEROVER;
+}
+
+static void mark_parents_uninteresting(git_commit_list_node *commit)
+{
+ unsigned short i;
+ git_commit_list *parents = NULL;
+
+ for (i = 0; i < commit->out_degree; i++)
+ git_commit_list_insert(commit->parents[i], &parents);
+
+
+ while (parents) {
+ commit = git_commit_list_pop(&parents);
+
+ while (commit) {
+ if (commit->uninteresting)
+ break;
+
+ commit->uninteresting = 1;
+ /*
+ * If we've reached this commit some other way
+ * already, we need to mark its parents uninteresting
+ * as well.
+ */
+ if (!commit->parents)
+ break;
+
+ for (i = 0; i < commit->out_degree; i++)
+ git_commit_list_insert(commit->parents[i], &parents);
+ commit = commit->parents[0];
}
+ }
+}
+
+static int add_parents_to_list(git_revwalk *walk, git_commit_list_node *commit, git_commit_list **list)
+{
+ unsigned short i;
+ int error;
+ if (commit->added)
+ return 0;
- max = next->out_degree;
- if (walk->first_parent && next->out_degree)
- max = 1;
+ commit->added = 1;
+
+ /*
+ * Go full on in the uninteresting case as we want to include
+ * as many of these as we can.
+ *
+ * Usually we haven't parsed the parent of a parent, but if we
+ * have it we reached it via other means so we want to mark
+ * its parents recursively too.
+ */
+ if (commit->uninteresting) {
+ for (i = 0; i < commit->out_degree; i++) {
+ git_commit_list_node *p = commit->parents[i];
+ p->uninteresting = 1;
- for (i = 0; i < max; ++i) {
- git_commit_list_node *parent = next->parents[i];
+ /* git does it gently here, but we don't like missing objects */
+ if ((error = git_commit_list_parse(walk, p)) < 0)
+ return error;
- if (--parent->in_degree == 0 && parent->topo_delay) {
- parent->topo_delay = 0;
- if (git_commit_list_insert(parent, &walk->iterator_topo) == NULL)
- return -1;
- }
+ if (p->parents)
+ mark_parents_uninteresting(p);
+
+ p->seen = 1;
+ git_commit_list_insert_by_date(p, list);
}
- *object_out = next;
return 0;
}
+
+ /*
+ * Now on to what we do if the commit is indeed
+ * interesting. Here we do want things like first-parent take
+ * effect as this is what we'll be showing.
+ */
+ for (i = 0; i < commit->out_degree; i++) {
+ git_commit_list_node *p = commit->parents[i];
+
+ if ((error = git_commit_list_parse(walk, p)) < 0)
+ return error;
+
+ if (walk->hide_cb && walk->hide_cb(&p->oid, walk->hide_cb_payload))
+ continue;
+
+ if (!p->seen) {
+ p->seen = 1;
+ git_commit_list_insert_by_date(p, list);
+ }
+
+ if (walk->first_parent)
+ break;
+ }
+ return 0;
}
-static int revwalk_next_reverse(git_commit_list_node **object_out, git_revwalk *walk)
+static int everybody_uninteresting(git_commit_list *orig)
{
- *object_out = git_commit_list_pop(&walk->iterator_reverse);
- return *object_out ? 0 : GIT_ITEROVER;
+ git_commit_list *list = orig;
+
+ while (list) {
+ git_commit_list_node *commit = list->item;
+ list = list->next;
+ if (!commit->uninteresting)
+ return 0;
+ }
+
+ return 1;
}
+/* How many unintersting commits we want to look at after we run out of interesting ones */
+#define SLOP 5
-static int interesting(git_pqueue *list)
+static int still_interesting(git_commit_list *list, int64_t time, int slop)
{
- size_t i;
+ /* The empty list is pretty boring */
+ if (!list)
+ return 0;
- for (i = 0; i < git_pqueue_size(list); i++) {
- git_commit_list_node *commit = git_pqueue_get(list, i);
- if (!commit->uninteresting)
- return 1;
- }
+ /*
+ * If the destination list has commits with an earlier date
+ * than our source we want to continue looking.
+ */
+ if (time <= list->item->time)
+ return SLOP;
- return 0;
+ /* If we find interesting commits, we reset the slop count */
+ if (!everybody_uninteresting(list))
+ return SLOP;
+
+ /* Everything's uninteresting, reduce the count */
+ return slop - 1;
}
-static int contains(git_pqueue *list, git_commit_list_node *node)
+static int limit_list(git_commit_list **out, git_revwalk *walk, git_commit_list *commits)
{
- size_t i;
+ int error, slop = SLOP;
+ int64_t time = ~0ll;
+ git_commit_list *list = commits;
+ git_commit_list *newlist = NULL;
+ git_commit_list **p = &newlist;
+
+ while (list) {
+ git_commit_list_node *commit = git_commit_list_pop(&list);
- for (i = 0; i < git_pqueue_size(list); i++) {
- git_commit_list_node *commit = git_pqueue_get(list, i);
- if (commit == node)
- return 1;
+ if ((error = add_parents_to_list(walk, commit, &list)) < 0)
+ return error;
+
+ if (commit->uninteresting) {
+ mark_parents_uninteresting(commit);
+
+ slop = still_interesting(list, time, slop);
+ if (slop)
+ continue;
+
+ break;
+ }
+
+ if (!commit->uninteresting && walk->hide_cb && walk->hide_cb(&commit->oid, walk->hide_cb_payload))
+ continue;
+
+ time = commit->time;
+ p = &git_commit_list_insert(commit, p)->next;
}
+ git_commit_list_free(&list);
+ *out = newlist;
return 0;
}
-static int premark_uninteresting(git_revwalk *walk)
+static int sort_in_topological_order(git_commit_list **out, git_revwalk *walk, git_commit_list *list)
{
- int error = 0;
+ git_commit_list *ll = NULL, *newlist, **pptr;
+ git_commit_list_node *next;
+ git_pqueue queue;
+ git_vector_cmp queue_cmp = NULL;
unsigned short i;
- git_pqueue q;
- git_commit_list *list;
- git_commit_list_node *commit, *parent;
+ int error;
- if ((error = git_pqueue_init(&q, 0, 8, git_commit_list_time_cmp)) < 0)
- return error;
+ if (walk->sorting & GIT_SORT_TIME)
+ queue_cmp = git_commit_list_time_cmp;
- for (list = walk->user_input; list; list = list->next) {
- if ((error = git_commit_list_parse(walk, list->item)) < 0)
- goto cleanup;
+ if ((error = git_pqueue_init(&queue, 0, 8, queue_cmp)))
+ return error;
- if ((error = git_pqueue_insert(&q, list->item)) < 0)
- goto cleanup;
+ /*
+ * Start by resetting the in-degree to 1 for the commits in
+ * our list. We want to go through this list again, so we
+ * store it in the commit list as we extract it from the lower
+ * machinery.
+ */
+ for (ll = list; ll; ll = ll->next) {
+ ll->item->in_degree = 1;
}
- while (interesting(&q)) {
- commit = git_pqueue_pop(&q);
-
- for (i = 0; i < commit->out_degree; i++) {
- parent = commit->parents[i];
+ /*
+ * Count up how many children each commit has. We limit
+ * ourselves to those commits in the original list (in-degree
+ * of 1) avoiding setting it for any parent that was hidden.
+ */
+ for(ll = list; ll; ll = ll->next) {
+ for (i = 0; i < ll->item->out_degree; ++i) {
+ git_commit_list_node *parent = ll->item->parents[i];
+ if (parent->in_degree)
+ parent->in_degree++;
+ }
+ }
- if ((error = git_commit_list_parse(walk, parent)) < 0)
+ /*
+ * Now we find the tips i.e. those not reachable from any other node
+ * i.e. those which still have an in-degree of 1.
+ */
+ for(ll = list; ll; ll = ll->next) {
+ if (ll->item->in_degree == 1) {
+ if ((error = git_pqueue_insert(&queue, ll->item)))
goto cleanup;
+ }
+ }
- if (commit->uninteresting)
- parent->uninteresting = 1;
+ /*
+ * We need to output the tips in the order that they came out of the
+ * traversal, so if we're not doing time-sorting, we need to reverse the
+ * pqueue in order to get them to come out as we inserted them.
+ */
+ if ((walk->sorting & GIT_SORT_TIME) == 0)
+ git_pqueue_reverse(&queue);
- if (contains(&q, parent))
+
+ pptr = &newlist;
+ newlist = NULL;
+ while ((next = git_pqueue_pop(&queue)) != NULL) {
+ for (i = 0; i < next->out_degree; ++i) {
+ git_commit_list_node *parent = next->parents[i];
+ if (parent->in_degree == 0)
continue;
- if ((error = git_pqueue_insert(&q, parent)) < 0)
- goto cleanup;
+ if (--parent->in_degree == 1) {
+ if ((error = git_pqueue_insert(&queue, parent)))
+ goto cleanup;
+ }
}
+
+ /* All the children of 'item' have been emitted (since we got to it via the priority queue) */
+ next->in_degree = 0;
+
+ pptr = &git_commit_list_insert(next, pptr)->next;
}
+ *out = newlist;
+ error = 0;
+
cleanup:
- git_pqueue_free(&q);
+ git_pqueue_free(&queue);
return error;
}
static int prepare_walk(git_revwalk *walk)
{
int error;
- git_commit_list *list;
+ git_commit_list *list, *commits = NULL;
git_commit_list_node *next;
/* If there were no pushes, we know that the walk is already over */
@@ -481,32 +547,42 @@ static int prepare_walk(git_revwalk *walk)
return GIT_ITEROVER;
}
- if (walk->did_hide && (error = premark_uninteresting(walk)) < 0)
- return error;
-
for (list = walk->user_input; list; list = list->next) {
- if (process_commit(walk, list->item, list->item->uninteresting) < 0)
- return -1;
- }
+ git_commit_list_node *commit = list->item;
+ if ((error = git_commit_list_parse(walk, commit)) < 0)
+ return error;
+ if (commit->uninteresting)
+ mark_parents_uninteresting(commit);
- if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
- unsigned short i;
+ if (!commit->seen) {
+ commit->seen = 1;
+ git_commit_list_insert(commit, &commits);
+ }
+ }
- while ((error = walk->get_next(&next, walk)) == 0) {
- for (i = 0; i < next->out_degree; ++i) {
- git_commit_list_node *parent = next->parents[i];
- parent->in_degree++;
- }
+ if ((error = limit_list(&commits, walk, commits)) < 0)
+ return error;
- if (git_commit_list_insert(next, &walk->iterator_topo) == NULL)
- return -1;
- }
+ if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
+ error = sort_in_topological_order(&walk->iterator_topo, walk, commits);
+ git_commit_list_free(&commits);
- if (error != GIT_ITEROVER)
+ if (error < 0)
return error;
walk->get_next = &revwalk_next_toposort;
+ } else if (walk->sorting & GIT_SORT_TIME) {
+ for (list = commits; list && !error; list = list->next)
+ error = walk->enqueue(walk, list->item);
+
+ git_commit_list_free(&commits);
+
+ if (error < 0)
+ return error;
+ } else {
+ walk->iterator_rand = commits;
+ walk->get_next = revwalk_next_unsorted;
}
if (walk->sorting & GIT_SORT_REVERSE) {
@@ -627,11 +703,12 @@ void git_revwalk_reset(git_revwalk *walk)
assert(walk);
- kh_foreach_value(walk->commits, commit, {
+ git_oidmap_foreach_value(walk->commits, commit, {
commit->seen = 0;
commit->in_degree = 0;
commit->topo_delay = 0;
commit->uninteresting = 0;
+ commit->added = 0;
commit->flags = 0;
});
@@ -657,7 +734,7 @@ int git_revwalk_add_hide_cb(
if (walk->hide_cb) {
/* There is already a callback added */
- giterr_set(GITERR_INVALID, "There is already a callback added to hide commits in revision walker.");
+ giterr_set(GITERR_INVALID, "there is already a callback added to hide commits in revwalk");
return -1;
}
diff --git a/src/revwalk.h b/src/revwalk.h
index 6b363d40f..578328b72 100644
--- a/src/revwalk.h
+++ b/src/revwalk.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_revwalk_h__
#define INCLUDE_revwalk_h__
+#include "common.h"
+
#include "git2/revwalk.h"
#include "oidmap.h"
#include "commit_list.h"
diff --git a/src/settings.c b/src/settings.c
index cb2317f74..ba2f6a4db 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -5,16 +5,20 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#ifdef GIT_OPENSSL
# include <openssl/err.h>
#endif
#include <git2.h>
-#include "common.h"
#include "sysdir.h"
#include "cache.h"
#include "global.h"
#include "object.h"
+#include "odb.h"
+#include "refs.h"
+#include "transports/smart.h"
void git_libgit2_version(int *major, int *minor, int *rev)
{
@@ -29,7 +33,9 @@ int git_libgit2_features(void)
#ifdef GIT_THREADS
| GIT_FEATURE_THREADS
#endif
+#ifdef GIT_HTTPS
| GIT_FEATURE_HTTPS
+#endif
#if defined(GIT_SSH)
| GIT_FEATURE_SSH
#endif
@@ -62,7 +68,7 @@ static int config_level_to_sysdir(int config_level)
break;
default:
giterr_set(
- GITERR_INVALID, "Invalid config path selector %d", config_level);
+ GITERR_INVALID, "invalid config path selector %d", config_level);
}
return val;
@@ -191,6 +197,10 @@ int git_libgit2_opts(int key, ...)
git_object__strict_input_validation = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
+ git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
+ break;
+
case GIT_OPT_SET_SSL_CIPHERS:
#ifdef GIT_OPENSSL
{
@@ -215,6 +225,30 @@ int git_libgit2_opts(int key, ...)
}
break;
+ case GIT_OPT_ENABLE_OFS_DELTA:
+ git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
+ break;
+
+ case GIT_OPT_ENABLE_FSYNC_GITDIR:
+ git_repository__fsync_gitdir = (va_arg(ap, int) != 0);
+ break;
+
+ case GIT_OPT_GET_WINDOWS_SHAREMODE:
+#ifdef GIT_WIN32
+ *(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
+#endif
+ break;
+
+ case GIT_OPT_SET_WINDOWS_SHAREMODE:
+#ifdef GIT_WIN32
+ git_win32__createfile_sharemode = va_arg(ap, unsigned long);
+#endif
+ break;
+
+ case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
+ git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
+ break;
+
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c
index c6b561340..14fcb40e5 100644
--- a/src/sha1_lookup.c
+++ b/src/sha1_lookup.c
@@ -5,225 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <stdio.h>
-
#include "sha1_lookup.h"
-#include "common.h"
-#include "oid.h"
-/*
- * Conventional binary search loop looks like this:
- *
- * unsigned lo, hi;
- * do {
- * unsigned mi = (lo + hi) / 2;
- * int cmp = "entry pointed at by mi" minus "target";
- * if (!cmp)
- * return (mi is the wanted one)
- * if (cmp > 0)
- * hi = mi; "mi is larger than target"
- * else
- * lo = mi+1; "mi is smaller than target"
- * } while (lo < hi);
- *
- * The invariants are:
- *
- * - When entering the loop, lo points at a slot that is never
- * above the target (it could be at the target), hi points at a
- * slot that is guaranteed to be above the target (it can never
- * be at the target).
- *
- * - We find a point 'mi' between lo and hi (mi could be the same
- * as lo, but never can be as same as hi), and check if it hits
- * the target. There are three cases:
- *
- * - if it is a hit, we are happy.
- *
- * - if it is strictly higher than the target, we set it to hi,
- * and repeat the search.
- *
- * - if it is strictly lower than the target, we update lo to
- * one slot after it, because we allow lo to be at the target.
- *
- * If the loop exits, there is no matching entry.
- *
- * When choosing 'mi', we do not have to take the "middle" but
- * anywhere in between lo and hi, as long as lo <= mi < hi is
- * satisfied. When we somehow know that the distance between the
- * target and lo is much shorter than the target and hi, we could
- * pick mi that is much closer to lo than the midway.
- *
- * Now, we can take advantage of the fact that SHA-1 is a good hash
- * function, and as long as there are enough entries in the table, we
- * can expect uniform distribution. An entry that begins with for
- * example "deadbeef..." is much likely to appear much later than in
- * the midway of the table. It can reasonably be expected to be near
- * 87% (222/256) from the top of the table.
- *
- * However, we do not want to pick "mi" too precisely. If the entry at
- * the 87% in the above example turns out to be higher than the target
- * we are looking for, we would end up narrowing the search space down
- * only by 13%, instead of 50% we would get if we did a simple binary
- * search. So we would want to hedge our bets by being less aggressive.
- *
- * The table at "table" holds at least "nr" entries of "elem_size"
- * bytes each. Each entry has the SHA-1 key at "key_offset". The
- * table is sorted by the SHA-1 key of the entries. The caller wants
- * to find the entry with "key", and knows that the entry at "lo" is
- * not higher than the entry it is looking for, and that the entry at
- * "hi" is higher than the entry it is looking for.
- */
-int sha1_entry_pos(const void *table,
- size_t elem_size,
- size_t key_offset,
- unsigned lo, unsigned hi, unsigned nr,
- const unsigned char *key)
-{
- const unsigned char *base = (const unsigned char*)table;
- const unsigned char *hi_key, *lo_key;
- unsigned ofs_0;
-
- if (!nr || lo >= hi)
- return -1;
-
- if (nr == hi)
- hi_key = NULL;
- else
- hi_key = base + elem_size * hi + key_offset;
- lo_key = base + elem_size * lo + key_offset;
-
- ofs_0 = 0;
- do {
- int cmp;
- unsigned ofs, mi, range;
- unsigned lov, hiv, kyv;
- const unsigned char *mi_key;
-
- range = hi - lo;
- if (hi_key) {
- for (ofs = ofs_0; ofs < 20; ofs++)
- if (lo_key[ofs] != hi_key[ofs])
- break;
- ofs_0 = ofs;
- /*
- * byte 0 thru (ofs-1) are the same between
- * lo and hi; ofs is the first byte that is
- * different.
- *
- * If ofs==20, then no bytes are different,
- * meaning we have entries with duplicate
- * keys. We know that we are in a solid run
- * of this entry (because the entries are
- * sorted, and our lo and hi are the same,
- * there can be nothing but this single key
- * in between). So we can stop the search.
- * Either one of these entries is it (and
- * we do not care which), or we do not have
- * it.
- *
- * Furthermore, we know that one of our
- * endpoints must be the edge of the run of
- * duplicates. For example, given this
- * sequence:
- *
- * idx 0 1 2 3 4 5
- * key A C C C C D
- *
- * If we are searching for "B", we might
- * hit the duplicate run at lo=1, hi=3
- * (e.g., by first mi=3, then mi=0). But we
- * can never have lo > 1, because B < C.
- * That is, if our key is less than the
- * run, we know that "lo" is the edge, but
- * we can say nothing of "hi". Similarly,
- * if our key is greater than the run, we
- * know that "hi" is the edge, but we can
- * say nothing of "lo".
- *
- * Therefore if we do not find it, we also
- * know where it would go if it did exist:
- * just on the far side of the edge that we
- * know about.
- */
- if (ofs == 20) {
- mi = lo;
- mi_key = base + elem_size * mi + key_offset;
- cmp = memcmp(mi_key, key, 20);
- if (!cmp)
- return mi;
- if (cmp < 0)
- return -1 - hi;
- else
- return -1 - lo;
- }
-
- hiv = hi_key[ofs_0];
- if (ofs_0 < 19)
- hiv = (hiv << 8) | hi_key[ofs_0+1];
- } else {
- hiv = 256;
- if (ofs_0 < 19)
- hiv <<= 8;
- }
- lov = lo_key[ofs_0];
- kyv = key[ofs_0];
- if (ofs_0 < 19) {
- lov = (lov << 8) | lo_key[ofs_0+1];
- kyv = (kyv << 8) | key[ofs_0+1];
- }
- assert(lov < hiv);
-
- if (kyv < lov)
- return -1 - lo;
- if (hiv < kyv)
- return -1 - hi;
-
- /*
- * Even if we know the target is much closer to 'hi'
- * than 'lo', if we pick too precisely and overshoot
- * (e.g. when we know 'mi' is closer to 'hi' than to
- * 'lo', pick 'mi' that is higher than the target), we
- * end up narrowing the search space by a smaller
- * amount (i.e. the distance between 'mi' and 'hi')
- * than what we would have (i.e. about half of 'lo'
- * and 'hi'). Hedge our bets to pick 'mi' less
- * aggressively, i.e. make 'mi' a bit closer to the
- * middle than we would otherwise pick.
- */
- kyv = (kyv * 6 + lov + hiv) / 8;
- if (lov < hiv - 1) {
- if (kyv == lov)
- kyv++;
- else if (kyv == hiv)
- kyv--;
- }
- mi = (range - 1) * (kyv - lov) / (hiv - lov) + lo;
-
-#ifdef INDEX_DEBUG_LOOKUP
- printf("lo %u hi %u rg %u mi %u ", lo, hi, range, mi);
- printf("ofs %u lov %x, hiv %x, kyv %x\n",
- ofs_0, lov, hiv, kyv);
-#endif
-
- if (!(lo <= mi && mi < hi)) {
- giterr_set(GITERR_INVALID, "Assertion failure. Binary search invariant is false");
- return -1;
- }
+#include <stdio.h>
- mi_key = base + elem_size * mi + key_offset;
- cmp = memcmp(mi_key + ofs_0, key + ofs_0, 20 - ofs_0);
- if (!cmp)
- return mi;
- if (cmp > 0) {
- hi = mi;
- hi_key = mi_key;
- } else {
- lo = mi + 1;
- lo_key = mi_key + elem_size;
- }
- } while (lo < hi);
- return -((int)lo)-1;
-}
+#include "oid.h"
int sha1_position(const void *table,
size_t stride,
@@ -232,7 +18,7 @@ int sha1_position(const void *table,
{
const unsigned char *base = table;
- do {
+ while (lo < hi) {
unsigned mi = (lo + hi) / 2;
int cmp = git_oid__hashcmp(base + mi * stride, key);
@@ -243,7 +29,7 @@ int sha1_position(const void *table,
hi = mi;
else
lo = mi+1;
- } while (lo < hi);
+ }
return -((int)lo)-1;
}
diff --git a/src/sha1_lookup.h b/src/sha1_lookup.h
index 3799620c7..841ea5b22 100644
--- a/src/sha1_lookup.h
+++ b/src/sha1_lookup.h
@@ -7,13 +7,9 @@
#ifndef INCLUDE_sha1_lookup_h__
#define INCLUDE_sha1_lookup_h__
-#include <stdlib.h>
+#include "common.h"
-int sha1_entry_pos(const void *table,
- size_t elem_size,
- size_t key_offset,
- unsigned lo, unsigned hi, unsigned nr,
- const unsigned char *key);
+#include <stdlib.h>
int sha1_position(const void *table,
size_t stride,
diff --git a/src/signature.c b/src/signature.c
index dcc379717..bc3cf330a 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "signature.h"
+
#include "repository.h"
#include "git2/common.h"
#include "posix.h"
@@ -25,7 +25,7 @@ void git_signature_free(git_signature *sig)
static int signature_error(const char *msg)
{
- giterr_set(GITERR_INVALID, "Failed to parse signature - %s", msg);
+ giterr_set(GITERR_INVALID, "failed to parse signature - %s", msg);
return -1;
}
@@ -228,8 +228,12 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
const char *time_start = email_end + 2;
const char *time_end;
- if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0)
+ if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
+ git__free(sig->name);
+ git__free(sig->email);
+ sig->name = sig->email = NULL;
return signature_error("invalid Unix timestamp");
+ }
/* do we have a timezone? */
if (time_end + 1 < buffer_end) {
@@ -251,7 +255,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
* only store timezone if it's not overflowing;
* see http://www.worldtimezone.com/faq.html
*/
- if (hours < 14 && mins < 59) {
+ if (hours <= 14 && mins <= 59) {
sig->when.offset = (hours * 60) + mins;
if (tz_start[0] == '-')
sig->when.offset = -sig->when.offset;
diff --git a/src/signature.h b/src/signature.h
index 75265df52..40d7c54f9 100644
--- a/src/signature.h
+++ b/src/signature.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_signature_h__
#define INCLUDE_signature_h__
+#include "common.h"
+
#include "git2/common.h"
#include "git2/signature.h"
#include "repository.h"
diff --git a/src/socket_stream.c b/src/socket_stream.c
index 71f49118e..4c795e462 100644
--- a/src/socket_stream.c
+++ b/src/socket_stream.c
@@ -5,11 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "socket_stream.h"
+
#include "posix.h"
#include "netops.h"
#include "stream.h"
-#include "socket_stream.h"
#ifndef _WIN32
# include <sys/types.h>
@@ -57,7 +57,7 @@ static int close_socket(GIT_SOCKET s)
return -1;
if (0 != WSACleanup()) {
- giterr_set(GITERR_OS, "Winsock cleanup failed");
+ giterr_set(GITERR_OS, "winsock cleanup failed");
return -1;
}
@@ -82,13 +82,13 @@ int socket_connect(git_stream *stream)
WSADATA wsd;
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- giterr_set(GITERR_OS, "Winsock init failed");
+ giterr_set(GITERR_OS, "winsock init failed");
return -1;
}
if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) {
WSACleanup();
- giterr_set(GITERR_OS, "Winsock init failed");
+ giterr_set(GITERR_OS, "winsock init failed");
return -1;
}
#endif
@@ -99,17 +99,15 @@ int socket_connect(git_stream *stream)
if ((ret = p_getaddrinfo(st->host, st->port, &hints, &info)) != 0) {
giterr_set(GITERR_NET,
- "Failed to resolve address for %s: %s", st->host, p_gai_strerror(ret));
+ "failed to resolve address for %s: %s", st->host, p_gai_strerror(ret));
return -1;
}
for (p = info; p != NULL; p = p->ai_next) {
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
- if (s == INVALID_SOCKET) {
- net_set_error("error creating socket");
- break;
- }
+ if (s == INVALID_SOCKET)
+ continue;
if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0)
break;
@@ -121,7 +119,7 @@ int socket_connect(git_stream *stream)
/* Oops, we couldn't connect to any address */
if (s == INVALID_SOCKET && p == NULL) {
- giterr_set(GITERR_OS, "Failed to connect to %s", st->host);
+ giterr_set(GITERR_OS, "failed to connect to %s", st->host);
p_freeaddrinfo(info);
return -1;
}
diff --git a/src/socket_stream.h b/src/socket_stream.h
index 8e9949fcd..1f9ff78d1 100644
--- a/src/socket_stream.h
+++ b/src/socket_stream.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_socket_stream_h__
#define INCLUDE_socket_stream_h__
+#include "common.h"
+
#include "netops.h"
typedef struct {
diff --git a/src/sortedcache.c b/src/sortedcache.c
index 5c2a167a7..76672d9f7 100644
--- a/src/sortedcache.c
+++ b/src/sortedcache.c
@@ -1,6 +1,11 @@
-#include "sortedcache.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.
+ */
-GIT__USE_STRMAP
+#include "sortedcache.h"
int git_sortedcache_new(
git_sortedcache **out,
@@ -27,7 +32,7 @@ int git_sortedcache_new(
goto fail;
if (git_rwlock_init(&sc->lock)) {
- giterr_set(GITERR_OS, "Failed to initialize lock");
+ giterr_set(GITERR_OS, "failed to initialize lock");
goto fail;
}
@@ -162,7 +167,7 @@ int git_sortedcache_wlock(git_sortedcache *sc)
GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */
if (git_rwlock_wrlock(&sc->lock) < 0) {
- giterr_set(GITERR_OS, "Unable to acquire write lock on cache");
+ giterr_set(GITERR_OS, "unable to acquire write lock on cache");
return -1;
}
return 0;
@@ -181,7 +186,7 @@ int git_sortedcache_rlock(git_sortedcache *sc)
GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */
if (git_rwlock_rdlock(&sc->lock) < 0) {
- giterr_set(GITERR_OS, "Unable to acquire read lock on cache");
+ giterr_set(GITERR_OS, "unable to acquire read lock on cache");
return -1;
}
return 0;
@@ -200,6 +205,7 @@ void git_sortedcache_runlock(git_sortedcache *sc)
int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf)
{
int error, fd;
+ struct stat st;
if ((error = git_sortedcache_wlock(sc)) < 0)
return error;
@@ -207,19 +213,27 @@ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf)
if ((error = git_futils_filestamp_check(&sc->stamp, sc->path)) <= 0)
goto unlock;
- if (!git__is_sizet(sc->stamp.size)) {
- giterr_set(GITERR_INVALID, "Unable to load file larger than size_t");
+ if ((fd = git_futils_open_ro(sc->path)) < 0) {
+ error = fd;
+ goto unlock;
+ }
+
+ if (p_fstat(fd, &st) < 0) {
+ giterr_set(GITERR_OS, "failed to stat file");
error = -1;
+ (void)p_close(fd);
goto unlock;
}
- if ((fd = git_futils_open_ro(sc->path)) < 0) {
- error = fd;
+ if (!git__is_sizet(st.st_size)) {
+ giterr_set(GITERR_INVALID, "unable to load file larger than size_t");
+ error = -1;
+ (void)p_close(fd);
goto unlock;
}
if (buf)
- error = git_futils_readbuffer_fd(buf, fd, (size_t)sc->stamp.size);
+ error = git_futils_readbuffer_fd(buf, fd, (size_t)st.st_size);
(void)p_close(fd);
@@ -285,13 +299,13 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key)
item_key = ((char *)item) + sc->item_path_offset;
memcpy(item_key, key, keylen);
- pos = kh_put(str, sc->map, item_key, &error);
+ pos = git_strmap_put(sc->map, item_key, &error);
if (error < 0)
goto done;
if (!error)
- kh_key(sc->map, pos) = item_key;
- kh_val(sc->map, pos) = item;
+ git_strmap_set_key_at(sc->map, pos, item_key);
+ git_strmap_set_value_at(sc->map, pos, item);
error = git_vector_insert(&sc->items, item);
if (error < 0)
@@ -364,7 +378,7 @@ int git_sortedcache_remove(git_sortedcache *sc, size_t pos)
*/
if ((item = git_vector_get(&sc->items, pos)) == NULL) {
- giterr_set(GITERR_INVALID, "Removing item out of range");
+ giterr_set(GITERR_INVALID, "removing item out of range");
return GIT_ENOTFOUND;
}
diff --git a/src/sortedcache.h b/src/sortedcache.h
index 4cacad62b..a53ff48a3 100644
--- a/src/sortedcache.h
+++ b/src/sortedcache.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_sorted_cache_h__
#define INCLUDE_sorted_cache_h__
+#include "common.h"
+
#include "util.h"
#include "fileops.h"
#include "vector.h"
diff --git a/src/stash.c b/src/stash.c
index f5f4f36bf..8a8c57a83 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "repository.h"
#include "commit.h"
#include "message.h"
@@ -27,7 +28,7 @@
static int create_error(int error, const char *msg)
{
- giterr_set(GITERR_STASH, "Cannot stash changes - %s", msg);
+ giterr_set(GITERR_STASH, "cannot stash changes - %s", msg);
return error;
}
@@ -36,7 +37,7 @@ static int retrieve_head(git_reference **out, git_repository *repo)
int error = git_repository_head(out, repo);
if (error == GIT_EUNBORNBRANCH)
- return create_error(error, "You do not have the initial commit yet.");
+ return create_error(error, "you do not have the initial commit yet.");
return error;
}
@@ -198,7 +199,7 @@ static int stash_update_index_from_diff(
/* Unimplemented */
giterr_set(
GITERR_INVALID,
- "Cannot update index. Unimplemented status (%d)",
+ "cannot update index. Unimplemented status (%d)",
delta->status);
return -1;
}
@@ -479,7 +480,7 @@ static int ensure_there_are_changes_to_stash(
return 0;
if (!error)
- return create_error(GIT_ENOTFOUND, "There is nothing to stash.");
+ return create_error(GIT_ENOTFOUND, "there is nothing to stash.");
return error;
}
@@ -593,7 +594,7 @@ static int retrieve_stash_commit(
max = git_reflog_entrycount(reflog);
if (!max || index > max - 1) {
error = GIT_ENOTFOUND;
- giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
+ giterr_set(GITERR_STASH, "no stashed state at position %" PRIuZ, index);
goto cleanup;
}
@@ -1036,7 +1037,7 @@ int git_stash_drop(
if (!max || index > max - 1) {
error = GIT_ENOTFOUND;
- giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index);
+ giterr_set(GITERR_STASH, "no stashed state at position %" PRIuZ, index);
goto cleanup;
}
diff --git a/src/status.c b/src/status.c
index e610f5fe1..03682bc72 100644
--- a/src/status.c
+++ b/src/status.c
@@ -5,13 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "status.h"
+
#include "git2.h"
#include "fileops.h"
#include "hash.h"
#include "vector.h"
#include "tree.h"
-#include "status.h"
#include "git2/status.h"
#include "repository.h"
#include "ignore.h"
@@ -243,13 +243,13 @@ static int status_validate_options(const git_status_options *opts)
GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options");
if (opts->show > GIT_STATUS_SHOW_WORKDIR_ONLY) {
- giterr_set(GITERR_INVALID, "Unknown status 'show' option");
+ giterr_set(GITERR_INVALID, "unknown status 'show' option");
return -1;
}
if ((opts->flags & GIT_STATUS_OPT_NO_REFRESH) != 0 &&
(opts->flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) {
- giterr_set(GITERR_INVALID, "Updating index from status "
+ giterr_set(GITERR_INVALID, "updating index from status "
"is not allowed when index refresh is disabled");
return -1;
}
@@ -510,13 +510,13 @@ int git_status_file(
if (error < 0 && sfi.ambiguous) {
giterr_set(GITERR_INVALID,
- "Ambiguous path '%s' given to git_status_file", sfi.expected);
+ "ambiguous path '%s' given to git_status_file", sfi.expected);
error = GIT_EAMBIGUOUS;
}
if (!error && !sfi.count) {
giterr_set(GITERR_INVALID,
- "Attempt to get status of nonexistent file '%s'", path);
+ "attempt to get status of nonexistent file '%s'", path);
error = GIT_ENOTFOUND;
}
diff --git a/src/status.h b/src/status.h
index 33008b89c..907479a22 100644
--- a/src/status.h
+++ b/src/status.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_status_h__
#define INCLUDE_status_h__
+#include "common.h"
+
#include "diff.h"
#include "git2/status.h"
#include "git2/diff.h"
diff --git a/src/stransport_stream.c b/src/stransport_stream.c
index 50ed9452c..18371ef92 100644
--- a/src/stransport_stream.c
+++ b/src/stransport_stream.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "stransport_stream.h"
+
#ifdef GIT_SECURE_TRANSPORT
#include <CoreFoundation/CoreFoundation.h>
diff --git a/src/stransport_stream.h b/src/stransport_stream.h
index 714f90273..f5bbfd952 100644
--- a/src/stransport_stream.h
+++ b/src/stransport_stream.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_stransport_stream_h__
#define INCLUDE_stransport_stream_h__
+#include "common.h"
+
#include "git2/sys/stream.h"
extern int git_stransport_stream_new(git_stream **out, const char *host, const char *port);
diff --git a/src/strmap.c b/src/strmap.c
index b26a13d1f..de6826d03 100644
--- a/src/strmap.c
+++ b/src/strmap.c
@@ -7,6 +7,101 @@
#include "strmap.h"
+__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
+
+int git_strmap_alloc(git_strmap **map)
+{
+ if ((*map = kh_init(str)) == NULL) {
+ giterr_set_oom();
+ return -1;
+ }
+
+ return 0;
+}
+
+void git_strmap_free(git_strmap *map)
+{
+ kh_destroy(str, map);
+}
+
+void git_strmap_clear(git_strmap *map)
+{
+ kh_clear(str, map);
+}
+
+size_t git_strmap_num_entries(git_strmap *map)
+{
+ return kh_size(map);
+}
+
+size_t git_strmap_lookup_index(git_strmap *map, const char *key)
+{
+ return kh_get(str, map, key);
+}
+
+int git_strmap_valid_index(git_strmap *map, size_t idx)
+{
+ return idx != kh_end(map);
+}
+
+int git_strmap_exists(git_strmap *map, const char *key)
+{
+ return kh_get(str, map, key) != kh_end(map);
+}
+
+int git_strmap_has_data(git_strmap *map, size_t idx)
+{
+ return kh_exist(map, idx);
+}
+
+const char *git_strmap_key(git_strmap *map, size_t idx)
+{
+ return kh_key(map, idx);
+}
+
+void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key)
+{
+ kh_val(map, idx) = key;
+}
+
+void *git_strmap_value_at(git_strmap *map, size_t idx)
+{
+ return kh_val(map, idx);
+}
+
+void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value)
+{
+ kh_val(map, idx) = value;
+}
+
+void git_strmap_delete_at(git_strmap *map, size_t idx)
+{
+ kh_del(str, map, idx);
+}
+
+int git_strmap_put(git_strmap *map, const char *key, int *err)
+{
+ return kh_put(str, map, key, err);
+}
+
+void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval)
+{
+ khiter_t idx = kh_put(str, map, key, rval);
+
+ if ((*rval) >= 0) {
+ if ((*rval) == 0)
+ kh_key(map, idx) = key;
+ kh_val(map, idx) = value;
+ }
+}
+
+void git_strmap_delete(git_strmap *map, const char *key)
+{
+ khiter_t idx = git_strmap_lookup_index(map, key);
+ if (git_strmap_valid_index(map, idx))
+ git_strmap_delete_at(map, idx);
+}
+
int git_strmap_next(
void **data,
git_strmap_iter* iter,
diff --git a/src/strmap.h b/src/strmap.h
index 520984744..802b92494 100644
--- a/src/strmap.h
+++ b/src/strmap.h
@@ -20,49 +20,27 @@ __KHASH_TYPE(str, const char *, void *)
typedef khash_t(str) git_strmap;
typedef khiter_t git_strmap_iter;
-#define GIT__USE_STRMAP \
- __KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
+int git_strmap_alloc(git_strmap **map);
+void git_strmap_free(git_strmap *map);
+void git_strmap_clear(git_strmap *map);
-#define git_strmap_alloc(hp) \
- ((*(hp) = kh_init(str)) == NULL) ? giterr_set_oom(), -1 : 0
+size_t git_strmap_num_entries(git_strmap *map);
-#define git_strmap_free(h) kh_destroy(str, h), h = NULL
-#define git_strmap_clear(h) kh_clear(str, h)
+size_t git_strmap_lookup_index(git_strmap *map, const char *key);
+int git_strmap_valid_index(git_strmap *map, size_t idx);
-#define git_strmap_num_entries(h) kh_size(h)
+int git_strmap_exists(git_strmap *map, const char *key);
+int git_strmap_has_data(git_strmap *map, size_t idx);
-#define git_strmap_lookup_index(h, k) kh_get(str, h, k)
-#define git_strmap_valid_index(h, idx) (idx != kh_end(h))
+const char *git_strmap_key(git_strmap *map, size_t idx);
+void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key);
+void *git_strmap_value_at(git_strmap *map, size_t idx);
+void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value);
+void git_strmap_delete_at(git_strmap *map, size_t idx);
-#define git_strmap_exists(h, k) (kh_get(str, h, k) != kh_end(h))
-#define git_strmap_has_data(h, idx) kh_exist(h, idx)
-
-#define git_strmap_key(h, idx) kh_key(h, idx)
-#define git_strmap_value_at(h, idx) kh_val(h, idx)
-#define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v
-#define git_strmap_delete_at(h, idx) kh_del(str, h, idx)
-
-#define git_strmap_insert(h, key, val, rval) do { \
- khiter_t __pos = kh_put(str, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) kh_key(h, __pos) = key; \
- kh_val(h, __pos) = val; \
- } } while (0)
-
-#define git_strmap_insert2(h, key, val, oldv, rval) do { \
- khiter_t __pos = kh_put(str, h, key, &rval); \
- if (rval >= 0) { \
- if (rval == 0) { \
- oldv = kh_val(h, __pos); \
- kh_key(h, __pos) = key; \
- } else { oldv = NULL; } \
- kh_val(h, __pos) = val; \
- } } while (0)
-
-#define git_strmap_delete(h, key) do { \
- khiter_t __pos = git_strmap_lookup_index(h, key); \
- if (git_strmap_valid_index(h, __pos)) \
- git_strmap_delete_at(h, __pos); } while (0)
+int git_strmap_put(git_strmap *map, const char *key, int *err);
+void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval);
+void git_strmap_delete(git_strmap *map, const char *key);
#define git_strmap_foreach kh_foreach
#define git_strmap_foreach_value kh_foreach_value
diff --git a/src/submodule.c b/src/submodule.c
index 86ad53be0..6c3e5f6bd 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "submodule.h"
+
#include "git2/config.h"
#include "git2/sys/config.h"
#include "git2/types.h"
@@ -17,11 +18,11 @@
#include "config_file.h"
#include "config.h"
#include "repository.h"
-#include "submodule.h"
#include "tree.h"
#include "iterator.h"
#include "path.h"
#include "index.h"
+#include "worktree.h"
#define GIT_MODULES_FILE ".gitmodules"
@@ -124,8 +125,8 @@ static void submodule_set_lookup_error(int error, const char *name)
return;
giterr_set(GITERR_SUBMODULE, (error == GIT_ENOTFOUND) ?
- "No submodule named '%s'" :
- "Submodule '%s' has not been added yet", name);
+ "no submodule named '%s'" :
+ "submodule '%s' has not been added yet", name);
}
typedef struct {
@@ -149,40 +150,52 @@ static int find_by_path(const git_config_entry *entry, void *payload)
}
/**
- * Find out the name of a submodule from its path
+ * Release the name map returned by 'load_submodule_names'.
+ */
+static void free_submodule_names(git_strmap *names)
+{
+ git_buf *name = 0;
+ if (names == NULL)
+ return;
+ git_strmap_foreach_value(names, name, {
+ git__free(name);
+ });
+ git_strmap_free(names);
+ return;
+}
+
+/**
+ * Map submodule paths to names.
+ * TODO: for some use-cases, this might need case-folding on a
+ * case-insensitive filesystem
*/
-static int name_from_path(git_buf *out, git_config *cfg, const char *path)
+static int load_submodule_names(git_strmap *out, git_config *cfg)
{
const char *key = "submodule\\..*\\.path";
git_config_iterator *iter;
git_config_entry *entry;
- int error;
+ git_buf buf = GIT_BUF_INIT;
+ int rval;
+ int error = 0;
if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0)
return error;
- while ((error = git_config_next(&entry, iter)) == 0) {
+ while (git_config_next(&entry, iter) == 0) {
const char *fdot, *ldot;
- /* TODO: this should maybe be strcasecmp on a case-insensitive fs */
- if (strcmp(path, entry->value) != 0)
- continue;
-
fdot = strchr(entry->name, '.');
ldot = strrchr(entry->name, '.');
- git_buf_clear(out);
- git_buf_put(out, fdot + 1, ldot - fdot - 1);
- goto cleanup;
- }
-
- if (error == GIT_ITEROVER) {
- giterr_set(GITERR_SUBMODULE, "could not find a submodule name for '%s'", path);
- error = GIT_ENOTFOUND;
+ git_buf_put(&buf, fdot + 1, ldot - fdot - 1);
+ git_strmap_insert(out, entry->value, git_buf_detach(&buf), &rval);
+ if (rval < 0) {
+ giterr_set(GITERR_NOMEMORY, "error inserting submodule into hash table");
+ return -1;
+ }
}
-cleanup:
git_config_iterator_free(iter);
- return error;
+ return 0;
}
int git_submodule_lookup(
@@ -196,6 +209,22 @@ int git_submodule_lookup(
assert(repo && name);
+ if (repo->is_bare) {
+ giterr_set(GITERR_SUBMODULE, "cannot get submodules without a working tree");
+ return -1;
+ }
+
+ if (repo->submodule_cache != NULL) {
+ khiter_t pos = git_strmap_lookup_index(repo->submodule_cache, name);
+ if (git_strmap_valid_index(repo->submodule_cache, pos)) {
+ if (out) {
+ *out = git_strmap_value_at(repo->submodule_cache, pos);
+ GIT_REFCOUNT_INC(*out);
+ }
+ return 0;
+ }
+ }
+
if ((error = submodule_alloc(&sm, repo, name)) < 0)
return error;
@@ -306,7 +335,7 @@ static int submodule_get_or_create(git_submodule **out, git_repository *repo, gi
if ((error = submodule_alloc(&sm, repo, name)) < 0)
return error;
- pos = kh_put(str, map, sm->name, &error);
+ pos = git_strmap_put(map, sm->name, &error);
/* nobody can beat us to adding it */
assert(error != 0);
if (error < 0) {
@@ -324,89 +353,108 @@ done:
static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cfg)
{
- int error;
- git_iterator *i;
- const git_index_entry *entry;
- git_buf name = GIT_BUF_INIT;
-
- if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0)
- return error;
+ int error;
+ git_iterator *i = NULL;
+ const git_index_entry *entry;
+ git_strmap *names = 0;
- while (!(error = git_iterator_advance(&entry, i))) {
- khiter_t pos = git_strmap_lookup_index(map, entry->path);
- git_submodule *sm;
+ git_strmap_alloc(&names);
+ if ((error = load_submodule_names(names, cfg)))
+ goto done;
- git_buf_clear(&name);
- if (!name_from_path(&name, cfg, entry->path)) {
- git_strmap_lookup_index(map, name.ptr);
- }
+ if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0)
+ goto done;
- if (git_strmap_valid_index(map, pos)) {
- sm = git_strmap_value_at(map, pos);
+ while (!(error = git_iterator_advance(&entry, i))) {
+ khiter_t pos = git_strmap_lookup_index(map, entry->path);
+ git_submodule *sm;
+
+ if (git_strmap_valid_index(map, pos)) {
+ sm = git_strmap_value_at(map, pos);
+
+ if (S_ISGITLINK(entry->mode))
+ submodule_update_from_index_entry(sm, entry);
+ else
+ sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
+ } else if (S_ISGITLINK(entry->mode)) {
+ khiter_t name_pos;
+ const char *name;
+
+ name_pos = git_strmap_lookup_index(names, entry->path);
+ if (git_strmap_valid_index(names, name_pos)) {
+ name = git_strmap_value_at(names, name_pos);
+ } else {
+ name = entry->path;
+ }
- if (S_ISGITLINK(entry->mode))
- submodule_update_from_index_entry(sm, entry);
- else
- sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE;
- } else if (S_ISGITLINK(entry->mode)) {
- if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name.ptr ? name.ptr : entry->path)) {
- submodule_update_from_index_entry(sm, entry);
- git_submodule_free(sm);
- }
- }
- }
+ if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name)) {
+ submodule_update_from_index_entry(sm, entry);
+ git_submodule_free(sm);
+ }
+ }
+ }
- if (error == GIT_ITEROVER)
- error = 0;
+ if (error == GIT_ITEROVER)
+ error = 0;
- git_buf_free(&name);
- git_iterator_free(i);
+done:
+ git_iterator_free(i);
+ free_submodule_names(names);
- return error;
+ return error;
}
static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg)
{
- int error;
- git_iterator *i;
- const git_index_entry *entry;
- git_buf name = GIT_BUF_INIT;
-
- if ((error = git_iterator_for_tree(&i, head, NULL)) < 0)
- return error;
-
- while (!(error = git_iterator_advance(&entry, i))) {
- khiter_t pos = git_strmap_lookup_index(map, entry->path);
- git_submodule *sm;
+ int error;
+ git_iterator *i = NULL;
+ const git_index_entry *entry;
+ git_strmap *names = 0;
+ git_strmap_alloc(&names);
+ if ((error = load_submodule_names(names, cfg)))
+ goto done;
- git_buf_clear(&name);
- if (!name_from_path(&name, cfg, entry->path)) {
- git_strmap_lookup_index(map, name.ptr);
- }
+ if ((error = git_iterator_for_tree(&i, head, NULL)) < 0)
+ goto done;
- if (git_strmap_valid_index(map, pos)) {
- sm = git_strmap_value_at(map, pos);
+ while (!(error = git_iterator_advance(&entry, i))) {
+ khiter_t pos = git_strmap_lookup_index(map, entry->path);
+ git_submodule *sm;
+
+ if (git_strmap_valid_index(map, pos)) {
+ sm = git_strmap_value_at(map, pos);
+
+ if (S_ISGITLINK(entry->mode))
+ submodule_update_from_head_data(sm, entry->mode, &entry->id);
+ else
+ sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
+ } else if (S_ISGITLINK(entry->mode)) {
+ khiter_t name_pos;
+ const char *name;
+
+ name_pos = git_strmap_lookup_index(names, entry->path);
+ if (git_strmap_valid_index(names, name_pos)) {
+ name = git_strmap_value_at(names, name_pos);
+ } else {
+ name = entry->path;
+ }
- if (S_ISGITLINK(entry->mode))
- submodule_update_from_head_data(sm, entry->mode, &entry->id);
- else
- sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE;
- } else if (S_ISGITLINK(entry->mode)) {
- if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name.ptr ? name.ptr : entry->path)) {
- submodule_update_from_head_data(
- sm, entry->mode, &entry->id);
- git_submodule_free(sm);
- }
- }
- }
+ if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name)) {
+ submodule_update_from_head_data(
+ sm, entry->mode, &entry->id);
+ git_submodule_free(sm);
+ }
+ }
+ }
- if (error == GIT_ITEROVER)
- error = 0;
+ if (error == GIT_ITEROVER)
+ error = 0;
- git_buf_free(&name);
- git_iterator_free(i);
+done:
+ git_iterator_free(i);
+ free_submodule_names(names);
- return error;
+ return error;
}
/* If have_sm is true, sm is populated, otherwise map an repo are. */
@@ -416,7 +464,7 @@ typedef struct {
git_repository *repo;
} lfc_data;
-static int all_submodules(git_repository *repo, git_strmap *map)
+int git_submodule__map(git_repository *repo, git_strmap *map)
{
int error = 0;
git_index *idx = NULL;
@@ -470,12 +518,12 @@ static int all_submodules(git_repository *repo, git_strmap *map)
goto cleanup;
}
/* add back submodule information from index */
- if (idx) {
+ if (mods && idx) {
if ((error = submodules_from_index(map, idx, mods)) < 0)
goto cleanup;
}
/* add submodule information from HEAD */
- if (head) {
+ if (mods && head) {
if ((error = submodules_from_head(map, head, mods)) < 0)
goto cleanup;
}
@@ -506,14 +554,19 @@ int git_submodule_foreach(
int error;
size_t i;
+ if (repo->is_bare) {
+ giterr_set(GITERR_SUBMODULE, "cannot get submodules without a working tree");
+ return -1;
+ }
+
if ((error = git_strmap_alloc(&submodules)) < 0)
return error;
- if ((error = all_submodules(repo, submodules)) < 0)
+ if ((error = git_submodule__map(repo, submodules)) < 0)
goto done;
if (!(error = git_vector_init(
- &snapshot, kh_size(submodules), submodule_cmp))) {
+ &snapshot, git_strmap_num_entries(submodules), submodule_cmp))) {
git_strmap_foreach_value(submodules, sm, {
if ((error = git_vector_insert(&snapshot, sm)) < 0)
@@ -574,8 +627,10 @@ static int submodule_repo_init(
* Old style: sub-repo goes directly into repo/<name>/.git/
*/
if (use_gitlink) {
- error = git_buf_join3(
- &repodir, '/', git_repository_path(parent_repo), "modules", path);
+ error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
+ if (error < 0)
+ goto cleanup;
+ error = git_buf_joinpath(&repodir, repodir.ptr, path);
if (error < 0)
goto cleanup;
@@ -618,7 +673,7 @@ int git_submodule_add_setup(
giterr_clear();
else {
giterr_set(GITERR_SUBMODULE,
- "Attempt to add submodule '%s' that already exists", path);
+ "attempt to add submodule '%s' that already exists", path);
return GIT_EEXISTS;
}
@@ -628,7 +683,7 @@ int git_submodule_add_setup(
path += strlen(git_repository_workdir(repo));
if (git_path_root(path) >= 0) {
- giterr_set(GITERR_SUBMODULE, "Submodule path must be a relative path");
+ giterr_set(GITERR_SUBMODULE, "submodule path must be a relative path");
error = -1;
goto cleanup;
}
@@ -637,7 +692,7 @@ int git_submodule_add_setup(
if (!(mods = open_gitmodules(repo, GITMODULES_CREATE))) {
giterr_set(GITERR_SUBMODULE,
- "Adding submodules to a bare repository is not supported");
+ "adding submodules to a bare repository is not supported");
return -1;
}
@@ -758,7 +813,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
/* read stat information for submodule working directory */
if (p_stat(path.ptr, &st) < 0) {
giterr_set(GITERR_SUBMODULE,
- "Cannot add submodule without working directory");
+ "cannot add submodule without working directory");
error = -1;
goto cleanup;
}
@@ -771,7 +826,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
/* calling git_submodule_open will have set sm->wd_oid if possible */
if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) {
giterr_set(GITERR_SUBMODULE,
- "Cannot add submodule without HEAD to index");
+ "cannot add submodule without HEAD to index");
error = -1;
goto cleanup;
}
@@ -861,7 +916,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
} else if (strchr(url, ':') != NULL || url[0] == '/') {
error = git_buf_sets(out, url);
} else {
- giterr_set(GITERR_SUBMODULE, "Invalid format for submodule URL");
+ giterr_set(GITERR_SUBMODULE, "invalid format for submodule URL");
error = -1;
}
@@ -1042,8 +1097,10 @@ static int submodule_repo_create(
* <repo-dir>/modules/<name>/ with a gitlink in the
* sub-repo workdir directory to that repository.
*/
- error = git_buf_join3(
- &repodir, '/', git_repository_path(parent_repo), "modules", path);
+ error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES);
+ if (error < 0)
+ goto cleanup;
+ error = git_buf_joinpath(&repodir, repodir.ptr, path);
if (error < 0)
goto cleanup;
@@ -1133,7 +1190,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
goto done;
if (!init) {
- giterr_set(GITERR_SUBMODULE, "Submodule is not initialized.");
+ giterr_set(GITERR_SUBMODULE, "submodule is not initialized");
error = GIT_ERROR;
goto done;
}
@@ -1160,13 +1217,14 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
* will checkout the specific commit manually.
*/
clone_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
- update_options.checkout_opts.checkout_strategy = update_options.clone_checkout_strategy;
if ((error = git_clone(&sub_repo, submodule_url, sm->path, &clone_options)) < 0 ||
(error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0 ||
(error = git_checkout_head(sub_repo, &update_options.checkout_opts)) != 0)
goto done;
} else {
+ const git_oid *oid;
+
/**
* Work dir is initialized - look up the commit in the parent repository's index,
* update the workdir contents of the subrepository, and set the subrepository's
@@ -1175,8 +1233,14 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
if ((error = git_submodule_open(&sub_repo, sm)) < 0)
goto done;
+ if ((oid = git_submodule_index_id(sm)) == NULL) {
+ giterr_set(GITERR_SUBMODULE, "could not get ID of submodule in index");
+ error = -1;
+ goto done;
+ }
+
/* Look up the target commit in the submodule. */
- if ((error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0) {
+ if ((error = git_object_lookup(&target_commit, sub_repo, oid, GIT_OBJ_COMMIT)) < 0) {
/* If it isn't found then fetch and try again. */
if (error != GIT_ENOTFOUND || !update_options.allow_fetch ||
(error = lookup_default_remote(&remote, sub_repo)) < 0 ||
@@ -1215,7 +1279,7 @@ int git_submodule_init(git_submodule *sm, int overwrite)
if (!sm->url) {
giterr_set(GITERR_SUBMODULE,
- "No URL configured for submodule '%s'", sm->name);
+ "no URL configured for submodule '%s'", sm->name);
return -1;
}
@@ -1259,7 +1323,7 @@ int git_submodule_sync(git_submodule *sm)
if (!sm->url) {
giterr_set(GITERR_SUBMODULE,
- "No URL configured for submodule '%s'", sm->name);
+ "no URL configured for submodule '%s'", sm->name);
return -1;
}
@@ -1502,13 +1566,22 @@ int git_submodule__status(
return 0;
}
- /* refresh the index OID */
- if (submodule_update_index(sm) < 0)
- return -1;
+ /* If the user has requested caching submodule state, performing these
+ * expensive operations (especially `submodule_update_head`, which is
+ * bottlenecked on `git_repository_head_tree`) eliminates much of the
+ * advantage. We will, therefore, interpret the request for caching to
+ * apply here to and skip them.
+ */
- /* refresh the HEAD OID */
- if (submodule_update_head(sm) < 0)
- return -1;
+ if (sm->repo->submodule_cache == NULL) {
+ /* refresh the index OID */
+ if (submodule_update_index(sm) < 0)
+ return -1;
+
+ /* refresh the HEAD OID */
+ if (submodule_update_head(sm) < 0)
+ return -1;
+ }
/* for ignore == dirty, don't scan the working directory */
if (ign == GIT_SUBMODULE_IGNORE_DIRTY) {
@@ -1566,7 +1639,6 @@ int git_submodule_location(unsigned int *location, git_submodule *sm)
location, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_ALL);
}
-
/*
* INTERNAL FUNCTIONS
*/
@@ -1578,7 +1650,7 @@ static int submodule_alloc(
git_submodule *sm;
if (!name || !(namelen = strlen(name))) {
- giterr_set(GITERR_SUBMODULE, "Invalid submodule name");
+ giterr_set(GITERR_SUBMODULE, "invalid submodule name");
return -1;
}
@@ -1630,7 +1702,7 @@ void git_submodule_free(git_submodule *sm)
static int submodule_config_error(const char *property, const char *value)
{
giterr_set(GITERR_INVALID,
- "Invalid value for submodule '%s' property: '%s'", property, value);
+ "invalid value for submodule '%s' property: '%s'", property, value);
return -1;
}
@@ -1813,7 +1885,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
goto done;
}
- git_strmap_insert(map, sm->name, sm, error);
+ git_strmap_insert(map, sm->name, sm, &error);
assert(error != 0);
if (error < 0)
goto done;
@@ -1968,7 +2040,7 @@ static int lookup_default_remote(git_remote **remote, git_repository *repo)
if (error == GIT_ENOTFOUND)
giterr_set(
GITERR_SUBMODULE,
- "Cannot get default remote for submodule - no local tracking "
+ "cannot get default remote for submodule - no local tracking "
"branch for HEAD and origin does not exist");
return error;
@@ -1977,17 +2049,28 @@ static int lookup_default_remote(git_remote **remote, git_repository *repo)
static int get_url_base(git_buf *url, git_repository *repo)
{
int error;
+ git_worktree *wt = NULL;
git_remote *remote = NULL;
- if (!(error = lookup_default_remote(&remote, repo))) {
+ if ((error = lookup_default_remote(&remote, repo)) == 0) {
error = git_buf_sets(url, git_remote_url(remote));
- git_remote_free(remote);
- }
- else if (error == GIT_ENOTFOUND) {
- /* if repository does not have a default remote, use workdir instead */
+ goto out;
+ } else if (error != GIT_ENOTFOUND)
+ goto out;
+ else
giterr_clear();
+
+ /* if repository does not have a default remote, use workdir instead */
+ if (git_repository_is_worktree(repo)) {
+ if ((error = git_worktree_open_from_repository(&wt, repo)) < 0)
+ goto out;
+ error = git_buf_sets(url, wt->parent_path);
+ } else
error = git_buf_sets(url, git_repository_workdir(repo));
- }
+
+out:
+ git_remote_free(remote);
+ git_worktree_free(wt);
return error;
}
diff --git a/src/submodule.h b/src/submodule.h
index 2ef2031b3..72867a322 100644
--- a/src/submodule.h
+++ b/src/submodule.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_submodule_h__
#define INCLUDE_submodule_h__
+#include "common.h"
+
#include "git2/submodule.h"
#include "git2/repository.h"
#include "fileops.h"
@@ -143,4 +145,7 @@ extern int git_submodule_parse_ignore(
extern int git_submodule_parse_update(
git_submodule_update_t *out, const char *value);
+extern int git_submodule__map(
+ git_repository *repo,
+ git_strmap *map);
#endif
diff --git a/src/sysdir.c b/src/sysdir.c
index 29e53e239..7480e82fd 100644
--- a/src/sysdir.c
+++ b/src/sysdir.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "sysdir.h"
+
#include "global.h"
#include "buffer.h"
#include "path.h"
@@ -150,7 +150,7 @@ int git_sysdir_get_str(
GITERR_CHECK_ERROR(git_sysdir_get(&path, which));
if (!out || path->size >= outlen) {
- giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path");
+ giterr_set(GITERR_NOMEMORY, "buffer is too short for the path");
return GIT_EBUFS;
}
@@ -171,7 +171,7 @@ int git_sysdir_set(git_sysdir_t which, const char *search_path)
expand_path = strstr(search_path, PATH_MAGIC);
/* reset the default if this path has been cleared */
- if (!search_path || expand_path)
+ if (!search_path)
git_sysdir__dirs[which].guess(&git_sysdir__dirs[which].buf);
/* if $PATH is not referenced, then just set the path */
@@ -241,7 +241,7 @@ static int git_sysdir_find_in_dirlist(
done:
git_buf_free(path);
- giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name);
+ giterr_set(GITERR_OS, "the %s file '%s' doesn't exist", label, name);
return GIT_ENOTFOUND;
}
@@ -275,3 +275,14 @@ int git_sysdir_find_template_dir(git_buf *path)
path, NULL, GIT_SYSDIR_TEMPLATE, "template");
}
+int git_sysdir_expand_global_file(git_buf *path, const char *filename)
+{
+ int error;
+
+ if ((error = git_sysdir_find_global_file(path, NULL)) == 0) {
+ if (filename)
+ error = git_buf_joinpath(path, path->ptr, filename);
+ }
+
+ return error;
+}
diff --git a/src/sysdir.h b/src/sysdir.h
index 11878981c..8f4466b46 100644
--- a/src/sysdir.h
+++ b/src/sysdir.h
@@ -8,6 +8,7 @@
#define INCLUDE_sysdir_h__
#include "common.h"
+
#include "posix.h"
#include "buffer.h"
@@ -55,6 +56,18 @@ extern int git_sysdir_find_programdata_file(git_buf *path, const char *filename)
*/
extern int git_sysdir_find_template_dir(git_buf *path);
+/**
+ * Expand the name of a "global" file (i.e. one in a user's home
+ * directory). Unlike `find_global_file` (above), this makes no
+ * attempt to check for the existence of the file, and is useful if
+ * you want the full path regardless of existence.
+ *
+ * @param path buffer to write the full path into
+ * @param filename name of file in the home directory
+ * @return 0 on success or -1 on error
+ */
+extern int git_sysdir_expand_global_file(git_buf *path, const char *filename);
+
typedef enum {
GIT_SYSDIR_SYSTEM = 0,
GIT_SYSDIR_GLOBAL = 1,
diff --git a/src/tag.c b/src/tag.c
index fe840fe82..445c3ff1d 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "commit.h"
#include "tag.h"
+
+#include "commit.h"
#include "signature.h"
#include "message.h"
#include "git2/object.h"
@@ -61,7 +61,7 @@ const char *git_tag_message(const git_tag *t)
static int tag_error(const char *str)
{
- giterr_set(GITERR_TAG, "Failed to parse tag. %s", str);
+ giterr_set(GITERR_TAG, "failed to parse tag: %s", str);
return -1;
}
@@ -76,13 +76,13 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
char *search;
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
- return tag_error("Object field invalid");
+ return tag_error("object field invalid");
if (buffer + 5 >= buffer_end)
- return tag_error("Object too short");
+ return tag_error("object too short");
if (memcmp(buffer, "type ", 5) != 0)
- return tag_error("Type field not found");
+ return tag_error("type field not found");
buffer += 5;
tag->type = GIT_OBJ_BAD;
@@ -91,7 +91,7 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
size_t type_length = strlen(tag_types[i]);
if (buffer + type_length >= buffer_end)
- return tag_error("Object too short");
+ return tag_error("object too short");
if (memcmp(buffer, tag_types[i], type_length) == 0) {
tag->type = i;
@@ -101,19 +101,19 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
}
if (tag->type == GIT_OBJ_BAD)
- return tag_error("Invalid object type");
+ return tag_error("invalid object type");
if (buffer + 4 >= buffer_end)
- return tag_error("Object too short");
+ return tag_error("object too short");
if (memcmp(buffer, "tag ", 4) != 0)
- return tag_error("Tag field not found");
+ return tag_error("tag field not found");
buffer += 4;
search = memchr(buffer, '\n', buffer_end - buffer);
if (search == NULL)
- return tag_error("Object too short");
+ return tag_error("object too short");
text_len = search - buffer;
@@ -234,7 +234,7 @@ static int write_tag_annotation(
on_error:
git_buf_free(&tag);
- giterr_set(GITERR_OBJECT, "Failed to create tag annotation.");
+ giterr_set(GITERR_OBJECT, "failed to create tag annotation");
return -1;
}
@@ -257,7 +257,7 @@ static int git_tag_create__internal(
assert(!create_tag_annotation || (tagger && message));
if (git_object_owner(target) != repo) {
- giterr_set(GITERR_INVALID, "The given target does not belong to this repository");
+ giterr_set(GITERR_INVALID, "the given target does not belong to this repository");
return -1;
}
@@ -269,7 +269,7 @@ static int git_tag_create__internal(
* reference unless overwriting has explicitly been requested **/
if (error == 0 && !allow_ref_overwrite) {
git_buf_free(&ref_name);
- giterr_set(GITERR_TAG, "Tag already exists");
+ giterr_set(GITERR_TAG, "tag already exists");
return GIT_EEXISTS;
}
@@ -349,7 +349,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
goto on_error;
if (tag.type != target_obj->cached.type) {
- giterr_set(GITERR_TAG, "The type for the given target is invalid");
+ giterr_set(GITERR_TAG, "the type for the given target is invalid");
goto on_error;
}
@@ -366,7 +366,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
/** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explicitly been requested **/
if (error == 0 && !allow_ref_overwrite) {
- giterr_set(GITERR_TAG, "Tag already exists");
+ giterr_set(GITERR_TAG, "tag already exists");
return GIT_EEXISTS;
}
diff --git a/src/tag.h b/src/tag.h
index d0cd393c7..8aae37840 100644
--- a/src/tag.h
+++ b/src/tag.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_tag_h__
#define INCLUDE_tag_h__
+#include "common.h"
+
#include "git2/tag.h"
#include "repository.h"
#include "odb.h"
diff --git a/src/thread-utils.c b/src/thread-utils.c
index dc9b2f09e..e5ec6a843 100644
--- a/src/thread-utils.c
+++ b/src/thread-utils.c
@@ -4,6 +4,7 @@
* 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 "common.h"
#include "thread-utils.h"
diff --git a/src/thread-utils.h b/src/thread-utils.h
index f0161989f..2df2aeb99 100644
--- a/src/thread-utils.h
+++ b/src/thread-utils.h
@@ -7,6 +7,12 @@
#ifndef INCLUDE_thread_utils_h__
#define INCLUDE_thread_utils_h__
+#if defined(__GNUC__) && defined(GIT_THREADS)
+# if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
+# error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF
+# endif
+#endif
+
/* Common operations even if threading has been disabled */
typedef struct {
#if defined(GIT_WIN32)
diff --git a/src/tls_stream.c b/src/tls_stream.c
index 83e2d064a..fefb92f26 100644
--- a/src/tls_stream.c
+++ b/src/tls_stream.c
@@ -5,8 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "tls_stream.h"
+
#include "git2/errors.h"
-#include "common.h"
#include "openssl_stream.h"
#include "stransport_stream.h"
diff --git a/src/tls_stream.h b/src/tls_stream.h
index 98a704174..8971f7efc 100644
--- a/src/tls_stream.h
+++ b/src/tls_stream.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_tls_stream_h__
#define INCLUDE_tls_stream_h__
+#include "common.h"
+
#include "git2/sys/stream.h"
/**
diff --git a/src/trace.c b/src/trace.c
index ee5039f56..080d1e891 100644
--- a/src/trace.c
+++ b/src/trace.c
@@ -5,10 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "trace.h"
+
#include "buffer.h"
-#include "common.h"
#include "global.h"
-#include "trace.h"
#include "git2/trace.h"
#ifdef GIT_TRACE
@@ -32,7 +32,7 @@ int git_trace_set(git_trace_level_t level, git_trace_callback callback)
GIT_UNUSED(callback);
giterr_set(GITERR_INVALID,
- "This version of libgit2 was not built with tracing.");
+ "this version of libgit2 was not built with tracing.");
return -1;
#endif
}
diff --git a/src/trace.h b/src/trace.h
index 486084d01..498944035 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_trace_h__
#define INCLUDE_trace_h__
+#include "common.h"
+
#include <git2/trace.h>
#include "buffer.h"
diff --git a/src/transaction.c b/src/transaction.c
index 2c8a1e8bd..675023afd 100644
--- a/src/transaction.c
+++ b/src/transaction.c
@@ -5,7 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
+#include "transaction.h"
+
#include "repository.h"
#include "strmap.h"
#include "refdb.h"
@@ -19,8 +20,6 @@
#include "git2/sys/refs.h"
#include "git2/sys/refdb_backend.h"
-GIT__USE_STRMAP
-
typedef enum {
TRANSACTION_NONE,
TRANSACTION_REFS,
@@ -120,7 +119,7 @@ int git_transaction_lock_ref(git_transaction *tx, const char *refname)
if ((error = git_refdb_lock(&node->payload, tx->db, refname)) < 0)
return error;
- git_strmap_insert(tx->locks, node->name, node, error);
+ git_strmap_insert(tx->locks, node->name, node, &error);
if (error < 0)
goto cleanup;
@@ -323,7 +322,6 @@ static int update_target(git_refdb *db, transaction_node *node)
int git_transaction_commit(git_transaction *tx)
{
transaction_node *node;
- git_strmap_iter pos;
int error = 0;
assert(tx);
@@ -335,11 +333,7 @@ int git_transaction_commit(git_transaction *tx)
return error;
}
- for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
- if (!git_strmap_has_data(tx->locks, pos))
- continue;
-
- node = git_strmap_value_at(tx->locks, pos);
+ git_strmap_foreach_value(tx->locks, node, {
if (node->reflog) {
if ((error = tx->db->backend->reflog_write(tx->db->backend, node->reflog)) < 0)
return error;
@@ -349,7 +343,7 @@ int git_transaction_commit(git_transaction *tx)
if ((error = update_target(tx->db, node)) < 0)
return error;
}
- }
+ });
return 0;
}
@@ -358,7 +352,6 @@ void git_transaction_free(git_transaction *tx)
{
transaction_node *node;
git_pool pool;
- git_strmap_iter pos;
assert(tx);
@@ -373,16 +366,12 @@ void git_transaction_free(git_transaction *tx)
}
/* start by unlocking the ones we've left hanging, if any */
- for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
- if (!git_strmap_has_data(tx->locks, pos))
- continue;
-
- node = git_strmap_value_at(tx->locks, pos);
+ git_strmap_foreach_value(tx->locks, node, {
if (node->committed)
continue;
git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL);
- }
+ });
git_refdb_free(tx->db);
git_strmap_free(tx->locks);
diff --git a/src/transport.c b/src/transport.c
index f08d2dc68..f1e18b323 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -4,7 +4,9 @@
* 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 "common.h"
+
#include "git2/types.h"
#include "git2/remote.h"
#include "git2/net.h"
@@ -121,7 +123,7 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url)
int error;
if ((error = transport_find_fn(&fn, url, &param)) == GIT_ENOTFOUND) {
- giterr_set(GITERR_NET, "Unsupported URL protocol");
+ giterr_set(GITERR_NET, "unsupported URL protocol");
return -1;
} else if (error < 0)
return error;
diff --git a/src/transports/auth.c b/src/transports/auth.c
index c1154db34..9597cc249 100644
--- a/src/transports/auth.c
+++ b/src/transports/auth.c
@@ -5,9 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "auth.h"
+
#include "git2.h"
#include "buffer.h"
-#include "auth.h"
static int basic_next_token(
git_buf *out, git_http_auth_context *ctx, git_cred *c)
diff --git a/src/transports/auth.h b/src/transports/auth.h
index 52138cf8f..06af79dec 100644
--- a/src/transports/auth.h
+++ b/src/transports/auth.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_http_auth_h__
#define INCLUDE_http_auth_h__
+#include "common.h"
+
#include "git2.h"
#include "netops.h"
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
index 8b99fc735..c9bc3043d 100644
--- a/src/transports/auth_negotiate.c
+++ b/src/transports/auth_negotiate.c
@@ -5,10 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "auth_negotiate.h"
+
#ifdef GIT_GSSAPI
#include "git2.h"
-#include "common.h"
#include "buffer.h"
#include "auth.h"
@@ -107,13 +108,13 @@ static int negotiate_next_token(
challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0;
if (challenge_len < 9) {
- giterr_set(GITERR_NET, "No negotiate challenge sent from server");
+ giterr_set(GITERR_NET, "no negotiate challenge sent from server");
error = -1;
goto done;
} else if (challenge_len > 9) {
if (git_buf_decode_base64(&input_buf,
ctx->challenge + 10, challenge_len - 10) < 0) {
- giterr_set(GITERR_NET, "Invalid negotiate challenge from server");
+ giterr_set(GITERR_NET, "invalid negotiate challenge from server");
error = -1;
goto done;
}
@@ -122,7 +123,7 @@ static int negotiate_next_token(
input_token.length = input_buf.size;
input_token_ptr = &input_token;
} else if (ctx->gss_context != GSS_C_NO_CONTEXT) {
- giterr_set(GITERR_NET, "Could not restart authentication");
+ giterr_set(GITERR_NET, "could not restart authentication");
error = -1;
goto done;
}
@@ -228,7 +229,7 @@ static int negotiate_init_context(
gss_release_oid_set(&status_minor, &mechanism_list);
if (!ctx->oid) {
- giterr_set(GITERR_NET, "Negotiate authentication is not supported");
+ giterr_set(GITERR_NET, "negotiate authentication is not supported");
return -1;
}
diff --git a/src/transports/auth_negotiate.h b/src/transports/auth_negotiate.h
index d7270b7ab..5866c19c3 100644
--- a/src/transports/auth_negotiate.h
+++ b/src/transports/auth_negotiate.h
@@ -8,6 +8,7 @@
#ifndef INCLUDE_auth_negotiate_h__
#define INCLUDE_auth_negotiate_h__
+#include "common.h"
#include "git2.h"
#include "auth.h"
diff --git a/src/transports/cred.c b/src/transports/cred.c
index 49ede48bf..8055e2d65 100644
--- a/src/transports/cred.c
+++ b/src/transports/cred.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "cred.h"
+
#include "git2.h"
#include "smart.h"
#include "git2/cred_helpers.h"
@@ -216,7 +218,7 @@ int git_cred_ssh_key_memory_new(
GIT_UNUSED(passphrase);
giterr_set(GITERR_INVALID,
- "This version of libgit2 was not built with ssh memory credentials.");
+ "this version of libgit2 was not built with ssh memory credentials.");
return -1;
#endif
}
diff --git a/src/transports/cred.h b/src/transports/cred.h
index 2de8deee8..dceab9aa3 100644
--- a/src/transports/cred.h
+++ b/src/transports/cred.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_git_cred_h__
#define INCLUDE_git_cred_h__
+#include "common.h"
+
#include "git2/transport.h"
const char *git_cred__username(git_cred *cred);
diff --git a/src/transports/cred_helpers.c b/src/transports/cred_helpers.c
index 5cc9b0869..fdc56b17e 100644
--- a/src/transports/cred_helpers.c
+++ b/src/transports/cred_helpers.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+
#include "git2/cred_helpers.h"
int git_cred_userpass(
diff --git a/src/transports/git.c b/src/transports/git.c
index 6c6acf9c5..e019878b5 100644
--- a/src/transports/git.c
+++ b/src/transports/git.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include "git2.h"
#include "buffer.h"
#include "netops.h"
@@ -45,7 +47,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
delim = strchr(url, '/');
if (delim == NULL) {
- giterr_set(GITERR_NET, "Malformed URL");
+ giterr_set(GITERR_NET, "malformed URL");
return -1;
}
@@ -240,7 +242,7 @@ static int _git_uploadpack(
return 0;
}
- giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK");
+ giterr_set(GITERR_NET, "must call UPLOADPACK_LS before UPLOADPACK");
return -1;
}
@@ -296,7 +298,7 @@ static int _git_receivepack(
return 0;
}
- giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK");
+ giterr_set(GITERR_NET, "must call RECEIVEPACK_LS before RECEIVEPACK");
return -1;
}
diff --git a/src/transports/http.c b/src/transports/http.c
index ca1f5042f..332e6280b 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -4,6 +4,9 @@
* 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 "common.h"
+
#ifndef GIT_WINHTTP
#include "git2.h"
@@ -208,7 +211,7 @@ static int gen_request(
git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
- git_buf_printf(buf, "User-Agent: git/1.0 (%s)\r\n", user_agent());
+ git_buf_printf(buf, "User-Agent: git/2.0 (%s)\r\n", user_agent());
git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host);
if (s->chunked || content_length > 0) {
@@ -403,7 +406,7 @@ static int on_headers_complete(http_parser *parser)
t->location) {
if (s->redirect_count >= 7) {
- giterr_set(GITERR_NET, "Too many redirects");
+ giterr_set(GITERR_NET, "too many redirects");
return t->parse_error = PARSE_ERROR_GENERIC;
}
@@ -428,14 +431,14 @@ static int on_headers_complete(http_parser *parser)
/* Check for a 200 HTTP status code. */
if (parser->status_code != 200) {
giterr_set(GITERR_NET,
- "Unexpected HTTP status code: %d",
+ "unexpected HTTP status code: %d",
parser->status_code);
return t->parse_error = PARSE_ERROR_GENERIC;
}
/* The response must contain a Content-Type header. */
if (!t->content_type) {
- giterr_set(GITERR_NET, "No Content-Type header in response");
+ giterr_set(GITERR_NET, "no Content-Type header in response");
return t->parse_error = PARSE_ERROR_GENERIC;
}
@@ -455,7 +458,7 @@ static int on_headers_complete(http_parser *parser)
if (strcmp(t->content_type, git_buf_cstr(&buf))) {
git_buf_free(&buf);
giterr_set(GITERR_NET,
- "Invalid Content-Type: %s",
+ "invalid Content-Type: %s",
t->content_type);
return t->parse_error = PARSE_ERROR_GENERIC;
}
@@ -488,7 +491,7 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
return 0;
if (ctx->buf_size < len) {
- giterr_set(GITERR_NET, "Can't fit data in the buffer");
+ giterr_set(GITERR_NET, "can't fit data in the buffer");
return t->parse_error = PARSE_ERROR_GENERIC;
}
@@ -575,6 +578,9 @@ static int apply_proxy_config(http_subtransport *t)
if ((error = git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &url)) < 0)
return error;
+ opts.credentials = t->owner->proxy.credentials;
+ opts.certificate_check = t->owner->proxy.certificate_check;
+ opts.payload = t->owner->proxy.payload;
opts.type = GIT_PROXY_SPECIFIED;
opts.url = url;
error = git_stream_set_proxy(t->io, &opts);
@@ -624,13 +630,12 @@ static int http_connect(http_subtransport *t)
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
git_stream_is_encrypted(t->io)) {
git_cert *cert;
- int is_valid;
+ int is_valid = (error == GIT_OK);
if ((error = git_stream_certificate(&cert, t->io)) < 0)
return error;
giterr_clear();
- is_valid = error != GIT_ECERTIFICATE;
error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
if (error < 0) {
@@ -857,7 +862,7 @@ static int http_stream_write_single(
assert(t->connected);
if (s->sent_request) {
- giterr_set(GITERR_NET, "Subtransport configured for only one write");
+ giterr_set(GITERR_NET, "subtransport configured for only one write");
return -1;
}
diff --git a/src/transports/local.c b/src/transports/local.c
index 4eae9dead..733ed2c20 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -4,7 +4,9 @@
* 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 "common.h"
+
#include "git2/types.h"
#include "git2/net.h"
#include "git2/repository.h"
@@ -16,6 +18,7 @@
#include "git2/pack.h"
#include "git2/commit.h"
#include "git2/revparse.h"
+
#include "pack-objects.h"
#include "refs.h"
#include "posix.h"
@@ -252,7 +255,7 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t
transport_local *t = (transport_local *)transport;
if (!t->have_refs) {
- giterr_set(GITERR_NET, "The transport has not yet loaded the refs");
+ giterr_set(GITERR_NET, "the transport has not yet loaded the refs");
return -1;
}
@@ -371,11 +374,12 @@ static int local_push(
but we forbid all pushes just in case */
if (!remote_repo->is_bare) {
error = GIT_EBAREREPO;
- giterr_set(GITERR_INVALID, "Local push doesn't (yet) support pushing to non-bare repos.");
+ giterr_set(GITERR_INVALID, "local push doesn't (yet) support pushing to non-bare repos.");
goto on_error;
}
- if ((error = git_buf_joinpath(&odb_path, git_repository_path(remote_repo), "objects/pack")) < 0)
+ if ((error = git_repository_item_path(&odb_path, remote_repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
+ || (error = git_buf_joinpath(&odb_path, odb_path.ptr, "pack")) < 0)
goto on_error;
error = git_packbuilder_write(push->pb, odb_path.ptr, 0, transfer_to_push_transfer, (void *) cbs);
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 7a35c39d8..6d5d95fbf 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -4,8 +4,10 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "git2.h"
+
#include "smart.h"
+
+#include "git2.h"
#include "refs.h"
#include "refspec.h"
#include "proxy.h"
@@ -231,7 +233,7 @@ static int git_smart__connect(
else if (GIT_DIRECTION_PUSH == t->direction)
service = GIT_SERVICE_RECEIVEPACK_LS;
else {
- giterr_set(GITERR_NET, "Invalid direction");
+ giterr_set(GITERR_NET, "invalid direction");
return -1;
}
@@ -252,7 +254,7 @@ static int git_smart__connect(
pkt = (git_pkt *)git_vector_get(&t->refs, 0);
if (!pkt || GIT_PKT_COMMENT != pkt->type) {
- giterr_set(GITERR_NET, "Invalid response");
+ giterr_set(GITERR_NET, "invalid response");
return -1;
} else {
/* Remove the comment pkt from the list */
@@ -299,7 +301,7 @@ static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transpo
transport_smart *t = (transport_smart *)transport;
if (!t->have_refs) {
- giterr_set(GITERR_NET, "The transport has not yet loaded the refs");
+ giterr_set(GITERR_NET, "the transport has not yet loaded the refs");
return -1;
}
@@ -319,7 +321,7 @@ int git_smart__negotiation_step(git_transport *transport, void *data, size_t len
return -1;
if (GIT_DIRECTION_FETCH != t->direction) {
- giterr_set(GITERR_NET, "This operation is only valid for fetch");
+ giterr_set(GITERR_NET, "this operation is only valid for fetch");
return -1;
}
@@ -348,7 +350,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
return -1;
if (GIT_DIRECTION_PUSH != t->direction) {
- giterr_set(GITERR_NET, "This operation is only valid for push");
+ giterr_set(GITERR_NET, "this operation is only valid for push");
return -1;
}
@@ -472,6 +474,12 @@ int git_transport_smart_credentials(git_cred **out, git_transport *transport, co
return t->cred_acquire_cb(out, t->url, user, methods, t->cred_acquire_payload);
}
+int git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport)
+{
+ transport_smart *t = (transport_smart *) transport;
+ return git_proxy_options_dup(out, &t->proxy);
+}
+
int git_transport_smart(git_transport **out, git_remote *owner, void *param)
{
transport_smart *t;
diff --git a/src/transports/smart.h b/src/transports/smart.h
index 0a0c3fc1b..f1ad70479 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -4,6 +4,9 @@
* 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 "common.h"
+
#include "git2.h"
#include "vector.h"
#include "netops.h"
@@ -26,6 +29,8 @@
#define GIT_CAP_THIN_PACK "thin-pack"
#define GIT_CAP_SYMREF "symref"
+extern bool git_smart__ofs_delta_enabled;
+
enum git_pkt_type {
GIT_PKT_CMD,
GIT_PKT_FLUSH,
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index 2297cc94f..a661dfe13 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -226,7 +226,7 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
/* Check for a bit of consistency */
if (line[GIT_OID_HEXSZ] != ' ') {
- giterr_set(GITERR_NET, "Error parsing pkt-line");
+ giterr_set(GITERR_NET, "error parsing pkt-line");
error = -1;
goto error_out;
}
@@ -270,7 +270,7 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
line += 3; /* skip "ok " */
if (!(ptr = strchr(line, '\n'))) {
- giterr_set(GITERR_NET, "Invalid packet line");
+ giterr_set(GITERR_NET, "invalid packet line");
git__free(pkt);
return -1;
}
@@ -327,7 +327,7 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
return 0;
out_err:
- giterr_set(GITERR_NET, "Invalid packet line");
+ giterr_set(GITERR_NET, "invalid packet line");
git__free(pkt->ref);
git__free(pkt);
return -1;
@@ -427,15 +427,23 @@ int git_pkt_parse_line(
if (bufflen > 0 && bufflen < (size_t)len)
return GIT_EBUFS;
+ /*
+ * The length has to be exactly 0 in case of a flush
+ * packet or greater than PKT_LEN_SIZE, as the decoded
+ * length includes its own encoded length of four bytes.
+ */
+ if (len != 0 && len < PKT_LEN_SIZE)
+ return GIT_ERROR;
+
line += PKT_LEN_SIZE;
/*
- * TODO: How do we deal with empty lines? Try again? with the next
- * line?
+ * The Git protocol does not specify empty lines as part
+ * of the protocol. Not knowing what to do with an empty
+ * line, we should return an error upon hitting one.
*/
if (len == PKT_LEN_SIZE) {
- *head = NULL;
- *out = line;
- return 0;
+ giterr_set_str(GITERR_NET, "Invalid empty packet");
+ return GIT_ERROR;
}
if (len == 0) { /* Flush pkt */
@@ -535,7 +543,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca
if (len > 0xffff) {
giterr_set(GITERR_NET,
- "Tried to produce packet with invalid length %" PRIuZ, len);
+ "tried to produce packet with invalid length %" PRIuZ, len);
return -1;
}
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 3448fa7fb..d51238f12 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -4,6 +4,9 @@
* 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 "common.h"
+
#include "git2.h"
#include "git2/odb_backend.h"
@@ -19,6 +22,8 @@
/* The minimal interval between progress updates (in seconds). */
#define MIN_PROGRESS_UPDATE_INTERVAL 0.5
+bool git_smart__ofs_delta_enabled = true;
+
int git_smart__store_refs(transport_smart *t, int flushes)
{
gitno_buffer *buf = &t->buffer;
@@ -50,7 +55,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
if ((recvd = gitno_recv(buf)) < 0)
return recvd;
- if (recvd == 0 && !flush) {
+ if (recvd == 0) {
giterr_set(GITERR_NET, "early EOF");
return GIT_EEOF;
}
@@ -60,7 +65,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
gitno_consume(buf, line_end);
if (pkt->type == GIT_PKT_ERR) {
- giterr_set(GITERR_NET, "Remote error: %s", ((git_pkt_err *)pkt)->error);
+ giterr_set(GITERR_NET, "remote error: %s", ((git_pkt_err *)pkt)->error);
git__free(pkt);
return -1;
}
@@ -138,7 +143,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
if (*ptr == ' ')
ptr++;
- if (!git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) {
+ if (git_smart__ofs_delta_enabled && !git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) {
caps->common = caps->ofs_delta = 1;
ptr += strlen(GIT_CAP_OFS_DELTA);
continue;
@@ -222,8 +227,12 @@ static int recv_pkt(git_pkt **out, gitno_buffer *buf)
if (error < 0 && error != GIT_EBUFS)
return error;
- if ((ret = gitno_recv(buf)) < 0)
+ if ((ret = gitno_recv(buf)) < 0) {
return ret;
+ } else if (ret == 0) {
+ giterr_set(GITERR_NET, "early EOF");
+ return GIT_EEOF;
+ }
} while (error);
gitno_consume(buf, line_end);
@@ -319,7 +328,8 @@ static int wait_while_ack(gitno_buffer *buf)
if (pkt->type == GIT_PKT_ACK &&
(pkt->status != GIT_ACK_CONTINUE &&
- pkt->status != GIT_ACK_COMMON)) {
+ pkt->status != GIT_ACK_COMMON &&
+ pkt->status != GIT_ACK_READY)) {
git__free(pkt);
return 0;
}
@@ -408,12 +418,12 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if (i % 20 == 0 && t->rpc) {
git_pkt_ack *pkt;
- unsigned int i;
+ unsigned int j;
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
goto on_error;
- git_vector_foreach(&t->common, i, pkt) {
+ git_vector_foreach(&t->common, j, pkt) {
if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
goto on_error;
}
@@ -428,12 +438,12 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
/* Tell the other end that we're done negotiating */
if (t->rpc && t->common.length > 0) {
git_pkt_ack *pkt;
- unsigned int i;
+ unsigned int j;
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
goto on_error;
- git_vector_foreach(&t->common, i, pkt) {
+ git_vector_foreach(&t->common, j, pkt) {
if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
goto on_error;
}
@@ -724,7 +734,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_buf *data_pkt_buf)
{
git_pkt *pkt;
- const char *line, *line_end;
+ const char *line, *line_end = NULL;
size_t line_len;
int error;
int reading_from_buf = data_pkt_buf->size > 0;
@@ -759,14 +769,6 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
line_len -= (line_end - line);
line = line_end;
- /* When a valid packet with no content has been
- * read, git_pkt_parse_line does not report an
- * error, but the pkt pointer has not been set.
- * Handle this by skipping over empty packets.
- */
- if (pkt == NULL)
- continue;
-
error = add_push_report_pkt(push, pkt);
git_pkt_free(pkt);
@@ -821,9 +823,6 @@ static int parse_report(transport_smart *transport, git_push *push)
error = 0;
- if (pkt == NULL)
- continue;
-
switch (pkt->type) {
case GIT_PKT_DATA:
/* This is a sideband packet which contains other packets */
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index cfd573665..47d328c41 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -5,17 +5,19 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "ssh.h"
+
#ifdef GIT_SSH
#include <libssh2.h>
#endif
+#include "global.h"
#include "git2.h"
#include "buffer.h"
#include "netops.h"
#include "smart.h"
#include "cred.h"
#include "socket_stream.h"
-#include "ssh.h"
#ifdef GIT_SSH
@@ -83,7 +85,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
done:
if (!repo) {
- giterr_set(GITERR_NET, "Malformed git protocol URL");
+ giterr_set(GITERR_NET, "malformed git protocol URL");
return -1;
}
@@ -274,7 +276,7 @@ static int git_ssh_extract_url_parts(
}
if (colon == NULL || (colon < start)) {
- giterr_set(GITERR_NET, "Malformed URL");
+ giterr_set(GITERR_NET, "malformed URL");
return -1;
}
@@ -445,7 +447,7 @@ static int request_creds(git_cred **out, ssh_subtransport *t, const char *user,
else if (error < 0)
return error;
else if (!cred) {
- giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials");
+ giterr_set(GITERR_SSH, "callback failed to initialize SSH credentials");
return -1;
}
}
@@ -478,7 +480,7 @@ static int _git_ssh_session_create(
s = libssh2_session_init();
if (!s) {
- giterr_set(GITERR_NET, "Failed to initialize SSH session");
+ giterr_set(GITERR_NET, "failed to initialize SSH session");
return -1;
}
@@ -487,7 +489,7 @@ static int _git_ssh_session_create(
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
if (rc != LIBSSH2_ERROR_NONE) {
- ssh_error(s, "Failed to start SSH session");
+ ssh_error(s, "failed to start SSH session");
libssh2_session_free(s);
return -1;
}
@@ -685,7 +687,7 @@ static int ssh_uploadpack(
return 0;
}
- giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK");
+ giterr_set(GITERR_NET, "must call UPLOADPACK_LS before UPLOADPACK");
return -1;
}
@@ -712,7 +714,7 @@ static int ssh_receivepack(
return 0;
}
- giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK");
+ giterr_set(GITERR_NET, "must call RECEIVEPACK_LS before RECEIVEPACK");
return -1;
}
@@ -844,7 +846,7 @@ int git_smart_subtransport_ssh(
assert(out);
*out = NULL;
- giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support");
+ giterr_set(GITERR_INVALID, "cannot create SSH transport. Library was built without SSH support");
return -1;
#endif
}
@@ -888,16 +890,27 @@ int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *p
assert(out);
*out = NULL;
- giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support");
+ giterr_set(GITERR_INVALID, "cannot create SSH transport. Library was built without SSH support");
return -1;
#endif
}
+#ifdef GIT_SSH
+static void shutdown_ssh(void)
+{
+ libssh2_exit();
+}
+#endif
+
int git_transport_ssh_global_init(void)
{
#ifdef GIT_SSH
+ if (libssh2_init(0) < 0) {
+ giterr_set(GITERR_SSH, "unable to initialize libssh2");
+ return -1;
+ }
- libssh2_init(0);
+ git__on_shutdown(shutdown_ssh);
return 0;
#else
diff --git a/src/transports/ssh.h b/src/transports/ssh.h
index 2db2cc5df..e36e7246e 100644
--- a/src/transports/ssh.h
+++ b/src/transports/ssh.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_ssh_h__
#define INCLUDE_ssh_h__
+#include "common.h"
+
int git_transport_ssh_global_init(void);
#endif
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 78e42cf3b..6689c8ce3 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#ifdef GIT_WINHTTP
#include "git2.h"
@@ -68,7 +70,9 @@ static const IID IID_IInternetSecurityManager_mingw =
typedef enum {
GIT_WINHTTP_AUTH_BASIC = 1,
- GIT_WINHTTP_AUTH_NEGOTIATE = 2,
+ GIT_WINHTTP_AUTH_NTLM = 2,
+ GIT_WINHTTP_AUTH_NEGOTIATE = 4,
+ GIT_WINHTTP_AUTH_DIGEST = 8,
} winhttp_authmechanism_t;
typedef struct {
@@ -95,79 +99,71 @@ typedef struct {
git_cred *cred;
git_cred *url_cred;
git_cred *proxy_cred;
- int auth_mechanism;
+ int auth_mechanisms;
HINTERNET session;
HINTERNET connection;
} winhttp_subtransport;
-static int apply_basic_credential_proxy(HINTERNET request, git_cred *cred)
+static int _apply_userpass_credential(HINTERNET request, DWORD target, DWORD scheme, git_cred *cred)
{
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
wchar_t *user, *pass;
- int error;
+ int user_len = 0, pass_len = 0, error = 0;
- if ((error = git__utf8_to_16_alloc(&user, c->username)) < 0)
- return error;
+ if ((error = user_len = git__utf8_to_16_alloc(&user, c->username)) < 0)
+ goto done;
- if ((error = git__utf8_to_16_alloc(&pass, c->password)) < 0)
- return error;
+ if ((error = pass_len = git__utf8_to_16_alloc(&pass, c->password)) < 0)
+ goto done;
- if (!WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC,
- user, pass, NULL)) {
- giterr_set(GITERR_OS, "failed to set proxy auth");
+ if (!WinHttpSetCredentials(request, target, scheme, user, pass, NULL)) {
+ giterr_set(GITERR_OS, "failed to set credentials");
error = -1;
}
+done:
+ if (user_len > 0)
+ git__memzero(user, user_len * sizeof(wchar_t));
+
+ if (pass_len > 0)
+ git__memzero(pass, pass_len * sizeof(wchar_t));
+
git__free(user);
git__free(pass);
return error;
}
-static int apply_basic_credential(HINTERNET request, git_cred *cred)
+static int apply_userpass_credential_proxy(HINTERNET request, git_cred *cred, int mechanisms)
{
- git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
- git_buf buf = GIT_BUF_INIT, raw = GIT_BUF_INIT;
- wchar_t *wide = NULL;
- int error = -1, wide_len;
-
- git_buf_printf(&raw, "%s:%s", c->username, c->password);
-
- if (git_buf_oom(&raw) ||
- git_buf_puts(&buf, "Authorization: Basic ") < 0 ||
- git_buf_encode_base64(&buf, git_buf_cstr(&raw), raw.size) < 0)
- goto on_error;
-
- if ((wide_len = git__utf8_to_16_alloc(&wide, git_buf_cstr(&buf))) < 0) {
- giterr_set(GITERR_OS, "Failed to convert string to wide form");
- goto on_error;
- }
-
- if (!WinHttpAddRequestHeaders(request, wide, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
- goto on_error;
+ if (GIT_WINHTTP_AUTH_DIGEST & mechanisms) {
+ return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY,
+ WINHTTP_AUTH_SCHEME_DIGEST, cred);
}
- error = 0;
-
-on_error:
- /* We were dealing with plaintext passwords, so clean up after ourselves a bit. */
- if (wide)
- memset(wide, 0x0, wide_len * sizeof(wchar_t));
+ return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY,
+ WINHTTP_AUTH_SCHEME_BASIC, cred);
+}
- if (buf.size)
- memset(buf.ptr, 0x0, buf.size);
+static int apply_userpass_credential(HINTERNET request, int mechanisms, git_cred *cred)
+{
+ DWORD native_scheme;
- if (raw.size)
- memset(raw.ptr, 0x0, raw.size);
+ if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) ||
+ (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE)) {
+ native_scheme = WINHTTP_AUTH_SCHEME_NTLM;
+ } else if (mechanisms & GIT_WINHTTP_AUTH_BASIC) {
+ native_scheme = WINHTTP_AUTH_SCHEME_BASIC;
+ } else {
+ giterr_set(GITERR_NET, "invalid authentication scheme");
+ return -1;
+ }
- git__free(wide);
- git_buf_free(&buf);
- git_buf_free(&raw);
- return error;
+ return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_SERVER,
+ native_scheme, cred);
}
-static int apply_default_credentials(HINTERNET request)
+static int apply_default_credentials(HINTERNET request, int mechanisms)
{
/* Either the caller explicitly requested that default credentials be passed,
* or our fallback credential callback was invoked and checked that the target
@@ -177,6 +173,12 @@ static int apply_default_credentials(HINTERNET request)
* to Internet Explorer security zones, but in fact does not. */
DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
+ if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) == 0 &&
+ (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) == 0) {
+ giterr_set(GITERR_NET, "invalid authentication scheme");
+ return -1;
+ }
+
if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD)))
return -1;
@@ -202,7 +204,7 @@ static int fallback_cred_acquire_cb(
/* Convert URL to wide characters */
if (git__utf8_to_16_alloc(&wide_url, url) < 0) {
- giterr_set(GITERR_OS, "Failed to convert string to wide form");
+ giterr_set(GITERR_OS, "failed to convert string to wide form");
return -1;
}
@@ -248,8 +250,12 @@ static int certificate_check(winhttp_stream *s, int valid)
git_cert_x509 cert;
/* If there is no override, we should fail if WinHTTP doesn't think it's fine */
- if (t->owner->certificate_check_cb == NULL && !valid)
+ if (t->owner->certificate_check_cb == NULL && !valid) {
+ if (!giterr_last())
+ giterr_set(GITERR_NET, "unknown certificate check failure");
+
return GIT_ECERTIFICATE;
+ }
if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl)
return 0;
@@ -351,7 +357,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
/* Convert URL to wide characters */
if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
- giterr_set(GITERR_OS, "Failed to convert string to wide form");
+ giterr_set(GITERR_OS, "failed to convert string to wide form");
goto on_error;
}
@@ -366,12 +372,12 @@ static int winhttp_stream_connect(winhttp_stream *s)
t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0);
if (!s->request) {
- giterr_set(GITERR_OS, "Failed to open request");
+ giterr_set(GITERR_OS, "failed to open request");
goto on_error;
}
if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
- giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP");
+ giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
goto on_error;
}
@@ -425,7 +431,6 @@ static int winhttp_stream_connect(winhttp_stream *s)
git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port);
if (git_buf_oom(&processed_url)) {
- giterr_set_oom();
error = -1;
goto on_error;
}
@@ -444,7 +449,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
WINHTTP_OPTION_PROXY,
&proxy_info,
sizeof(WINHTTP_PROXY_INFO))) {
- giterr_set(GITERR_OS, "Failed to set proxy");
+ giterr_set(GITERR_OS, "failed to set proxy");
git__free(proxy_wide);
goto on_error;
}
@@ -453,7 +458,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
if (t->proxy_cred) {
if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) {
- if ((error = apply_basic_credential_proxy(s->request, t->proxy_cred)) < 0)
+ if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred, t->auth_mechanisms)) < 0)
goto on_error;
}
}
@@ -467,7 +472,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
WINHTTP_OPTION_DISABLE_FEATURE,
&disable_redirects,
sizeof(disable_redirects))) {
- giterr_set(GITERR_OS, "Failed to disable redirects");
+ giterr_set(GITERR_OS, "failed to disable redirects");
goto on_error;
}
@@ -481,7 +486,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
/* Send Pragma: no-cache header */
if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
+ giterr_set(GITERR_OS, "failed to add a header to the request");
goto on_error;
}
@@ -494,13 +499,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
goto on_error;
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
- giterr_set(GITERR_OS, "Failed to convert content-type to wide characters");
+ giterr_set(GITERR_OS, "failed to convert content-type to wide characters");
goto on_error;
}
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
+ giterr_set(GITERR_OS, "failed to add a header to the request");
goto on_error;
}
@@ -511,13 +516,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
goto on_error;
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
- giterr_set(GITERR_OS, "Failed to convert accept header to wide characters");
+ giterr_set(GITERR_OS, "failed to convert accept header to wide characters");
goto on_error;
}
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
+ giterr_set(GITERR_OS, "failed to add a header to the request");
goto on_error;
}
}
@@ -527,13 +532,13 @@ static int winhttp_stream_connect(winhttp_stream *s)
git_buf_clear(&buf);
git_buf_puts(&buf, t->owner->custom_headers.strings[i]);
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
- giterr_set(GITERR_OS, "Failed to convert custom header to wide characters");
+ giterr_set(GITERR_OS, "failed to convert custom header to wide characters");
goto on_error;
}
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
+ giterr_set(GITERR_OS, "failed to add a header to the request");
goto on_error;
}
}
@@ -550,13 +555,11 @@ static int winhttp_stream_connect(winhttp_stream *s)
/* If we have a credential on the subtransport, apply it to the request */
if (t->cred &&
t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
- t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC &&
- apply_basic_credential(s->request, t->cred) < 0)
+ apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0)
goto on_error;
else if (t->cred &&
t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
- t->auth_mechanism == GIT_WINHTTP_AUTH_NEGOTIATE &&
- apply_default_credentials(s->request) < 0)
+ apply_default_credentials(s->request, t->auth_mechanisms) < 0)
goto on_error;
/* If no other credentials have been applied and the URL has username and
@@ -565,7 +568,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
if (!t->url_cred &&
git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0)
goto on_error;
- if (apply_basic_credential(s->request, t->url_cred) < 0)
+ if (apply_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, t->url_cred) < 0)
goto on_error;
}
@@ -585,30 +588,40 @@ on_error:
static int parse_unauthorized_response(
HINTERNET request,
int *allowed_types,
- int *auth_mechanism)
+ int *allowed_mechanisms)
{
DWORD supported, first, target;
*allowed_types = 0;
- *auth_mechanism = 0;
+ *allowed_mechanisms = 0;
- /* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes().
- * We can assume this was already done, since we know we are unauthorized.
+ /* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes().
+ * We can assume this was already done, since we know we are unauthorized.
*/
if (!WinHttpQueryAuthSchemes(request, &supported, &first, &target)) {
- giterr_set(GITERR_OS, "Failed to parse supported auth schemes");
+ giterr_set(GITERR_OS, "failed to parse supported auth schemes");
return -1;
}
- if (WINHTTP_AUTH_SCHEME_BASIC & supported) {
+ if (WINHTTP_AUTH_SCHEME_NTLM & supported) {
*allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
- *auth_mechanism = GIT_WINHTTP_AUTH_BASIC;
+ *allowed_types |= GIT_CREDTYPE_DEFAULT;
+ *allowed_mechanisms = GIT_WINHTTP_AUTH_NEGOTIATE;
}
- if ((WINHTTP_AUTH_SCHEME_NTLM & supported) ||
- (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported)) {
+ if (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported) {
*allowed_types |= GIT_CREDTYPE_DEFAULT;
- *auth_mechanism = GIT_WINHTTP_AUTH_NEGOTIATE;
+ *allowed_mechanisms = GIT_WINHTTP_AUTH_NEGOTIATE;
+ }
+
+ if (WINHTTP_AUTH_SCHEME_BASIC & supported) {
+ *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
+ *allowed_mechanisms |= GIT_WINHTTP_AUTH_BASIC;
+ }
+
+ if (WINHTTP_AUTH_SCHEME_DIGEST & supported) {
+ *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
+ *allowed_mechanisms |= GIT_WINHTTP_AUTH_DIGEST;
}
return 0;
@@ -629,7 +642,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
git_buf_cstr(&buf), (DWORD)git_buf_len(&buf),
&bytes_written)) {
git_buf_free(&buf);
- giterr_set(GITERR_OS, "Failed to write chunk header");
+ giterr_set(GITERR_OS, "failed to write chunk header");
return -1;
}
@@ -639,7 +652,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
if (!WinHttpWriteData(request,
buffer, (DWORD)len,
&bytes_written)) {
- giterr_set(GITERR_OS, "Failed to write chunk");
+ giterr_set(GITERR_OS, "failed to write chunk");
return -1;
}
@@ -647,7 +660,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
if (!WinHttpWriteData(request,
"\r\n", 2,
&bytes_written)) {
- giterr_set(GITERR_OS, "Failed to write chunk footer");
+ giterr_set(GITERR_OS, "failed to write chunk footer");
return -1;
}
@@ -660,7 +673,7 @@ static int winhttp_close_connection(winhttp_subtransport *t)
if (t->connection) {
if (!WinHttpCloseHandle(t->connection)) {
- giterr_set(GITERR_OS, "Unable to close connection");
+ giterr_set(GITERR_OS, "unable to close connection");
ret = -1;
}
@@ -669,7 +682,7 @@ static int winhttp_close_connection(winhttp_subtransport *t)
if (t->session) {
if (!WinHttpCloseHandle(t->session)) {
- giterr_set(GITERR_OS, "Unable to close session");
+ giterr_set(GITERR_OS, "unable to close session");
ret = -1;
}
@@ -694,6 +707,38 @@ static int user_agent(git_buf *ua)
return git_buf_putc(ua, ')');
}
+static void CALLBACK winhttp_status(
+ HINTERNET connection,
+ DWORD_PTR ctx,
+ DWORD code,
+ LPVOID info,
+ DWORD info_len)
+{
+ DWORD status;
+
+ if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
+ return;
+
+ status = *((DWORD *)info);
+
+ if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
+ giterr_set(GITERR_NET, "SSL certificate issued for different common name");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
+ giterr_set(GITERR_NET, "SSL certificate has expired");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
+ giterr_set(GITERR_NET, "SSL certificate signed by unknown CA");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
+ giterr_set(GITERR_NET, "SSL certificate is invalid");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
+ giterr_set(GITERR_NET, "certificate revocation check failed");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
+ giterr_set(GITERR_NET, "SSL certificate was revoked");
+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
+ giterr_set(GITERR_NET, "security libraries could not be loaded");
+ else
+ giterr_set(GITERR_NET, "unknown security error %d", status);
+}
+
static int winhttp_connect(
winhttp_subtransport *t)
{
@@ -714,7 +759,7 @@ static int winhttp_connect(
/* Prepare host */
if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) {
- giterr_set(GITERR_OS, "Unable to convert host to wide characters");
+ giterr_set(GITERR_OS, "unable to convert host to wide characters");
return -1;
}
@@ -724,7 +769,7 @@ static int winhttp_connect(
}
if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
- giterr_set(GITERR_OS, "Unable to convert host to wide characters");
+ giterr_set(GITERR_OS, "unable to convert host to wide characters");
git__free(wide_host);
git_buf_free(&ua);
return -1;
@@ -741,16 +786,16 @@ static int winhttp_connect(
0);
if (!t->session) {
- giterr_set(GITERR_OS, "Failed to init WinHTTP");
+ giterr_set(GITERR_OS, "failed to init WinHTTP");
goto on_error;
}
if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
- giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP");
+ giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
goto on_error;
}
-
+
/* Establish connection */
t->connection = WinHttpConnect(
t->session,
@@ -759,7 +804,12 @@ static int winhttp_connect(
0);
if (!t->connection) {
- giterr_set(GITERR_OS, "Failed to connect to host");
+ giterr_set(GITERR_OS, "failed to connect to host");
+ goto on_error;
+ }
+
+ if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
+ giterr_set(GITERR_OS, "failed to set status callback");
goto on_error;
}
@@ -801,16 +851,15 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length)
int request_failed = 0, cert_valid = 1, error = 0;
DWORD ignore_flags;
- if ((error = do_send_request(s, len, ignore_length)) < 0)
- request_failed = 1;
-
- if (request_failed) {
+ giterr_clear();
+ if ((error = do_send_request(s, len, ignore_length)) < 0) {
if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
giterr_set(GITERR_OS, "failed to send request");
return -1;
- } else {
- cert_valid = 0;
}
+
+ request_failed = 1;
+ cert_valid = 0;
}
giterr_clear();
@@ -826,14 +875,14 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length)
return 0;
ignore_flags = no_check_cert_flags;
-
+
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
giterr_set(GITERR_OS, "failed to set security options");
return -1;
}
if ((error = do_send_request(s, len, ignore_length)) < 0)
- giterr_set(GITERR_OS, "failed to send request");
+ giterr_set(GITERR_OS, "failed to send request with unchecked certificate");
return error;
}
@@ -853,7 +902,7 @@ static int winhttp_stream_read(
replay:
/* Enforce a reasonable cap on the number of replays */
if (++replay_count >= 7) {
- giterr_set(GITERR_NET, "Too many redirects or authentication replays");
+ giterr_set(GITERR_NET, "too many redirects or authentication replays");
return -1;
}
@@ -888,7 +937,7 @@ replay:
if (!WinHttpWriteData(s->request,
"0\r\n\r\n", 5,
&bytes_written)) {
- giterr_set(GITERR_OS, "Failed to write final chunk");
+ giterr_set(GITERR_OS, "failed to write final chunk");
return -1;
}
}
@@ -899,7 +948,7 @@ replay:
if (INVALID_SET_FILE_POINTER == SetFilePointer(s->post_body,
0, 0, FILE_BEGIN) &&
NO_ERROR != GetLastError()) {
- giterr_set(GITERR_OS, "Failed to reset file pointer");
+ giterr_set(GITERR_OS, "failed to reset file pointer");
return -1;
}
@@ -913,14 +962,14 @@ replay:
&bytes_read, NULL) ||
!bytes_read) {
git__free(buffer);
- giterr_set(GITERR_OS, "Failed to read from temp file");
+ giterr_set(GITERR_OS, "failed to read from temp file");
return -1;
}
if (!WinHttpWriteData(s->request, buffer,
bytes_read, &bytes_written)) {
git__free(buffer);
- giterr_set(GITERR_OS, "Failed to write data");
+ giterr_set(GITERR_OS, "failed to write data");
return -1;
}
@@ -936,7 +985,7 @@ replay:
}
if (!WinHttpReceiveResponse(s->request, 0)) {
- giterr_set(GITERR_OS, "Failed to receive response");
+ giterr_set(GITERR_OS, "failed to receive response");
return -1;
}
@@ -948,7 +997,7 @@ replay:
WINHTTP_HEADER_NAME_BY_INDEX,
&status_code, &status_code_length,
WINHTTP_NO_HEADER_INDEX)) {
- giterr_set(GITERR_OS, "Failed to retrieve status code");
+ giterr_set(GITERR_OS, "failed to retrieve status code");
return -1;
}
@@ -978,7 +1027,7 @@ replay:
&location_length,
WINHTTP_NO_HEADER_INDEX) ||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- giterr_set(GITERR_OS, "Failed to read Location header");
+ giterr_set(GITERR_OS, "failed to read Location header");
return -1;
}
@@ -991,14 +1040,14 @@ replay:
location,
&location_length,
WINHTTP_NO_HEADER_INDEX)) {
- giterr_set(GITERR_OS, "Failed to read Location header");
+ giterr_set(GITERR_OS, "failed to read Location header");
git__free(location);
return -1;
}
/* Convert the Location header to UTF-8 */
if (git__utf16_to_8_alloc(&location8, location) < 0) {
- giterr_set(GITERR_OS, "Failed to convert Location header to UTF-8");
+ giterr_set(GITERR_OS, "failed to convert Location header to UTF-8");
git__free(location);
return -1;
}
@@ -1029,13 +1078,13 @@ replay:
if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) {
int allowed_types;
- if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0)
+ if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0)
return -1;
/* TODO: extract the username from the url, no payload? */
if (t->owner->proxy.credentials) {
int cred_error = 1;
- cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, NULL);
+ cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, t->owner->proxy.payload);
if (cred_error < 0)
return cred_error;
@@ -1049,7 +1098,7 @@ replay:
if (HTTP_STATUS_DENIED == status_code && get_verb == s->verb) {
int allowed_types;
- if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0)
+ if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0)
return -1;
if (allowed_types) {
@@ -1090,7 +1139,7 @@ replay:
}
if (HTTP_STATUS_OK != status_code) {
- giterr_set(GITERR_NET, "Request failed with status code: %d", status_code);
+ giterr_set(GITERR_NET, "request failed with status code: %d", status_code);
return -1;
}
@@ -1101,7 +1150,7 @@ replay:
p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service);
if (git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8) < 0) {
- giterr_set(GITERR_OS, "Failed to convert expected content-type to wide characters");
+ giterr_set(GITERR_OS, "failed to convert expected content-type to wide characters");
return -1;
}
@@ -1112,12 +1161,12 @@ replay:
WINHTTP_HEADER_NAME_BY_INDEX,
&content_type, &content_type_length,
WINHTTP_NO_HEADER_INDEX)) {
- giterr_set(GITERR_OS, "Failed to retrieve response content-type");
+ giterr_set(GITERR_OS, "failed to retrieve response content-type");
return -1;
}
if (wcscmp(expected_content_type, content_type)) {
- giterr_set(GITERR_NET, "Received unexpected content-type");
+ giterr_set(GITERR_NET, "received unexpected content-type");
return -1;
}
@@ -1129,7 +1178,7 @@ replay:
(DWORD)buf_size,
&dw_bytes_read))
{
- giterr_set(GITERR_OS, "Failed to read data");
+ giterr_set(GITERR_OS, "failed to read data");
return -1;
}
@@ -1152,7 +1201,7 @@ static int winhttp_stream_write_single(
/* This implementation of write permits only a single call. */
if (s->sent_request) {
- giterr_set(GITERR_NET, "Subtransport configured for only one write");
+ giterr_set(GITERR_NET, "subtransport configured for only one write");
return -1;
}
@@ -1165,7 +1214,7 @@ static int winhttp_stream_write_single(
(LPCVOID)buffer,
(DWORD)len,
&bytes_written)) {
- giterr_set(GITERR_OS, "Failed to write data");
+ giterr_set(GITERR_OS, "failed to write data");
return -1;
}
@@ -1183,12 +1232,12 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
if (RPC_S_OK != status &&
RPC_S_UUID_LOCAL_ONLY != status &&
RPC_S_UUID_NO_ADDRESS != status) {
- giterr_set(GITERR_NET, "Unable to generate name for temp file");
+ giterr_set(GITERR_NET, "unable to generate name for temp file");
return -1;
}
if (buffer_len_cch < UUID_LENGTH_CCH + 1) {
- giterr_set(GITERR_NET, "Buffer too small for name of temp file");
+ giterr_set(GITERR_NET, "buffer too small for name of temp file");
return -1;
}
@@ -1203,7 +1252,7 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
if (result < UUID_LENGTH_CCH) {
- giterr_set(GITERR_OS, "Unable to generate name for temp file");
+ giterr_set(GITERR_OS, "unable to generate name for temp file");
return -1;
}
@@ -1215,7 +1264,7 @@ static int get_temp_file(LPWSTR buffer, DWORD buffer_len_cch)
size_t len;
if (!GetTempPathW(buffer_len_cch, buffer)) {
- giterr_set(GITERR_OS, "Failed to get temp path");
+ giterr_set(GITERR_OS, "failed to get temp path");
return -1;
}
@@ -1258,13 +1307,13 @@ static int winhttp_stream_write_buffered(
if (INVALID_HANDLE_VALUE == s->post_body) {
s->post_body = NULL;
- giterr_set(GITERR_OS, "Failed to create temporary file");
+ giterr_set(GITERR_OS, "failed to create temporary file");
return -1;
}
}
if (!WriteFile(s->post_body, buffer, (DWORD)len, &bytes_written, NULL)) {
- giterr_set(GITERR_OS, "Failed to write to temporary file");
+ giterr_set(GITERR_OS, "failed to write to temporary file");
return -1;
}
@@ -1291,7 +1340,7 @@ static int winhttp_stream_write_chunked(
if (!WinHttpAddRequestHeaders(s->request,
transfer_encoding, (ULONG) -1L,
WINHTTP_ADDREQ_FLAG_ADD)) {
- giterr_set(GITERR_OS, "Failed to add a header to the request");
+ giterr_set(GITERR_OS, "failed to add a header to the request");
return -1;
}
diff --git a/src/tree-cache.c b/src/tree-cache.c
index b37be0f0d..b331d22a2 100644
--- a/src/tree-cache.c
+++ b/src/tree-cache.c
@@ -6,6 +6,7 @@
*/
#include "tree-cache.h"
+
#include "pool.h"
#include "tree.h"
@@ -137,7 +138,7 @@ static int read_tree_internal(git_tree_cache **out,
return 0;
corrupted:
- giterr_set(GITERR_INDEX, "Corrupted TREE extension in index");
+ giterr_set(GITERR_INDEX, "corrupted TREE extension in index");
return -1;
}
@@ -149,7 +150,7 @@ int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer
return -1;
if (buffer < buffer_end) {
- giterr_set(GITERR_INDEX, "Corrupted TREE extension in index (unexpected trailing data)");
+ giterr_set(GITERR_INDEX, "corrupted TREE extension in index (unexpected trailing data)");
return -1;
}
diff --git a/src/tree-cache.h b/src/tree-cache.h
index c44ca7cf5..e02300e6e 100644
--- a/src/tree-cache.h
+++ b/src/tree-cache.h
@@ -9,6 +9,7 @@
#define INCLUDE_tree_cache_h__
#include "common.h"
+
#include "pool.h"
#include "buffer.h"
#include "git2/oid.h"
diff --git a/src/tree.c b/src/tree.c
index 5db2446bf..fcee7f3b3 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "commit.h"
#include "tree.h"
+
+#include "commit.h"
#include "git2/repository.h"
#include "git2/object.h"
#include "fileops.h"
@@ -20,8 +20,6 @@
#define TREE_ENTRY_CHECK_NAMELEN(n) \
if (n > UINT16_MAX) { giterr_set(GITERR_INVALID, "tree entry path too long"); }
-GIT__USE_STRMAP
-
static bool valid_filemode(const int filemode)
{
return (filemode == GIT_FILEMODE_TREE
@@ -447,7 +445,12 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
if ((nul = memchr(buffer, 0, buffer_end - buffer)) == NULL)
return tree_error("Failed to parse tree. Object is corrupted", NULL);
- filename_len = nul - buffer;
+ if ((filename_len = nul - buffer) == 0)
+ return tree_error("Failed to parse tree. Can't parse filename", NULL);
+
+ if ((buffer_end - (nul + 1)) < GIT_OID_RAWSZ)
+ return tree_error("Failed to parse tree. Can't parse OID", NULL);
+
/* Allocate the entry */
{
entry = git_array_alloc(tree->entries);
@@ -500,7 +503,7 @@ static int append_entry(
entry->attr = (uint16_t)filemode;
- git_strmap_insert(bld->map, entry->filename, entry, error);
+ git_strmap_insert(bld->map, entry->filename, entry, &error);
if (error < 0) {
git_tree_entry_free(entry);
giterr_set(GITERR_TREE, "failed to append entry %s to the tree builder", filename);
@@ -515,7 +518,8 @@ static int write_tree(
git_repository *repo,
git_index *index,
const char *dirname,
- size_t start)
+ size_t start,
+ git_buf *shared_buf)
{
git_treebuilder *bld = NULL;
size_t i, entries = git_index_entrycount(index);
@@ -568,7 +572,7 @@ static int write_tree(
GITERR_CHECK_ALLOC(subdir);
/* Write out the subtree */
- written = write_tree(&sub_oid, repo, index, subdir, i);
+ written = write_tree(&sub_oid, repo, index, subdir, i, shared_buf);
if (written < 0) {
git__free(subdir);
goto on_error;
@@ -600,7 +604,7 @@ static int write_tree(
}
}
- if (git_treebuilder_write(oid, bld) < 0)
+ if (git_treebuilder_write_with_buffer(oid, bld, shared_buf) < 0)
goto on_error;
git_treebuilder_free(bld);
@@ -616,13 +620,14 @@ int git_tree__write_index(
{
int ret;
git_tree *tree;
+ git_buf shared_buf = GIT_BUF_INIT;
bool old_ignore_case = false;
assert(oid && index && repo);
if (git_index_has_conflicts(index)) {
giterr_set(GITERR_INDEX,
- "Cannot create a tree from a not fully merged index.");
+ "cannot create a tree from a not fully merged index.");
return GIT_EUNMERGED;
}
@@ -641,7 +646,8 @@ int git_tree__write_index(
git_index__set_ignore_case(index, false);
}
- ret = write_tree(oid, repo, index, "", 0);
+ ret = write_tree(oid, repo, index, "", 0, &shared_buf);
+ git_buf_free(&shared_buf);
if (old_ignore_case)
git_index__set_ignore_case(index, true);
@@ -746,7 +752,7 @@ int git_treebuilder_insert(
entry = alloc_entry(filename, strlen(filename), id);
GITERR_CHECK_ALLOC(entry);
- git_strmap_insert(bld->map, entry->filename, entry, error);
+ git_strmap_insert(bld->map, entry->filename, entry, &error);
if (error < 0) {
git_tree_entry_free(entry);
@@ -797,46 +803,60 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
int git_treebuilder_write(git_oid *oid, git_treebuilder *bld)
{
+ int error;
+ git_buf buffer = GIT_BUF_INIT;
+
+ error = git_treebuilder_write_with_buffer(oid, bld, &buffer);
+
+ git_buf_free(&buffer);
+ return error;
+}
+
+int git_treebuilder_write_with_buffer(git_oid *oid, git_treebuilder *bld, git_buf *tree)
+{
int error = 0;
size_t i, entrycount;
- git_buf tree = GIT_BUF_INIT;
git_odb *odb;
git_tree_entry *entry;
- git_vector entries;
+ git_vector entries = GIT_VECTOR_INIT;
assert(bld);
+ assert(tree);
+
+ git_buf_clear(tree);
entrycount = git_strmap_num_entries(bld->map);
- if (git_vector_init(&entries, entrycount, entry_sort_cmp) < 0)
- return -1;
+ if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0)
+ goto out;
+
+ if (tree->asize == 0 &&
+ (error = git_buf_grow(tree, entrycount * 72)) < 0)
+ goto out;
git_strmap_foreach_value(bld->map, entry, {
- if (git_vector_insert(&entries, entry) < 0)
- return -1;
+ if ((error = git_vector_insert(&entries, entry)) < 0)
+ goto out;
});
git_vector_sort(&entries);
- /* Grow the buffer beforehand to an estimated size */
- error = git_buf_grow(&tree, entrycount * 72);
-
for (i = 0; i < entries.length && !error; ++i) {
- git_tree_entry *entry = git_vector_get(&entries, i);
+ entry = git_vector_get(&entries, i);
- git_buf_printf(&tree, "%o ", entry->attr);
- git_buf_put(&tree, entry->filename, entry->filename_len + 1);
- git_buf_put(&tree, (char *)entry->oid->id, GIT_OID_RAWSZ);
+ git_buf_printf(tree, "%o ", entry->attr);
+ git_buf_put(tree, entry->filename, entry->filename_len + 1);
+ git_buf_put(tree, (char *)entry->oid->id, GIT_OID_RAWSZ);
- if (git_buf_oom(&tree))
+ if (git_buf_oom(tree)) {
error = -1;
+ goto out;
+ }
}
+ if ((error = git_repository_odb__weakptr(&odb, bld->repo)) == 0)
+ error = git_odb_write(oid, odb, tree->ptr, tree->size, GIT_OBJ_TREE);
- if (!error &&
- !(error = git_repository_odb__weakptr(&odb, bld->repo)))
- error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
-
- git_buf_free(&tree);
+out:
git_vector_free(&entries);
return error;
@@ -904,7 +924,7 @@ int git_tree_entry_bypath(
filename_len = subpath_len(path);
if (filename_len == 0) {
- giterr_set(GITERR_TREE, "Invalid tree path given");
+ giterr_set(GITERR_TREE, "invalid tree path given");
return GIT_ENOTFOUND;
}
@@ -912,7 +932,7 @@ int git_tree_entry_bypath(
if (entry == NULL) {
giterr_set(GITERR_TREE,
- "the path '%.*s' does not exist in the given tree", filename_len, path);
+ "the path '%.*s' does not exist in the given tree", (int) filename_len, path);
return GIT_ENOTFOUND;
}
@@ -922,7 +942,7 @@ int git_tree_entry_bypath(
* then this entry *must* be a tree */
if (!git_tree_entry__is_tree(entry)) {
giterr_set(GITERR_TREE,
- "the path '%.*s' exists but is not a tree", filename_len, path);
+ "the path '%.*s' exists but is not a tree", (int) filename_len, path);
return GIT_ENOTFOUND;
}
@@ -1022,7 +1042,7 @@ int git_tree_walk(
git_buf root_path = GIT_BUF_INIT;
if (mode != GIT_TREEWALK_POST && mode != GIT_TREEWALK_PRE) {
- giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk");
+ giterr_set(GITERR_INVALID, "invalid walking mode for tree walk");
return -1;
}
@@ -1159,8 +1179,8 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
goto cleanup;
for (i = 0; i < nupdates; i++) {
- const git_tree_update *last_update = i == 0 ? NULL : &updates[i-1];
- const git_tree_update *update = &updates[i];
+ const git_tree_update *last_update = i == 0 ? NULL : git_vector_get(&entries, i-1);
+ const git_tree_update *update = git_vector_get(&entries, i);
size_t common_prefix = 0, steps_up, j;
const char *path;
@@ -1195,6 +1215,9 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
last = git_array_last(stack);
entry = last->tree ? git_tree_entry_byname(last->tree, component.ptr) : NULL;
+ if (!entry)
+ entry = treebuilder_get(last->bld, component.ptr);
+
if (entry && git_tree_entry_type(entry) != GIT_OBJ_TREE) {
giterr_set(GITERR_TREE, "D/F conflict when updating tree");
error = -1;
@@ -1229,7 +1252,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
const git_tree_entry *e = git_treebuilder_get(last->bld, basename);
if (e && git_tree_entry_type(e) != git_object__type_from_filemode(update->filemode)) {
git__free(basename);
- giterr_set(GITERR_TREE, "Cannot replace '%s' with '%s' at '%s'",
+ giterr_set(GITERR_TREE, "cannot replace '%s' with '%s' at '%s'",
git_object_type2string(git_tree_entry_type(e)),
git_object_type2string(git_object__type_from_filemode(update->filemode)),
update->path);
@@ -1249,7 +1272,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli
break;
}
default:
- giterr_set(GITERR_TREE, "unkown action for update");
+ giterr_set(GITERR_TREE, "unknown action for update");
error = -1;
goto cleanup;
}
diff --git a/src/tree.h b/src/tree.h
index 5e7a66e04..00f4b06eb 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_tree_h__
#define INCLUDE_tree_h__
+#include "common.h"
+
#include "git2/tree.h"
#include "repository.h"
#include "odb.h"
diff --git a/src/tsort.c b/src/tsort.c
index e59819204..8d1ed9787 100644
--- a/src/tsort.c
+++ b/src/tsort.c
@@ -310,7 +310,6 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr,
#define PUSH_NEXT() do {\
len = count_run(dst, curr, size, store);\
run = minrun;\
- if (run < minrun) run = minrun;\
if (run > (ssize_t)size - curr) run = size - curr;\
if (run > len) {\
bisort(&dst[curr], len, run, cmp, payload);\
diff --git a/src/unix/map.c b/src/unix/map.c
index c55ad1aa7..8a07fcff9 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -4,7 +4,10 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <git2/common.h>
+
+#include "common.h"
+
+#include "git2/common.h"
#if !defined(GIT_WIN32) && !defined(NO_MMAP)
@@ -52,7 +55,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
out->data = mmap(NULL, len, mprot, mflag, fd, offset);
if (!out->data || out->data == MAP_FAILED) {
- giterr_set(GITERR_OS, "Failed to mmap. Could not write data");
+ giterr_set(GITERR_OS, "failed to mmap. Could not write data");
return -1;
}
diff --git a/src/unix/posix.h b/src/unix/posix.h
index 482d2c803..ee36ea0f3 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_posix__unix_h__
#define INCLUDE_posix__unix_h__
+#ifndef LIBGIT2_NO_FEATURES_H
+# include "git2/sys/features.h"
+#endif
+
#include <stdio.h>
#include <dirent.h>
#include <sys/param.h>
@@ -40,9 +44,14 @@ typedef int GIT_SOCKET;
#define p_link(o,n) link(o, n)
#define p_unlink(p) unlink(p)
#define p_mkdir(p,m) mkdir(p, m)
-#define p_fsync(fd) fsync(fd)
extern char *p_realpath(const char *, char *);
+GIT_INLINE(int) p_fsync(int fd)
+{
+ p_fsync__cnt++;
+ return fsync(fd);
+}
+
#define p_recv(s,b,l,f) recv(s,b,l,f)
#define p_send(s,b,l,f) send(s,b,l,f)
#define p_inet_pton(a, b, c) inet_pton(a, b, c)
@@ -50,7 +59,7 @@ extern char *p_realpath(const char *, char *);
#define p_strcasecmp(s1, s2) strcasecmp(s1, s2)
#define p_strncasecmp(s1, s2, c) strncasecmp(s1, s2, c)
#define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a)
-#define p_snprintf(b, c, f, ...) snprintf(b, c, f, __VA_ARGS__)
+#define p_snprintf(b, c, ...) snprintf(b, c, __VA_ARGS__)
#define p_mkstemp(p) mkstemp(p)
#define p_chdir(p) chdir(p)
#define p_chmod(p,m) chmod(p, m)
@@ -66,7 +75,7 @@ extern char *p_realpath(const char *, char *);
#define p_timeval timeval
-#ifdef HAVE_FUTIMENS
+#ifdef GIT_USE_FUTIMENS
GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2])
{
struct timespec s[2];
@@ -80,4 +89,14 @@ GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2])
# define p_futimes futimes
#endif
+#ifdef GIT_USE_REGCOMP_L
+#include <xlocale.h>
+GIT_INLINE(int) p_regcomp(regex_t *preg, const char *pattern, int cflags)
+{
+ return regcomp_l(preg, pattern, cflags, (locale_t) 0);
+}
+#else
+# define p_regcomp regcomp
+#endif
+
#endif
diff --git a/src/unix/pthread.h b/src/unix/pthread.h
index 0f3f17927..3f23d10d5 100644
--- a/src/unix/pthread.h
+++ b/src/unix/pthread.h
@@ -17,6 +17,8 @@ typedef struct {
pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
#define git_thread_join(git_thread_ptr, status) \
pthread_join((git_thread_ptr)->thread, status)
+#define git_thread_currentid() ((size_t)(pthread_self()))
+#define git_thread_exit(retval) pthread_exit(retval)
/* Git Mutex */
#define git_mutex pthread_mutex_t
diff --git a/src/unix/realpath.c b/src/unix/realpath.c
index 2e49150c2..893bac87b 100644
--- a/src/unix/realpath.c
+++ b/src/unix/realpath.c
@@ -4,7 +4,10 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <git2/common.h>
+
+#include "common.h"
+
+#include "git2/common.h"
#ifndef GIT_WIN32
diff --git a/src/util.c b/src/util.c
index 76ca711b2..6ae5cdaec 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4,8 +4,10 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include <git2.h>
-#include "common.h"
+
+#include "util.h"
+
+#include "git2.h"
#include <stdio.h>
#include <ctype.h>
#include "posix.h"
@@ -136,7 +138,7 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
Return:
if (ndig == 0) {
- giterr_set(GITERR_INVALID, "Failed to convert string to long. Not a number");
+ giterr_set(GITERR_INVALID, "failed to convert string to long: not a number");
return -1;
}
@@ -144,7 +146,7 @@ Return:
*endptr = p;
if (ovfl) {
- giterr_set(GITERR_INVALID, "Failed to convert string to long. Overflow error");
+ giterr_set(GITERR_INVALID, "failed to convert string to long: overflow error");
return -1;
}
@@ -169,7 +171,7 @@ int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const cha
tmp_int = tmp_long & 0xFFFFFFFF;
if (tmp_int != tmp_long) {
- giterr_set(GITERR_INVALID, "Failed to convert. '%s' is too large", nptr);
+ giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr);
return -1;
}
diff --git a/src/util.h b/src/util.h
index eb15250d8..b85e03b6d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -7,39 +7,11 @@
#ifndef INCLUDE_util_h__
#define INCLUDE_util_h__
+#include "common.h"
+
#include "git2/buffer.h"
#include "buffer.h"
-
-#if defined(GIT_MSVC_CRTDBG)
-/* Enable MSVC CRTDBG memory leak reporting.
- *
- * We DO NOT use the "_CRTDBG_MAP_ALLOC" macro described in the MSVC
- * documentation because all allocs/frees in libgit2 already go through
- * the "git__" routines defined in this file. Simply using the normal
- * reporting mechanism causes all leaks to be attributed to a routine
- * here in util.h (ie, the actual call to calloc()) rather than the
- * caller of git__calloc().
- *
- * Therefore, we declare a set of "git__crtdbg__" routines to replace
- * the corresponding "git__" routines and re-define the "git__" symbols
- * as macros. This allows us to get and report the file:line info of
- * the real caller.
- *
- * We DO NOT replace the "git__free" routine because it needs to remain
- * a function pointer because it is used as a function argument when
- * setting up various structure "destructors".
- *
- * We also DO NOT use the "_CRTDBG_MAP_ALLOC" macro because it causes
- * "free" to be remapped to "_free_dbg" and this causes problems for
- * structures which define a field named "free".
- *
- * Finally, CRTDBG must be explicitly enabled and configured at program
- * startup. See tests/main.c for an example.
- */
-#include <stdlib.h>
-#include <crtdbg.h>
-#include "win32/w32_crtdbg_stacktrace.h"
-#endif
+#include "thread-utils.h"
#include "common.h"
#include "strnlen.h"
@@ -67,79 +39,33 @@
#if defined(GIT_MSVC_CRTDBG)
-GIT_INLINE(void *) git__crtdbg__malloc(size_t len, const char *file, int line)
-{
- void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) giterr_set_oom();
- return ptr;
-}
-
-GIT_INLINE(void *) git__crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line)
-{
- void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) giterr_set_oom();
- return ptr;
-}
-
-GIT_INLINE(char *) git__crtdbg__strdup(const char *str, const char *file, int line)
-{
- char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!ptr) giterr_set_oom();
- return ptr;
-}
-
-GIT_INLINE(char *) git__crtdbg__strndup(const char *str, size_t n, const char *file, int line)
-{
- size_t length = 0, alloclength;
- char *ptr;
-
- length = p_strnlen(str, n);
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = git__crtdbg__malloc(alloclength, file, line)))
- return NULL;
-
- if (length)
- memcpy(ptr, str, length);
-
- ptr[length] = '\0';
-
- return ptr;
-}
-
-GIT_INLINE(char *) git__crtdbg__substrdup(const char *start, size_t n, const char *file, int line)
-{
- char *ptr;
- size_t alloclen;
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = git__crtdbg__malloc(alloclen, file, line)))
- return NULL;
-
- memcpy(ptr, start, n);
- ptr[n] = '\0';
- return ptr;
-}
-
-GIT_INLINE(void *) git__crtdbg__realloc(void *ptr, size_t size, const char *file, int line)
-{
- void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
- if (!new_ptr) giterr_set_oom();
- return new_ptr;
-}
-
-GIT_INLINE(void *) git__crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
-{
- size_t newsize;
-
- return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ?
- NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
-}
+/* Enable MSVC CRTDBG memory leak reporting.
+ *
+ * We DO NOT use the "_CRTDBG_MAP_ALLOC" macro described in the MSVC
+ * documentation because all allocs/frees in libgit2 already go through
+ * the "git__" routines defined in this file. Simply using the normal
+ * reporting mechanism causes all leaks to be attributed to a routine
+ * here in util.h (ie, the actual call to calloc()) rather than the
+ * caller of git__calloc().
+ *
+ * Therefore, we declare a set of "git__crtdbg__" routines to replace
+ * the corresponding "git__" routines and re-define the "git__" symbols
+ * as macros. This allows us to get and report the file:line info of
+ * the real caller.
+ *
+ * We DO NOT replace the "git__free" routine because it needs to remain
+ * a function pointer because it is used as a function argument when
+ * setting up various structure "destructors".
+ *
+ * We also DO NOT use the "_CRTDBG_MAP_ALLOC" macro because it causes
+ * "free" to be remapped to "_free_dbg" and this causes problems for
+ * structures which define a field named "free".
+ *
+ * Finally, CRTDBG must be explicitly enabled and configured at program
+ * startup. See tests/main.c for an example.
+ */
-GIT_INLINE(void *) git__crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
-{
- return git__crtdbg__reallocarray(NULL, nelem, elsize, file, line);
-}
+#include "win32/w32_crtdbg_stacktrace.h"
#define git__malloc(len) git__crtdbg__malloc(len, __FILE__, __LINE__)
#define git__calloc(nelem, elsize) git__crtdbg__calloc(nelem, elsize, __FILE__, __LINE__)
@@ -363,8 +289,6 @@ extern int git__strncasecmp(const char *a, const char *b, size_t sz);
extern int git__strcasesort_cmp(const char *a, const char *b);
-#include "thread-utils.h"
-
typedef struct {
git_atomic refcount;
void *owner;
diff --git a/src/varint.c b/src/varint.c
index 2f868607c..9ffc1d744 100644
--- a/src/varint.c
+++ b/src/varint.c
@@ -5,7 +5,6 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "varint.h"
uintmax_t git_decode_varint(const unsigned char *bufp, size_t *varint_len)
@@ -36,7 +35,7 @@ int git_encode_varint(unsigned char *buf, size_t bufsize, uintmax_t value)
while (value >>= 7)
varint[--pos] = 128 | (--value & 127);
if (buf) {
- if (bufsize < pos)
+ if (bufsize < (sizeof(varint) - pos))
return -1;
memcpy(buf, varint + pos, sizeof(varint) - pos);
}
diff --git a/src/varint.h b/src/varint.h
index 650ec7d2a..652e22486 100644
--- a/src/varint.h
+++ b/src/varint.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_varint_h__
#define INCLUDE_varint_h__
+#include "common.h"
+
#include <stdint.h>
extern int git_encode_varint(unsigned char *, size_t, uintmax_t);
diff --git a/src/vector.c b/src/vector.c
index db1dcf89a..b12fa942d 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "vector.h"
+
#include "integer.h"
/* In elements, not bytes */
@@ -401,3 +401,22 @@ int git_vector_verify_sorted(const git_vector *v)
return 0;
}
+
+void git_vector_reverse(git_vector *v)
+{
+ size_t a, b;
+
+ if (v->length == 0)
+ return;
+
+ a = 0;
+ b = v->length - 1;
+
+ while (a < b) {
+ void *tmp = v->contents[a];
+ v->contents[a] = v->contents[b];
+ v->contents[b] = tmp;
+ a++;
+ b--;
+ }
+}
diff --git a/src/vector.h b/src/vector.h
index 96d149e16..cc4c314d5 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -118,4 +118,9 @@ GIT_INLINE(void) git_vector_set_cmp(git_vector *v, git_vector_cmp cmp)
/* Just use this in tests, not for realz. returns -1 if not sorted */
int git_vector_verify_sorted(const git_vector *v);
+/**
+ * Reverse the vector in-place.
+ */
+void git_vector_reverse(git_vector *v);
+
#endif
diff --git a/src/win32/dir.c b/src/win32/dir.c
index c15757085..1d37874e4 100644
--- a/src/win32/dir.c
+++ b/src/win32/dir.c
@@ -4,6 +4,9 @@
* 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 "dir.h"
+
#define GIT__WIN32_NO_WRAP_DIR
#include "posix.h"
@@ -28,7 +31,7 @@ git__DIR *git__opendir(const char *dir)
new->h = FindFirstFileW(filter_w, &new->f);
if (new->h == INVALID_HANDLE_VALUE) {
- giterr_set(GITERR_OS, "Could not open directory '%s'", dir);
+ giterr_set(GITERR_OS, "could not open directory '%s'", dir);
git__free(new);
return NULL;
}
@@ -53,7 +56,7 @@ int git__readdir_ext(
else if (!FindNextFileW(d->h, &d->f)) {
if (GetLastError() == ERROR_NO_MORE_FILES)
return 0;
- giterr_set(GITERR_OS, "Could not read from directory '%s'", d->dir);
+ giterr_set(GITERR_OS, "could not read from directory '%s'", d->dir);
return -1;
}
@@ -98,7 +101,7 @@ void git__rewinddir(git__DIR *d)
d->h = FindFirstFileW(filter_w, &d->f);
if (d->h == INVALID_HANDLE_VALUE)
- giterr_set(GITERR_OS, "Could not open directory '%s'", d->dir);
+ giterr_set(GITERR_OS, "could not open directory '%s'", d->dir);
else
d->first = 1;
}
diff --git a/src/win32/dir.h b/src/win32/dir.h
index bef39d774..704a9a8a9 100644
--- a/src/win32/dir.h
+++ b/src/win32/dir.h
@@ -8,6 +8,7 @@
#define INCLUDE_dir_h__
#include "common.h"
+
#include "w32_util.h"
struct git__dirent {
diff --git a/src/win32/error.c b/src/win32/error.c
index 6b450093f..3a52fb5a9 100644
--- a/src/win32/error.c
+++ b/src/win32/error.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "error.h"
+
#include "utf-conv.h"
#ifdef GIT_WINHTTP
diff --git a/src/win32/error.h b/src/win32/error.h
index 12947a2e6..a2ecf6a6a 100644
--- a/src/win32/error.h
+++ b/src/win32/error.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_git_win32_error_h__
#define INCLUDE_git_win32_error_h__
+#include "common.h"
+
extern char *git_win32_get_error_message(DWORD error_code);
#endif
diff --git a/src/win32/findfile.c b/src/win32/findfile.c
index 58c22279e..d56aa1fd2 100644
--- a/src/win32/findfile.c
+++ b/src/win32/findfile.c
@@ -5,10 +5,11 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "findfile.h"
+
#include "path_w32.h"
#include "utf-conv.h"
#include "path.h"
-#include "findfile.h"
#define REG_MSYSGIT_INSTALL_LOCAL L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1"
@@ -38,7 +39,7 @@ static int win32_path_to_8(git_buf *dest, const wchar_t *src)
git_win32_utf8_path utf8_path;
if (git_win32_path_to_utf8(utf8_path, src) < 0) {
- giterr_set(GITERR_OS, "Unable to convert path to UTF-8");
+ giterr_set(GITERR_OS, "unable to convert path to UTF-8");
return -1;
}
diff --git a/src/win32/findfile.h b/src/win32/findfile.h
index 3d5fff439..1eae4691c 100644
--- a/src/win32/findfile.h
+++ b/src/win32/findfile.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_git_findfile_h__
#define INCLUDE_git_findfile_h__
+#include "common.h"
+
extern int git_win32__find_system_dirs(git_buf *out, const wchar_t *subpath);
extern int git_win32__find_global_dirs(git_buf *out);
extern int git_win32__find_xdg_dirs(git_buf *out);
diff --git a/src/win32/map.c b/src/win32/map.c
index 03a3646a6..6a17aeb64 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -5,6 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "common.h"
+
#include "map.h"
#include <errno.h>
@@ -67,7 +69,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
if (fh == INVALID_HANDLE_VALUE) {
errno = EBADF;
- giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value");
+ giterr_set(GITERR_OS, "failed to mmap. Invalid handle value");
return -1;
}
@@ -86,13 +88,13 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
if (page_offset != 0) { /* offset must be multiple of the allocation granularity */
errno = EINVAL;
- giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of allocation granularity");
+ giterr_set(GITERR_OS, "failed to mmap. Offset must be multiple of allocation granularity");
return -1;
}
out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
- giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value");
+ giterr_set(GITERR_OS, "failed to mmap. Invalid handle value");
out->fmh = NULL;
return -1;
}
@@ -103,7 +105,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
off_hi = (DWORD)(page_start >> 32);
out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
if (!out->data) {
- giterr_set(GITERR_OS, "Failed to mmap. No data written");
+ giterr_set(GITERR_OS, "failed to mmap. No data written");
CloseHandle(out->fmh);
out->fmh = NULL;
return -1;
@@ -121,7 +123,7 @@ int p_munmap(git_map *map)
if (map->data) {
if (!UnmapViewOfFile(map->data)) {
- giterr_set(GITERR_OS, "Failed to munmap. Could not unmap view of file");
+ giterr_set(GITERR_OS, "failed to munmap. Could not unmap view of file");
error = -1;
}
map->data = NULL;
@@ -129,7 +131,7 @@ int p_munmap(git_map *map)
if (map->fmh) {
if (!CloseHandle(map->fmh)) {
- giterr_set(GITERR_OS, "Failed to munmap. Could not close handle");
+ giterr_set(GITERR_OS, "failed to munmap. Could not close handle");
error = -1;
}
map->fmh = NULL;
diff --git a/src/win32/path_w32.c b/src/win32/path_w32.c
index 40b95c33b..f8416b848 100644
--- a/src/win32/path_w32.c
+++ b/src/win32/path_w32.c
@@ -5,9 +5,9 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
-#include "path.h"
#include "path_w32.h"
+
+#include "path.h"
#include "utf-conv.h"
#include "posix.h"
#include "reparse.h"
diff --git a/src/win32/path_w32.h b/src/win32/path_w32.h
index 3d9f82860..ac1fb4b9e 100644
--- a/src/win32/path_w32.h
+++ b/src/win32/path_w32.h
@@ -8,6 +8,7 @@
#define INCLUDE_git_path_w32_h__
#include "common.h"
+
#include "vector.h"
/*
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 5fab267c2..64769ecd3 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -14,6 +14,9 @@
#include "utf-conv.h"
#include "dir.h"
+extern unsigned long git_win32__createfile_sharemode;
+extern int git_win32__retries;
+
typedef SOCKET GIT_SOCKET;
#define p_lseek(f,n,w) _lseeki64(f, n, w)
@@ -57,4 +60,7 @@ extern int p_lstat_posixly(const char *filename, struct stat *buf);
extern struct tm * p_localtime_r(const time_t *timer, struct tm *result);
extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result);
+/* Use the bundled regcomp */
+#define p_regcomp regcomp
+
#endif
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index fea634b00..f51e1e546 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -4,6 +4,9 @@
* 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 "common.h"
+
#include "../posix.h"
#include "../fileops.h"
#include "path.h"
@@ -26,15 +29,6 @@
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
-/* Options which we always provide to _wopen.
- *
- * _O_BINARY - Raw access; no translation of CR or LF characters
- * _O_NOINHERIT - Do not mark the created handle as inheritable by child processes.
- * The Windows default is 'not inheritable', but the CRT's default (following
- * POSIX convention) is 'inheritable'. We have no desire for our handles to be
- * inheritable on Windows, so specify the flag to get default behavior back. */
-#define STANDARD_OPEN_FLAGS (_O_BINARY | _O_NOINHERIT)
-
/* Allowable mode bits on Win32. Using mode bits that are not supported on
* Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it
* so we simply remove them.
@@ -44,6 +38,167 @@
/* GetFinalPathNameByHandleW signature */
typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
+unsigned long git_win32__createfile_sharemode =
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
+int git_win32__retries = 10;
+
+GIT_INLINE(void) set_errno(void)
+{
+ switch (GetLastError()) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_NO_MORE_FILES:
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_NET_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ errno = ENOENT;
+ break;
+ case ERROR_BAD_ENVIRONMENT:
+ errno = E2BIG;
+ break;
+ case ERROR_BAD_FORMAT:
+ case ERROR_INVALID_STARTING_CODESEG:
+ case ERROR_INVALID_STACKSEG:
+ case ERROR_INVALID_MODULETYPE:
+ case ERROR_INVALID_EXE_SIGNATURE:
+ case ERROR_EXE_MARKED_INVALID:
+ case ERROR_BAD_EXE_FORMAT:
+ case ERROR_ITERATED_DATA_EXCEEDS_64k:
+ case ERROR_INVALID_MINALLOCSIZE:
+ case ERROR_DYNLINK_FROM_INVALID_RING:
+ case ERROR_IOPL_NOT_ENABLED:
+ case ERROR_INVALID_SEGDPL:
+ case ERROR_AUTODATASEG_EXCEEDS_64k:
+ case ERROR_RING2SEG_MUST_BE_MOVABLE:
+ case ERROR_RELOC_CHAIN_XEEDS_SEGLIM:
+ case ERROR_INFLOOP_IN_RELOC_CHAIN:
+ errno = ENOEXEC;
+ break;
+ case ERROR_INVALID_HANDLE:
+ case ERROR_INVALID_TARGET_HANDLE:
+ case ERROR_DIRECT_ACCESS_HANDLE:
+ errno = EBADF;
+ break;
+ case ERROR_WAIT_NO_CHILDREN:
+ case ERROR_CHILD_NOT_COMPLETE:
+ errno = ECHILD;
+ break;
+ case ERROR_NO_PROC_SLOTS:
+ case ERROR_MAX_THRDS_REACHED:
+ case ERROR_NESTING_NOT_ALLOWED:
+ errno = EAGAIN;
+ break;
+ case ERROR_ARENA_TRASHED:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_NOT_ENOUGH_QUOTA:
+ errno = ENOMEM;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_CURRENT_DIRECTORY:
+ case ERROR_WRITE_PROTECT:
+ case ERROR_BAD_UNIT:
+ case ERROR_NOT_READY:
+ case ERROR_BAD_COMMAND:
+ case ERROR_CRC:
+ case ERROR_BAD_LENGTH:
+ case ERROR_SEEK:
+ case ERROR_NOT_DOS_DISK:
+ case ERROR_SECTOR_NOT_FOUND:
+ case ERROR_OUT_OF_PAPER:
+ case ERROR_WRITE_FAULT:
+ case ERROR_READ_FAULT:
+ case ERROR_GEN_FAILURE:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_WRONG_DISK:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ case ERROR_CANNOT_MAKE:
+ case ERROR_FAIL_I24:
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_SEEK_ON_DEVICE:
+ case ERROR_NOT_LOCKED:
+ case ERROR_LOCK_FAILED:
+ errno = EACCES;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ errno = EEXIST;
+ break;
+ case ERROR_NOT_SAME_DEVICE:
+ errno = EXDEV;
+ break;
+ case ERROR_INVALID_FUNCTION:
+ case ERROR_INVALID_ACCESS:
+ case ERROR_INVALID_DATA:
+ case ERROR_INVALID_PARAMETER:
+ case ERROR_NEGATIVE_SEEK:
+ errno = EINVAL;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ errno = EMFILE;
+ break;
+ case ERROR_DISK_FULL:
+ errno = ENOSPC;
+ break;
+ case ERROR_BROKEN_PIPE:
+ errno = EPIPE;
+ break;
+ case ERROR_DIR_NOT_EMPTY:
+ errno = ENOTEMPTY;
+ break;
+ default:
+ errno = EINVAL;
+ }
+}
+
+GIT_INLINE(bool) last_error_retryable(void)
+{
+ int os_error = GetLastError();
+
+ return (os_error == ERROR_SHARING_VIOLATION ||
+ os_error == ERROR_ACCESS_DENIED);
+}
+
+#define do_with_retries(fn, remediation) \
+ do { \
+ int __retry, __ret; \
+ for (__retry = git_win32__retries; __retry; __retry--) { \
+ if ((__ret = (fn)) != GIT_RETRY) \
+ return __ret; \
+ if (__retry > 1 && (__ret = (remediation)) != 0) { \
+ if (__ret == GIT_RETRY) \
+ continue; \
+ return __ret; \
+ } \
+ Sleep(5); \
+ } \
+ return -1; \
+ } while (0) \
+
+static int ensure_writable(wchar_t *path)
+{
+ DWORD attrs;
+
+ if ((attrs = GetFileAttributesW(path)) == INVALID_FILE_ATTRIBUTES)
+ goto on_error;
+
+ if ((attrs & FILE_ATTRIBUTE_READONLY) == 0)
+ return 0;
+
+ if (!SetFileAttributesW(path, (attrs & ~FILE_ATTRIBUTE_READONLY)))
+ goto on_error;
+
+ return GIT_RETRY;
+
+on_error:
+ set_errno();
+ return -1;
+}
+
/**
* Truncate or extend file.
*
@@ -89,30 +244,34 @@ int p_link(const char *old, const char *new)
return -1;
}
-int p_unlink(const char *path)
+GIT_INLINE(int) unlink_once(const wchar_t *path)
{
- git_win32_path buf;
- int error;
+ if (DeleteFileW(path))
+ return 0;
- if (git_win32_path_from_utf8(buf, path) < 0)
- return -1;
+ if (last_error_retryable())
+ return GIT_RETRY;
- error = _wunlink(buf);
+ set_errno();
+ return -1;
+}
- /* If the file could not be deleted because it was
- * read-only, clear the bit and try again */
- if (error == -1 && errno == EACCES) {
- _wchmod(buf, 0666);
- error = _wunlink(buf);
- }
+int p_unlink(const char *path)
+{
+ git_win32_path wpath;
- return error;
+ if (git_win32_path_from_utf8(wpath, path) < 0)
+ return -1;
+
+ do_with_retries(unlink_once(wpath), ensure_writable(wpath));
}
int p_fsync(int fd)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
+ p_fsync__cnt++;
+
if (fh == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
@@ -210,44 +369,6 @@ int p_lstat_posixly(const char *filename, struct stat *buf)
return do_lstat(filename, buf, true);
}
-int p_utimes(const char *filename, const struct p_timeval times[2])
-{
- int fd, error;
-
- if ((fd = p_open(filename, O_RDWR)) < 0)
- return fd;
-
- error = p_futimes(fd, times);
-
- close(fd);
- return error;
-}
-
-int p_futimes(int fd, const struct p_timeval times[2])
-{
- HANDLE handle;
- FILETIME atime = {0}, mtime = {0};
-
- if (times == NULL) {
- SYSTEMTIME st;
-
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &atime);
- SystemTimeToFileTime(&st, &mtime);
- } else {
- git_win32__timeval_to_filetime(&atime, times[0]);
- git_win32__timeval_to_filetime(&mtime, times[1]);
- }
-
- if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
- return -1;
-
- if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
- return -1;
-
- return 0;
-}
-
int p_readlink(const char *path, char *buf, size_t bufsiz)
{
git_win32_path path_w, target_w;
@@ -280,12 +401,91 @@ int p_symlink(const char *old, const char *new)
return git_futils_fake_symlink(old, new);
}
+struct open_opts {
+ DWORD access;
+ DWORD sharing;
+ SECURITY_ATTRIBUTES security;
+ DWORD creation_disposition;
+ DWORD attributes;
+ int osf_flags;
+};
+
+GIT_INLINE(void) open_opts_from_posix(struct open_opts *opts, int flags, mode_t mode)
+{
+ memset(opts, 0, sizeof(struct open_opts));
+
+ switch (flags & (O_WRONLY | O_RDWR)) {
+ case O_WRONLY:
+ opts->access = GENERIC_WRITE;
+ break;
+ case O_RDWR:
+ opts->access = GENERIC_READ | GENERIC_WRITE;
+ break;
+ default:
+ opts->access = GENERIC_READ;
+ break;
+ }
+
+ opts->sharing = (DWORD)git_win32__createfile_sharemode;
+
+ switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) {
+ case O_CREAT | O_EXCL:
+ case O_CREAT | O_TRUNC | O_EXCL:
+ opts->creation_disposition = CREATE_NEW;
+ break;
+ case O_CREAT | O_TRUNC:
+ opts->creation_disposition = CREATE_ALWAYS;
+ break;
+ case O_TRUNC:
+ opts->creation_disposition = TRUNCATE_EXISTING;
+ break;
+ case O_CREAT:
+ opts->creation_disposition = OPEN_ALWAYS;
+ break;
+ default:
+ opts->creation_disposition = OPEN_EXISTING;
+ break;
+ }
+
+ opts->attributes = ((flags & O_CREAT) && !(mode & S_IWRITE)) ?
+ FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL;
+ opts->osf_flags = flags & (O_RDONLY | O_APPEND);
+
+ opts->security.nLength = sizeof(SECURITY_ATTRIBUTES);
+ opts->security.lpSecurityDescriptor = NULL;
+ opts->security.bInheritHandle = 0;
+}
+
+GIT_INLINE(int) open_once(
+ const wchar_t *path,
+ struct open_opts *opts)
+{
+ int fd;
+
+ HANDLE handle = CreateFileW(path, opts->access, opts->sharing,
+ &opts->security, opts->creation_disposition, opts->attributes, 0);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ if (last_error_retryable())
+ return GIT_RETRY;
+
+ set_errno();
+ return -1;
+ }
+
+ if ((fd = _open_osfhandle((intptr_t)handle, opts->osf_flags)) < 0)
+ CloseHandle(handle);
+
+ return fd;
+}
+
int p_open(const char *path, int flags, ...)
{
- git_win32_path buf;
+ git_win32_path wpath;
mode_t mode = 0;
+ struct open_opts opts = {0};
- if (git_win32_path_from_utf8(buf, path) < 0)
+ if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
if (flags & O_CREAT) {
@@ -296,19 +496,83 @@ int p_open(const char *path, int flags, ...)
va_end(arg_list);
}
- return _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode & WIN32_MODE_MASK);
+ open_opts_from_posix(&opts, flags, mode);
+
+ do_with_retries(
+ open_once(wpath, &opts),
+ 0);
}
int p_creat(const char *path, mode_t mode)
{
- git_win32_path buf;
+ return p_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+}
- if (git_win32_path_from_utf8(buf, path) < 0)
+int p_utimes(const char *path, const struct p_timeval times[2])
+{
+ git_win32_path wpath;
+ int fd, error;
+ DWORD attrs_orig, attrs_new = 0;
+ struct open_opts opts = { 0 };
+
+ if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
- return _wopen(buf,
- _O_WRONLY | _O_CREAT | _O_TRUNC | STANDARD_OPEN_FLAGS,
- mode & WIN32_MODE_MASK);
+ attrs_orig = GetFileAttributesW(wpath);
+
+ if (attrs_orig & FILE_ATTRIBUTE_READONLY) {
+ attrs_new = attrs_orig & ~FILE_ATTRIBUTE_READONLY;
+
+ if (!SetFileAttributesW(wpath, attrs_new)) {
+ giterr_set(GITERR_OS, "failed to set attributes");
+ return -1;
+ }
+ }
+
+ open_opts_from_posix(&opts, O_RDWR, 0);
+
+ if ((fd = open_once(wpath, &opts)) < 0) {
+ error = -1;
+ goto done;
+ }
+
+ error = p_futimes(fd, times);
+ close(fd);
+
+done:
+ if (attrs_orig != attrs_new) {
+ DWORD os_error = GetLastError();
+ SetFileAttributesW(wpath, attrs_orig);
+ SetLastError(os_error);
+ }
+
+ return error;
+}
+
+int p_futimes(int fd, const struct p_timeval times[2])
+{
+ HANDLE handle;
+ FILETIME atime = { 0 }, mtime = { 0 };
+
+ if (times == NULL) {
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &atime);
+ SystemTimeToFileTime(&st, &mtime);
+ }
+ else {
+ git_win32__timeval_to_filetime(&atime, times[0]);
+ git_win32__timeval_to_filetime(&mtime, times[1]);
+ }
+
+ if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
+ return -1;
+
+ if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
+ return -1;
+
+ return 0;
}
int p_getcwd(char *buffer_out, size_t size)
@@ -581,62 +845,27 @@ int p_access(const char* path, mode_t mode)
return _waccess(buf, mode & WIN32_MODE_MASK);
}
-static int ensure_writable(wchar_t *fpath)
+GIT_INLINE(int) rename_once(const wchar_t *from, const wchar_t *to)
{
- DWORD attrs;
-
- attrs = GetFileAttributesW(fpath);
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- return 0;
-
- giterr_set(GITERR_OS, "failed to get attributes");
- return -1;
- }
-
- if (!(attrs & FILE_ATTRIBUTE_READONLY))
+ if (MoveFileExW(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
return 0;
- attrs &= ~FILE_ATTRIBUTE_READONLY;
- if (!SetFileAttributesW(fpath, attrs)) {
- giterr_set(GITERR_OS, "failed to set attributes");
- return -1;
- }
+ if (last_error_retryable())
+ return GIT_RETRY;
- return 0;
+ set_errno();
+ return -1;
}
int p_rename(const char *from, const char *to)
{
- git_win32_path wfrom;
- git_win32_path wto;
- int rename_tries;
- int rename_succeeded;
- int error;
+ git_win32_path wfrom, wto;
if (git_win32_path_from_utf8(wfrom, from) < 0 ||
git_win32_path_from_utf8(wto, to) < 0)
return -1;
- /* wait up to 50ms if file is locked by another thread or process */
- rename_tries = 0;
- rename_succeeded = 0;
- while (rename_tries < 10) {
- if (ensure_writable(wto) == 0 &&
- MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
- rename_succeeded = 1;
- break;
- }
-
- error = GetLastError();
- if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
- Sleep(5);
- rename_tries++;
- } else
- break;
- }
-
- return rename_succeeded ? 0 : -1;
+ do_with_retries(rename_once(wfrom, wto), ensure_writable(wto));
}
int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
diff --git a/src/win32/precompiled.h b/src/win32/precompiled.h
index 10ca0b80c..851a083d5 100644
--- a/src/win32/precompiled.h
+++ b/src/win32/precompiled.h
@@ -1,3 +1,5 @@
+#include "common.h"
+
#include <assert.h>
#include <errno.h>
#include <limits.h>
@@ -20,4 +22,3 @@
#endif
#include "git2.h"
-#include "common.h"
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 80d56ce5d..2d9600515 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -6,6 +6,7 @@
*/
#include "thread.h"
+
#include "../global.h"
#define CLEAN_THREAD_EXIT 0x6F012842
@@ -26,6 +27,9 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
{
git_thread *thread = lpParameter;
+ /* Set the current thread for `git_thread_exit` */
+ GIT_GLOBAL->current_thread = thread;
+
thread->result = thread->proc(thread->param);
git__free_tls_data();
@@ -95,6 +99,21 @@ int git_thread_join(
return 0;
}
+void git_thread_exit(void *value)
+{
+ assert(GIT_GLOBAL->current_thread);
+ GIT_GLOBAL->current_thread->result = value;
+
+ git__free_tls_data();
+
+ ExitThread(CLEAN_THREAD_EXIT);
+}
+
+size_t git_thread_currentid(void)
+{
+ return GetCurrentThreadId();
+}
+
int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
{
InitializeCriticalSection(mutex);
diff --git a/src/win32/thread.h b/src/win32/thread.h
index 0d01822a6..d217722ec 100644
--- a/src/win32/thread.h
+++ b/src/win32/thread.h
@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_thread_h__
#define INCLUDE_win32_thread_h__
-#include "../common.h"
+#include "common.h"
#if defined (_MSC_VER)
# define GIT_RESTRICT __restrict
@@ -41,6 +41,8 @@ int git_thread_create(git_thread *GIT_RESTRICT,
void *(*) (void *),
void *GIT_RESTRICT);
int git_thread_join(git_thread *, void **);
+size_t git_thread_currentid(void);
+void git_thread_exit(void *);
int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
int git_mutex_free(git_mutex *);
diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c
index 96fd4606e..4bde3023a 100644
--- a/src/win32/utf-conv.c
+++ b/src/win32/utf-conv.c
@@ -5,7 +5,6 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "utf-conv.h"
GIT_INLINE(void) git__set_errno(void)
diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h
index 33b95f59f..bab7ba9fd 100644
--- a/src/win32/utf-conv.h
+++ b/src/win32/utf-conv.h
@@ -7,9 +7,10 @@
#ifndef INCLUDE_git_utfconv_h__
#define INCLUDE_git_utfconv_h__
-#include <wchar.h>
#include "common.h"
+#include <wchar.h>
+
#ifndef WC_ERR_INVALID_CHARS
# define WC_ERR_INVALID_CHARS 0x80
#endif
diff --git a/src/win32/w32_buffer.c b/src/win32/w32_buffer.c
index 9122baaa6..45c024d31 100644
--- a/src/win32/w32_buffer.c
+++ b/src/win32/w32_buffer.c
@@ -5,8 +5,8 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
-#include "common.h"
#include "w32_buffer.h"
+
#include "../buffer.h"
#include "utf-conv.h"
diff --git a/src/win32/w32_buffer.h b/src/win32/w32_buffer.h
index 62243986f..e15ea6864 100644
--- a/src/win32/w32_buffer.h
+++ b/src/win32/w32_buffer.h
@@ -7,6 +7,8 @@
#ifndef INCLUDE_git_win32_buffer_h__
#define INCLUDE_git_win32_buffer_h__
+#include "common.h"
+
#include "../buffer.h"
/**
diff --git a/src/win32/w32_crtdbg_stacktrace.c b/src/win32/w32_crtdbg_stacktrace.c
index a778f4164..7b3c3fb4c 100644
--- a/src/win32/w32_crtdbg_stacktrace.c
+++ b/src/win32/w32_crtdbg_stacktrace.c
@@ -5,9 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "w32_crtdbg_stacktrace.h"
+
#if defined(GIT_MSVC_CRTDBG)
#include "w32_stack.h"
-#include "w32_crtdbg_stacktrace.h"
#define CRTDBG_STACKTRACE__UID_LEN (15)
@@ -253,11 +254,11 @@ int git_win32__crtdbg_stacktrace__dump(
bool b_quiet = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__QUIET);
if (b_leaks_since_mark && b_leaks_total) {
- giterr_set(GITERR_INVALID, "Cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL.");
+ giterr_set(GITERR_INVALID, "cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL.");
return GIT_ERROR;
}
if (!b_set_mark && !b_leaks_since_mark && !b_leaks_total) {
- giterr_set(GITERR_INVALID, "Nothing to do.");
+ giterr_set(GITERR_INVALID, "nothing to do.");
return GIT_ERROR;
}
diff --git a/src/win32/w32_crtdbg_stacktrace.h b/src/win32/w32_crtdbg_stacktrace.h
index 40ca60d53..bb869b347 100644
--- a/src/win32/w32_crtdbg_stacktrace.h
+++ b/src/win32/w32_crtdbg_stacktrace.h
@@ -7,8 +7,16 @@
#ifndef INCLUDE_w32_crtdbg_stacktrace_h__
#define INCLUDE_w32_crtdbg_stacktrace_h__
+#include "common.h"
+
#if defined(GIT_MSVC_CRTDBG)
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#include "git2/errors.h"
+#include "strnlen.h"
+
/**
* Initialize our memory leak tracking and de-dup data structures.
* This should ONLY be called by git_libgit2_init().
@@ -89,5 +97,80 @@ GIT_EXTERN(int) git_win32__crtdbg_stacktrace__dump(
*/
const char *git_win32__crtdbg_stacktrace(int skip, const char *file);
+GIT_INLINE(void *) git__crtdbg__malloc(size_t len, const char *file, int line)
+{
+ void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
+ if (!ptr) giterr_set_oom();
+ return ptr;
+}
+
+GIT_INLINE(void *) git__crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line)
+{
+ void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
+ if (!ptr) giterr_set_oom();
+ return ptr;
+}
+
+GIT_INLINE(char *) git__crtdbg__strdup(const char *str, const char *file, int line)
+{
+ char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
+ if (!ptr) giterr_set_oom();
+ return ptr;
+}
+
+GIT_INLINE(char *) git__crtdbg__strndup(const char *str, size_t n, const char *file, int line)
+{
+ size_t length = 0, alloclength;
+ char *ptr;
+
+ length = p_strnlen(str, n);
+
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
+ !(ptr = git__crtdbg__malloc(alloclength, file, line)))
+ return NULL;
+
+ if (length)
+ memcpy(ptr, str, length);
+
+ ptr[length] = '\0';
+
+ return ptr;
+}
+
+GIT_INLINE(char *) git__crtdbg__substrdup(const char *start, size_t n, const char *file, int line)
+{
+ char *ptr;
+ size_t alloclen;
+
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
+ !(ptr = git__crtdbg__malloc(alloclen, file, line)))
+ return NULL;
+
+ memcpy(ptr, start, n);
+ ptr[n] = '\0';
+ return ptr;
+}
+
+GIT_INLINE(void *) git__crtdbg__realloc(void *ptr, size_t size, const char *file, int line)
+{
+ void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
+ if (!new_ptr) giterr_set_oom();
+ return new_ptr;
+}
+
+GIT_INLINE(void *) git__crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
+{
+ size_t newsize;
+
+ return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ?
+ NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
+}
+
+GIT_INLINE(void *) git__crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
+{
+ return git__crtdbg__reallocarray(NULL, nelem, elsize, file, line);
+}
+
+
#endif
#endif
diff --git a/src/win32/w32_stack.c b/src/win32/w32_stack.c
index 15af3dcb7..b40f9d2b4 100644
--- a/src/win32/w32_stack.c
+++ b/src/win32/w32_stack.c
@@ -5,11 +5,12 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "w32_stack.h"
+
#if defined(GIT_MSVC_CRTDBG)
#include "Windows.h"
#include "Dbghelp.h"
#include "win32/posix.h"
-#include "w32_stack.h"
#include "hash.h"
/**
diff --git a/src/win32/w32_stack.h b/src/win32/w32_stack.h
index 21170bd2f..a514ace6f 100644
--- a/src/win32/w32_stack.h
+++ b/src/win32/w32_stack.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_w32_stack_h__
#define INCLUDE_w32_stack_h__
+#include "common.h"
+
#if defined(GIT_MSVC_CRTDBG)
/**
diff --git a/src/win32/w32_util.c b/src/win32/w32_util.c
index 60311bb50..b7b1ffa10 100644
--- a/src/win32/w32_util.c
+++ b/src/win32/w32_util.c
@@ -68,7 +68,7 @@ int git_win32__set_hidden(const char *path, bool hidden)
newattrs = attrs & ~FILE_ATTRIBUTE_HIDDEN;
if (attrs != newattrs && !SetFileAttributesW(buf, newattrs)) {
- giterr_set(GITERR_OS, "Failed to %s hidden bit for '%s'",
+ giterr_set(GITERR_OS, "failed to %s hidden bit for '%s'",
hidden ? "set" : "unset", path);
return -1;
}
diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h
index 2e475e5e9..d81e55a00 100644
--- a/src/win32/w32_util.h
+++ b/src/win32/w32_util.h
@@ -8,6 +8,8 @@
#ifndef INCLUDE_w32_util_h__
#define INCLUDE_w32_util_h__
+#include "common.h"
+
#include "utf-conv.h"
#include "posix.h"
#include "path_w32.h"
@@ -174,7 +176,7 @@ GIT_INLINE(int) git_win32__file_attribute_to_stat(
/* st_size gets the UTF-8 length of the target name, in bytes,
* not counting the NULL terminator */
if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) {
- giterr_set(GITERR_OS, "Could not convert reparse point name for '%s'", path);
+ giterr_set(GITERR_OS, "could not convert reparse point name for '%ls'", path);
return -1;
}
}
diff --git a/src/worktree.c b/src/worktree.c
new file mode 100644
index 000000000..5a814a2ec
--- /dev/null
+++ b/src/worktree.c
@@ -0,0 +1,557 @@
+/*
+ * 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 "worktree.h"
+
+#include "git2/branch.h"
+#include "git2/commit.h"
+#include "git2/worktree.h"
+
+#include "repository.h"
+
+static bool is_worktree_dir(const char *dir)
+{
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ if (git_buf_sets(&buf, dir) < 0)
+ return -1;
+
+ error = git_path_contains_file(&buf, "commondir")
+ && git_path_contains_file(&buf, "gitdir")
+ && git_path_contains_file(&buf, "HEAD");
+
+ git_buf_free(&buf);
+ return error;
+}
+
+int git_worktree_list(git_strarray *wts, git_repository *repo)
+{
+ git_vector worktrees = GIT_VECTOR_INIT;
+ git_buf path = GIT_BUF_INIT;
+ char *worktree;
+ unsigned i, len;
+ int error;
+
+ assert(wts && repo);
+
+ wts->count = 0;
+ wts->strings = NULL;
+
+ if ((error = git_buf_printf(&path, "%s/worktrees/", repo->commondir)) < 0)
+ goto exit;
+ if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr))
+ goto exit;
+ if ((error = git_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0)
+ goto exit;
+
+ len = path.size;
+
+ git_vector_foreach(&worktrees, i, worktree) {
+ git_buf_truncate(&path, len);
+ git_buf_puts(&path, worktree);
+
+ if (!is_worktree_dir(path.ptr)) {
+ git_vector_remove(&worktrees, i);
+ git__free(worktree);
+ }
+ }
+
+ wts->strings = (char **)git_vector_detach(&wts->count, NULL, &worktrees);
+
+exit:
+ git_buf_free(&path);
+
+ return error;
+}
+
+char *git_worktree__read_link(const char *base, const char *file)
+{
+ git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+
+ assert(base && file);
+
+ if (git_buf_joinpath(&path, base, file) < 0)
+ goto err;
+ if (git_futils_readbuffer(&buf, path.ptr) < 0)
+ goto err;
+ git_buf_free(&path);
+
+ git_buf_rtrim(&buf);
+
+ if (!git_path_is_relative(buf.ptr))
+ return git_buf_detach(&buf);
+
+ if (git_buf_sets(&path, base) < 0)
+ goto err;
+ if (git_path_apply_relative(&path, buf.ptr) < 0)
+ goto err;
+ git_buf_free(&buf);
+
+ return git_buf_detach(&path);
+
+err:
+ git_buf_free(&buf);
+ git_buf_free(&path);
+
+ return NULL;
+}
+
+static int write_wtfile(const char *base, const char *file, const git_buf *buf)
+{
+ git_buf path = GIT_BUF_INIT;
+ int err;
+
+ assert(base && file && buf);
+
+ if ((err = git_buf_joinpath(&path, base, file)) < 0)
+ goto out;
+
+ if ((err = git_futils_writebuffer(buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
+ goto out;
+
+out:
+ git_buf_free(&path);
+
+ return err;
+}
+
+static int open_worktree_dir(git_worktree **out, const char *parent, const char *dir, const char *name)
+{
+ git_buf gitdir = GIT_BUF_INIT;
+ git_worktree *wt = NULL;
+ int error = 0;
+
+ if (!is_worktree_dir(dir)) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt = git__calloc(1, sizeof(struct git_repository))) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt->name = git__strdup(name)) == NULL
+ || (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL
+ || (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL
+ || (wt->parent_path = git__strdup(parent)) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if ((error = git_path_prettify_dir(&gitdir, dir, NULL)) < 0)
+ goto out;
+ wt->gitdir_path = git_buf_detach(&gitdir);
+
+ wt->locked = !!git_worktree_is_locked(NULL, wt);
+
+ *out = wt;
+
+out:
+ if (error)
+ git_worktree_free(wt);
+ git_buf_free(&gitdir);
+
+ return error;
+}
+
+int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_worktree *wt = NULL;
+ int error;
+
+ assert(repo && name);
+
+ *out = NULL;
+
+ if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
+ goto out;
+
+ if ((error = (open_worktree_dir(out, git_repository_workdir(repo), path.ptr, name))) < 0)
+ goto out;
+
+out:
+ git_buf_free(&path);
+
+ if (error)
+ git_worktree_free(wt);
+
+ return error;
+}
+
+int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
+{
+ git_buf parent = GIT_BUF_INIT;
+ const char *gitdir, *commondir;
+ char *name = NULL;
+ int error = 0;
+
+ if (!git_repository_is_worktree(repo)) {
+ giterr_set(GITERR_WORKTREE, "cannot open worktree of a non-worktree repo");
+ error = -1;
+ goto out;
+ }
+
+ gitdir = git_repository_path(repo);
+ commondir = git_repository_commondir(repo);
+
+ if ((error = git_path_prettify_dir(&parent, "..", commondir)) < 0)
+ goto out;
+
+ /* The name is defined by the last component in '.git/worktree/%s' */
+ name = git_path_basename(gitdir);
+
+ if ((error = open_worktree_dir(out, parent.ptr, gitdir, name)) < 0)
+ goto out;
+
+out:
+ git__free(name);
+ git_buf_free(&parent);
+
+ return error;
+}
+
+void git_worktree_free(git_worktree *wt)
+{
+ if (!wt)
+ return;
+
+ git__free(wt->commondir_path);
+ git__free(wt->gitlink_path);
+ git__free(wt->gitdir_path);
+ git__free(wt->parent_path);
+ git__free(wt->name);
+ git__free(wt);
+}
+
+int git_worktree_validate(const git_worktree *wt)
+{
+ git_buf buf = GIT_BUF_INIT;
+ int err = 0;
+
+ assert(wt);
+
+ git_buf_puts(&buf, wt->gitdir_path);
+ if (!is_worktree_dir(buf.ptr)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree gitdir ('%s') is not valid",
+ wt->gitlink_path);
+ err = -1;
+ goto out;
+ }
+
+ if (!git_path_exists(wt->parent_path)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree parent directory ('%s') does not exist ",
+ wt->parent_path);
+ err = -2;
+ goto out;
+ }
+
+ if (!git_path_exists(wt->commondir_path)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree common directory ('%s') does not exist ",
+ wt->commondir_path);
+ err = -3;
+ goto out;
+ }
+
+out:
+ git_buf_free(&buf);
+
+ return err;
+}
+
+int git_worktree_add_init_options(git_worktree_add_options *opts,
+ unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
+ git_worktree_add_options, GIT_WORKTREE_ADD_OPTIONS_INIT);
+ return 0;
+}
+
+int git_worktree_add(git_worktree **out, git_repository *repo,
+ const char *name, const char *worktree,
+ const git_worktree_add_options *opts)
+{
+ git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+ git_reference *ref = NULL, *head = NULL;
+ git_commit *commit = NULL;
+ git_repository *wt = NULL;
+ git_checkout_options coopts = GIT_CHECKOUT_OPTIONS_INIT;
+ git_worktree_add_options wtopts = GIT_WORKTREE_ADD_OPTIONS_INIT;
+ int err;
+
+ GITERR_CHECK_VERSION(
+ opts, GIT_WORKTREE_ADD_OPTIONS_VERSION, "git_worktree_add_options");
+
+ if (opts)
+ memcpy(&wtopts, opts, sizeof(wtopts));
+
+ assert(out && repo && name && worktree);
+
+ *out = NULL;
+
+ /* Create gitdir directory ".git/worktrees/<name>" */
+ if ((err = git_buf_joinpath(&gitdir, repo->commondir, "worktrees")) < 0)
+ goto out;
+ if (!git_path_exists(gitdir.ptr))
+ if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
+ goto out;
+ if ((err = git_buf_joinpath(&gitdir, gitdir.ptr, name)) < 0)
+ goto out;
+ if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
+ goto out;
+ if ((err = git_path_prettify_dir(&gitdir, gitdir.ptr, NULL)) < 0)
+ goto out;
+
+ /* Create worktree work dir */
+ if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0)
+ goto out;
+ if ((err = git_path_prettify_dir(&wddir, worktree, NULL)) < 0)
+ goto out;
+
+ if (wtopts.lock) {
+ int fd;
+
+ if ((err = git_buf_joinpath(&buf, gitdir.ptr, "locked")) < 0)
+ goto out;
+
+ if ((fd = p_creat(buf.ptr, 0644)) < 0) {
+ err = fd;
+ goto out;
+ }
+
+ p_close(fd);
+ git_buf_clear(&buf);
+ }
+
+ /* Create worktree .git file */
+ if ((err = git_buf_printf(&buf, "gitdir: %s\n", gitdir.ptr)) < 0)
+ goto out;
+ if ((err = write_wtfile(wddir.ptr, ".git", &buf)) < 0)
+ goto out;
+
+ /* Create gitdir files */
+ if ((err = git_path_prettify_dir(&buf, repo->commondir, NULL) < 0)
+ || (err = git_buf_putc(&buf, '\n')) < 0
+ || (err = write_wtfile(gitdir.ptr, "commondir", &buf)) < 0)
+ goto out;
+ if ((err = git_buf_joinpath(&buf, wddir.ptr, ".git")) < 0
+ || (err = git_buf_putc(&buf, '\n')) < 0
+ || (err = write_wtfile(gitdir.ptr, "gitdir", &buf)) < 0)
+ goto out;
+
+ /* Create new branch */
+ if ((err = git_repository_head(&head, repo)) < 0)
+ goto out;
+ if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0)
+ goto out;
+ if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0)
+ goto out;
+
+ /* Set worktree's HEAD */
+ if ((err = git_repository_create_head(gitdir.ptr, git_reference_name(ref))) < 0)
+ goto out;
+ if ((err = git_repository_open(&wt, wddir.ptr)) < 0)
+ goto out;
+
+ /* Checkout worktree's HEAD */
+ coopts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ if ((err = git_checkout_head(wt, &coopts)) < 0)
+ goto out;
+
+ /* Load result */
+ if ((err = git_worktree_lookup(out, repo, name)) < 0)
+ goto out;
+
+out:
+ git_buf_free(&gitdir);
+ git_buf_free(&wddir);
+ git_buf_free(&buf);
+ git_reference_free(ref);
+ git_reference_free(head);
+ git_commit_free(commit);
+ git_repository_free(wt);
+
+ return err;
+}
+
+int git_worktree_lock(git_worktree *wt, char *creason)
+{
+ git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
+ int err;
+
+ assert(wt);
+
+ if ((err = git_worktree_is_locked(NULL, wt)) < 0)
+ goto out;
+
+ if ((err = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+ goto out;
+
+ if (creason)
+ git_buf_attach_notowned(&buf, creason, strlen(creason));
+
+ if ((err = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
+ goto out;
+
+ wt->locked = 1;
+
+out:
+ git_buf_free(&path);
+
+ return err;
+}
+
+int git_worktree_unlock(git_worktree *wt)
+{
+ git_buf path = GIT_BUF_INIT;
+
+ assert(wt);
+
+ if (!git_worktree_is_locked(NULL, wt))
+ return 0;
+
+ if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
+ return -1;
+
+ if (p_unlink(path.ptr) != 0) {
+ git_buf_free(&path);
+ return -1;
+ }
+
+ wt->locked = 0;
+
+ git_buf_free(&path);
+
+ return 0;
+}
+
+int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
+{
+ git_buf path = GIT_BUF_INIT;
+ int ret;
+
+ assert(wt);
+
+ if (reason)
+ git_buf_clear(reason);
+
+ if ((ret = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
+ goto out;
+ if ((ret = git_path_exists(path.ptr)) && reason)
+ git_futils_readbuffer(reason, path.ptr);
+
+out:
+ git_buf_free(&path);
+
+ return ret;
+}
+
+int git_worktree_prune_init_options(
+ git_worktree_prune_options *opts,
+ unsigned int version)
+{
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
+ git_worktree_prune_options, GIT_WORKTREE_PRUNE_OPTIONS_INIT);
+ return 0;
+}
+
+int git_worktree_is_prunable(git_worktree *wt,
+ git_worktree_prune_options *opts)
+{
+ git_buf reason = GIT_BUF_INIT;
+ git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
+
+ GITERR_CHECK_VERSION(
+ opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
+ "git_worktree_prune_options");
+
+ if (opts)
+ memcpy(&popts, opts, sizeof(popts));
+
+ if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
+ git_worktree_is_locked(&reason, wt))
+ {
+ if (!reason.size)
+ git_buf_attach_notowned(&reason, "no reason given", 15);
+ giterr_set(GITERR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr);
+ git_buf_free(&reason);
+
+ return 0;
+ }
+
+ if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
+ git_worktree_validate(wt) == 0)
+ {
+ giterr_set(GITERR_WORKTREE, "Not pruning valid working tree");
+ return 0;
+ }
+
+ return 1;
+}
+
+int git_worktree_prune(git_worktree *wt,
+ git_worktree_prune_options *opts)
+{
+ git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
+ git_buf path = GIT_BUF_INIT;
+ char *wtpath;
+ int err;
+
+ GITERR_CHECK_VERSION(
+ opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
+ "git_worktree_prune_options");
+
+ if (opts)
+ memcpy(&popts, opts, sizeof(popts));
+
+ if (!git_worktree_is_prunable(wt, &popts)) {
+ err = -1;
+ goto out;
+ }
+
+ /* Delete gitdir in parent repository */
+ if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->commondir_path, wt->name)) < 0)
+ goto out;
+ if (!git_path_exists(path.ptr))
+ {
+ giterr_set(GITERR_WORKTREE, "Worktree gitdir '%s' does not exist", path.ptr);
+ err = -1;
+ goto out;
+ }
+ if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
+ goto out;
+
+ /* Skip deletion of the actual working tree if it does
+ * not exist or deletion was not requested */
+ if ((popts.flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
+ !git_path_exists(wt->gitlink_path))
+ {
+ goto out;
+ }
+
+ if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL)
+ goto out;
+ git_buf_attach(&path, wtpath, 0);
+ if (!git_path_exists(path.ptr))
+ {
+ giterr_set(GITERR_WORKTREE, "Working tree '%s' does not exist", path.ptr);
+ err = -1;
+ goto out;
+ }
+ if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
+ goto out;
+
+out:
+ git_buf_free(&path);
+
+ return err;
+}
diff --git a/src/worktree.h b/src/worktree.h
new file mode 100644
index 000000000..52d13cced
--- /dev/null
+++ b/src/worktree.h
@@ -0,0 +1,37 @@
+/*
+ * 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_worktree_h__
+#define INCLUDE_worktree_h__
+
+#include "common.h"
+
+#include "git2/common.h"
+#include "git2/worktree.h"
+
+struct git_worktree {
+ /* Name of the working tree. This is the name of the
+ * containing directory in the `$PARENT/.git/worktrees/`
+ * directory. */
+ char *name;
+
+ /* Path to the .git file in the working tree's repository */
+ char *gitlink_path;
+ /* Path to the .git directory inside the parent's
+ * worktrees directory */
+ char *gitdir_path;
+ /* Path to the common directory contained in the parent
+ * repository */
+ char *commondir_path;
+ /* Path to the parent's working directory */
+ char *parent_path;
+
+ int locked:1;
+};
+
+char *git_worktree__read_link(const char *base, const char *file);
+
+#endif
diff --git a/src/zstream.c b/src/zstream.c
index d9ad4ca89..4895bdb16 100644
--- a/src/zstream.c
+++ b/src/zstream.c
@@ -5,9 +5,10 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "zstream.h"
+
#include <zlib.h>
-#include "zstream.h"
#include "buffer.h"
#define ZSTREAM_BUFFER_SIZE (1024 * 1024)
@@ -21,9 +22,9 @@ static int zstream_seterr(git_zstream *zs)
if (zs->zerr == Z_MEM_ERROR)
giterr_set_oom();
else if (zs->z.msg)
- giterr_set(GITERR_ZLIB, zs->z.msg);
+ giterr_set_str(GITERR_ZLIB, zs->z.msg);
else
- giterr_set(GITERR_ZLIB, "Unknown compression error");
+ giterr_set(GITERR_ZLIB, "unknown compression error");
return -1;
}
diff --git a/src/zstream.h b/src/zstream.h
index f0006d32e..fcc4a3148 100644
--- a/src/zstream.h
+++ b/src/zstream.h
@@ -7,9 +7,10 @@
#ifndef INCLUDE_zstream_h__
#define INCLUDE_zstream_h__
+#include "common.h"
+
#include <zlib.h>
-#include "common.h"
#include "buffer.h"
typedef enum {