Commit c3b7ace9 by Edward Thomson

refactor: make util an object library

Instead of simply including the utility files directly, make them a
cmake object library for easy reusability between other projects within
libgit2.

Now the top-level `src` is responsible for platform selection, while the
next-level `libgit2` and `util` configurations are responsible for
identifying what objects they include.
parent ef4ab298
......@@ -21,9 +21,6 @@ endif()
if(USE_SHA1 STREQUAL "CollisionDetection")
set(GIT_SHA1_COLLISIONDETECT 1)
add_definitions(-DSHA1DC_NO_STANDARD_INCLUDES=1)
add_definitions(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
add_definitions(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
elseif(USE_SHA1 STREQUAL "OpenSSL")
# OPENSSL_FOUND should already be set, we're checking USE_HTTPS
......
# The main libgit2 source tree: this CMakeLists.txt identifies platform
# support and includes the subprojects that make up core libgit2 support.
#
# Optional build configuration settings
#
if(DEPRECATE_HARD)
add_definitions(-DGIT_DEPRECATE_HARD)
endif()
if(USE_LEAK_CHECKER STREQUAL "valgrind")
add_definitions(-DVALGRIND)
endif()
#
# Optional debugging functionality
#
if(DEBUG_POOL)
set(GIT_DEBUG_POOL 1)
endif()
add_feature_info(debugpool GIT_DEBUG_POOL "debug pool allocator")
if(DEBUG_STRICT_ALLOC)
set(GIT_DEBUG_STRICT_ALLOC 1)
endif()
add_feature_info(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
if(DEBUG_STRICT_OPEN)
set(GIT_DEBUG_STRICT_OPEN 1)
endif()
add_feature_info(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
#
# Optional feature enablement
#
include(SelectGSSAPI)
include(SelectHTTPSBackend)
include(SelectHashes)
include(SelectHTTPParser)
include(SelectRegex)
include(SelectSSH)
include(SelectWinHTTP)
include(SelectZlib)
#
# Platform support
#
# futimes/futimens
if(HAVE_FUTIMENS)
set(GIT_USE_FUTIMENS 1)
endif ()
add_feature_info(futimens GIT_USE_FUTIMENS "futimens support")
# qsort
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" GIT_QSORT_R_BSD)
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
"" "stdlib.h" GIT_QSORT_R_GNU)
check_function_exists(qsort_s GIT_QSORT_S)
# 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()
# nanosecond mtime/ctime support
if(USE_NSEC)
set(GIT_USE_NSEC 1)
endif()
# high-resolution stat support
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()
# realtime support
check_library_exists(rt clock_gettime "time.h" NEED_LIBRT)
if(NEED_LIBRT)
list(APPEND LIBGIT2_SYSTEM_LIBS rt)
list(APPEND LIBGIT2_PC_LIBS "-lrt")
endif()
# platform libraries
if(WIN32)
list(APPEND LIBGIT2_SYSTEM_LIBS ws2_32)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
list(APPEND LIBGIT2_SYSTEM_LIBS socket nsl)
list(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Haiku")
list(APPEND LIBGIT2_SYSTEM_LIBS network)
list(APPEND LIBGIT2_PC_LIBS "-lnetwork")
endif()
if(AMIGA)
add_definitions(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
endif()
# threads
if(USE_THREADS)
if(NOT WIN32)
find_package(Threads REQUIRED)
list(APPEND LIBGIT2_SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
list(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
endif()
set(GIT_THREADS 1)
endif()
add_feature_info(threadsafe USE_THREADS "threadsafe support")
#
# Optional bundled features
#
# ntlmclient
if(USE_NTLMCLIENT)
set(GIT_NTLM 1)
add_subdirectory("${libgit2_SOURCE_DIR}/deps/ntlmclient" "${libgit2_BINARY_DIR}/deps/ntlmclient")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${libgit2_SOURCE_DIR}/deps/ntlmclient")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$<TARGET_OBJECTS:ntlmclient>")
endif()
add_feature_info(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
#
# Optional external dependencies
# iconv
if(USE_ICONV)
find_package(Iconv)
endif()
if(ICONV_FOUND)
set(GIT_USE_ICONV 1)
list(APPEND LIBGIT2_SYSTEM_INCLUDES ${ICONV_INCLUDE_DIR})
list(APPEND LIBGIT2_SYSTEM_LIBS ${ICONV_LIBRARIES})
list(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
endif()
add_feature_info(iconv GIT_USE_ICONV "iconv encoding conversion support")
#
# Configure support
#
configure_file(features.h.in git2/sys/features.h)
#
# Include child projects
#
add_subdirectory(libgit2)
add_subdirectory(util)
# re-export these to the root so that peer projects (tests, fuzzers,
# examples) can use them
......
# libgit2 sources
This is the source that makes up the core of libgit2 and its related
projects.
* `libgit2`
This is the libgit2 project, a cross-platform, linkable library
implementation of Git that you can use in your application.
* `util`
A shared utility library for these projects.
......@@ -2,94 +2,99 @@ add_library(git2internal OBJECT)
set_target_properties(git2internal PROPERTIES C_STANDARD 90)
set_target_properties(git2internal PROPERTIES C_EXTENSIONS OFF)
if(DEPRECATE_HARD)
add_definitions(-DGIT_DEPRECATE_HARD)
endif()
if(DEBUG_POOL)
set(GIT_DEBUG_POOL 1)
endif()
add_feature_info(debugpool GIT_DEBUG_POOL "debug pool allocator")
if(DEBUG_STRICT_ALLOC)
set(GIT_DEBUG_STRICT_ALLOC 1)
endif()
add_feature_info(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
if(DEBUG_STRICT_OPEN)
set(GIT_DEBUG_STRICT_OPEN 1)
endif()
add_feature_info(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open")
include(PkgBuildConfig)
include(SanitizeBool)
# 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}"
"${PROJECT_BINARY_DIR}/src"
"${PROJECT_SOURCE_DIR}/src/libgit2"
"${PROJECT_SOURCE_DIR}/src/util"
"${PROJECT_SOURCE_DIR}/include")
if(HAVE_FUTIMENS)
set(GIT_USE_FUTIMENS 1)
endif ()
add_feature_info(futimens GIT_USE_FUTIMENS "futimens support")
if(WIN32 AND EMBED_SSH_PATH)
file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
list(SORT SRC_SSH)
target_sources(git2internal PRIVATE ${SRC_SSH})
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
"" "stdlib.h" GIT_QSORT_R_BSD)
list(APPEND LIBGIT2_SYSTEM_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()
check_prototype_definition(qsort_r
"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
"" "stdlib.h" GIT_QSORT_R_GNU)
<<<<<<< HEAD
include(SelectHTTPSBackend)
include(SelectHashes)
include(SelectHTTPParser)
include(SelectRegex)
include(SelectSSH)
include(SelectWinHTTP)
include(SelectZlib)
check_function_exists(qsort_s GIT_QSORT_S)
# Find required dependencies
if(USE_SHA1 STREQUAL "CollisionDetection")
file(GLOB SRC_SHA1 hash/sha1/collisiondetect.* hash/sha1/sha1dc/*)
elseif(USE_SHA1 STREQUAL "OpenSSL")
file(GLOB SRC_SHA1 hash/sha1/openssl.*)
elseif(USE_SHA1 STREQUAL "CommonCrypto")
file(GLOB SRC_SHA1 hash/sha1/common_crypto.*)
elseif(USE_SHA1 STREQUAL "mbedTLS")
file(GLOB SRC_SHA1 hash/sha1/mbedtls.*)
elseif(USE_SHA1 STREQUAL "Win32")
file(GLOB SRC_SHA1 hash/sha1/win32.*)
elseif(USE_SHA1 STREQUAL "Generic")
file(GLOB SRC_SHA1 hash/sha1/generic.*)
endif()
list(APPEND SRC_SHA1 "hash/sha1.h")
target_sources(git2internal PRIVATE ${SRC_SHA1})
if(WIN32)
list(APPEND LIBGIT2_SYSTEM_LIBS ws2_32)
elseif(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
list(APPEND LIBGIT2_SYSTEM_LIBS socket nsl)
list(APPEND LIBGIT2_PC_LIBS "-lsocket" "-lnsl")
elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku")
list(APPEND LIBGIT2_SYSTEM_LIBS network)
list(APPEND LIBGIT2_PC_LIBS "-lnetwork")
# Optional external dependency: ntlmclient
if(USE_NTLMCLIENT)
set(GIT_NTLM 1)
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/ntlmclient" "${PROJECT_BINARY_DIR}/deps/ntlmclient")
list(APPEND LIBGIT2_DEPENDENCY_INCLUDES "${PROJECT_SOURCE_DIR}/deps/ntlmclient")
list(APPEND LIBGIT2_DEPENDENCY_OBJECTS "$<TARGET_OBJECTS:ntlmclient>")
endif()
add_feature_info(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
check_library_exists(rt clock_gettime "time.h" NEED_LIBRT)
if(NEED_LIBRT)
list(APPEND LIBGIT2_SYSTEM_LIBS rt)
list(APPEND LIBGIT2_PC_LIBS "-lrt")
# Optional external dependency: GSSAPI
include(SelectGSSAPI)
# Optional external dependency: iconv
if(USE_ICONV)
find_package(Iconv)
endif()
if(ICONV_FOUND)
set(GIT_USE_ICONV 1)
list(APPEND LIBGIT2_SYSTEM_INCLUDES ${ICONV_INCLUDE_DIR})
list(APPEND LIBGIT2_SYSTEM_LIBS ${ICONV_LIBRARIES})
list(APPEND LIBGIT2_PC_LIBS ${ICONV_LIBRARIES})
endif()
add_feature_info(iconv GIT_USE_ICONV "iconv encoding conversion support")
if(USE_THREADS)
list(APPEND LIBGIT2_SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
list(APPEND LIBGIT2_PC_LIBS ${CMAKE_THREAD_LIBS_INIT})
endif()
add_feature_info(threadsafe USE_THREADS "threadsafe support")
if(NOT WIN32)
find_package(Threads REQUIRED)
endif()
set(GIT_THREADS 1)
endif()
if(WIN32 AND EMBED_SSH_PATH)
file(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c")
list(SORT SRC_SSH)
target_sources(git2internal PRIVATE ${SRC_SSH})
if(USE_NSEC)
set(GIT_USE_NSEC 1)
endif()
list(APPEND LIBGIT2_SYSTEM_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)
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()
target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
||||||| parent of a930dafb4 (refactor: make util an object library)
include(SelectHTTPSBackend)
include(SelectHashes)
include(SelectHTTPParser)
......@@ -163,6 +168,8 @@ endif()
target_compile_definitions(git2internal PRIVATE _FILE_OFFSET_BITS=64)
=======
>>>>>>> a930dafb4 (refactor: make util an object library)
# Collect sourcefiles
file(GLOB SRC_H
"${PROJECT_SOURCE_DIR}/include/git2.h"
......@@ -171,33 +178,18 @@ file(GLOB SRC_H
list(SORT SRC_H)
target_sources(git2internal PRIVATE ${SRC_H})
# On Windows use specific platform sources
if(WIN32 AND NOT CYGWIN)
set(WIN_RC "win32/git2.rc")
file(GLOB SRC_OS win32/*.c win32/*.h)
list(SORT SRC_OS)
target_sources(git2internal PRIVATE ${SRC_OS})
elseif(AMIGA)
target_compile_definitions(git2internal PRIVATE NO_ADDRINFO NO_READDIR_R NO_MMAP)
else()
file(GLOB SRC_OS unix/*.c unix/*.h)
list(SORT SRC_OS)
target_sources(git2internal PRIVATE ${SRC_OS})
endif()
if(USE_LEAK_CHECKER STREQUAL "valgrind")
target_compile_definitions(git2internal PRIVATE VALGRIND)
endif()
file(GLOB SRC_GIT2 *.c *.h
allocators/*.c allocators/*.h
streams/*.c streams/*.h
transports/*.c transports/*.h
xdiff/*.c xdiff/*.h)
list(SORT SRC_GIT2)
target_sources(git2internal PRIVATE ${SRC_GIT2})
if(WIN32 AND NOT CYGWIN)
# Add resource information on Windows
set(SRC_RC "git2.rc")
endif()
if(APPLE)
# The old Secure Transport API has been deprecated in macOS 10.15.
set_source_files_properties(streams/stransport.c PROPERTIES COMPILE_FLAGS -Wno-deprecated)
......@@ -220,21 +212,8 @@ else()
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
endif()
# 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)
ide_split_sources(git2internal)
list(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:git2internal> ${LIBGIT2_DEPENDENCY_OBJECTS})
list(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:util> $<TARGET_OBJECTS:git2internal> ${LIBGIT2_DEPENDENCY_OBJECTS})
target_include_directories(git2internal PRIVATE ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_include_directories(git2internal SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
......@@ -254,7 +233,7 @@ if(XCODE_VERSION)
endif()
# Compile and link libgit2
add_library(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
add_library(git2 ${SRC_RC} ${LIBGIT2_OBJECTS})
target_link_libraries(git2 ${LIBGIT2_SYSTEM_LIBS})
set_target_properties(git2 PROPERTIES C_STANDARD 90)
......
......@@ -101,7 +101,7 @@ static int write_file_stream(
git_oid *id, git_odb *odb, const char *path, git_object_size_t file_size)
{
int fd, error;
char buffer[FILEIO_BUFSIZE];
char buffer[GIT_BUFSIZE_FILEIO];
git_odb_stream *stream = NULL;
ssize_t read_len = -1;
git_object_size_t written = 0;
......
......@@ -7,136 +7,31 @@
#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"
/** Declare a function as always inlined. */
#if defined(_MSC_VER)
# define GIT_INLINE(type) static __inline type
#elif defined(__GNUC__)
# define GIT_INLINE(type) static __inline__ type
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define GIT_INLINE(type) static inline type
#else
# define GIT_INLINE(type) static type
#endif
/** Support for gcc/clang __has_builtin intrinsic */
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
/**
* Declare that a function's return value must be used.
*
* Used mostly to guard against potential silent bugs at runtime. This is
* recommended to be added to functions that:
*
* - Allocate / reallocate memory. This prevents memory leaks or errors where
* buffers are expected to have grown to a certain size, but could not be
* resized.
* - Acquire locks. When a lock cannot be acquired, that will almost certainly
* cause a data race / undefined behavior.
*/
#if defined(__GNUC__)
# define GIT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define GIT_WARN_UNUSED_RESULT
#endif
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef GIT_WIN32
# include <io.h>
# include <direct.h>
# include <winsock2.h>
# include <windows.h>
# include <ws2tcpip.h>
# include "win32/msvc-compat.h"
# include "win32/mingw-compat.h"
# include "win32/w32_common.h"
# include "win32/win32-compat.h"
# include "win32/error.h"
# include "win32/version.h"
# ifdef GIT_THREADS
# include "win32/thread.h"
# endif
#else
# include <unistd.h>
# include <strings.h>
# ifdef GIT_THREADS
# include <pthread.h>
# include <sched.h>
# endif
#define GIT_LIBGIT2_CALL
#define GIT_SYSTEM_CALL
#ifdef GIT_USE_STAT_ATIMESPEC
# define st_atim st_atimespec
# define st_ctim st_ctimespec
# define st_mtim st_mtimespec
#endif
# include <arpa/inet.h>
#endif
#include "git2/types.h"
#include "git2/errors.h"
#include "git2_util.h"
#include "errors.h"
#include "thread.h"
#include "integer.h"
#include "assert_safe.h"
#include "utf8.h"
/*
* Include the declarations for deprecated functions; this ensures
* that they're decorated with the proper extern/visibility attributes.
*/
* Include the declarations for deprecated functions; this ensures
* that they're decorated with the proper extern/visibility attributes.
*/
#include "git2/deprecated.h"
#include "posix.h"
#define DEFAULT_BUFSIZE 65536
#define FILEIO_BUFSIZE DEFAULT_BUFSIZE
#define FILTERIO_BUFSIZE DEFAULT_BUFSIZE
#define NETIO_BUFSIZE DEFAULT_BUFSIZE
/**
* Check a pointer allocation result, returning -1 if it failed.
*/
#define GIT_ERROR_CHECK_ALLOC(ptr) do { \
if ((ptr) == NULL) { return -1; } \
} while(0)
/**
* Check a string buffer allocation result, returning -1 if it failed.
* Initialize a structure with a version.
*/
#define GIT_ERROR_CHECK_ALLOC_STR(buf) do { \
if ((void *)(buf) == NULL || git_str_oom(buf)) { return -1; } \
} while(0)
GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
{
memset(structure, 0, len);
*((int*)structure) = version;
}
#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
/**
* Check a return value and propagate result if non-zero.
*/
#define GIT_ERROR_CHECK_ERROR(code) \
do { int _err = (code); if (_err) return _err; } while (0)
#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \
TYPE _tmpl = TPL; \
GIT_ERROR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \
memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
/**
* Check a versioned structure for validity
......@@ -157,58 +52,4 @@ GIT_INLINE(int) git_error__check_version(const void *structure, unsigned int exp
}
#define GIT_ERROR_CHECK_VERSION(S,V,N) if (git_error__check_version(S,V,N) < 0) return -1
/**
* Initialize a structure with a version.
*/
GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
{
memset(structure, 0, len);
*((int*)structure) = version;
}
#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
#define GIT_INIT_STRUCTURE_FROM_TEMPLATE(PTR,VERSION,TYPE,TPL) do { \
TYPE _tmpl = TPL; \
GIT_ERROR_CHECK_VERSION(&(VERSION), _tmpl.version, #TYPE); \
memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_ADD_SIZET_OVERFLOW(out, one, two) \
(git__add_sizet_overflow(out, one, two) ? (git_error_set_oom(), 1) : 0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize) \
(git__multiply_sizet_overflow(out, nelem, elsize) ? (git_error_set_oom(), 1) : 0)
/** Check for additive overflow, failing if it would occur. */
#define GIT_ERROR_CHECK_ALLOC_ADD(out, one, two) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD3(out, one, two, three) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD4(out, one, two, three, four) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD5(out, one, two, three, four, five) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), five)) { return -1; }
/** Check for multiplicative overflow, failing if it would occur. */
#define GIT_ERROR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }
/* NOTE: other git_error functions are in the public errors.h header file */
/* Forward declare git_str */
typedef struct git_str git_str;
#include "util.h"
#endif
......@@ -11,6 +11,7 @@
#include "diff.h"
#include "diff_driver.h"
#include "patch_generate.h"
#include "utf8.h"
static int git_xdiff_scan_int(const char **str, int *value)
{
......
......@@ -1085,7 +1085,7 @@ int git_filter_list_stream_file(
const char *path,
git_writestream *target)
{
char buf[FILTERIO_BUFSIZE];
char buf[GIT_BUFSIZE_FILTERIO];
git_str abspath = GIT_STR_INIT;
const char *base = repo ? git_repository_workdir(repo) : NULL;
git_vector filter_streams = GIT_VECTOR_INIT;
......
#include <winver.h>
#include "../../../include/git2/version.h"
#include "../../include/git2/version.h"
#ifndef LIBGIT2_FILENAME
# ifdef __GNUC__
......
......@@ -12,7 +12,6 @@
#include "posix.h"
#include "str.h"
#include "http_parser.h"
#include "runtime.h"
int gitno_recv(gitno_buffer *buf)
......
......@@ -198,7 +198,7 @@ void git_odb_object_free(git_odb_object *object)
int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
{
size_t hdr_len;
char hdr[64], buffer[FILEIO_BUFSIZE];
char hdr[64], buffer[GIT_BUFSIZE_FILEIO];
git_hash_ctx ctx;
ssize_t read_len = 0;
int error = 0;
......
......@@ -9,6 +9,7 @@
#include "repository.h"
#include "fs_path.h"
#include "utf8.h"
typedef struct {
git_repository *repo;
......
#ifndef INCLUDE_platform_h__
#define INCLUDE_platform_h__
#cmakedefine GIT_DEBUG_POOL 1
#cmakedefine GIT_DEBUG_STRICT_ALLOC 1
#cmakedefine GIT_DEBUG_STRICT_OPEN 1
#cmakedefine GIT_WIN32_LEAKCHECK 1
#cmakedefine GIT_ARCH_64 1
#cmakedefine GIT_ARCH_32 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_QSORT_R_BSD 1
#cmakedefine GIT_USE_QSORT_R_GNU 1
#cmakedefine GIT_USE_QSORT_S 1
#cmakedefine GIT_REGEX_REGCOMP_L 1
#cmakedefine GIT_REGEX_REGCOMP 1
#cmakedefine GIT_REGEX_PCRE 1
#cmakedefine GIT_REGEX_PCRE2 1
#cmakedefine GIT_REGEX_BUILTIN 1
#cmakedefine GIT_SHA1_COLLISIONDETECT 1
#cmakedefine GIT_SHA1_WIN32 1
#cmakedefine GIT_SHA1_COMMON_CRYPTO 1
#cmakedefine GIT_SHA1_OPENSSL 1
#cmakedefine GIT_SHA1_MBEDTLS 1
#endif
# util: a shared library for common utility functions for libgit2 projects
add_library(util OBJECT)
set_target_properties(util PROPERTIES C_STANDARD 90)
set_target_properties(util PROPERTIES C_EXTENSIONS OFF)
set(UTIL_INCLUDES
"${PROJECT_BINARY_DIR}/src"
"${PROJECT_SOURCE_DIR}/src/util"
"${PROJECT_SOURCE_DIR}/include")
file(GLOB UTIL_SRC *.c *.h allocators/*.c allocators/*.h hash/sha1.h)
list(SORT UTIL_SRC)
#
# Platform specific sources
#
if(WIN32 AND NOT CYGWIN)
file(GLOB UTIL_SRC_OS win32/*.c win32/*.h)
list(SORT UTIL_SRC_OS)
elseif(NOT AMIGA)
file(GLOB UTIL_SRC_OS unix/*.c unix/*.h)
list(SORT UTIL_SRC_OS)
endif()
#
# Hash backend selection
#
if(USE_SHA1 STREQUAL "CollisionDetection")
file(GLOB UTIL_SRC_HASH hash/sha1/collisiondetect.* hash/sha1/sha1dc/*)
target_compile_definitions(util PRIVATE SHA1DC_NO_STANDARD_INCLUDES=1)
target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_SHA1_C=\"git2_util.h\")
target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"git2_util.h\")
elseif(USE_SHA1 STREQUAL "OpenSSL")
file(GLOB UTIL_SRC_HASH hash/sha1/openssl.*)
elseif(USE_SHA1 STREQUAL "CommonCrypto")
file(GLOB UTIL_SRC_HASH hash/sha1/common_crypto.*)
elseif(USE_SHA1 STREQUAL "mbedTLS")
file(GLOB UTIL_SRC_HASH hash/sha1/mbedtls.*)
elseif(USE_SHA1 STREQUAL "Win32")
file(GLOB UTIL_SRC_HASH hash/sha1/win32.*)
elseif(USE_SHA1 STREQUAL "Generic")
file(GLOB UTIL_SRC_HASH hash/sha1/generic.*)
else()
message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
endif()
list(SORT UTIL_SRC_HASH)
#
# Build the library
#
target_sources(util PRIVATE ${UTIL_SRC} ${UTIL_SRC_OS} ${UTIL_SRC_HASH})
target_include_directories(util PRIVATE ${UTIL_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include)
target_include_directories(util SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_failalloc_h__
#define INCLUDE_allocators_failalloc_h__
#include "common.h"
#include "git2_util.h"
extern void *git_failalloc_malloc(size_t len, const char *file, int line);
extern void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line);
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_stdalloc_h__
#define INCLUDE_allocators_stdalloc_h__
#include "common.h"
#include "git2_util.h"
#include "alloc.h"
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_allocators_win32_leakcheck_h
#define INCLUDE_allocators_win32_leakcheck_h
#include "common.h"
#include "git2_util.h"
#include "alloc.h"
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_array_h__
#define INCLUDE_array_h__
#include "common.h"
#include "git2_util.h"
/*
* Use this to declare a typesafe resizable array of items, a la:
......
/*
* GIT - The information manager from hell
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* Copyright (C) Linus Torvalds, 2005
* 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_util.h"
#ifndef GIT_WIN32
#include <sys/time.h>
......
......@@ -65,7 +65,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
if ((flags & GIT_FILEBUF_APPEND) && git_fs_path_exists(file->path_original) == true) {
git_file source;
char buffer[FILEIO_BUFSIZE];
char buffer[GIT_BUFSIZE_FILEIO];
ssize_t read_bytes;
int error = 0;
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_filebuf_h__
#define INCLUDE_filebuf_h__
#include "common.h"
#include "git2_util.h"
#include "futils.h"
#include "hash.h"
......
......@@ -7,8 +7,9 @@
#include "fs_path.h"
#include "git2_util.h"
#include "futils.h"
#include "posix.h"
#include "repository.h"
#ifdef GIT_WIN32
#include "win32/posix.h"
#include "win32/w32_buffer.h"
......@@ -21,6 +22,13 @@
#include <stdio.h>
#include <ctype.h>
#define ensure_error_set(code) do { \
const git_error *e = git_error_last(); \
if (!e || !e->message) \
git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, \
"filesystem callback returned %d", code); \
} while(0)
static int dos_drive_prefix_length(const char *path)
{
int i;
......@@ -530,7 +538,7 @@ int git_fs_path_walk_up(
if (!scan) {
error = cb(data, "");
if (error)
git_error_set_after_callback(error);
ensure_error_set(error);
return error;
}
......@@ -543,7 +551,7 @@ int git_fs_path_walk_up(
iter.ptr[scan] = oldc;
if (error) {
git_error_set_after_callback(error);
ensure_error_set(error);
break;
}
......@@ -563,7 +571,7 @@ int git_fs_path_walk_up(
if (!error && stop == 0 && iter.ptr[0] != '/') {
error = cb(data, "");
if (error)
git_error_set_after_callback(error);
ensure_error_set(error);
}
return error;
......@@ -1167,7 +1175,7 @@ int git_fs_path_direach(
/* Only set our own error if the callback did not set one already */
if (error != 0) {
if (!git_error_last())
git_error_set_after_callback(error);
ensure_error_set(error);
break;
}
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_fs_path_h__
#define INCLUDE_fs_path_h__
#include "common.h"
#include "git2_util.h"
#include "posix.h"
#include "str.h"
......
......@@ -856,7 +856,7 @@ int git_futils_fake_symlink(const char *target, const char *path)
static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done)
{
int error = 0;
char buffer[FILEIO_BUFSIZE];
char buffer[GIT_BUFSIZE_FILEIO];
ssize_t len = 0;
while (!error && (len = p_read(ifd, buffer, sizeof(buffer))) > 0)
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_futils_h__
#define INCLUDE_futils_h__
#include "common.h"
#include "git2_util.h"
#include "map.h"
#include "posix.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.
*/
#ifndef INCLUDE_git2_util_h__
#define INCLUDE_git2_util_h__
#ifndef LIBGIT2_NO_FEATURES_H
# include "git2/sys/features.h"
#endif
#include "git2/common.h"
#include "cc-compat.h"
typedef struct git_str git_str;
/** Declare a function as always inlined. */
#if defined(_MSC_VER)
# define GIT_INLINE(type) static __inline type
#elif defined(__GNUC__)
# define GIT_INLINE(type) static __inline__ type
#else
# define GIT_INLINE(type) static type
#endif
/** Support for gcc/clang __has_builtin intrinsic */
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
/**
* Declare that a function's return value must be used.
*
* Used mostly to guard against potential silent bugs at runtime. This is
* recommended to be added to functions that:
*
* - Allocate / reallocate memory. This prevents memory leaks or errors where
* buffers are expected to have grown to a certain size, but could not be
* resized.
* - Acquire locks. When a lock cannot be acquired, that will almost certainly
* cause a data race / undefined behavior.
*/
#if defined(__GNUC__)
# define GIT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define GIT_WARN_UNUSED_RESULT
#endif
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef GIT_WIN32
# include <io.h>
# include <direct.h>
# include <winsock2.h>
# include <windows.h>
# include <ws2tcpip.h>
# include "win32/msvc-compat.h"
# include "win32/mingw-compat.h"
# include "win32/win32-compat.h"
# include "win32/w32_common.h"
# include "win32/version.h"
# include "win32/error.h"
# ifdef GIT_THREADS
# include "win32/thread.h"
# endif
#else
# include <unistd.h>
# include <strings.h>
# ifdef GIT_THREADS
# include <pthread.h>
# include <sched.h>
# endif
#define GIT_LIBGIT2_CALL
#define GIT_SYSTEM_CALL
#ifdef GIT_USE_STAT_ATIMESPEC
# define st_atim st_atimespec
# define st_ctim st_ctimespec
# define st_mtim st_mtimespec
#endif
# include <arpa/inet.h>
#endif
#include "git2/types.h"
#include "git2/errors.h"
#include "thread.h"
#include "integer.h"
#include "assert_safe.h"
#include "posix.h"
#define GIT_BUFSIZE_DEFAULT 65536
#define GIT_BUFSIZE_FILEIO GIT_BUFSIZE_DEFAULT
#define GIT_BUFSIZE_FILTERIO GIT_BUFSIZE_DEFAULT
#define GIT_BUFSIZE_NETIO GIT_BUFSIZE_DEFAULT
/**
* Check a pointer allocation result, returning -1 if it failed.
*/
#define GIT_ERROR_CHECK_ALLOC(ptr) do { \
if ((ptr) == NULL) { return -1; } \
} while(0)
/**
* Check a buffer allocation result, returning -1 if it failed.
*/
#define GIT_ERROR_CHECK_ALLOC_STR(buf) do { \
if ((void *)(buf) == NULL || git_str_oom(buf)) { return -1; } \
} while(0)
/**
* Check a return value and propagate result if non-zero.
*/
#define GIT_ERROR_CHECK_ERROR(code) \
do { int _err = (code); if (_err) return _err; } while (0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_ADD_SIZET_OVERFLOW(out, one, two) \
(git__add_sizet_overflow(out, one, two) ? (git_error_set_oom(), 1) : 0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize) \
(git__multiply_sizet_overflow(out, nelem, elsize) ? (git_error_set_oom(), 1) : 0)
/** Check for additive overflow, failing if it would occur. */
#define GIT_ERROR_CHECK_ALLOC_ADD(out, one, two) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD3(out, one, two, three) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD4(out, one, two, three, four) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four)) { return -1; }
#define GIT_ERROR_CHECK_ALLOC_ADD5(out, one, two, three, four, five) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), three) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), four) || \
GIT_ADD_SIZET_OVERFLOW(out, *(out), five)) { return -1; }
/** Check for multiplicative overflow, failing if it would occur. */
#define GIT_ERROR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }
#include "util.h"
#endif
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_hash_h__
#define INCLUDE_hash_h__
#include "common.h"
#include "git2_util.h"
#include "hash/sha1.h"
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_hash_sha1_h__
#define INCLUDE_hash_sha1_h__
#include "common.h"
#include "git2_util.h"
typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_map_h__
#define INCLUDE_map_h__
#include "common.h"
#include "git2_util.h"
/* p_mmap() prot values */
......
......@@ -6,7 +6,6 @@
*/
#include "net.h"
#include "netops.h"
#include <ctype.h>
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_net_h__
#define INCLUDE_net_h__
#include "common.h"
#include "git2_util.h"
typedef struct git_net_url {
char *scheme;
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_pool_h__
#define INCLUDE_pool_h__
#include "common.h"
#include "git2_util.h"
#include "vector.h"
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_posix_h__
#define INCLUDE_posix_h__
#include "common.h"
#include "git2_util.h"
#include <stdlib.h>
#include <fcntl.h>
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_pqueue_h__
#define INCLUDE_pqueue_h__
#include "common.h"
#include "git2_util.h"
#include "vector.h"
......
......@@ -6,7 +6,7 @@ worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
#include "common.h"
#include "git2_util.h"
#include "rand.h"
#include "runtime.h"
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_rand_h__
#define INCLUDE_rand_h__
#include "common.h"
#include "git2_util.h"
/**
* Initialize the random number generation subsystem. This will
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_regexp_h__
#define INCLUDE_regexp_h__
#include "common.h"
#include "git2_util.h"
#if defined(GIT_REGEX_BUILTIN) || defined(GIT_REGEX_PCRE)
# include "pcre.h"
......
......@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "git2_util.h"
#include "runtime.h"
static git_runtime_shutdown_fn shutdown_callback[32];
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_runtime_h__
#define INCLUDE_runtime_h__
#include "common.h"
#include "git2_util.h"
typedef int (*git_runtime_init_fn)(void);
typedef void (*git_runtime_shutdown_fn)(void);
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_sorted_cache_h__
#define INCLUDE_sorted_cache_h__
#include "common.h"
#include "git2_util.h"
#include "util.h"
#include "futils.h"
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_str_h__
#define INCLUDE_str_h__
#include "common.h"
#include "git2_util.h"
struct git_str {
char *ptr;
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_strmap_h__
#define INCLUDE_strmap_h__
#include "common.h"
#include "git2_util.h"
/** A map with C strings as key. */
typedef struct kh_str_s git_strmap;
......
......@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "git2_util.h"
#if !defined(GIT_THREADS)
......
......@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "git2_util.h"
/**
* An array-of-pointers implementation of Python's Timsort
......
......@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "git2_util.h"
#if !defined(GIT_WIN32) && !defined(NO_MMAP)
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_unix_posix_h__
#define INCLUDE_unix_posix_h__
#include "common.h"
#include "git2_util.h"
#include <stdio.h>
#include <dirent.h>
......
......@@ -5,7 +5,7 @@
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "git2_util.h"
#ifndef GIT_WIN32
......
......@@ -7,7 +7,7 @@
#include "utf8.h"
#include "common.h"
#include "git2_util.h"
/*
* git_utf8_iterate is taken from the utf8proc project,
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_utf8_h__
#define INCLUDE_utf8_h__
#include "common.h"
#include "git2_util.h"
/*
* Iterate through an UTF-8 string, yielding one codepoint at a time.
......
......@@ -7,7 +7,7 @@
#include "util.h"
#include "common.h"
#include "git2_util.h"
#ifdef GIT_WIN32
# include "win32/utf-conv.h"
......
......@@ -12,7 +12,7 @@
#endif
#include "str.h"
#include "common.h"
#include "git2_util.h"
#include "strnlen.h"
#include "thread.h"
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_varint_h__
#define INCLUDE_varint_h__
#include "common.h"
#include "git2_util.h"
#include <stdint.h>
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_vector_h__
#define INCLUDE_vector_h__
#include "common.h"
#include "git2_util.h"
typedef int (*git_vector_cmp)(const void *, const void *);
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_wildmatch_h__
#define INCLUDE_wildmatch_h__
#include "common.h"
#include "git2_util.h"
#define WM_CASEFOLD 1
#define WM_PATHNAME 2
......
......@@ -7,7 +7,7 @@
#ifndef INCLUDE_win32_dir_h__
#define INCLUDE_win32_dir_h__
#include "common.h"
#include "git2_util.h"
#include "w32_util.h"
......
......@@ -8,7 +8,7 @@
#ifndef INCLUDE_win32_error_h__
#define INCLUDE_win32_error_h__
#include "common.h"
#include "git2_util.h"
extern char *git_win32_get_error_message(DWORD error_code);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment