Commit 28f087c8 by Vicent Marti

libgit2 v0.21.0

parents 4b0a36e8 1589aa0c
...@@ -3,23 +3,39 @@ ...@@ -3,23 +3,39 @@
language: c language: c
os:
- linux
- osx
compiler: compiler:
- gcc - gcc
- clang - clang
# Settings to try # Settings to try
env: env:
global:
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
matrix:
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release" - OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release"
- OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=ON" - OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=ON"
matrix: matrix:
fast_finish: true
exclude:
- os: osx
compiler: gcc
include: include:
- compiler: i586-mingw32msvc-gcc - compiler: i586-mingw32msvc-gcc
env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON" env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON -DUSE_SSH=OFF"
os: linux
- compiler: gcc
env: COVERITY=1
os: linux
allow_failures:
- env: COVERITY=1
install: install:
- sudo apt-get -qq update - ./script/install-deps-${TRAVIS_OS_NAME}.sh
- sudo apt-get -qq install cmake libssh2-1-dev openssh-client openssh-server
# Run the Build script and tests # Run the Build script and tests
script: script:
...@@ -27,8 +43,8 @@ script: ...@@ -27,8 +43,8 @@ script:
# Run Tests # Run Tests
after_success: after_success:
- sudo apt-get -qq install valgrind - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install valgrind; fi
- valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline - if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
# Only watch the development branch # Only watch the development branch
branches: branches:
......
...@@ -6,6 +6,7 @@ Alexei Sholik ...@@ -6,6 +6,7 @@ Alexei Sholik
Andreas Ericsson Andreas Ericsson
Anton "antong" Gyllenberg Anton "antong" Gyllenberg
Ankur Sethi Ankur Sethi
Arthur Schreiber
Ben Noordhuis Ben Noordhuis
Ben Straub Ben Straub
Benjamin C Meyer Benjamin C Meyer
...@@ -25,6 +26,7 @@ Florian Forster ...@@ -25,6 +26,7 @@ Florian Forster
Holger Weiss Holger Weiss
Ingmar Vanhassel Ingmar Vanhassel
J. David Ibáñez J. David Ibáñez
Jacques Germishuys
Jakob Pfender Jakob Pfender
Jason Penny Jason Penny
Jason R. McNeil Jason R. McNeil
......
...@@ -15,7 +15,10 @@ PROJECT(libgit2 C) ...@@ -15,7 +15,10 @@ PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# Add find modules to the path # Add find modules to the path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
INCLUDE(CheckLibraryExists)
INCLUDE(AddCFlagIfSupported)
# Build options # Build options
# #
...@@ -33,8 +36,9 @@ OPTION( ANDROID "Build for android NDK" OFF ) ...@@ -33,8 +36,9 @@ OPTION( ANDROID "Build for android NDK" OFF )
OPTION( USE_ICONV "Link with and use iconv library" OFF ) OPTION( USE_ICONV "Link with and use iconv library" OFF )
OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
OPTION( VALGRIND "Configure build for valgrind" OFF )
IF(APPLE) IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET( USE_ICONV ON ) SET( USE_ICONV ON )
ENDIF() ENDIF()
...@@ -54,6 +58,10 @@ IF(MSVC) ...@@ -54,6 +58,10 @@ IF(MSVC)
# By default, libgit2 is built with WinHTTP. To use the built-in # By default, libgit2 is built with WinHTTP. To use the built-in
# HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument. # HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument.
OPTION( WINHTTP "Use Win32 WinHTTP routines" ON ) OPTION( WINHTTP "Use Win32 WinHTTP routines" ON )
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
ENDIF() ENDIF()
# This variable will contain the libraries we need to put into # This variable will contain the libraries we need to put into
...@@ -77,17 +85,13 @@ FUNCTION(TARGET_OS_LIBRARIES target) ...@@ -77,17 +85,13 @@ FUNCTION(TARGET_OS_LIBRARIES target)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
TARGET_LINK_LIBRARIES(${target} socket nsl) TARGET_LINK_LIBRARIES(${target} socket nsl)
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lsocket -lnsl" PARENT_SCOPE) SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lsocket -lnsl" PARENT_SCOPE)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") ENDIF()
CHECK_LIBRARY_EXISTS(rt clock_gettime "time.h" NEED_LIBRT)
IF(NEED_LIBRT)
TARGET_LINK_LIBRARIES(${target} rt) TARGET_LINK_LIBRARIES(${target} rt)
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lrt" PARENT_SCOPE) SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lrt" PARENT_SCOPE)
ENDIF() ENDIF()
IF(USE_ICONV)
TARGET_LINK_LIBRARIES(${target} iconv)
ADD_DEFINITIONS(-DGIT_USE_ICONV)
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -liconv" PARENT_SCOPE)
ENDIF()
IF(THREADSAFE) IF(THREADSAFE)
TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
ENDIF() ENDIF()
...@@ -123,6 +127,9 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_V ...@@ -123,6 +127,9 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_V
STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}") STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBGIT2_VERSION_REV "${GIT2_HEADER}")
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}") SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
FILE(STRINGS "include/git2/version.h" GIT2_HEADER_SOVERSION REGEX "^#define LIBGIT2_SOVERSION [0-9]+$")
STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "${GIT2_HEADER_SOVERSION}")
# Find required dependencies # Find required dependencies
INCLUDE_DIRECTORIES(src include) INCLUDE_DIRECTORIES(src include)
...@@ -135,13 +142,13 @@ ELSE () ...@@ -135,13 +142,13 @@ ELSE ()
FIND_PACKAGE(OpenSSL) FIND_PACKAGE(OpenSSL)
ENDIF () ENDIF ()
FIND_PACKAGE(HTTP_Parser QUIET) FIND_PACKAGE(HTTP_Parser)
IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS})
LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES})
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lhttp_parser") SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lhttp_parser")
ELSE() ELSE()
MESSAGE("http-parser was not found or is too old; using bundled 3rd-party sources.") MESSAGE(STATUS "http-parser was not found or is too old; using bundled 3rd-party sources.")
INCLUDE_DIRECTORIES(deps/http-parser) INCLUDE_DIRECTORIES(deps/http-parser)
FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h)
ENDIF() ENDIF()
...@@ -153,7 +160,11 @@ IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") ...@@ -153,7 +160,11 @@ IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin")
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin")
ADD_DEFINITIONS(-DOPENSSL_SHA1) ADD_DEFINITIONS(-DOPENSSL_SHA1)
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl") IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lssl")
ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl")
ENDIF ()
ELSE() ELSE()
FILE(GLOB SRC_SHA1 src/hash/hash_generic.c) FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
ENDIF() ENDIF()
...@@ -164,34 +175,31 @@ IF (ENABLE_TRACE STREQUAL "ON") ...@@ -164,34 +175,31 @@ IF (ENABLE_TRACE STREQUAL "ON")
ENDIF() ENDIF()
# Include POSIX regex when it is required # Include POSIX regex when it is required
IF(WIN32 OR AMIGA OR ANDROID) IF(WIN32 OR AMIGA OR ANDROID OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
INCLUDE_DIRECTORIES(deps/regex) INCLUDE_DIRECTORIES(deps/regex)
SET(SRC_REGEX deps/regex/regex.c) SET(SRC_REGEX deps/regex/regex.c)
ENDIF() ENDIF()
# Optional external dependency: zlib # Optional external dependency: zlib
# It's optional, but FIND_PACKAGE gives a warning that looks more like an FIND_PACKAGE(ZLIB)
# error.
FIND_PACKAGE(ZLIB QUIET)
IF (ZLIB_FOUND) IF (ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
LINK_LIBRARIES(${ZLIB_LIBRARIES}) LINK_LIBRARIES(${ZLIB_LIBRARIES})
IF(APPLE) IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lz") SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lz")
ELSE() ELSE()
SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib") SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib")
ENDIF() ENDIF()
# Fake the message CMake would have shown
MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}")
ELSE() ELSE()
MESSAGE( "zlib was not found; using bundled 3rd-party sources." ) MESSAGE(STATUS "zlib was not found; using bundled 3rd-party sources." )
INCLUDE_DIRECTORIES(deps/zlib) INCLUDE_DIRECTORIES(deps/zlib)
ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP) ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h) FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h)
ENDIF() ENDIF()
IF (USE_SSH AND NOT MINGW) # Optional external dependency: libssh2
FIND_PACKAGE(LIBSSH2 QUIET) IF (USE_SSH)
FIND_PACKAGE(LIBSSH2)
ENDIF() ENDIF()
IF (LIBSSH2_FOUND) IF (LIBSSH2_FOUND)
ADD_DEFINITIONS(-DGIT_SSH) ADD_DEFINITIONS(-DGIT_SSH)
...@@ -200,6 +208,15 @@ IF (LIBSSH2_FOUND) ...@@ -200,6 +208,15 @@ IF (LIBSSH2_FOUND)
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES}) SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
ENDIF() ENDIF()
# Optional external dependency: iconv
IF (USE_ICONV)
FIND_PACKAGE(Iconv)
ENDIF()
IF (ICONV_FOUND)
ADD_DEFINITIONS(-DGIT_USE_ICONV)
INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${ICONV_LIBRARIES}")
ENDIF()
# Platform specific compilation flags # Platform specific compilation flags
IF (MSVC) IF (MSVC)
...@@ -274,7 +291,11 @@ IF (MSVC) ...@@ -274,7 +291,11 @@ IF (MSVC)
# Precompiled headers # Precompiled headers
ELSE () ELSE ()
SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra ${CMAKE_C_FLAGS}")
IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}")
ENDIF()
IF (WIN32 AND NOT CYGWIN) IF (WIN32 AND NOT CYGWIN)
SET(CMAKE_C_FLAGS_DEBUG "-D_DEBUG") SET(CMAKE_C_FLAGS_DEBUG "-D_DEBUG")
...@@ -288,11 +309,22 @@ ELSE () ...@@ -288,11 +309,22 @@ ELSE ()
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1) ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
ELSEIF (BUILD_SHARED_LIBS) ELSEIF (BUILD_SHARED_LIBS)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fPIC") ADD_C_FLAG_IF_SUPPORTED(-fvisibility=hidden)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ENDIF () ENDIF ()
ADD_C_FLAG_IF_SUPPORTED(-Wno-missing-field-initializers)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-aliasing=2)
ADD_C_FLAG_IF_SUPPORTED(-Wstrict-prototypes)
ADD_C_FLAG_IF_SUPPORTED(-Wdeclaration-after-statement)
ADD_C_FLAG_IF_SUPPORTED(-Wno-unused-const-variable)
ADD_C_FLAG_IF_SUPPORTED(-Wno-unused-function)
IF (APPLE) # Apple deprecated OpenSSL IF (APPLE) # Apple deprecated OpenSSL
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") ADD_C_FLAG_IF_SUPPORTED(-Wno-deprecated-declarations)
ENDIF () ENDIF()
IF (PROFILE) IF (PROFILE)
SET(CMAKE_C_FLAGS "-pg ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-pg ${CMAKE_C_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "-pg ${CMAKE_EXE_LINKER_FLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "-pg ${CMAKE_EXE_LINKER_FLAGS}")
...@@ -317,7 +349,7 @@ ENDIF() ...@@ -317,7 +349,7 @@ ENDIF()
IF (THREADSAFE) IF (THREADSAFE)
IF (NOT WIN32) IF (NOT WIN32)
find_package(Threads REQUIRED) FIND_PACKAGE(Threads REQUIRED)
ENDIF() ENDIF()
ADD_DEFINITIONS(-DGIT_THREADS) ADD_DEFINITIONS(-DGIT_THREADS)
...@@ -333,9 +365,11 @@ IF (WIN32 AND NOT CYGWIN) ...@@ -333,9 +365,11 @@ IF (WIN32 AND NOT CYGWIN)
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501) ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501)
FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h) FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h)
ELSEIF (AMIGA) ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R) ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h)
ELSE() ELSE()
IF (VALGRIND)
ADD_DEFINITIONS(-DNO_MMAP)
ENDIF()
FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h) FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h)
ENDIF() ENDIF()
FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h) FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h)
...@@ -346,13 +380,14 @@ IF (CMAKE_SIZEOF_VOID_P EQUAL 8) ...@@ -346,13 +380,14 @@ IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4) ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
ADD_DEFINITIONS(-DGIT_ARCH_32) ADD_DEFINITIONS(-DGIT_ARCH_32)
ELSE() ELSE()
message(FATAL_ERROR "Unsupported architecture") MESSAGE(FATAL_ERROR "Unsupported architecture")
ENDIF() ENDIF()
# Compile and link libgit2 # Compile and link libgit2
ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC}) ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES}) TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES}) TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${ICONV_LIBRARIES})
TARGET_OS_LIBRARIES(git2) TARGET_OS_LIBRARIES(git2)
# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240) # Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
...@@ -365,7 +400,7 @@ MSVC_SPLIT_SOURCES(git2) ...@@ -365,7 +400,7 @@ MSVC_SPLIT_SOURCES(git2)
IF (SONAME) IF (SONAME)
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING}) SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR}) SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_SOVERSION})
IF (LIBGIT2_FILENAME) IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\") ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME}) SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
...@@ -418,6 +453,7 @@ IF (BUILD_CLAR) ...@@ -418,6 +453,7 @@ IF (BUILD_CLAR)
TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES}) TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES}) TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${ICONV_LIBRARIES})
TARGET_OS_LIBRARIES(libgit2_clar) TARGET_OS_LIBRARIES(libgit2_clar)
MSVC_SPLIT_SOURCES(libgit2_clar) MSVC_SPLIT_SOURCES(libgit2_clar)
...@@ -433,7 +469,7 @@ ENDIF () ...@@ -433,7 +469,7 @@ ENDIF ()
IF (TAGS) IF (TAGS)
FIND_PROGRAM(CTAGS ctags) FIND_PROGRAM(CTAGS ctags)
IF (NOT CTAGS) IF (NOT CTAGS)
message(FATAL_ERROR "Could not find ctags command") MESSAGE(FATAL_ERROR "Could not find ctags command")
ENDIF () ENDIF ()
FILE(GLOB_RECURSE SRC_ALL *.[ch]) FILE(GLOB_RECURSE SRC_ALL *.[ch])
......
...@@ -5,9 +5,13 @@ your help. ...@@ -5,9 +5,13 @@ your help.
## Licensing ## Licensing
By contributing to libgit2, you agree to release your contribution under the terms of the license. By contributing to libgit2, you agree to release your contribution under
For code under `examples`, this is governed by the [CC0 Public Domain Dedication](examples/COPYING). the terms of the license. Except for the `examples` directory, all code
All other code is released under the [GPL v2 with linking exception](COPYING). is released under the [GPL v2 with linking exception](COPYING).
The `examples` code is governed by the
[CC0 Public Domain Dedication](examples/COPYING), so that you may copy
from them into your own application.
## Discussion & Chat ## Discussion & Chat
...@@ -76,15 +80,19 @@ you're porting code *from* to see what you need to do. As a general rule, ...@@ -76,15 +80,19 @@ you're porting code *from* to see what you need to do. As a general rule,
MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0 MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0
license typically doesn't work due to GPL incompatibility. license typically doesn't work due to GPL incompatibility.
If you are pulling in code from core Git, another project or code you've pulled from If you are pulling in code from core Git, another project or code you've
a forum / Stack Overflow then please flag this in your PR and also make sure you've pulled from a forum / Stack Overflow then please flag this in your PR and
given proper credit to the original author in the code snippet. also make sure you've given proper credit to the original author in the
code snippet.
## Style Guide ## Style Guide
`libgit2` is written in [ANSI C](http://en.wikipedia.org/wiki/ANSI_C) The public API of `libgit2` is [ANSI C](http://en.wikipedia.org/wiki/ANSI_C)
(a.k.a. C89) with some specific conventions for function and type naming, (a.k.a. C89) compatible. Internally, `libgit2` is written using a portable
code formatting, and testing. subset of C99 - in order to compile with GCC, Clang, MSVC, etc., we keep
local variable declarations at the tops of blocks only and avoid `//` style
comments. Additionally, `libgit2` follows some extra conventions for
function and type naming, code formatting, and testing.
We like to keep the source code consistent and easy to read. Maintaining We like to keep the source code consistent and easy to read. Maintaining
this takes some discipline, but it's been more than worth it. Take a look this takes some discipline, but it's been more than worth it. Take a look
...@@ -93,22 +101,4 @@ at the ...@@ -93,22 +101,4 @@ at the
## Starter Projects ## Starter Projects
So, you want to start helping out with `libgit2`? That's fantastic? We See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
welcome contributions and we promise we'll try to be nice.
If you want to jump in, you can look at our issues list to see if there
are any unresolved issues to jump in on. Also, here is a list of some
smaller project ideas that could help you become familiar with the code
base and make a nice first step:
* Convert a `git_*modulename*_foreach()` callback-based iteration API
into a `git_*modulename*_iterator` object with a create/advance style
of API. This helps folks writing language bindings and usually isn't
too complicated.
* Write a new `examples/` program that mirrors a particular core git
command. (See `examples/diff.c` for example.) This lets you (and us)
easily exercise a particular facet of the API and measure compatability
and feature parity with core git.
* Submit a PR to clarify documentation! While we do try to document all of
the APIs, your fresh eyes on the documentation will find areas that are
confusing much more easily.
...@@ -6,14 +6,18 @@ guidelines that should help with that. ...@@ -6,14 +6,18 @@ guidelines that should help with that.
## Compatibility ## Compatibility
`libgit2` runs on many different platforms with many different compilers. `libgit2` runs on many different platforms with many different compilers.
It is written in [ANSI C](http://en.wikipedia.org/wiki/ANSI_C) (a.k.a. C89)
with some specific standards for function and type naming, code formatting,
and testing.
We try to avoid more recent extensions to maximize portability. We also, to The public API of `libgit2` is [ANSI C](http://en.wikipedia.org/wiki/ANSI_C)
the greatest extent possible, try to avoid lots of `#ifdef`s inside the core (a.k.a. C89) compatible.
code base. This is somewhat unavoidable, but since it can really hamper
maintainability, we keep it to a minimum. Internally, `libgit2` is written using a portable subset of C99 - in order
to maximize compatibility (e.g. with MSVC) we avoid certain C99
extensions. Specifically, we keep local variable declarations at the tops
of blocks only and we avoid `//` style comments.
Also, to the greatest extent possible, we try to avoid lots of `#ifdef`s
inside the core code base. This is somewhat unavoidable, but since it can
really hamper maintainability, we keep it to a minimum.
## Match Surrounding Code ## Match Surrounding Code
...@@ -209,6 +213,9 @@ All inlined functions must be declared as: ...@@ -209,6 +213,9 @@ All inlined functions must be declared as:
GIT_INLINE(result_type) git_modulename_functionname(arg_list); GIT_INLINE(result_type) git_modulename_functionname(arg_list);
``` ```
`GIT_INLINE` (or `inline`) should not be used in public headers in order
to preserve ANSI C compatibility.
## Tests ## Tests
`libgit2` uses the [clar](https://github.com/vmg/clar) testing framework. `libgit2` uses the [clar](https://github.com/vmg/clar) testing framework.
......
...@@ -388,19 +388,7 @@ Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler ...@@ -388,19 +388,7 @@ Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
---------------------------------------------------------------------- ----------------------------------------------------------------------
The priority queue implementation is based on code licensed under the The Clar framework is licensed under the MIT license:
Apache 2.0 license:
Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
Copyright 2006-2010 The Apache Software Foundation
The full text of the Apache 2.0 license is available at:
http://www.apache.org/licenses/LICENSE-2.0
----------------------------------------------------------------------
The Clay framework is licensed under the MIT license:
Copyright (C) 2011 by Vicent Marti Copyright (C) 2011 by Vicent Marti
...@@ -930,64 +918,3 @@ necessary. Here is a sample; alter the names: ...@@ -930,64 +918,3 @@ necessary. Here is a sample; alter the names:
That's all there is to it! That's all there is to it!
---------------------------------------------------------------------- ----------------------------------------------------------------------
Portions of src/win32/posix_w32.c are derrived from link_win32.c in PHP:
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2012 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes PHP software, freely available from
<http://www.php.net/software/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
Projects For LibGit2
====================
So, you want to start helping out with `libgit2`? That's fantastic! We
welcome contributions and we promise we'll try to be nice.
This is a list of libgit2 related projects that new contributors can take
on. It includes a number of good starter projects and well as some larger
ideas that no one is actively working on.
## Before You Start
Please start by reading the README.md, CONTRIBUTING.md, and CONVENTIONS.md
files before diving into one of these projects. Those will explain our
work flow and coding conventions to help ensure that your work will be
easily integrated into libgit2.
Next, work through the build instructions and make sure you can clone the
repository, compile it, and run the tests successfully. That will make
sure that your development environment is set up correctly and you are
ready to start on libgit2 development.
## Starter Projects
These are good small projects to get started with libgit2.
* Look at the `examples/` programs, find an existing one that mirrors a
core Git command and add a missing command-line option. There are many
gaps right now and this helps demonstrate how to use the library. Here
are some specific ideas:
* Fix the `examples/diff.c` implementation of the `-B`
(a.k.a. `--break-rewrites`) command line option to actually look for
the optional `[<n>][/<m>]` configuration values. There is an
existing comment that reads `/* TODO: parse thresholds */`. The
trick to this one will be doing it in a manner that is clean and
simple, but still handles the various cases correctly (e.g. `-B/70%`
is apparently a legal setting).
* Implement the `--log-size` option for `examples/log.c`. I think all
the data is available, you would just need to add the code into the
`print_commit()` routine (along with a way of passing the option
into that function).
* As an extension to the matching idea for `examples/log.c`, add the
`-i` option to use `strcasestr()` for matches.
* For `examples/log.c`, implement the `--first-parent` option now that
libgit2 supports it in the revwalk API.
* Pick a Git command that is not already emulated in `examples/` and write
a new example that mirrors the behavior. Examples don't have to be
perfect emulations, but should demonstrate how to use the libgit2 APIs
to get results that are similar to Git commands. This lets you (and us)
easily exercise a particular facet of the API and measure compatability
and feature parity with core git.
* Submit a PR to clarify documentation! While we do try to document all of
the APIs, your fresh eyes on the documentation will find areas that are
confusing much more easily.
* Add support for the symref protocol extension, so we don't guess
what the remote's default branch is
[#2006](https://github.com/libgit2/libgit2/issues/2006)
If none of these appeal to you, take a look at our issues list to see if
there are any unresolved issues you'd like to jump in on.
## Larger Projects
These are ideas for larger projects mostly taken from our backlog of
[Issues](https://github.com/libgit2/libgit2/issues). Please don't dive
into one of these as a first project for libgit2 - we'd rather get to
know you first by successfully shipping your work on one of the smaller
projects above.
* Port part of the Git test suite to run against the command line emulation
in examples/
* Fix symlink support for files in the .git directory (i.e. don't overwrite
the symlinks when writing the file contents back out)
* Implement a 'git describe' like API
* Add hooks API to enumerate and manage hooks (not run them at this point)
* Isolate logic of ignore evaluation into a standalone API
* Upgrade internal libxdiff code to latest from core Git
* Add a hashtable lookup for files in the index instead of binary search
every time
* Make the index write the cache out to disk (with tests to gain
confidence that the caching invalidation works correctly)
* Have the tree builder use a hash table when building instead of a
list.
* Move the tagopt mechanism to the newer git 1.9 interpretation of
--tags [#2120](https://github.com/libgit2/libgit2/issues/2120)
...@@ -2,10 +2,11 @@ libgit2 - the Git linkable library ...@@ -2,10 +2,11 @@ libgit2 - the Git linkable library
================================== ==================================
[![Build Status](https://secure.travis-ci.org/libgit2/libgit2.png?branch=development)](http://travis-ci.org/libgit2/libgit2) [![Build Status](https://secure.travis-ci.org/libgit2/libgit2.png?branch=development)](http://travis-ci.org/libgit2/libgit2)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639)
`libgit2` is a portable, pure C implementation of the Git core methods provided as a `libgit2` is a portable, pure C implementation of the Git core methods
re-entrant linkable library with a solid API, allowing you to write native provided as a re-entrant linkable library with a solid API, allowing you to
speed custom Git applications in any language with bindings. write native speed custom Git applications in any language with bindings.
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special `libgit2` is licensed under a **very permissive license** (GPLv2 with a special
Linking Exception). This basically means that you can link it (unmodified) Linking Exception). This basically means that you can link it (unmodified)
...@@ -19,18 +20,19 @@ Additionally, the example code has been released to the public domain (see the ...@@ -19,18 +20,19 @@ Additionally, the example code has been released to the public domain (see the
* API documentation: <http://libgit2.github.com/libgit2> * API documentation: <http://libgit2.github.com/libgit2>
* IRC: [#libgit2](irc://irc.freenode.net/libgit2) on irc.freenode.net. * IRC: [#libgit2](irc://irc.freenode.net/libgit2) on irc.freenode.net.
* Mailing list: The libgit2 mailing list was * Mailing list: The libgit2 mailing list was
traditionally hosted in Librelist but has been deprecated. We encourage you to traditionally hosted in Librelist but has been deprecated. We encourage you to
[use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding
the library, or [open an issue](https://github.com/libgit2/libgit2/issues) the library, or [open an issue](https://github.com/libgit2/libgit2/issues)
on GitHub for bug reports. The mailing list archives are still available at on GitHub for bug reports. The mailing list archives are still available at
<http://librelist.com/browser/libgit2/>. <http://librelist.com/browser/libgit2/>.
What It Can Do What It Can Do
============== ==============
`libgit2` is already very usable and is being used in production for many applications including the GitHub.com site, in Plastic SCM `libgit2` is already very usable and is being used in production for many
and also powering Microsoft's Visual Studio tools for Git. The library provides: applications including the GitHub.com site, in Plastic SCM and also powering
Microsoft's Visual Studio tools for Git. The library provides:
* SHA conversions, formatting and shortening * SHA conversions, formatting and shortening
* abstracted ODB backend system * abstracted ODB backend system
...@@ -64,7 +66,7 @@ Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthrea ...@@ -64,7 +66,7 @@ Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthrea
they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
for threading. for threading.
The `libgit2` library is built using `CMake 2.6+` (<http://www.cmake.org>) on all platforms. The `libgit2` library is built using [CMake](<http://www.cmake.org>) (version 2.6 or newer) on all platforms.
On most systems you can build the library using the following commands On most systems you can build the library using the following commands
...@@ -164,11 +166,12 @@ Here are the bindings to libgit2 that are currently available: ...@@ -164,11 +166,12 @@ Here are the bindings to libgit2 that are currently available:
* libgit2-glib <https://live.gnome.org/Libgit2-glib> * libgit2-glib <https://live.gnome.org/Libgit2-glib>
* Haskell * Haskell
* hgit2 <https://github.com/fpco/gitlib> * hgit2 <https://github.com/fpco/gitlib>
* Java
* Jagged <https://github.com/ethomson/jagged>
* Lua * Lua
* luagit2 <https://github.com/libgit2/luagit2> * luagit2 <https://github.com/libgit2/luagit2>
* .NET * .NET
* libgit2sharp <https://github.com/libgit2/libgit2sharp> * libgit2sharp <https://github.com/libgit2/libgit2sharp>
* libgit2net, low level bindings superseded by libgit2sharp <https://github.com/txdv/libgit2net>
* Node.js * Node.js
* node-gitteh <https://github.com/libgit2/node-gitteh> * node-gitteh <https://github.com/libgit2/node-gitteh>
* nodegit <https://github.com/tbranyen/nodegit> * nodegit <https://github.com/tbranyen/nodegit>
...@@ -182,8 +185,12 @@ Here are the bindings to libgit2 that are currently available: ...@@ -182,8 +185,12 @@ Here are the bindings to libgit2 that are currently available:
* Git-Raw <https://github.com/ghedo/p5-Git-Raw> * Git-Raw <https://github.com/ghedo/p5-Git-Raw>
* PHP * PHP
* php-git <https://github.com/libgit2/php-git> * php-git <https://github.com/libgit2/php-git>
* PowerShell
* GitPowerShell <https://github.com/ethomson/gitpowershell>
* Python * Python
* pygit2 <https://github.com/libgit2/pygit2> * pygit2 <https://github.com/libgit2/pygit2>
* R
* git2r <https://github.com/ropensci/git2r>
* Ruby * Ruby
* Rugged <https://github.com/libgit2/rugged> * Rugged <https://github.com/libgit2/rugged>
* Vala * Vala
...@@ -195,14 +202,16 @@ we can add it to the list. ...@@ -195,14 +202,16 @@ we can add it to the list.
How Can I Contribute? How Can I Contribute?
================================== ==================================
Check the [contribution guidelines](CONTRIBUTING.md). Check the [contribution guidelines](CONTRIBUTING.md) to understand our
workflow, the libgit2 [coding conventions](CONVENTIONS.md), and out list of
[good starting projects](PROJECTS.md).
License License
================================== ==================================
`libgit2` is under GPL2 **with linking exemption**. This means you
can link to and use the library from any program, proprietary or open source; paid `libgit2` is under GPL2 **with linking exemption**. This means you can link to
or gratis. However, you cannot modify libgit2 and distribute it without and use the library from any program, proprietary or open source; paid or
gratis. However, you cannot modify libgit2 and distribute it without
supplying the source. supplying the source.
See the COPYING file for the full license text. See the [COPYING file](COPYING) for the full license text.
# - Append compiler flag to CMAKE_C_FLAGS if compiler supports it
# ADD_C_FLAG_IF_SUPPORTED(<flag>)
# <flag> - the compiler flag to test
# This internally calls the CHECK_C_COMPILER_FLAG macro.
INCLUDE(CheckCCompilerFlag)
MACRO(ADD_C_FLAG_IF_SUPPORTED _FLAG)
STRING(TOUPPER ${_FLAG} UPCASE)
STRING(REGEX REPLACE "^-" "" UPCASE_PRETTY ${UPCASE})
CHECK_C_COMPILER_FLAG(${_FLAG} IS_${UPCASE_PRETTY}_SUPPORTED)
IF(IS_${UPCASE_PRETTY}_SUPPORTED)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAG}")
ENDIF()
ENDMACRO()
# - Try to find Iconv
# Once done this will define
#
# ICONV_FOUND - system has Iconv
# ICONV_INCLUDE_DIR - the Iconv include directory
# ICONV_LIBRARIES - Link these to use Iconv
#
IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
# Already in cache, be silent
SET(ICONV_FIND_QUIETLY TRUE)
ENDIF()
FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /opt/local/include NO_DEFAULT_PATH)
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c NO_DEFAULT_PATH PATHS /opt/local/lib)
FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
IF(ICONV_INCLUDE_DIR AND iconv_lib)
SET(ICONV_FOUND TRUE)
ENDIF()
IF(ICONV_FOUND)
# split iconv into -L and -l linker options, so we can set them for pkg-config
GET_FILENAME_COMPONENT(iconv_path ${iconv_lib} PATH)
GET_FILENAME_COMPONENT(iconv_name ${iconv_lib} NAME_WE)
STRING(REGEX REPLACE "^lib" "" iconv_name ${iconv_name})
SET(ICONV_LIBRARIES "-L${iconv_path} -l${iconv_name}")
IF(NOT ICONV_FIND_QUIETLY)
MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
ENDIF(NOT ICONV_FIND_QUIETLY)
ELSE()
IF(Iconv_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Iconv")
ENDIF(Iconv_FIND_REQUIRED)
ENDIF()
MARK_AS_ADVANCED(
ICONV_INCLUDE_DIR
ICONV_LIBRARIES
)
...@@ -67,10 +67,17 @@ ...@@ -67,10 +67,17 @@
#include "regex_internal.h" #include "regex_internal.h"
#include "regex_internal.c" #include "regex_internal.c"
#ifdef GAWK #ifdef GAWK
#define bool int # define bool int
#define true (1)
#define false (0) # ifndef true
# define true (1)
# endif
# ifndef false
# define false (0)
# endif
#endif #endif
#include "regcomp.c" #include "regcomp.c"
#include "regexec.c" #include "regexec.c"
......
...@@ -21,7 +21,7 @@ content, everything goes through diff drivers that are implemented in ...@@ -21,7 +21,7 @@ content, everything goes through diff drivers that are implemented in
External Objects External Objects
---------------- ----------------
* `git_diff_options` repesents user choices about how a diff should be * `git_diff_options` represents user choices about how a diff should be
performed and is passed to most diff generating functions. performed and is passed to most diff generating functions.
* `git_diff_file` represents an item on one side of a possible delta * `git_diff_file` represents an item on one side of a possible delta
* `git_diff_delta` represents a pair of items that have changed in some * `git_diff_delta` represents a pair of items that have changed in some
...@@ -37,7 +37,7 @@ External Objects ...@@ -37,7 +37,7 @@ External Objects
header that compactly represents that information, and it will have a header that compactly represents that information, and it will have a
number of lines of context surrounding added and deleted lines. number of lines of context surrounding added and deleted lines.
* A `line` is simple a line of data along with a `git_diff_line_t` value * A `line` is simple a line of data along with a `git_diff_line_t` value
that tells how the data should be interpretted (e.g. context or added). that tells how the data should be interpreted (e.g. context or added).
Internal Objects Internal Objects
---------------- ----------------
......
...@@ -8,4 +8,6 @@ init ...@@ -8,4 +8,6 @@ init
log log
rev-parse rev-parse
status status
tag
for-each-ref
*.dSYM *.dSYM
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
CC = gcc CC = gcc
CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers
LFLAGS = -L../build -lgit2 -lz LFLAGS = -L../build -lgit2 -lz
APPS = general showindex diff rev-list cat-file status log rev-parse init blame APPS = general showindex diff rev-list cat-file status log rev-parse init blame tag
APPS += for-each-ref
all: $(APPS) all: $(APPS)
......
...@@ -78,7 +78,7 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo ...@@ -78,7 +78,7 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo
git_status_t status; git_status_t status;
(void)matched_pathspec; (void)matched_pathspec;
if (git_status_file(&status, p.repo, path)) { if (git_status_file((unsigned int*)(&status), p.repo, path)) {
return -1; //abort return -1; //abort
} }
......
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
#include "common.h" #include "common.h"
#ifdef _MSC_VER
#define snprintf sprintf_s
#define strcasecmp strcmpi
#endif
/** /**
* This example demonstrates how to invoke the libgit2 blame API to roughly * This example demonstrates how to invoke the libgit2 blame API to roughly
* simulate the output of `git blame` and a few of its command line arguments. * simulate the output of `git blame` and a few of its command line arguments.
...@@ -26,6 +31,7 @@ struct opts { ...@@ -26,6 +31,7 @@ struct opts {
int M; int M;
int start_line; int start_line;
int end_line; int end_line;
int F;
}; };
static void parse_opts(struct opts *o, int argc, char *argv[]); static void parse_opts(struct opts *o, int argc, char *argv[]);
...@@ -47,6 +53,7 @@ int main(int argc, char *argv[]) ...@@ -47,6 +53,7 @@ int main(int argc, char *argv[])
parse_opts(&o, argc, argv); parse_opts(&o, argc, argv);
if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES;
if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES;
if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT;
/** Open the repository. */ /** Open the repository. */
check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL); check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL);
...@@ -100,8 +107,9 @@ int main(int argc, char *argv[]) ...@@ -100,8 +107,9 @@ int main(int argc, char *argv[])
if (break_on_null_hunk && !hunk) break; if (break_on_null_hunk && !hunk) break;
if (hunk) { if (hunk) {
break_on_null_hunk = 1;
char sig[128] = {0}; char sig[128] = {0};
break_on_null_hunk = 1;
git_oid_tostr(oid, 10, &hunk->final_commit_id); git_oid_tostr(oid, 10, &hunk->final_commit_id);
snprintf(sig, 30, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); snprintf(sig, 30, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email);
...@@ -141,6 +149,7 @@ static void usage(const char *msg, const char *arg) ...@@ -141,6 +149,7 @@ static void usage(const char *msg, const char *arg)
fprintf(stderr, " -L <n,m> process only line range n-m, counting from 1\n"); fprintf(stderr, " -L <n,m> process only line range n-m, counting from 1\n");
fprintf(stderr, " -M find line moves within and across files\n"); fprintf(stderr, " -M find line moves within and across files\n");
fprintf(stderr, " -C find line copies within and across files\n"); fprintf(stderr, " -C find line copies within and across files\n");
fprintf(stderr, " -F follow only the first parent commits\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
exit(1); exit(1);
} }
...@@ -169,6 +178,8 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) ...@@ -169,6 +178,8 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
o->M = 1; o->M = 1;
else if (!strcasecmp(a, "-C")) else if (!strcasecmp(a, "-C"))
o->C = 1; o->C = 1;
else if (!strcasecmp(a, "-F"))
o->F = 1;
else if (!strcasecmp(a, "-L")) { else if (!strcasecmp(a, "-L")) {
i++; a = argv[i]; i++; a = argv[i];
if (i >= argc) fatal("Not enough arguments to -L", NULL); if (i >= argc) fatal("Not enough arguments to -L", NULL);
......
...@@ -42,7 +42,7 @@ static void print_signature(const char *header, const git_signature *sig) ...@@ -42,7 +42,7 @@ static void print_signature(const char *header, const git_signature *sig)
static void show_blob(const git_blob *blob) static void show_blob(const git_blob *blob)
{ {
/* ? Does this need crlf filtering? */ /* ? Does this need crlf filtering? */
fwrite(git_blob_rawcontent(blob), git_blob_rawsize(blob), 1, stdout); fwrite(git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob), 1, stdout);
} }
/** Show each entry with its type, id and attributes */ /** Show each entry with its type, id and attributes */
......
...@@ -156,7 +156,7 @@ int diff_output( ...@@ -156,7 +156,7 @@ int diff_output(
const git_diff_line *l, const git_diff_line *l,
void *p) void *p)
{ {
FILE *fp = p; FILE *fp = (FILE*)p;
(void)d; (void)h; (void)d; (void)h;
......
...@@ -33,12 +33,27 @@ static const char *colors[] = { ...@@ -33,12 +33,27 @@ static const char *colors[] = {
"\033[36m" /* cyan */ "\033[36m" /* cyan */
}; };
enum {
OUTPUT_DIFF = (1 << 0),
OUTPUT_STAT = (1 << 1),
OUTPUT_SHORTSTAT = (1 << 2),
OUTPUT_NUMSTAT = (1 << 3),
OUTPUT_SUMMARY = (1 << 4)
};
enum {
CACHE_NORMAL = 0,
CACHE_ONLY = 1,
CACHE_NONE = 2
};
/** The 'opts' struct captures all the various parsed command line options. */ /** The 'opts' struct captures all the various parsed command line options. */
struct opts { struct opts {
git_diff_options diffopts; git_diff_options diffopts;
git_diff_find_options findopts; git_diff_find_options findopts;
int color; int color;
int cached; int cache;
int output;
git_diff_format_t format; git_diff_format_t format;
const char *treeish1; const char *treeish1;
const char *treeish2; const char *treeish2;
...@@ -46,9 +61,11 @@ struct opts { ...@@ -46,9 +61,11 @@ struct opts {
}; };
/** These functions are implemented at the end */ /** These functions are implemented at the end */
static void usage(const char *message, const char *arg);
static void parse_opts(struct opts *o, int argc, char *argv[]); static void parse_opts(struct opts *o, int argc, char *argv[]);
static int color_printer( static int color_printer(
const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*);
static void diff_print_stats(git_diff *diff, struct opts *o);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
...@@ -57,7 +74,7 @@ int main(int argc, char *argv[]) ...@@ -57,7 +74,7 @@ int main(int argc, char *argv[])
git_diff *diff; git_diff *diff;
struct opts o = { struct opts o = {
GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT,
-1, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
}; };
git_threads_init(); git_threads_init();
...@@ -74,6 +91,7 @@ int main(int argc, char *argv[]) ...@@ -74,6 +91,7 @@ int main(int argc, char *argv[])
* * &lt;sha1&gt; --cached * * &lt;sha1&gt; --cached
* * &lt;sha1&gt; * * &lt;sha1&gt;
* * --cached * * --cached
* * --nocache (don't use index data in diff at all)
* * nothing * * nothing
* *
* Currently ranged arguments like &lt;sha1&gt;..&lt;sha2&gt; and &lt;sha1&gt;...&lt;sha2&gt; * Currently ranged arguments like &lt;sha1&gt;..&lt;sha2&gt; and &lt;sha1&gt;...&lt;sha2&gt;
...@@ -89,20 +107,23 @@ int main(int argc, char *argv[]) ...@@ -89,20 +107,23 @@ int main(int argc, char *argv[])
check_lg2( check_lg2(
git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts),
"diff trees", NULL); "diff trees", NULL);
else if (t1 && o.cached) else if (o.cache != CACHE_NORMAL) {
check_lg2( if (!t1)
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), treeish_to_tree(&t1, repo, "HEAD");
"diff tree to index", NULL);
if (o.cache == CACHE_NONE)
check_lg2(
git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
"diff tree to working directory", NULL);
else
check_lg2(
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
"diff tree to index", NULL);
}
else if (t1) else if (t1)
check_lg2( check_lg2(
git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts),
"diff tree to working directory", NULL); "diff tree to working directory", NULL);
else if (o.cached) {
treeish_to_tree(&t1, repo, "HEAD");
check_lg2(
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
"diff tree to index", NULL);
}
else else
check_lg2( check_lg2(
git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
...@@ -117,15 +138,23 @@ int main(int argc, char *argv[]) ...@@ -117,15 +138,23 @@ int main(int argc, char *argv[])
/** Generate simple output using libgit2 display helper. */ /** Generate simple output using libgit2 display helper. */
if (o.color >= 0) if (!o.output)
fputs(colors[0], stdout); o.output = OUTPUT_DIFF;
check_lg2( if (o.output != OUTPUT_DIFF)
git_diff_print(diff, o.format, color_printer, &o.color), diff_print_stats(diff, &o);
"displaying diff", NULL);
if (o.color >= 0) if ((o.output & OUTPUT_DIFF) != 0) {
fputs(colors[0], stdout); if (o.color >= 0)
fputs(colors[0], stdout);
check_lg2(
git_diff_print(diff, o.format, color_printer, &o.color),
"displaying diff", NULL);
if (o.color >= 0)
fputs(colors[0], stdout);
}
/** Cleanup before exiting. */ /** Cleanup before exiting. */
...@@ -200,16 +229,25 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) ...@@ -200,16 +229,25 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
usage("Only one or two tree identifiers can be provided", NULL); usage("Only one or two tree identifiers can be provided", NULL);
} }
else if (!strcmp(a, "-p") || !strcmp(a, "-u") || else if (!strcmp(a, "-p") || !strcmp(a, "-u") ||
!strcmp(a, "--patch")) !strcmp(a, "--patch")) {
o->output |= OUTPUT_DIFF;
o->format = GIT_DIFF_FORMAT_PATCH; o->format = GIT_DIFF_FORMAT_PATCH;
}
else if (!strcmp(a, "--cached")) else if (!strcmp(a, "--cached"))
o->cached = 1; o->cache = CACHE_ONLY;
else if (!strcmp(a, "--name-only")) else if (!strcmp(a, "--nocache"))
o->cache = CACHE_NONE;
else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name"))
o->format = GIT_DIFF_FORMAT_NAME_ONLY; o->format = GIT_DIFF_FORMAT_NAME_ONLY;
else if (!strcmp(a, "--name-status")) else if (!strcmp(a, "--name-status") ||
!strcmp(a, "--format=name-status"))
o->format = GIT_DIFF_FORMAT_NAME_STATUS; o->format = GIT_DIFF_FORMAT_NAME_STATUS;
else if (!strcmp(a, "--raw")) else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw"))
o->format = GIT_DIFF_FORMAT_RAW; o->format = GIT_DIFF_FORMAT_RAW;
else if (!strcmp(a, "--format=diff-index")) {
o->format = GIT_DIFF_FORMAT_RAW;
o->diffopts.id_abbrev = 40;
}
else if (!strcmp(a, "--color")) else if (!strcmp(a, "--color"))
o->color = 0; o->color = 0;
else if (!strcmp(a, "--no-color")) else if (!strcmp(a, "--no-color"))
...@@ -228,6 +266,18 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) ...@@ -228,6 +266,18 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
o->diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED; o->diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED;
else if (!strcmp(a, "--untracked")) else if (!strcmp(a, "--untracked"))
o->diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; o->diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
else if (!strcmp(a, "--patience"))
o->diffopts.flags |= GIT_DIFF_PATIENCE;
else if (!strcmp(a, "--minimal"))
o->diffopts.flags |= GIT_DIFF_MINIMAL;
else if (!strcmp(a, "--stat"))
o->output |= OUTPUT_STAT;
else if (!strcmp(a, "--numstat"))
o->output |= OUTPUT_NUMSTAT;
else if (!strcmp(a, "--shortstat"))
o->output |= OUTPUT_SHORTSTAT;
else if (!strcmp(a, "--summary"))
o->output |= OUTPUT_SUMMARY;
else if (match_uint16_arg( else if (match_uint16_arg(
&o->findopts.rename_threshold, &args, "-M") || &o->findopts.rename_threshold, &args, "-M") ||
match_uint16_arg( match_uint16_arg(
...@@ -249,9 +299,39 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) ...@@ -249,9 +299,39 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
&o->diffopts.context_lines, &args, "--unified") && &o->diffopts.context_lines, &args, "--unified") &&
!match_uint16_arg( !match_uint16_arg(
&o->diffopts.interhunk_lines, &args, "--inter-hunk-context") && &o->diffopts.interhunk_lines, &args, "--inter-hunk-context") &&
!match_uint16_arg(
&o->diffopts.id_abbrev, &args, "--abbrev") &&
!match_str_arg(&o->diffopts.old_prefix, &args, "--src-prefix") && !match_str_arg(&o->diffopts.old_prefix, &args, "--src-prefix") &&
!match_str_arg(&o->diffopts.new_prefix, &args, "--dst-prefix") && !match_str_arg(&o->diffopts.new_prefix, &args, "--dst-prefix") &&
!match_str_arg(&o->dir, &args, "--git-dir")) !match_str_arg(&o->dir, &args, "--git-dir"))
usage("Unknown command line argument", a); usage("Unknown command line argument", a);
} }
} }
/** Display diff output with "--stat", "--numstat", or "--shortstat" */
static void diff_print_stats(git_diff *diff, struct opts *o)
{
git_diff_stats *stats;
git_buf b = GIT_BUF_INIT_CONST(NULL, 0);
git_diff_stats_format_t format = 0;
check_lg2(
git_diff_get_stats(&stats, diff), "generating stats for diff", NULL);
if (o->output & OUTPUT_STAT)
format |= GIT_DIFF_STATS_FULL;
if (o->output & OUTPUT_SHORTSTAT)
format |= GIT_DIFF_STATS_SHORT;
if (o->output & OUTPUT_NUMSTAT)
format |= GIT_DIFF_STATS_NUMBER;
if (o->output & OUTPUT_SUMMARY)
format |= GIT_DIFF_STATS_INCLUDE_SUMMARY;
check_lg2(
git_diff_stats_to_buf(&b, stats, format, 80), "formatting stats", NULL);
fputs(b.ptr, stdout);
git_buf_free(&b);
git_diff_stats_free(stats);
}
#include <git2.h>
#include <stdio.h>
#include "common.h"
static int show_ref(git_reference *ref, void *data)
{
git_repository *repo = data;
git_reference *resolved = NULL;
char hex[GIT_OID_HEXSZ+1];
const git_oid *oid;
git_object *obj;
if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
check_lg2(git_reference_resolve(&resolved, ref),
"Unable to resolve symbolic reference",
git_reference_name(ref));
oid = git_reference_target(resolved ? resolved : ref);
git_oid_fmt(hex, oid);
hex[GIT_OID_HEXSZ] = 0;
check_lg2(git_object_lookup(&obj, repo, oid, GIT_OBJ_ANY),
"Unable to lookup object", hex);
printf("%s %-6s\t%s\n",
hex,
git_object_type2string(git_object_type(obj)),
git_reference_name(ref));
if (resolved)
git_reference_free(resolved);
return 0;
}
int main(int argc, char **argv)
{
git_repository *repo;
if (argc != 1 || argv[1] /* silence -Wunused-parameter */)
fatal("Sorry, no for-each-ref options supported yet", NULL);
check_lg2(git_repository_open(&repo, "."),
"Could not open repository", NULL);
check_lg2(git_reference_foreach(repo, show_ref, repo),
"Could not iterate over references", NULL);
return 0;
}
...@@ -47,11 +47,10 @@ ...@@ -47,11 +47,10 @@
// as an example. // as an example.
static void check_error(int error_code, const char *action) static void check_error(int error_code, const char *action)
{ {
const git_error *error = giterr_last();
if (!error_code) if (!error_code)
return; return;
const git_error *error = giterr_last();
printf("Error %d %s - %s\n", error_code, action, printf("Error %d %s - %s\n", error_code, action,
(error && error->message) ? error->message : "???"); (error && error->message) ? error->message : "???");
......
...@@ -54,8 +54,9 @@ struct log_options { ...@@ -54,8 +54,9 @@ struct log_options {
int min_parents, max_parents; int min_parents, max_parents;
git_time_t before; git_time_t before;
git_time_t after; git_time_t after;
char *author; const char *author;
char *committer; const char *committer;
const char *grep;
}; };
/** utility functions that parse options and help with log output */ /** utility functions that parse options and help with log output */
...@@ -65,6 +66,9 @@ static void print_time(const git_time *intime, const char *prefix); ...@@ -65,6 +66,9 @@ static void print_time(const git_time *intime, const char *prefix);
static void print_commit(git_commit *commit); static void print_commit(git_commit *commit);
static int match_with_parent(git_commit *commit, int i, git_diff_options *); static int match_with_parent(git_commit *commit, int i, git_diff_options *);
/** utility functions for filtering */
static int signature_matches(const git_signature *sig, const char *filter);
static int log_message_matches(const git_commit *commit, const char *filter);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
...@@ -128,6 +132,15 @@ int main(int argc, char *argv[]) ...@@ -128,6 +132,15 @@ int main(int argc, char *argv[])
continue; continue;
} }
if (!signature_matches(git_commit_author(commit), opt.author))
continue;
if (!signature_matches(git_commit_committer(commit), opt.committer))
continue;
if (!log_message_matches(commit, opt.grep))
continue;
if (count++ < opt.skip) if (count++ < opt.skip)
continue; continue;
if (opt.limit != -1 && printed++ >= opt.limit) { if (opt.limit != -1 && printed++ >= opt.limit) {
...@@ -172,6 +185,32 @@ int main(int argc, char *argv[]) ...@@ -172,6 +185,32 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
/** Determine if the given git_signature does not contain the filter text. */
static int signature_matches(const git_signature *sig, const char *filter) {
if (filter == NULL)
return 1;
if (sig != NULL &&
(strstr(sig->name, filter) != NULL ||
strstr(sig->email, filter) != NULL))
return 1;
return 0;
}
static int log_message_matches(const git_commit *commit, const char *filter) {
const char *message = NULL;
if (filter == NULL)
return 1;
if ((message = git_commit_message(commit)) != NULL &&
strstr(message, filter) != NULL)
return 1;
return 0;
}
/** Push object (for hide or show) onto revwalker. */ /** Push object (for hide or show) onto revwalker. */
static void push_rev(struct log_state *s, git_object *obj, int hide) static void push_rev(struct log_state *s, git_object *obj, int hide)
{ {
...@@ -401,6 +440,12 @@ static int parse_options( ...@@ -401,6 +440,12 @@ static int parse_options(
set_sorting(s, GIT_SORT_TOPOLOGICAL); set_sorting(s, GIT_SORT_TOPOLOGICAL);
else if (!strcmp(a, "--reverse")) else if (!strcmp(a, "--reverse"))
set_sorting(s, GIT_SORT_REVERSE); set_sorting(s, GIT_SORT_REVERSE);
else if (match_str_arg(&opt->author, &args, "--author"))
/** Found valid --author */;
else if (match_str_arg(&opt->committer, &args, "--committer"))
/** Found valid --committer */;
else if (match_str_arg(&opt->grep, &args, "--grep"))
/** Found valid --grep */;
else if (match_str_arg(&s->repodir, &args, "--git-dir")) else if (match_str_arg(&s->repodir, &args, "--git-dir"))
/** Found git-dir. */; /** Found git-dir. */;
else if (match_int_arg(&opt->skip, &args, "--skip", 0)) else if (match_int_arg(&opt->skip, &args, "--skip", 0))
......
...@@ -22,7 +22,7 @@ static void print_progress(const progress_data *pd) ...@@ -22,7 +22,7 @@ static void print_progress(const progress_data *pd)
int index_percent = (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects; int index_percent = (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects;
int checkout_percent = pd->total_steps > 0 int checkout_percent = pd->total_steps > 0
? (100 * pd->completed_steps) / pd->total_steps ? (100 * pd->completed_steps) / pd->total_steps
: 0.f; : 0;
int kbytes = pd->fetch_progress.received_bytes / 1024; int kbytes = pd->fetch_progress.received_bytes / 1024;
if (pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) { if (pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) {
...@@ -62,7 +62,7 @@ int do_clone(git_repository *repo, int argc, char **argv) ...@@ -62,7 +62,7 @@ int do_clone(git_repository *repo, int argc, char **argv)
progress_data pd = {{0}}; progress_data pd = {{0}};
git_repository *cloned_repo = NULL; git_repository *cloned_repo = NULL;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
const char *url = argv[1]; const char *url = argv[1];
const char *path = argv[2]; const char *path = argv[2];
int error; int error;
......
...@@ -91,13 +91,13 @@ int fetch(git_repository *repo, int argc, char **argv) ...@@ -91,13 +91,13 @@ int fetch(git_repository *repo, int argc, char **argv)
// Figure out whether it's a named remote or a URL // Figure out whether it's a named remote or a URL
printf("Fetching %s for repo %p\n", argv[1], repo); printf("Fetching %s for repo %p\n", argv[1], repo);
if (git_remote_load(&remote, repo, argv[1]) < 0) { if (git_remote_load(&remote, repo, argv[1]) < 0) {
if (git_remote_create_inmemory(&remote, repo, NULL, argv[1]) < 0) if (git_remote_create_anonymous(&remote, repo, argv[1], NULL) < 0)
return -1; return -1;
} }
// Set up the callbacks (only update_tips for now) // Set up the callbacks (only update_tips for now)
callbacks.update_tips = &update_cb; callbacks.update_tips = &update_cb;
callbacks.progress = &progress_cb; callbacks.sideband_progress = &progress_cb;
callbacks.credentials = cred_acquire_cb; callbacks.credentials = cred_acquire_cb;
git_remote_set_callbacks(remote, &callbacks); git_remote_set_callbacks(remote, &callbacks);
...@@ -156,7 +156,7 @@ int fetch(git_repository *repo, int argc, char **argv) ...@@ -156,7 +156,7 @@ int fetch(git_repository *repo, int argc, char **argv)
// right commits. This may be needed even if there was no packfile // right commits. This may be needed even if there was no packfile
// to download, which can happen e.g. when the branches have been // to download, which can happen e.g. when the branches have been
// changed but all the neede objects are available locally. // changed but all the neede objects are available locally.
if (git_remote_update_tips(remote) < 0) if (git_remote_update_tips(remote, NULL, NULL) < 0)
return -1; return -1;
git_remote_free(remote); git_remote_free(remote);
......
...@@ -15,7 +15,7 @@ static int use_remote(git_repository *repo, char *name) ...@@ -15,7 +15,7 @@ static int use_remote(git_repository *repo, char *name)
// Find the remote by name // Find the remote by name
error = git_remote_load(&remote, repo, name); error = git_remote_load(&remote, repo, name);
if (error < 0) { if (error < 0) {
error = git_remote_create_inmemory(&remote, repo, NULL, name); error = git_remote_create_anonymous(&remote, repo, name, NULL);
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
} }
......
...@@ -49,7 +49,7 @@ int main (int argc, char** argv) ...@@ -49,7 +49,7 @@ int main (int argc, char** argv)
for (i = 0; i < ecount; ++i) { for (i = 0; i < ecount; ++i) {
const git_index_entry *e = git_index_get_byindex(index, i); const git_index_entry *e = git_index_get_byindex(index, i);
git_oid_fmt(out, &e->oid); git_oid_fmt(out, &e->id);
printf("File Path: %s\n", e->path); printf("File Path: %s\n", e->path);
printf(" Stage: %d\n", git_index_entry_stage(e)); printf(" Stage: %d\n", git_index_entry_stage(e));
......
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
*/ */
#include "common.h" #include "common.h"
#ifdef _WIN32
# include <Windows.h>
# define sleep(a) Sleep(a * 1000)
#else
# include <unistd.h>
#endif
/** /**
* This example demonstrates the use of the libgit2 status APIs, * This example demonstrates the use of the libgit2 status APIs,
...@@ -44,19 +50,22 @@ enum { ...@@ -44,19 +50,22 @@ enum {
#define MAX_PATHSPEC 8 #define MAX_PATHSPEC 8
struct opts { struct opts {
git_status_options statusopt; git_status_options statusopt;
char *repodir; char *repodir;
char *pathspec[MAX_PATHSPEC]; char *pathspec[MAX_PATHSPEC];
int npaths; int npaths;
int format; int format;
int zterm; int zterm;
int showbranch; int showbranch;
int showsubmod;
int repeat;
}; };
static void parse_opts(struct opts *o, int argc, char *argv[]); static void parse_opts(struct opts *o, int argc, char *argv[]);
static void show_branch(git_repository *repo, int format); static void show_branch(git_repository *repo, int format);
static void print_long(git_status_list *status); static void print_long(git_status_list *status);
static void print_short(git_repository *repo, git_status_list *status); static void print_short(git_repository *repo, git_status_list *status);
static int print_submod(git_submodule *sm, const char *name, void *payload);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
...@@ -84,6 +93,10 @@ int main(int argc, char *argv[]) ...@@ -84,6 +93,10 @@ int main(int argc, char *argv[])
fatal("Cannot report status on bare repository", fatal("Cannot report status on bare repository",
git_repository_path(repo)); git_repository_path(repo));
show_status:
if (o.repeat)
printf("\033[H\033[2J");
/** /**
* Run status on the repository * Run status on the repository
* *
...@@ -98,17 +111,29 @@ int main(int argc, char *argv[]) ...@@ -98,17 +111,29 @@ int main(int argc, char *argv[])
* about what results are presented. * about what results are presented.
*/ */
check_lg2(git_status_list_new(&status, repo, &o.statusopt), check_lg2(git_status_list_new(&status, repo, &o.statusopt),
"Could not get status", NULL); "Could not get status", NULL);
if (o.showbranch) if (o.showbranch)
show_branch(repo, o.format); show_branch(repo, o.format);
if (o.showsubmod) {
int submod_count = 0;
check_lg2(git_submodule_foreach(repo, print_submod, &submod_count),
"Cannot iterate submodules", o.repodir);
}
if (o.format == FORMAT_LONG) if (o.format == FORMAT_LONG)
print_long(status); print_long(status);
else else
print_short(repo, status); print_short(repo, status);
git_status_list_free(status); git_status_list_free(status);
if (o.repeat) {
sleep(o.repeat);
goto show_status;
}
git_repository_free(repo); git_repository_free(repo);
git_threads_shutdown(); git_threads_shutdown();
...@@ -363,22 +388,25 @@ static void print_short(git_repository *repo, git_status_list *status) ...@@ -363,22 +388,25 @@ static void print_short(git_repository *repo, git_status_list *status)
unsigned int smstatus = 0; unsigned int smstatus = 0;
if (!git_submodule_lookup( if (!git_submodule_lookup(
&sm, repo, s->index_to_workdir->new_file.path) && &sm, repo, s->index_to_workdir->new_file.path)) {
!git_submodule_status(&smstatus, sm))
{ if (!git_submodule_status(&smstatus, sm)) {
if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED) if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED)
extra = " (new commits)"; extra = " (new commits)";
else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED)
extra = " (modified content)"; extra = " (modified content)";
else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED)
extra = " (modified content)"; extra = " (modified content)";
else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED) else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED)
extra = " (untracked content)"; extra = " (untracked content)";
}
} }
git_submodule_free(sm);
} }
/** /**
* Now that we have all the information, it's time to format the output. * Now that we have all the information, format the output.
*/ */
if (s->head_to_index) { if (s->head_to_index) {
...@@ -414,6 +442,21 @@ static void print_short(git_repository *repo, git_status_list *status) ...@@ -414,6 +442,21 @@ static void print_short(git_repository *repo, git_status_list *status)
} }
} }
static int print_submod(git_submodule *sm, const char *name, void *payload)
{
int *count = payload;
(void)name;
if (*count == 0)
printf("# Submodules\n");
(*count)++;
printf("# - submodule '%s' at %s\n",
git_submodule_name(sm), git_submodule_path(sm));
return 0;
}
/** /**
* Parse options that git's status command supports. * Parse options that git's status command supports.
*/ */
...@@ -459,6 +502,12 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) ...@@ -459,6 +502,12 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
o->statusopt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; o->statusopt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES;
else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) else if (!strncmp(a, "--git-dir=", strlen("--git-dir=")))
o->repodir = a + strlen("--git-dir="); o->repodir = a + strlen("--git-dir=");
else if (!strcmp(a, "--repeat"))
o->repeat = 10;
else if (match_int_arg(&o->repeat, &args, "--repeat", 0))
/* okay */;
else if (!strcmp(a, "--list-submodules"))
o->showsubmod = 1;
else else
check_lg2(-1, "Unsupported option", a); check_lg2(-1, "Unsupported option", a);
} }
......
/*
* libgit2 "tag" example - shows how to list, create and delete tags
*
* Written by the libgit2 contributors
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "common.h"
/**
* The following example partially reimplements the `git tag` command
* and some of its options.
*
* These commands should work:
* - Tag name listing (`tag`)
* - Filtered tag listing with messages (`tag -n3 -l "v0.1*"`)
* - Lightweight tag creation (`tag test v0.18.0`)
* - Tag creation (`tag -a -m "Test message" test v0.18.0`)
* - Tag deletion (`tag -d test`)
*
* The command line parsing logic is simplified and doesn't handle
* all of the use cases.
*/
/** tag_options represents the parsed command line options */
typedef struct {
const char *message;
const char *pattern;
const char *tag_name;
const char *target;
int num_lines;
int force;
} tag_options;
/** tag_state represents the current program state for dragging around */
typedef struct {
git_repository *repo;
tag_options *opts;
} tag_state;
/** An action to execute based on the command line arguments */
typedef void (*tag_action)(tag_state *state);
typedef struct args_info args_info;
static void check(int result, const char *message)
{
if (result) fatal(message, NULL);
}
/** Tag listing: Print individual message lines */
static void print_list_lines(const char *message, const tag_state *state)
{
const char *msg = message;
int num = state->opts->num_lines - 1;
if (!msg) return;
/** first line - headline */
while(*msg && *msg != '\n') printf("%c", *msg++);
/** skip over new lines */
while(*msg && *msg == '\n') msg++;
printf("\n");
/** print just headline? */
if (num == 0) return;
if (*msg && msg[1]) printf("\n");
/** print individual commit/tag lines */
while (*msg && num-- >= 2) {
printf(" ");
while (*msg && *msg != '\n') printf("%c", *msg++);
/** handle consecutive new lines */
if (*msg && *msg == '\n' && msg[1] == '\n') {
num--;
printf("\n");
}
while(*msg && *msg == '\n') msg++;
printf("\n");
}
}
/** Tag listing: Print an actual tag object */
static void print_tag(git_tag *tag, const tag_state *state)
{
printf("%-16s", git_tag_name(tag));
if (state->opts->num_lines) {
const char *msg = git_tag_message(tag);
print_list_lines(msg, state);
} else {
printf("\n");
}
}
/** Tag listing: Print a commit (target of a lightweight tag) */
static void print_commit(git_commit *commit, const char *name,
const tag_state *state)
{
printf("%-16s", name);
if (state->opts->num_lines) {
const char *msg = git_commit_message(commit);
print_list_lines(msg, state);
} else {
printf("\n");
}
}
/** Tag listing: Fallback, should not happen */
static void print_name(const char *name)
{
printf("%s\n", name);
}
/** Tag listing: Lookup tags based on ref name and dispatch to print */
static int each_tag(const char *name, tag_state *state)
{
git_repository *repo = state->repo;
git_object *obj;
check_lg2(git_revparse_single(&obj, repo, name),
"Failed to lookup rev", name);
switch (git_object_type(obj)) {
case GIT_OBJ_TAG:
print_tag((git_tag *) obj, state);
break;
case GIT_OBJ_COMMIT:
print_commit((git_commit *) obj, name, state);
break;
default:
print_name(name);
}
git_object_free(obj);
return 0;
}
static void action_list_tags(tag_state *state)
{
const char *pattern = state->opts->pattern;
git_strarray tag_names = {0};
size_t i;
check_lg2(git_tag_list_match(&tag_names, pattern ? pattern : "*", state->repo),
"Unable to get list of tags", NULL);
for(i = 0; i < tag_names.count; i++) {
each_tag(tag_names.strings[i], state);
}
git_strarray_free(&tag_names);
}
static void action_delete_tag(tag_state *state)
{
tag_options *opts = state->opts;
git_object *obj;
git_buf abbrev_oid = {0};
check(!opts->tag_name, "Name required");
check_lg2(git_revparse_single(&obj, state->repo, opts->tag_name),
"Failed to lookup rev", opts->tag_name);
check_lg2(git_object_short_id(&abbrev_oid, obj),
"Unable to get abbreviated OID", opts->tag_name);
check_lg2(git_tag_delete(state->repo, opts->tag_name),
"Unable to delete tag", opts->tag_name);
printf("Deleted tag '%s' (was %s)\n", opts->tag_name, abbrev_oid.ptr);
git_buf_free(&abbrev_oid);
git_object_free(obj);
}
static void action_create_lighweight_tag(tag_state *state)
{
git_repository *repo = state->repo;
tag_options *opts = state->opts;
git_oid oid;
git_object *target;
check(!opts->tag_name, "Name required");
if (!opts->target) opts->target = "HEAD";
check(!opts->target, "Target required");
check_lg2(git_revparse_single(&target, repo, opts->target),
"Unable to resolve spec", opts->target);
check_lg2(git_tag_create_lightweight(&oid, repo, opts->tag_name,
target, opts->force), "Unable to create tag", NULL);
git_object_free(target);
}
static void action_create_tag(tag_state *state)
{
git_repository *repo = state->repo;
tag_options *opts = state->opts;
git_signature *tagger;
git_oid oid;
git_object *target;
check(!opts->tag_name, "Name required");
check(!opts->message, "Message required");
if (!opts->target) opts->target = "HEAD";
check_lg2(git_revparse_single(&target, repo, opts->target),
"Unable to resolve spec", opts->target);
check_lg2(git_signature_default(&tagger, repo),
"Unable to create signature", NULL);
check_lg2(git_tag_create(&oid, repo, opts->tag_name,
target, tagger, opts->message, opts->force), "Unable to create tag", NULL);
git_object_free(target);
git_signature_free(tagger);
}
static void print_usage()
{
fprintf(stderr, "usage: see `git help tag`\n");
exit(1);
}
/** Parse command line arguments and choose action to run when done */
static void parse_options(tag_action *action, tag_options *opts, int argc, char **argv)
{
args_info args = ARGS_INFO_INIT;
*action = &action_list_tags;
for (args.pos = 1; args.pos < argc; ++args.pos) {
const char *curr = argv[args.pos];
if (curr[0] != '-') {
if (!opts->tag_name)
opts->tag_name = curr;
else if (!opts->target)
opts->target = curr;
else
print_usage();
if (*action != &action_create_tag)
*action = &action_create_lighweight_tag;
} else if (!strcmp(curr, "-n")) {
opts->num_lines = 1;
*action = &action_list_tags;
} else if (!strcmp(curr, "-a")) {
*action = &action_create_tag;
} else if (!strcmp(curr, "-f")) {
opts->force = 1;
} else if (match_int_arg(&opts->num_lines, &args, "-n", 0)) {
*action = &action_list_tags;
} else if (match_str_arg(&opts->pattern, &args, "-l")) {
*action = &action_list_tags;
} else if (match_str_arg(&opts->tag_name, &args, "-d")) {
*action = &action_delete_tag;
} else if (match_str_arg(&opts->message, &args, "-m")) {
*action = &action_create_tag;
}
}
}
/** Initialize tag_options struct */
static void tag_options_init(tag_options *opts)
{
memset(opts, 0, sizeof(*opts));
opts->message = NULL;
opts->pattern = NULL;
opts->tag_name = NULL;
opts->target = NULL;
opts->num_lines = 0;
opts->force = 0;
}
int main(int argc, char **argv)
{
git_repository *repo;
tag_options opts;
tag_action action;
tag_state state;
git_threads_init();
check_lg2(git_repository_open_ext(&repo, ".", 0, NULL),
"Could not open repository", NULL);
tag_options_init(&opts);
parse_options(&action, &opts, argc, argv);
state.repo = repo;
state.opts = &opts;
action(&state);
git_repository_free(repo);
git_threads_shutdown();
return 0;
}
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
# his/her consent on a patch-by-patch basis. # his/her consent on a patch-by-patch basis.
# "???" means the person is a prominent contributor who has # "???" means the person is a prominent contributor who has
# not yet made his/her standpoint clear. # not yet made his/her standpoint clear.
# "ign" means the authors consent is ignored for the purpose
# of libification. This is because the author has contributed
# to areas that aren't interesting for the library.
# #
# Please try to keep the list alphabetically ordered. It will # Please try to keep the list alphabetically ordered. It will
# help in case we get all 600-ish git.git authors on it. # help in case we get all 600-ish git.git authors on it.
...@@ -39,33 +36,39 @@ ...@@ -39,33 +36,39 @@
# but has otherwise not contributed to git.) # but has otherwise not contributed to git.)
# #
ok Adam Simpkins <adam@adamsimpkins.net> (http transport) ok Adam Simpkins <adam@adamsimpkins.net> (http transport)
ok Adrian Johnson <ajohnson@redneon.com>
ok Alexey Shumkin <alex.crezoff@gmail.com>
ok Andreas Ericsson <ae@op5.se> ok Andreas Ericsson <ae@op5.se>
ok Boyd Lynn Gerber <gerberb@zenez.com> ok Boyd Lynn Gerber <gerberb@zenez.com>
ok Brandon Casey <drafnel@gmail.com>
ok Brian Downing <bdowning@lavos.net> ok Brian Downing <bdowning@lavos.net>
ok Brian Gernhardt <benji@silverinsanity.com> ok Brian Gernhardt <benji@silverinsanity.com>
ok Christian Couder <chriscool@tuxfamily.org> ok Christian Couder <chriscool@tuxfamily.org>
ok Daniel Barkalow <barkalow@iabervon.org> ok Daniel Barkalow <barkalow@iabervon.org>
ok Florian Forster <octo@verplant.org> ok Florian Forster <octo@verplant.org>
ok Gustaf Hendeby <hendeby@isy.liu.se>
ok Holger Weiss <holger@zedat.fu-berlin.de> ok Holger Weiss <holger@zedat.fu-berlin.de>
ok Jeff King <peff@peff.net> ok Jeff King <peff@peff.net>
ok Johannes Schindelin <Johannes.Schindelin@gmx.de> ok Johannes Schindelin <Johannes.Schindelin@gmx.de>
ok Johannes Sixt <j6t@kdbg.org> ok Johannes Sixt <j6t@kdbg.org>
ask Jonathan Nieder <jrnieder@gmail.com>
ok Junio C Hamano <gitster@pobox.com> ok Junio C Hamano <gitster@pobox.com>
ok Kristian Høgsberg <krh@redhat.com> ok Kristian Høgsberg <krh@redhat.com>
ok Linus Torvalds <torvalds@linux-foundation.org> ok Linus Torvalds <torvalds@linux-foundation.org>
ok Lukas Sandström <lukass@etek.chalmers.se> ok Lukas Sandström <lukass@etek.chalmers.se>
ok Matthieu Moy <Matthieu.Moy@imag.fr> ok Matthieu Moy <Matthieu.Moy@imag.fr>
ign Mike McCormack <mike@codeweavers.com> (imap-send) ok Michael Haggerty <mhagger@alum.mit.edu>
ok Nicolas Pitre <nico@fluxnic.net> <nico@cam.org> ok Nicolas Pitre <nico@fluxnic.net> <nico@cam.org>
ok Paolo Bonzini <bonzini@gnu.org> ok Paolo Bonzini <bonzini@gnu.org>
ok Paul Kocher <paul@cryptography.com> ok Paul Kocher <paul@cryptography.com>
ok Peter Hagervall <hager@cs.umu.se> ok Peter Hagervall <hager@cs.umu.se>
ok Petr Onderka <gsvick@gmail.com>
ok Pierre Habouzit <madcoder@debian.org> ok Pierre Habouzit <madcoder@debian.org>
ok Pieter de Bie <pdebie@ai.rug.nl> ok Pieter de Bie <pdebie@ai.rug.nl>
ok René Scharfe <rene.scharfe@lsrfire.ath.cx> ok René Scharfe <rene.scharfe@lsrfire.ath.cx>
ign Robert Shearman <rob@codeweavers.com> (imap-send)
ok Sebastian Schuberth <sschuberth@gmail.com> ok Sebastian Schuberth <sschuberth@gmail.com>
ok Shawn O. Pearce <spearce@spearce.org> ok Shawn O. Pearce <spearce@spearce.org>
ok Steffen Prohaska <prohaska@zib.de> ok Steffen Prohaska <prohaska@zib.de>
ok Sven Verdoolaege <skimo@kotnet.org> ok Sven Verdoolaege <skimo@kotnet.org>
ask Thomas Rast <tr@thomasrast.ch> (ok before 6-Oct-2013)
ok Torsten Bögershausen <tboegi@web.de> ok Torsten Bögershausen <tboegi@web.de>
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "git2/branch.h" #include "git2/branch.h"
#include "git2/buffer.h" #include "git2/buffer.h"
#include "git2/checkout.h" #include "git2/checkout.h"
#include "git2/cherrypick.h"
#include "git2/clone.h" #include "git2/clone.h"
#include "git2/commit.h" #include "git2/commit.h"
#include "git2/common.h" #include "git2/common.h"
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
#include "git2/remote.h" #include "git2/remote.h"
#include "git2/repository.h" #include "git2/repository.h"
#include "git2/reset.h" #include "git2/reset.h"
#include "git2/revert.h"
#include "git2/revparse.h" #include "git2/revparse.h"
#include "git2/revwalk.h" #include "git2/revwalk.h"
#include "git2/signature.h" #include "git2/signature.h"
......
...@@ -199,8 +199,9 @@ typedef int (*git_attr_foreach_cb)(const char *name, const char *value, void *pa ...@@ -199,8 +199,9 @@ typedef int (*git_attr_foreach_cb)(const char *name, const char *value, void *pa
* only once per attribute name, even if there are multiple * only once per attribute name, even if there are multiple
* rules for a given file. The highest priority rule will be * rules for a given file. The highest priority rule will be
* used. Return a non-zero value from this to stop looping. * used. Return a non-zero value from this to stop looping.
* The value will be returned from `git_attr_foreach`.
* @param payload Passed on as extra parameter to callback function. * @param payload Passed on as extra parameter to callback function.
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_attr_foreach( GIT_EXTERN(int) git_attr_foreach(
git_repository *repo, git_repository *repo,
......
...@@ -40,6 +40,9 @@ typedef enum { ...@@ -40,6 +40,9 @@ typedef enum {
* commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES. * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES.
* NOT IMPLEMENTED. */ * NOT IMPLEMENTED. */
GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3), GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3),
/** Restrict the search of commits to those reachable following only the
* first parents. */
GIT_BLAME_FIRST_PARENT = (1<<4),
} git_blame_flag_t; } git_blame_flag_t;
/** /**
...@@ -80,6 +83,18 @@ typedef struct git_blame_options { ...@@ -80,6 +83,18 @@ typedef struct git_blame_options {
#define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION} #define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION}
/** /**
* Initializes a `git_blame_options` with default values. Equivalent to
* creating an instance with GIT_BLAME_OPTIONS_INIT.
*
* @param opts The `git_blame_options` struct to initialize
* @param version Version of struct; pass `GIT_BLAME_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_blame_init_options(
git_blame_options *opts,
unsigned int version);
/**
* Structure that represents a blame hunk. * Structure that represents a blame hunk.
* *
* - `lines_in_hunk` is the number of lines in this hunk * - `lines_in_hunk` is the number of lines in this hunk
...@@ -183,7 +198,7 @@ GIT_EXTERN(int) git_blame_buffer( ...@@ -183,7 +198,7 @@ GIT_EXTERN(int) git_blame_buffer(
git_blame **out, git_blame **out,
git_blame *reference, git_blame *reference,
const char *buffer, const char *buffer,
uint32_t buffer_len); size_t buffer_len);
/** /**
* Free memory allocated by git_blame_file or git_blame_buffer. * Free memory allocated by git_blame_file or git_blame_buffer.
......
...@@ -84,7 +84,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob); ...@@ -84,7 +84,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob);
* time. * time.
* *
* @param blob pointer to the blob * @param blob pointer to the blob
* @return the pointer; NULL if the blob has no contents * @return the pointer
*/ */
GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob); GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
...@@ -159,37 +159,32 @@ typedef int (*git_blob_chunk_cb)(char *content, size_t max_length, void *payload ...@@ -159,37 +159,32 @@ typedef int (*git_blob_chunk_cb)(char *content, size_t max_length, void *payload
* Write a loose blob to the Object Database from a * Write a loose blob to the Object Database from a
* provider of chunks of data. * provider of chunks of data.
* *
* Provided the `hintpath` parameter is filled, its value * If the `hintpath` parameter is filled, it will be used to determine
* will help to determine what git filters should be applied * what git filters should be applied to the object before it is written
* to the object before it can be placed to the object database. * to the object database.
* *
* The implementation of the callback MUST respect the following rules:
* *
* The implementation of the callback has to respect the * - `content` must be filled by the callback. The maximum number of
* following rules: * bytes that the buffer can accept per call is defined by the
* `max_length` parameter. Allocation and freeing of the buffer will
* be taken care of by libgit2.
* *
* - `content` will have to be filled by the consumer. The maximum number * - The `callback` must return the number of bytes that have been
* of bytes that the buffer can accept per call is defined by the * written to the `content` buffer.
* `max_length` parameter. Allocation and freeing of the buffer will be taken
* care of by the function.
* *
* - The callback is expected to return the number of bytes * - When there is no more data to stream, `callback` should return
* that `content` have been filled with. * 0. This will prevent it from being invoked anymore.
*
* - When there is no more data to stream, the callback should
* return 0. This will prevent it from being invoked anymore.
*
* - When an error occurs, the callback should return -1.
* *
* - If an error occurs, the callback should return a negative value.
* This value will be returned to the caller.
* *
* @param id Return the id of the written blob * @param id Return the id of the written blob
* * @param repo Repository where the blob will be written.
* @param repo repository where the blob will be written. * This repository can be bare or not.
* This repository can be bare or not. * @param hintpath If not NULL, will be used to select data filters
* * to apply onto the content of the blob to be created.
* @param hintpath if not NULL, will help selecting the filters * @return 0 or error code (from either libgit2 or callback function)
* to apply onto the content of the blob to be created.
*
* @return 0 or an error code
*/ */
GIT_EXTERN(int) git_blob_create_fromchunks( GIT_EXTERN(int) git_blob_create_fromchunks(
git_oid *id, git_oid *id,
...@@ -201,26 +196,27 @@ GIT_EXTERN(int) git_blob_create_fromchunks( ...@@ -201,26 +196,27 @@ GIT_EXTERN(int) git_blob_create_fromchunks(
/** /**
* Write an in-memory buffer to the ODB as a blob * Write an in-memory buffer to the ODB as a blob
* *
* @param oid return the oid of the written blob * @param id return the id of the written blob
* @param repo repository where to blob will be written * @param repo repository where to blob will be written
* @param buffer data to be written into the blob * @param buffer data to be written into the blob
* @param len length of the data * @param len length of the data
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len); GIT_EXTERN(int) git_blob_create_frombuffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len);
/** /**
* Determine if the blob content is most certainly binary or not. * Determine if the blob content is most certainly binary or not.
* *
* The heuristic used to guess if a file is binary is taken from core git: * The heuristic used to guess if a file is binary is taken from core git:
* Searching for NUL bytes and looking for a reasonable ratio of printable * Searching for NUL bytes and looking for a reasonable ratio of printable
* to non-printable characters among the first 4000 bytes. * to non-printable characters among the first 8000 bytes.
* *
* @param blob The blob which content should be analyzed * @param blob The blob which content should be analyzed
* @return 1 if the content of the blob is detected * @return 1 if the content of the blob is detected
* as binary; 0 otherwise. * as binary; 0 otherwise.
*/ */
GIT_EXTERN(int) git_blob_is_binary(git_blob *blob); GIT_EXTERN(int) git_blob_is_binary(const git_blob *blob);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -43,6 +43,12 @@ GIT_BEGIN_DECL ...@@ -43,6 +43,12 @@ GIT_BEGIN_DECL
* *
* @param force Overwrite existing branch. * @param force Overwrite existing branch.
* *
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog.
* If NULL, the default is "Branch: created"; if you want something more
* useful, provide a message.
*
* @return 0, GIT_EINVALIDSPEC or an error code. * @return 0, GIT_EINVALIDSPEC or an error code.
* A proper reference is written in the refs/heads namespace * A proper reference is written in the refs/heads namespace
* pointing to the provided target commit. * pointing to the provided target commit.
...@@ -52,7 +58,9 @@ GIT_EXTERN(int) git_branch_create( ...@@ -52,7 +58,9 @@ GIT_EXTERN(int) git_branch_create(
git_repository *repo, git_repository *repo,
const char *branch_name, const char *branch_name,
const git_commit *target, const git_commit *target,
int force); int force,
const git_signature *signature,
const char *log_message);
/** /**
* Delete an existing branch reference. * Delete an existing branch reference.
...@@ -76,7 +84,7 @@ typedef struct git_branch_iterator git_branch_iterator; ...@@ -76,7 +84,7 @@ typedef struct git_branch_iterator git_branch_iterator;
* @param repo Repository where to find the branches. * @param repo Repository where to find the branches.
* @param list_flags Filtering flags for the branch * @param list_flags Filtering flags for the branch
* listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE * listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE
* or a combination of the two. * or GIT_BRANCH_ALL.
* *
* @return 0 on success or an error code * @return 0 on success or an error code
*/ */
...@@ -115,13 +123,19 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter); ...@@ -115,13 +123,19 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
* *
* @param force Overwrite existing branch. * @param force Overwrite existing branch.
* *
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog
*
* @return 0 on success, GIT_EINVALIDSPEC or an error code. * @return 0 on success, GIT_EINVALIDSPEC or an error code.
*/ */
GIT_EXTERN(int) git_branch_move( GIT_EXTERN(int) git_branch_move(
git_reference **out, git_reference **out,
git_reference *branch, git_reference *branch,
const char *new_branch_name, const char *new_branch_name,
int force); int force,
const git_signature *signature,
const char *log_message);
/** /**
* Lookup a branch by its name in a repository. * Lookup a branch by its name in a repository.
...@@ -165,8 +179,9 @@ GIT_EXTERN(int) git_branch_lookup( ...@@ -165,8 +179,9 @@ GIT_EXTERN(int) git_branch_lookup(
* @return 0 on success; otherwise an error code (e.g., if the * @return 0 on success; otherwise an error code (e.g., if the
* ref is no local or remote branch). * ref is no local or remote branch).
*/ */
GIT_EXTERN(int) git_branch_name(const char **out, GIT_EXTERN(int) git_branch_name(
git_reference *ref); const char **out,
const git_reference *ref);
/** /**
* Return the reference supporting the remote tracking branch, * Return the reference supporting the remote tracking branch,
...@@ -182,7 +197,7 @@ GIT_EXTERN(int) git_branch_name(const char **out, ...@@ -182,7 +197,7 @@ GIT_EXTERN(int) git_branch_name(const char **out,
*/ */
GIT_EXTERN(int) git_branch_upstream( GIT_EXTERN(int) git_branch_upstream(
git_reference **out, git_reference **out,
git_reference *branch); const git_reference *branch);
/** /**
* Set the upstream configuration for a given local branch * Set the upstream configuration for a given local branch
...@@ -200,25 +215,20 @@ GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstr ...@@ -200,25 +215,20 @@ GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstr
* Return the name of the reference supporting the remote tracking branch, * Return the name of the reference supporting the remote tracking branch,
* given the name of a local branch reference. * given the name of a local branch reference.
* *
* @param tracking_branch_name_out The user-allocated buffer which will be * @param out Pointer to the user-allocated git_buf which will be
* filled with the name of the reference. Pass NULL if you just want to * filled with the name of the reference.
* get the needed size of the name of the reference as the output value.
*
* @param buffer_size Size of the `out` buffer in bytes.
* *
* @param repo the repository where the branches live * @param repo the repository where the branches live
* *
* @param canonical_branch_name name of the local branch. * @param refname reference name of the local branch.
* *
* @return number of characters in the reference name * @return 0, GIT_ENOTFOUND when no remote tracking reference exists,
* including the trailing NUL byte; GIT_ENOTFOUND when no remote tracking * otherwise an error code.
* reference exists, otherwise an error code.
*/ */
GIT_EXTERN(int) git_branch_upstream_name( GIT_EXTERN(int) git_branch_upstream_name(
char *tracking_branch_name_out, git_buf *out,
size_t buffer_size,
git_repository *repo, git_repository *repo,
const char *canonical_branch_name); const char *refname);
/** /**
* Determine if the current local branch is pointed at by HEAD. * Determine if the current local branch is pointed at by HEAD.
...@@ -229,30 +239,24 @@ GIT_EXTERN(int) git_branch_upstream_name( ...@@ -229,30 +239,24 @@ GIT_EXTERN(int) git_branch_upstream_name(
* error code otherwise. * error code otherwise.
*/ */
GIT_EXTERN(int) git_branch_is_head( GIT_EXTERN(int) git_branch_is_head(
git_reference *branch); const git_reference *branch);
/** /**
* Return the name of remote that the remote tracking branch belongs to. * Return the name of remote that the remote tracking branch belongs to.
* *
* @param remote_name_out The user-allocated buffer which will be * @param out Pointer to the user-allocated git_buf which will be filled iwth the name of the remote.
* filled with the name of the remote. Pass NULL if you just want to
* get the needed size of the name of the remote as the output value.
*
* @param buffer_size Size of the `out` buffer in bytes.
* *
* @param repo The repository where the branch lives. * @param repo The repository where the branch lives.
* *
* @param canonical_branch_name name of the remote tracking branch. * @param canonical_branch_name name of the remote tracking branch.
* *
* @return Number of characters in the reference name * @return 0, GIT_ENOTFOUND
* including the trailing NUL byte; GIT_ENOTFOUND
* when no remote matching remote was found, * when no remote matching remote was found,
* GIT_EAMBIGUOUS when the branch maps to several remotes, * GIT_EAMBIGUOUS when the branch maps to several remotes,
* otherwise an error code. * otherwise an error code.
*/ */
GIT_EXTERN(int) git_branch_remote_name( GIT_EXTERN(int) git_branch_remote_name(
char *remote_name_out, git_buf *out,
size_t buffer_size,
git_repository *repo, git_repository *repo,
const char *canonical_branch_name); const char *canonical_branch_name);
......
...@@ -43,17 +43,17 @@ GIT_BEGIN_DECL ...@@ -43,17 +43,17 @@ GIT_BEGIN_DECL
* In between those are `GIT_CHECKOUT_SAFE` and `GIT_CHECKOUT_SAFE_CREATE` * In between those are `GIT_CHECKOUT_SAFE` and `GIT_CHECKOUT_SAFE_CREATE`
* both of which only make modifications that will not lose changes. * both of which only make modifications that will not lose changes.
* *
* | target == baseline | target != baseline | * | target == baseline | target != baseline |
* ---------------------|-----------------------|----------------------| * ---------------------|-----------------------|----------------------|
* workdir == baseline | no action | create, update, or | * workdir == baseline | no action | create, update, or |
* | | delete file | * | | delete file |
* ---------------------|-----------------------|----------------------| * ---------------------|-----------------------|----------------------|
* workdir exists and | no action | conflict (notify | * workdir exists and | no action | conflict (notify |
* is != baseline | notify dirty MODIFIED | and cancel checkout) | * is != baseline | notify dirty MODIFIED | and cancel checkout) |
* ---------------------|-----------------------|----------------------| * ---------------------|-----------------------|----------------------|
* workdir missing, | create if SAFE_CREATE | create file | * workdir missing, | create if SAFE_CREATE | create file |
* baseline present | notify dirty DELETED | | * baseline present | notify dirty DELETED | |
* ---------------------|-----------------------|----------------------| * ---------------------|-----------------------|----------------------|
* *
* The only difference between SAFE and SAFE_CREATE is that SAFE_CREATE * The only difference between SAFE and SAFE_CREATE is that SAFE_CREATE
* will cause a file to be checked out if it is missing from the working * will cause a file to be checked out if it is missing from the working
...@@ -99,9 +99,14 @@ GIT_BEGIN_DECL ...@@ -99,9 +99,14 @@ GIT_BEGIN_DECL
* files with unmerged index entries instead. GIT_CHECKOUT_USE_OURS and * files with unmerged index entries instead. GIT_CHECKOUT_USE_OURS and
* GIT_CHECKOUT_USE_THEIRS to proceed with the checkout using either the * GIT_CHECKOUT_USE_THEIRS to proceed with the checkout using either the
* stage 2 ("ours") or stage 3 ("theirs") version of files in the index. * stage 2 ("ours") or stage 3 ("theirs") version of files in the index.
*
* - GIT_CHECKOUT_DONT_OVERWRITE_IGNORED prevents ignored files from being
* overwritten. Normally, files that are ignored in the working directory
* are not considered "precious" and may be overwritten if the checkout
* target contains that file.
*/ */
typedef enum { typedef enum {
GIT_CHECKOUT_NONE = 0, /** default is a dry run, no actual updates */ GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */
/** Allow safe updates that cannot overwrite uncommitted data */ /** Allow safe updates that cannot overwrite uncommitted data */
GIT_CHECKOUT_SAFE = (1u << 0), GIT_CHECKOUT_SAFE = (1u << 0),
...@@ -144,6 +149,15 @@ typedef enum { ...@@ -144,6 +149,15 @@ typedef enum {
/** Ignore directories in use, they will be left empty */ /** Ignore directories in use, they will be left empty */
GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1u << 18), GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1u << 18),
/** Don't overwrite ignored files that exist in the checkout target */
GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1u << 19),
/** Write normal merge files for conflicts */
GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1u << 20),
/** Include common ancestor data in diff3 format files for conflicts */
GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1u << 21),
/** /**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/ */
...@@ -174,7 +188,12 @@ typedef enum { ...@@ -174,7 +188,12 @@ typedef enum {
* - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files. * - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files.
* *
* Returning a non-zero value from this callback will cancel the checkout. * Returning a non-zero value from this callback will cancel the checkout.
* Notification callbacks are made prior to modifying any files on disk. * The non-zero return value will be propagated back and returned by the
* git_checkout_... call.
*
* Notification callbacks are made prior to modifying any files on disk,
* so canceling on any notification will still happen prior to any files
* being modified.
*/ */
typedef enum { typedef enum {
GIT_CHECKOUT_NOTIFY_NONE = 0, GIT_CHECKOUT_NOTIFY_NONE = 0,
...@@ -206,12 +225,12 @@ typedef void (*git_checkout_progress_cb)( ...@@ -206,12 +225,12 @@ typedef void (*git_checkout_progress_cb)(
/** /**
* Checkout options structure * Checkout options structure
* *
* Zero out for defaults. Initialize with `GIT_CHECKOUT_OPTS_INIT` macro to * Zero out for defaults. Initialize with `GIT_CHECKOUT_OPTIONS_INIT` macro to
* correctly set the `version` field. E.g. * correctly set the `version` field. E.g.
* *
* git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; * git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
*/ */
typedef struct git_checkout_opts { typedef struct git_checkout_options {
unsigned int version; unsigned int version;
unsigned int checkout_strategy; /** default will be a dry run */ unsigned int checkout_strategy; /** default will be a dry run */
...@@ -239,12 +258,25 @@ typedef struct git_checkout_opts { ...@@ -239,12 +258,25 @@ typedef struct git_checkout_opts {
const char *target_directory; /** alternative checkout path to workdir */ const char *target_directory; /** alternative checkout path to workdir */
const char *ancestor_label; /** the name of the common ancestor side of conflicts */
const char *our_label; /** the name of the "our" side of conflicts */ const char *our_label; /** the name of the "our" side of conflicts */
const char *their_label; /** the name of the "their" side of conflicts */ const char *their_label; /** the name of the "their" side of conflicts */
} git_checkout_opts; } git_checkout_options;
#define GIT_CHECKOUT_OPTIONS_VERSION 1
#define GIT_CHECKOUT_OPTIONS_INIT {GIT_CHECKOUT_OPTIONS_VERSION}
#define GIT_CHECKOUT_OPTS_VERSION 1 /**
#define GIT_CHECKOUT_OPTS_INIT {GIT_CHECKOUT_OPTS_VERSION} * Initializes a `git_checkout_options` with default values. Equivalent to
* creating an instance with GIT_CHECKOUT_OPTIONS_INIT.
*
* @param opts the `git_checkout_options` struct to initialize.
* @param version Version of struct; pass `GIT_CHECKOUT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_checkout_init_options(
git_checkout_options *opts,
unsigned int version);
/** /**
* Updates files in the index and the working tree to match the content of * Updates files in the index and the working tree to match the content of
...@@ -252,13 +284,13 @@ typedef struct git_checkout_opts { ...@@ -252,13 +284,13 @@ typedef struct git_checkout_opts {
* *
* @param repo repository to check out (must be non-bare) * @param repo repository to check out (must be non-bare)
* @param opts specifies checkout options (may be NULL) * @param opts specifies checkout options (may be NULL)
* @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * @return 0 on success, GIT_EUNBORNBRANCH if HEAD points to a non
* branch, GIT_ERROR otherwise (use giterr_last for information * existing branch, non-zero value returned by `notify_cb`, or
* about the error) * other error code < 0 (use giterr_last for error details)
*/ */
GIT_EXTERN(int) git_checkout_head( GIT_EXTERN(int) git_checkout_head(
git_repository *repo, git_repository *repo,
const git_checkout_opts *opts); const git_checkout_options *opts);
/** /**
* Updates files in the working tree to match the content of the index. * Updates files in the working tree to match the content of the index.
...@@ -266,13 +298,13 @@ GIT_EXTERN(int) git_checkout_head( ...@@ -266,13 +298,13 @@ GIT_EXTERN(int) git_checkout_head(
* @param repo repository into which to check out (must be non-bare) * @param repo repository into which to check out (must be non-bare)
* @param index index to be checked out (or NULL to use repository index) * @param index index to be checked out (or NULL to use repository index)
* @param opts specifies checkout options (may be NULL) * @param opts specifies checkout options (may be NULL)
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * @return 0 on success, non-zero return value from `notify_cb`, or error
* about the error) * code < 0 (use giterr_last for error details)
*/ */
GIT_EXTERN(int) git_checkout_index( GIT_EXTERN(int) git_checkout_index(
git_repository *repo, git_repository *repo,
git_index *index, git_index *index,
const git_checkout_opts *opts); const git_checkout_options *opts);
/** /**
* Updates files in the index and working tree to match the content of the * Updates files in the index and working tree to match the content of the
...@@ -282,13 +314,13 @@ GIT_EXTERN(int) git_checkout_index( ...@@ -282,13 +314,13 @@ GIT_EXTERN(int) git_checkout_index(
* @param treeish a commit, tag or tree which content will be used to update * @param treeish a commit, tag or tree which content will be used to update
* the working directory (or NULL to use HEAD) * the working directory (or NULL to use HEAD)
* @param opts specifies checkout options (may be NULL) * @param opts specifies checkout options (may be NULL)
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * @return 0 on success, non-zero return value from `notify_cb`, or error
* about the error) * code < 0 (use giterr_last for error details)
*/ */
GIT_EXTERN(int) git_checkout_tree( GIT_EXTERN(int) git_checkout_tree(
git_repository *repo, git_repository *repo,
const git_object *treeish, const git_object *treeish,
const git_checkout_opts *opts); const git_checkout_options *opts);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_cherrypick_h__
#define INCLUDE_git_cherrypick_h__
#include "common.h"
#include "types.h"
#include "merge.h"
/**
* @file git2/cherrypick.h
* @brief Git cherry-pick routines
* @defgroup git_cherrypick Git cherry-pick routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
typedef struct {
unsigned int version;
/** For merge commits, the "mainline" is treated as the parent. */
unsigned int mainline;
git_merge_options merge_opts;
git_checkout_options checkout_opts;
} git_cherry_pick_options;
#define GIT_CHERRY_PICK_OPTIONS_VERSION 1
#define GIT_CHERRY_PICK_OPTIONS_INIT {GIT_CHERRY_PICK_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
/**
* Initializes a `git_cherry_pick_options` with default values. Equivalent to
* creating an instance with GIT_CHERRY_PICK_OPTIONS_INIT.
*
* @param opts the `git_cherry_pick_options` struct to initialize
* @param version Version of struct; pass `GIT_CHERRY_PICK_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick_init_options(
git_cherry_pick_options *opts,
unsigned int version);
/**
* Cherry-picks the given commit against the given "our" commit, producing an
* index that reflects the result of the cherry-pick.
*
* The returned index must be freed explicitly with `git_index_free`.
*
* @param out pointer to store the index result in
* @param repo the repository that contains the given commits
* @param cherry_pick_commit the commit to cherry-pick
* @param our_commit the commit to revert against (eg, HEAD)
* @param mainline the parent of the revert commit, if it is a merge
* @param merge_options the merge options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick_commit(
git_index **out,
git_repository *repo,
git_commit *cherry_pick_commit,
git_commit *our_commit,
unsigned int mainline,
const git_merge_options *merge_options);
/**
* Cherry-pick the given commit, producing changes in the index and working directory.
*
* @param repo the repository to cherry-pick
* @param commit the commit to cherry-pick
* @param cherry_pick_options the cherry-pick options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_cherry_pick(
git_repository *repo,
git_commit *commit,
const git_cherry_pick_options *cherry_pick_options);
/** @} */
GIT_END_DECL
#endif
...@@ -24,41 +24,108 @@ ...@@ -24,41 +24,108 @@
GIT_BEGIN_DECL GIT_BEGIN_DECL
/** /**
* Options for bypassing the git-aware transport on clone. Bypassing
* it means that instead of a fetch, libgit2 will copy the object
* database directory instead of figuring out what it needs, which is
* faster. If possible, it will hardlink the files to save space.
*/
typedef enum {
/**
* Auto-detect (default), libgit2 will bypass the git-aware
* transport for local paths, but use a normal fetch for
* `file://` urls.
*/
GIT_CLONE_LOCAL_AUTO,
/**
* Bypass the git-aware transport even for a `file://` url.
*/
GIT_CLONE_LOCAL,
/**
* Do no bypass the git-aware transport
*/
GIT_CLONE_NO_LOCAL,
/**
* Bypass the git-aware transport, but do not try to use
* hardlinks.
*/
GIT_CLONE_LOCAL_NO_LINKS,
} git_clone_local_t;
/**
* Clone options structure * Clone options structure
* *
* Use zeros to indicate default settings. It's easiest to use the * Use the GIT_CLONE_OPTIONS_INIT to get the default settings, like this:
* `GIT_CLONE_OPTIONS_INIT` macro:
* *
* git_clone_options opts = GIT_CLONE_OPTIONS_INIT; * git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
*
* - `checkout_opts` is options for the checkout step. To disable checkout,
* set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT.
* - `bare` should be set to zero to create a standard repo, non-zero for
* a bare repo
* - `ignore_cert_errors` should be set to 1 if errors validating the remote host's
* certificate should be ignored.
*
* ** "origin" remote options: **
* - `remote_name` is the name given to the "origin" remote. The default is
* "origin".
* - `checkout_branch` gives the name of the branch to checkout. NULL means
* use the remote's HEAD.
*/ */
typedef struct git_clone_options { typedef struct git_clone_options {
unsigned int version; unsigned int version;
git_checkout_opts checkout_opts; /**
* These options are passed to the checkout step. To disable
* checkout, set the `checkout_strategy` to
* `GIT_CHECKOUT_NONE`. Generally you will want the use
* GIT_CHECKOUT_SAFE_CREATE to create all files in the working
* directory for the newly cloned repository.
*/
git_checkout_options checkout_opts;
/**
* Callbacks to use for reporting fetch progress.
*/
git_remote_callbacks remote_callbacks; git_remote_callbacks remote_callbacks;
/**
* Set to zero (false) to create a standard repo, or non-zero
* for a bare repo
*/
int bare; int bare;
/**
* Set to 1 if errors validating the remote host's certificate
* should be ignored.
*/
int ignore_cert_errors; int ignore_cert_errors;
/**
* Whether to use a fetch or copy the object database.
*/
git_clone_local_t local;
/**
* The name to be given to the remote that will be
* created. The default is "origin".
*/
const char *remote_name; const char *remote_name;
/**
* The name of the branch to checkout. NULL means use the
* remote's default branch.
*/
const char* checkout_branch; const char* checkout_branch;
/**
* The identity used when updating the reflog. NULL means to
* use the default signature using the config.
*/
git_signature *signature;
} git_clone_options; } git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1 #define GIT_CLONE_OPTIONS_VERSION 1
#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT} #define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT}
/**
* Initializes a `git_clone_options` with default values. Equivalent to
* creating an instance with GIT_CLONE_OPTIONS_INIT.
*
* @param opts The `git_clone_options` struct to initialize
* @param version Version of struct; pass `GIT_CLONE_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_clone_init_options(
git_clone_options *opts,
unsigned int version);
/** /**
* Clone a remote repository. * Clone a remote repository.
...@@ -70,16 +137,17 @@ typedef struct git_clone_options { ...@@ -70,16 +137,17 @@ typedef struct git_clone_options {
* @param out pointer that will receive the resulting repository object * @param out pointer that will receive the resulting repository object
* @param url the remote repository to clone * @param url the remote repository to clone
* @param local_path local directory to clone to * @param local_path local directory to clone to
* @param options configuration options for the clone. If NULL, the function * @param options configuration options for the clone. If NULL, the
* works as though GIT_OPTIONS_INIT were passed. * function works as though GIT_OPTIONS_INIT were passed.
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * @return 0 on success, any non-zero return value from a callback
* about the error) * function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
*/ */
GIT_EXTERN(int) git_clone( GIT_EXTERN(int) git_clone(
git_repository **out, git_repository **out,
const char *url, const char *url,
const char *local_path, const char *local_path,
const git_clone_options *options); const git_clone_options *options);
/** /**
* Clone into a repository * Clone into a repository
...@@ -91,11 +159,48 @@ GIT_EXTERN(int) git_clone( ...@@ -91,11 +159,48 @@ GIT_EXTERN(int) git_clone(
* @param repo the repository to use * @param repo the repository to use
* @param remote the remote repository to clone from * @param remote the remote repository to clone from
* @param co_opts options to use during checkout * @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the remote's * @param branch the branch to checkout after the clone, pass NULL for the
* default branch * remote's default branch
* @return 0 on success or an error code * @param signature The identity used when updating the reflog.
* @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
*/
GIT_EXTERN(int) git_clone_into(
git_repository *repo,
git_remote *remote,
const git_checkout_options *co_opts,
const char *branch,
const git_signature *signature);
/**
* Perform a local clone into a repository
*
* A "local clone" bypasses any git-aware protocols and simply copies
* over the object database from the source repository. It is often
* faster than a git-aware clone, but no verification of the data is
* performed, and can copy over too much data.
*
* @param repo the repository to use
* @param remote the remote repository to clone from
* @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the
* remote's default branch
* @param link wether to use hardlinks instead of copying
* objects. This is only possible if both repositories are on the same
* filesystem.
* @param signature the identity used when updating the reflog
* @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message)
*/ */
GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch); GIT_EXTERN(int) git_clone_local_into(
git_repository *repo,
git_remote *remote,
const git_checkout_options *co_opts,
const char *branch,
int link,
const git_signature *signature);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -117,6 +117,17 @@ GIT_EXTERN(const char *) git_commit_message(const git_commit *commit); ...@@ -117,6 +117,17 @@ GIT_EXTERN(const char *) git_commit_message(const git_commit *commit);
GIT_EXTERN(const char *) git_commit_message_raw(const git_commit *commit); GIT_EXTERN(const char *) git_commit_message_raw(const git_commit *commit);
/** /**
* Get the short "summary" of the git commit message.
*
* The returned message is the summary of the commit, comprising the
* first paragraph of the message with whitespace trimmed and squashed.
*
* @param commit a previously loaded commit.
* @return the summary of a commit or NULL on error
*/
GIT_EXTERN(const char *) git_commit_summary(git_commit *commit);
/**
* Get the commit time (i.e. committer time) of a commit. * Get the commit time (i.e. committer time) of a commit.
* *
* @param commit a previously loaded commit. * @param commit a previously loaded commit.
...@@ -231,8 +242,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor( ...@@ -231,8 +242,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
/** /**
* Create new commit in the repository from a list of `git_object` pointers * Create new commit in the repository from a list of `git_object` pointers
* *
* The message will not be cleaned up automatically. You can do that with * The message will **not** be cleaned up automatically. You can do that
* the `git_message_prettify()` function. * with the `git_message_prettify()` function.
* *
* @param id Pointer in which to store the OID of the newly created commit * @param id Pointer in which to store the OID of the newly created commit
* *
...@@ -243,7 +254,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor( ...@@ -243,7 +254,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
* is not direct, it will be resolved to a direct reference. * is not direct, it will be resolved to a direct reference.
* Use "HEAD" to update the HEAD of the current branch and * Use "HEAD" to update the HEAD of the current branch and
* make it point to this commit. If the reference doesn't * make it point to this commit. If the reference doesn't
* exist yet, it will be created. * exist yet, it will be created. If it does exist, the first
* parent must be the tip of this branch.
* *
* @param author Signature with author and author time of commit * @param author Signature with author and author time of commit
* *
...@@ -280,20 +292,20 @@ GIT_EXTERN(int) git_commit_create( ...@@ -280,20 +292,20 @@ GIT_EXTERN(int) git_commit_create(
const char *message_encoding, const char *message_encoding,
const char *message, const char *message,
const git_tree *tree, const git_tree *tree,
int parent_count, size_t parent_count,
const git_commit *parents[]); const git_commit *parents[]);
/** /**
* Create new commit in the repository using a variable argument list. * Create new commit in the repository using a variable argument list.
* *
* The message will be cleaned up from excess whitespace and it will be made * The message will **not** be cleaned up automatically. You can do that
* sure that the last line ends with a '\n'. * with the `git_message_prettify()` function.
* *
* The parents for the commit are specified as a variable list of pointers * The parents for the commit are specified as a variable list of pointers
* to `const git_commit *`. Note that this is a convenience method which may * to `const git_commit *`. Note that this is a convenience method which may
* not be safe to export for certain languages or compilers * not be safe to export for certain languages or compilers
* *
* All other parameters remain the same at `git_commit_create()`. * All other parameters remain the same as `git_commit_create()`.
* *
* @see git_commit_create * @see git_commit_create
*/ */
...@@ -306,9 +318,40 @@ GIT_EXTERN(int) git_commit_create_v( ...@@ -306,9 +318,40 @@ GIT_EXTERN(int) git_commit_create_v(
const char *message_encoding, const char *message_encoding,
const char *message, const char *message,
const git_tree *tree, const git_tree *tree,
int parent_count, size_t parent_count,
...); ...);
/**
* Amend an existing commit by replacing only non-NULL values.
*
* This creates a new commit that is exactly the same as the old commit,
* except that any non-NULL values will be updated. The new commit has
* the same parents as the old commit.
*
* The `update_ref` value works as in the regular `git_commit_create()`,
* updating the ref to point to the newly rewritten commit. If you want
* to amend a commit that is not currently the tip of the branch and then
* rewrite the following commits to reach a ref, pass this as NULL and
* update the rest of the commit chain and ref separately.
*
* Unlike `git_commit_create()`, the `author`, `committer`, `message`,
* `message_encoding`, and `tree` parameters can be NULL in which case this
* will use the values from the original `commit_to_amend`.
*
* All parameters have the same meanings as in `git_commit_create()`.
*
* @see git_commit_create
*/
GIT_EXTERN(int) git_commit_amend(
git_oid *id,
const git_commit *commit_to_amend,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_tree *tree);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
# define GIT_EXTERN(type) extern type # define GIT_EXTERN(type) extern type
#endif #endif
/** Declare a function as always inlined. */
#if defined(_MSC_VER)
# define GIT_INLINE(type) static __inline type
#else
# define GIT_INLINE(type) static inline type
#endif
/** Declare a function's takes printf style arguments. */ /** Declare a function's takes printf style arguments. */
#ifdef __GNUC__ #ifdef __GNUC__
# define GIT_FORMAT_PRINTF(a,b) __attribute__((format (printf, a, b))) # define GIT_FORMAT_PRINTF(a,b) __attribute__((format (printf, a, b)))
...@@ -101,29 +94,34 @@ GIT_BEGIN_DECL ...@@ -101,29 +94,34 @@ GIT_BEGIN_DECL
GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev);
/** /**
* Combinations of these values describe the capabilities of libgit2. * Combinations of these values describe the features with which libgit2
* was compiled
*/ */
typedef enum { typedef enum {
GIT_CAP_THREADS = ( 1 << 0 ), GIT_FEATURE_THREADS = (1 << 0),
GIT_CAP_HTTPS = ( 1 << 1 ), GIT_FEATURE_HTTPS = (1 << 1),
GIT_CAP_SSH = ( 1 << 2 ), GIT_FEATURE_SSH = (1 << 2),
} git_cap_t; } git_feature_t;
/** /**
* Query compile time options for libgit2. * Query compile time options for libgit2.
* *
* @return A combination of GIT_CAP_* values. * @return A combination of GIT_FEATURE_* values.
* *
* - GIT_CAP_THREADS * - GIT_FEATURE_THREADS
* Libgit2 was compiled with thread support. Note that thread support is * Libgit2 was compiled with thread support. Note that thread support is
* still to be seen as a 'work in progress' - basic object lookups are * still to be seen as a 'work in progress' - basic object lookups are
* believed to be threadsafe, but other operations may not be. * believed to be threadsafe, but other operations may not be.
* *
* - GIT_CAP_HTTPS * - GIT_FEATURE_HTTPS
* Libgit2 supports the https:// protocol. This requires the openssl * Libgit2 supports the https:// protocol. This requires the openssl
* library to be found when compiling libgit2. * library to be found when compiling libgit2.
*
* - GIT_FEATURE_SSH
* Libgit2 supports the SSH protocol for network operations. This requires
* the libssh2 library to be found when compiling libgit2
*/ */
GIT_EXTERN(int) git_libgit2_capabilities(void); GIT_EXTERN(int) git_libgit2_features(void);
typedef enum { typedef enum {
...@@ -163,12 +161,12 @@ typedef enum { ...@@ -163,12 +161,12 @@ typedef enum {
* >Set the maximum amount of memory that can be mapped at any time * >Set the maximum amount of memory that can be mapped at any time
* by the library * by the library
* *
* * opts(GIT_OPT_GET_SEARCH_PATH, int level, char *out, size_t len) * * opts(GIT_OPT_GET_SEARCH_PATH, int level, git_buf *buf)
* *
* > Get the search path for a given level of config data. "level" must * > Get the search path for a given level of config data. "level" must
* > be one of `GIT_CONFIG_LEVEL_SYSTEM`, `GIT_CONFIG_LEVEL_GLOBAL`, or * > be one of `GIT_CONFIG_LEVEL_SYSTEM`, `GIT_CONFIG_LEVEL_GLOBAL`, or
* > `GIT_CONFIG_LEVEL_XDG`. The search path is written to the `out` * > `GIT_CONFIG_LEVEL_XDG`. The search path is written to the `out`
* > buffer up to size `len`. Returns GIT_EBUFS if buffer is too small. * > buffer.
* *
* * opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path) * * opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path)
* *
...@@ -197,7 +195,7 @@ typedef enum { ...@@ -197,7 +195,7 @@ typedef enum {
* > across all repositories before libgit2 starts evicting objects * > across all repositories before libgit2 starts evicting objects
* > from the cache. This is a soft limit, in that the library might * > from the cache. This is a soft limit, in that the library might
* > briefly exceed it, but will start aggressively evicting objects * > briefly exceed it, but will start aggressively evicting objects
* > from cache when that happens. The default cache size is 256Mb. * > from cache when that happens. The default cache size is 256MB.
* *
* * opts(GIT_OPT_ENABLE_CACHING, int enabled) * * opts(GIT_OPT_ENABLE_CACHING, int enabled)
* *
...@@ -212,11 +210,10 @@ typedef enum { ...@@ -212,11 +210,10 @@ typedef enum {
* > Get the current bytes in cache and the maximum that would be * > Get the current bytes in cache and the maximum that would be
* > allowed in the cache. * > allowed in the cache.
* *
* * opts(GIT_OPT_GET_TEMPLATE_PATH, char *out, size_t len) * * opts(GIT_OPT_GET_TEMPLATE_PATH, git_buf *out)
* *
* > Get the default template path. * > Get the default template path.
* > The path is written to the `out` * > The path is written to the `out` buffer.
* > buffer up to size `len`. Returns GIT_EBUFS if buffer is too small.
* *
* * opts(GIT_OPT_SET_TEMPLATE_PATH, const char *path) * * opts(GIT_OPT_SET_TEMPLATE_PATH, const char *path)
* *
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "buffer.h"
/** /**
* @file git2/config.h * @file git2/config.h
...@@ -90,11 +91,10 @@ typedef struct { ...@@ -90,11 +91,10 @@ typedef struct {
* This method will not guess the path to the xdg compatible * This method will not guess the path to the xdg compatible
* config file (.config/git/config). * config file (.config/git/config).
* *
* @param out Buffer to store the path in * @param out Pointer to a user-allocated git_buf in which to store the path
* @param length size of the buffer in bytes * @return 0 if a global configuration file has been found. Its path will be stored in `out`.
* @return 0 if a global configuration file has been found. Its path will be stored in `buffer`.
*/ */
GIT_EXTERN(int) git_config_find_global(char *out, size_t length); GIT_EXTERN(int) git_config_find_global(git_buf *out);
/** /**
* Locate the path to the global xdg compatible configuration file * Locate the path to the global xdg compatible configuration file
...@@ -107,25 +107,23 @@ GIT_EXTERN(int) git_config_find_global(char *out, size_t length); ...@@ -107,25 +107,23 @@ GIT_EXTERN(int) git_config_find_global(char *out, size_t length);
* may be used on any `git_config` call to load the * may be used on any `git_config` call to load the
* xdg compatible configuration file. * xdg compatible configuration file.
* *
* @param out Buffer to store the path in * @param out Pointer to a user-allocated git_buf in which to store the path
* @param length size of the buffer in bytes
* @return 0 if a xdg compatible configuration file has been * @return 0 if a xdg compatible configuration file has been
* found. Its path will be stored in `buffer`. * found. Its path will be stored in `out`.
*/ */
GIT_EXTERN(int) git_config_find_xdg(char *out, size_t length); GIT_EXTERN(int) git_config_find_xdg(git_buf *out);
/** /**
* Locate the path to the system configuration file * Locate the path to the system configuration file
* *
* If /etc/gitconfig doesn't exist, it will look for * If /etc/gitconfig doesn't exist, it will look for
* %PROGRAMFILES%\Git\etc\gitconfig. * %PROGRAMFILES%\Git\etc\gitconfig.
*
* @param out Buffer to store the path in * @param out Pointer to a user-allocated git_buf in which to store the path
* @param length size of the buffer in bytes
* @return 0 if a system configuration file has been * @return 0 if a system configuration file has been
* found. Its path will be stored in `buffer`. * found. Its path will be stored in `out`.
*/ */
GIT_EXTERN(int) git_config_find_system(char *out, size_t length); GIT_EXTERN(int) git_config_find_system(git_buf *out);
/** /**
* Open the global, XDG and system configuration files * Open the global, XDG and system configuration files
...@@ -228,6 +226,22 @@ GIT_EXTERN(int) git_config_open_level( ...@@ -228,6 +226,22 @@ GIT_EXTERN(int) git_config_open_level(
*/ */
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config); GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
/**
* Create a snapshot of the configuration
*
* Create a snapshot of the current state of a configuration, which
* allows you to look into a consistent view of the configuration for
* looking up complex values (e.g. a remote, submodule).
*
* The string returned when querying such a config object is valid
* until it is freed.
*
* @param out pointer in which to store the snapshot config object
* @param config configuration to snapshot
* @return 0 or an error code
*/
GIT_EXTERN(int) git_config_snapshot(git_config **out, git_config *config);
/** /**
* Reload changed config files * Reload changed config files
...@@ -314,7 +328,8 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char ...@@ -314,7 +328,8 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char
* Get the value of a string config variable. * Get the value of a string config variable.
* *
* The string is owned by the variable and should not be freed by the * The string is owned by the variable and should not be freed by the
* user. * user. The pointer will be valid until the next operation on this
* config object.
* *
* All config files will be looked into, in the order of their * All config files will be looked into, in the order of their
* defined level. A higher level means a higher priority. The * defined level. A higher level means a higher priority. The
...@@ -355,6 +370,9 @@ GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, cons ...@@ -355,6 +370,9 @@ GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, cons
/** /**
* Return the current entry and advance the iterator * Return the current entry and advance the iterator
* *
* The pointers returned by this function are valid until the iterator
* is freed.
*
* @param entry pointer to store the entry * @param entry pointer to store the entry
* @param iter the iterator * @param iter the iterator
* @return 0 or an error code. GIT_ITEROVER if the iteration has completed * @return 0 or an error code. GIT_ITEROVER if the iteration has completed
...@@ -450,13 +468,16 @@ GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, co ...@@ -450,13 +468,16 @@ GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, co
* *
* The callback receives the normalized name and value of each variable * The callback receives the normalized name and value of each variable
* in the config backend, and the data pointer passed to this function. * in the config backend, and the data pointer passed to this function.
* As soon as one of the callback functions returns something other than 0, * If the callback returns a non-zero value, the function stops iterating
* this function stops iterating and returns `GIT_EUSER`. * and returns that value to the caller.
*
* The pointers passed to the callback are only valid as long as the
* iteration is ongoing.
* *
* @param cfg where to get the variables from * @param cfg where to get the variables from
* @param callback the function to call on each variable * @param callback the function to call on each variable
* @param payload the data to pass to the callback * @param payload the data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_config_foreach( GIT_EXTERN(int) git_config_foreach(
const git_config *cfg, const git_config *cfg,
...@@ -493,6 +514,9 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi ...@@ -493,6 +514,9 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi
* regular expression that filters which config keys are passed to the * regular expression that filters which config keys are passed to the
* callback. * callback.
* *
* The pointers passed to the callback are only valid as long as the
* iteration is ongoing.
*
* @param cfg where to get the variables from * @param cfg where to get the variables from
* @param regexp regular expression to match against config names * @param regexp regular expression to match against config names
* @param callback the function to call on each variable * @param callback the function to call on each variable
...@@ -612,8 +636,8 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value); ...@@ -612,8 +636,8 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
GIT_EXTERN(int) git_config_backend_foreach_match( GIT_EXTERN(int) git_config_backend_foreach_match(
git_config_backend *backend, git_config_backend *backend,
const char *regexp, const char *regexp,
int (*fn)(const git_config_entry *, void *), git_config_foreach_cb callback,
void *data); void *payload);
/** @} */ /** @} */
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#define INCLUDE_git_errors_h__ #define INCLUDE_git_errors_h__
#include "common.h" #include "common.h"
#include "buffer.h"
/** /**
* @file git2/errors.h * @file git2/errors.h
...@@ -20,25 +19,39 @@ GIT_BEGIN_DECL ...@@ -20,25 +19,39 @@ GIT_BEGIN_DECL
/** Generic return codes */ /** Generic return codes */
typedef enum { typedef enum {
GIT_OK = 0, GIT_OK = 0, /**< No error */
GIT_ERROR = -1,
GIT_ENOTFOUND = -3,
GIT_EEXISTS = -4,
GIT_EAMBIGUOUS = -5,
GIT_EBUFS = -6,
GIT_EUSER = -7,
GIT_EBAREREPO = -8,
GIT_EUNBORNBRANCH = -9,
GIT_EUNMERGED = -10,
GIT_ENONFASTFORWARD = -11,
GIT_EINVALIDSPEC = -12,
GIT_EMERGECONFLICT = -13,
GIT_ELOCKED = -14,
GIT_PASSTHROUGH = -30, GIT_ERROR = -1, /**< Generic error */
GIT_ITEROVER = -31, GIT_ENOTFOUND = -3, /**< Requested object could not be found */
GIT_EEXISTS = -4, /**< Object exists preventing operation */
GIT_EAMBIGUOUS = -5, /**< More than one object matches */
GIT_EBUFS = -6, /**< Output buffer too short to hold data */
/* GIT_EUSER is a special error that is never generated by libgit2
* code. You can return it from a callback (e.g to stop an iteration)
* to know that it was generated by the callback and not by libgit2.
*/
GIT_EUSER = -7,
GIT_EBAREREPO = -8, /**< Operation not allowed on bare repository */
GIT_EUNBORNBRANCH = -9, /**< HEAD refers to branch with no commits */
GIT_EUNMERGED = -10, /**< Merge in progress prevented operation */
GIT_ENONFASTFORWARD = -11, /**< Reference was not fast-forwardable */
GIT_EINVALIDSPEC = -12, /**< Name/ref spec was not in a valid format */
GIT_EMERGECONFLICT = -13, /**< Merge conflicts prevented operation */
GIT_ELOCKED = -14, /**< Lock file prevented operation */
GIT_EMODIFIED = -15, /**< Reference value does not match expected */
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
} git_error_code; } git_error_code;
/**
* Structure to store extra details of the last error that occurred.
*
* This is kept on a per-thread basis if GIT_THREADS was defined when the
* library was build, otherwise one is kept globally for the library
*/
typedef struct { typedef struct {
char *message; char *message;
int klass; int klass;
...@@ -71,6 +84,9 @@ typedef enum { ...@@ -71,6 +84,9 @@ typedef enum {
GITERR_MERGE, GITERR_MERGE,
GITERR_SSH, GITERR_SSH,
GITERR_FILTER, GITERR_FILTER,
GITERR_REVERT,
GITERR_CALLBACK,
GITERR_CHERRYPICK,
} git_error_t; } git_error_t;
/** /**
...@@ -90,7 +106,7 @@ GIT_EXTERN(void) giterr_clear(void); ...@@ -90,7 +106,7 @@ GIT_EXTERN(void) giterr_clear(void);
* Get the last error data and clear it. * Get the last error data and clear it.
* *
* This copies the last error into the given `git_error` struct * This copies the last error into the given `git_error` struct
* and returns 0 if the copy was successful, leaving the error * and returns 0 if the copy was successful, leaving the error
* cleared as if `giterr_clear` had been called. * cleared as if `giterr_clear` had been called.
* *
* If there was no existing error in the library, -1 will be returned * If there was no existing error in the library, -1 will be returned
......
...@@ -35,6 +35,11 @@ typedef enum { ...@@ -35,6 +35,11 @@ typedef enum {
GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB, GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB,
} git_filter_mode_t; } git_filter_mode_t;
typedef enum {
GIT_FILTER_OPT_DEFAULT = 0u,
GIT_FILTER_OPT_ALLOW_UNSAFE = (1u << 0),
} git_filter_opt_t;
/** /**
* A filter that can transform file data * A filter that can transform file data
* *
...@@ -75,6 +80,7 @@ typedef struct git_filter_list git_filter_list; ...@@ -75,6 +80,7 @@ typedef struct git_filter_list git_filter_list;
* @param blob The blob to which the filter will be applied (if known) * @param blob The blob to which the filter will be applied (if known)
* @param path Relative path of the file to be filtered * @param path Relative path of the file to be filtered
* @param mode Filtering direction (WT->ODB or ODB->WT) * @param mode Filtering direction (WT->ODB or ODB->WT)
* @param options Combination of `git_filter_opt_t` flags
* @return 0 on success (which could still return NULL if no filters are * @return 0 on success (which could still return NULL if no filters are
* needed for the requested file), <0 on error * needed for the requested file), <0 on error
*/ */
...@@ -83,7 +89,8 @@ GIT_EXTERN(int) git_filter_list_load( ...@@ -83,7 +89,8 @@ GIT_EXTERN(int) git_filter_list_load(
git_repository *repo, git_repository *repo,
git_blob *blob, /* can be NULL */ git_blob *blob, /* can be NULL */
const char *path, const char *path,
git_filter_mode_t mode); git_filter_mode_t mode,
uint32_t options);
/** /**
* Apply filter list to a data buffer. * Apply filter list to a data buffer.
......
...@@ -36,6 +36,20 @@ GIT_BEGIN_DECL ...@@ -36,6 +36,20 @@ GIT_BEGIN_DECL
*/ */
GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream); GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream);
/**
* Determine if a commit is the descendant of another commit.
*
* @param commit a previously loaded commit.
* @param ancestor a potential ancestor commit.
* @return 1 if the given commit is a descendant of the potential ancestor,
* 0 if not, error code otherwise.
*/
GIT_EXTERN(int) git_graph_descendant_of(
git_repository *repo,
const git_oid *commit,
const git_oid *ancestor);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -32,7 +32,7 @@ GIT_EXTERN(int) git_indexer_new( ...@@ -32,7 +32,7 @@ GIT_EXTERN(int) git_indexer_new(
const char *path, const char *path,
unsigned int mode, unsigned int mode,
git_odb *odb, git_odb *odb,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_cb_payload); void *progress_cb_payload);
/** /**
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define INCLUDE_git_message_h__ #define INCLUDE_git_message_h__
#include "common.h" #include "common.h"
#include "buffer.h"
/** /**
* @file git2/message.h * @file git2/message.h
...@@ -23,25 +24,19 @@ GIT_BEGIN_DECL ...@@ -23,25 +24,19 @@ GIT_BEGIN_DECL
* *
* Optionally, can remove lines starting with a "#". * Optionally, can remove lines starting with a "#".
* *
* @param out The user-allocated buffer which will be filled with the * @param out The user-allocated git_buf which will be filled with the
* cleaned up message. Pass NULL if you just want to get the needed * cleaned up message.
* size of the prettified message as the output value.
*
* @param out_size Size of the `out` buffer in bytes.
* *
* @param message The message to be prettified. * @param message The message to be prettified.
* *
* @param strip_comments Non-zero to remove lines starting with "#", 0 to * @param strip_comments Non-zero to remove comment lines, 0 to leave them in.
* leave them in. *
* @param comment_char Comment character. Lines starting with this character
* are considered to be comments and removed if `strip_comments` is non-zero.
* *
* @return -1 on error, else number of characters in prettified message * @return 0 or an error code.
* including the trailing NUL byte
*/ */
GIT_EXTERN(int) git_message_prettify( GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char);
char *out,
size_t out_size,
const char *message,
int strip_comments);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -41,6 +41,11 @@ struct git_remote_head { ...@@ -41,6 +41,11 @@ struct git_remote_head {
git_oid oid; git_oid oid;
git_oid loid; git_oid loid;
char *name; char *name;
/**
* If the server send a symref mapping for this ref, this will
* point to the target.
*/
char *symref_target;
}; };
/** /**
......
...@@ -106,12 +106,12 @@ GIT_EXTERN(const char *) git_note_message(const git_note *note); ...@@ -106,12 +106,12 @@ GIT_EXTERN(const char *) git_note_message(const git_note *note);
/** /**
* Get the note object OID * Get the note object's id
* *
* @param note the note * @param note the note
* @return the note object OID * @return the note object's id
*/ */
GIT_EXTERN(const git_oid *) git_note_oid(const git_note *note); GIT_EXTERN(const git_oid *) git_note_id(const git_note *note);
/** /**
* Add a note for an object * Add a note for an object
...@@ -189,7 +189,7 @@ GIT_EXTERN(int) git_note_default_ref(const char **out, git_repository *repo); ...@@ -189,7 +189,7 @@ GIT_EXTERN(int) git_note_default_ref(const char **out, git_repository *repo);
* *
* @param payload Extra parameter to callback function. * @param payload Extra parameter to callback function.
* *
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_note_foreach( GIT_EXTERN(int) git_note_foreach(
git_repository *repo, git_repository *repo,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "oid.h" #include "oid.h"
#include "buffer.h"
/** /**
* @file git2/object.h * @file git2/object.h
...@@ -104,6 +105,20 @@ GIT_EXTERN(int) git_object_lookup_bypath( ...@@ -104,6 +105,20 @@ GIT_EXTERN(int) git_object_lookup_bypath(
GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj); GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj);
/** /**
* Get a short abbreviated OID string for the object
*
* This starts at the "core.abbrev" length (default 7 characters) and
* iteratively extends to a longer string if that length is ambiguous.
* The result will be unambiguous (at least until new objects are added to
* the repository).
*
* @param out Buffer to write string into
* @param obj The object to get an ID for
* @return 0 on success, <0 for error
*/
GIT_EXTERN(int) git_object_short_id(git_buf *out, const git_object *obj);
/**
* Get the object type of an object * Get the object type of an object
* *
* @param obj the repository object * @param obj the repository object
...@@ -143,7 +158,7 @@ GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj); ...@@ -143,7 +158,7 @@ GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj);
GIT_EXTERN(void) git_object_free(git_object *object); GIT_EXTERN(void) git_object_free(git_object *object);
/** /**
* Convert an object type to it's string representation. * Convert an object type to its string representation.
* *
* The result is a pointer to a string in static memory and * The result is a pointer to a string in static memory and
* should not be free()'ed. * should not be free()'ed.
......
...@@ -159,6 +159,19 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_otype *type_out, git_od ...@@ -159,6 +159,19 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_otype *type_out, git_od
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id); GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
/** /**
* Determine if objects can be found in the object database from a short OID.
*
* @param out The full OID of the found object if just one is found.
* @param db The database to be searched for the given object.
* @param short_id A prefix of the id of the object to read.
* @param len The length of the prefix.
* @return 0 if found, GIT_ENOTFOUND if not found, GIT_EAMBIGUOUS if multiple
* matches were found, other value < 0 if there was a read error.
*/
GIT_EXTERN(int) git_odb_exists_prefix(
git_oid *out, git_odb *db, const git_oid *short_id, size_t len);
/**
* Refresh the object database to load newly added files. * Refresh the object database to load newly added files.
* *
* If the object databases have changed on disk while the library * If the object databases have changed on disk while the library
...@@ -189,7 +202,7 @@ GIT_EXTERN(int) git_odb_refresh(struct git_odb *db); ...@@ -189,7 +202,7 @@ GIT_EXTERN(int) git_odb_refresh(struct git_odb *db);
* @param db database to use * @param db database to use
* @param cb the callback to call for each object * @param cb the callback to call for each object
* @param payload data to pass to the callback * @param payload data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload); GIT_EXTERN(int) git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload);
...@@ -325,7 +338,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const gi ...@@ -325,7 +338,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const gi
GIT_EXTERN(int) git_odb_write_pack( GIT_EXTERN(int) git_odb_write_pack(
git_odb_writepack **out, git_odb_writepack **out,
git_odb *db, git_odb *db,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_payload); void *progress_payload);
/** /**
......
...@@ -167,10 +167,7 @@ GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b); ...@@ -167,10 +167,7 @@ GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);
* @param b second oid structure. * @param b second oid structure.
* @return true if equal, false otherwise * @return true if equal, false otherwise
*/ */
GIT_INLINE(int) git_oid_equal(const git_oid *a, const git_oid *b) GIT_EXTERN(int) git_oid_equal(const git_oid *a, const git_oid *b);
{
return !git_oid_cmp(a, b);
}
/** /**
* Compare the first 'len' hexadecimal characters (packets of 4 bits) * Compare the first 'len' hexadecimal characters (packets of 4 bits)
......
...@@ -52,7 +52,7 @@ typedef enum { ...@@ -52,7 +52,7 @@ typedef enum {
GIT_PACKBUILDER_ADDING_OBJECTS = 0, GIT_PACKBUILDER_ADDING_OBJECTS = 0,
GIT_PACKBUILDER_DELTAFICATION = 1, GIT_PACKBUILDER_DELTAFICATION = 1,
} git_packbuilder_stage_t; } git_packbuilder_stage_t;
/** /**
* Initialize a new packbuilder * Initialize a new packbuilder
* *
...@@ -115,6 +115,17 @@ GIT_EXTERN(int) git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid * ...@@ -115,6 +115,17 @@ GIT_EXTERN(int) git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *
GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *id); GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *id);
/** /**
* Write the contents of the packfile to an in-memory buffer
*
* The contents of the buffer will become a valid packfile, even though there
* will be no attached index
*
* @param buf Buffer where to write the packfile
* @param pb The packbuilder
*/
GIT_EXTERN(int) git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb);
/**
* Write the new pack and corresponding index file to path. * Write the new pack and corresponding index file to path.
* *
* @param pb The packbuilder * @param pb The packbuilder
...@@ -129,7 +140,7 @@ GIT_EXTERN(int) git_packbuilder_write( ...@@ -129,7 +140,7 @@ GIT_EXTERN(int) git_packbuilder_write(
git_packbuilder *pb, git_packbuilder *pb,
const char *path, const char *path,
unsigned int mode, unsigned int mode,
git_transfer_progress_callback progress_cb, git_transfer_progress_cb progress_cb,
void *progress_cb_payload); void *progress_cb_payload);
/** /**
...@@ -143,6 +154,7 @@ GIT_EXTERN(int) git_packbuilder_write( ...@@ -143,6 +154,7 @@ GIT_EXTERN(int) git_packbuilder_write(
GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb); GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb);
typedef int (*git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload); typedef int (*git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload);
/** /**
* Create the new pack and pass each object to the callback * Create the new pack and pass each object to the callback
* *
......
...@@ -106,6 +106,34 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer( ...@@ -106,6 +106,34 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer(
const git_diff_options *opts); const git_diff_options *opts);
/** /**
* Directly generate a patch from the difference between two buffers.
*
* This is just like `git_diff_buffers()` except it generates a patch
* object for the difference instead of directly making callbacks. You can
* use the standard `git_patch` accessor functions to read the patch
* data, and you must call `git_patch_free()` on the patch when done.
*
* @param out The generated patch; NULL on error
* @param old_buffer Raw data for old side of diff, or NULL for empty
* @param old_len Length of the raw data for old side of the diff
* @param old_as_path Treat old buffer as if it had this filename; can be NULL
* @param new_buffer Raw data for new side of diff, or NULL for empty
* @param new_len Length of raw data for new side of diff
* @param new_as_path Treat buffer as if it had this filename; can be NULL
* @param opts Options for diff, or NULL for default options
* @return 0 on success or error code < 0
*/
GIT_EXTERN(int) git_patch_from_buffers(
git_patch **out,
const void *old_buffer,
size_t old_len,
const char *old_as_path,
const char *new_buffer,
size_t new_len,
const char *new_as_path,
const git_diff_options *opts);
/**
* Free a git_patch object. * Free a git_patch object.
*/ */
GIT_EXTERN(void) git_patch_free(git_patch *patch); GIT_EXTERN(void) git_patch_free(git_patch *patch);
...@@ -113,12 +141,12 @@ GIT_EXTERN(void) git_patch_free(git_patch *patch); ...@@ -113,12 +141,12 @@ GIT_EXTERN(void) git_patch_free(git_patch *patch);
/** /**
* Get the delta associated with a patch * Get the delta associated with a patch
*/ */
GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(git_patch *patch); GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(const git_patch *patch);
/** /**
* Get the number of hunks in a patch * Get the number of hunks in a patch
*/ */
GIT_EXTERN(size_t) git_patch_num_hunks(git_patch *patch); GIT_EXTERN(size_t) git_patch_num_hunks(const git_patch *patch);
/** /**
* Get line counts of each type in a patch. * Get line counts of each type in a patch.
...@@ -169,7 +197,7 @@ GIT_EXTERN(int) git_patch_get_hunk( ...@@ -169,7 +197,7 @@ GIT_EXTERN(int) git_patch_get_hunk(
* @return Number of lines in hunk or -1 if invalid hunk index * @return Number of lines in hunk or -1 if invalid hunk index
*/ */
GIT_EXTERN(int) git_patch_num_lines_in_hunk( GIT_EXTERN(int) git_patch_num_lines_in_hunk(
git_patch *patch, const git_patch *patch,
size_t hunk_idx); size_t hunk_idx);
/** /**
...@@ -218,13 +246,13 @@ GIT_EXTERN(size_t) git_patch_size( ...@@ -218,13 +246,13 @@ GIT_EXTERN(size_t) git_patch_size(
* Serialize the patch to text via callback. * Serialize the patch to text via callback.
* *
* Returning a non-zero value from the callback will terminate the iteration * Returning a non-zero value from the callback will terminate the iteration
* and cause this return `GIT_EUSER`. * and return that value to the caller.
* *
* @param patch A git_patch representing changes to one file * @param patch A git_patch representing changes to one file
* @param print_cb Callback function to output lines of the patch. Will be * @param print_cb Callback function to output lines of the patch. Will be
* called for file headers, hunk headers, and diff lines. * called for file headers, hunk headers, and diff lines.
* @param payload Reference pointer that will be passed to your callbacks. * @param payload Reference pointer that will be passed to your callbacks.
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_patch_print( GIT_EXTERN(int) git_patch_print(
git_patch *patch, git_patch *patch,
...@@ -234,15 +262,14 @@ GIT_EXTERN(int) git_patch_print( ...@@ -234,15 +262,14 @@ GIT_EXTERN(int) git_patch_print(
/** /**
* Get the content of a patch as a single diff text. * Get the content of a patch as a single diff text.
* *
* @param string Allocated string; caller must free. * @param out The git_buf to be filled in
* @param patch A git_patch representing changes to one file * @param patch A git_patch representing changes to one file
* @return 0 on success, <0 on failure. * @return 0 on success, <0 on failure.
*/ */
GIT_EXTERN(int) git_patch_to_str( GIT_EXTERN(int) git_patch_to_buf(
char **string, git_buf *out,
git_patch *patch); git_patch *patch);
GIT_END_DECL GIT_END_DECL
/**@}*/ /**@}*/
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "strarray.h" #include "strarray.h"
#include "diff.h" #include "diff.h"
GIT_BEGIN_DECL
/** /**
* Compiled pathspec * Compiled pathspec
*/ */
...@@ -257,4 +259,5 @@ GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount( ...@@ -257,4 +259,5 @@ GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount(
GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry( GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry(
const git_pathspec_match_list *m, size_t pos); const git_pathspec_match_list *m, size_t pos);
GIT_END_DECL
#endif #endif
...@@ -39,6 +39,19 @@ typedef struct { ...@@ -39,6 +39,19 @@ typedef struct {
#define GIT_PUSH_OPTIONS_VERSION 1 #define GIT_PUSH_OPTIONS_VERSION 1
#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION } #define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION }
/**
* Initializes a `git_push_options` with default values. Equivalent to
* creating an instance with GIT_PUSH_OPTIONS_INIT.
*
* @param opts the `git_push_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_PUSH_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_push_init_options(
git_push_options *opts,
unsigned int version);
/** Push network progress notification function */ /** Push network progress notification function */
typedef int (*git_push_transfer_progress)( typedef int (*git_push_transfer_progress)(
unsigned int current, unsigned int current,
...@@ -103,10 +116,16 @@ GIT_EXTERN(int) git_push_add_refspec(git_push *push, const char *refspec); ...@@ -103,10 +116,16 @@ GIT_EXTERN(int) git_push_add_refspec(git_push *push, const char *refspec);
* Update remote tips after a push * Update remote tips after a push
* *
* @param push The push object * @param push The push object
* @param signature The identity to use when updating reflogs
* @param reflog_message The message to insert into the reflogs. If NULL, the
* default is "update by push".
* *
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_push_update_tips(git_push *push); GIT_EXTERN(int) git_push_update_tips(
git_push *push,
const git_signature *signature,
const char *reflog_message);
/** /**
* Actually push all given refspecs * Actually push all given refspecs
...@@ -129,20 +148,22 @@ GIT_EXTERN(int) git_push_finish(git_push *push); ...@@ -129,20 +148,22 @@ GIT_EXTERN(int) git_push_finish(git_push *push);
* *
* @return true if remote side successfully unpacked, false otherwise * @return true if remote side successfully unpacked, false otherwise
*/ */
GIT_EXTERN(int) git_push_unpack_ok(git_push *push); GIT_EXTERN(int) git_push_unpack_ok(const git_push *push);
/** /**
* Call callback `cb' on each status * Invoke callback `cb' on each status entry
* *
* For each of the updated references, we receive a status report in the * For each of the updated references, we receive a status report in the
* form of `ok refs/heads/master` or `ng refs/heads/master <msg>`. * form of `ok refs/heads/master` or `ng refs/heads/master <msg>`.
* `msg != NULL` means the reference has not been updated for the given * `msg != NULL` means the reference has not been updated for the given
* reason. * reason.
* *
* Return a non-zero value from the callback to stop the loop.
*
* @param push The push object * @param push The push object
* @param cb The callback to call on each object * @param cb The callback to call on each object
* *
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_push_status_foreach(git_push *push, GIT_EXTERN(int) git_push_status_foreach(git_push *push,
int (*cb)(const char *ref, const char *msg, void *data), int (*cb)(const char *ref, const char *msg, void *data),
......
...@@ -47,7 +47,7 @@ GIT_EXTERN(int) git_reflog_read(git_reflog **out, git_repository *repo, const c ...@@ -47,7 +47,7 @@ GIT_EXTERN(int) git_reflog_read(git_reflog **out, git_repository *repo, const c
GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); GIT_EXTERN(int) git_reflog_write(git_reflog *reflog);
/** /**
* Add a new entry to the reflog. * Add a new entry to the in-memory reflog.
* *
* `msg` is optional and can be NULL. * `msg` is optional and can be NULL.
* *
...@@ -60,23 +60,6 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); ...@@ -60,23 +60,6 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog);
GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const git_signature *committer, const char *msg); GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const git_signature *committer, const char *msg);
/** /**
* Add a new entry to the named reflog.
*
* This utility function loads the named reflog, appends to it and
* writes it back out to the backend.
*
* `msg` is optional and can be NULL.
*
* @param repo the repository to act on
* @param name the reflog's name
* @param id the OID the reference is now pointing to
* @param committer the signature of the committer
* @param msg the reflog message
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, const git_signature *committer, const char *msg);
/**
* Rename a reflog * Rename a reflog
* *
* The reflog to be renamed is expected to already exist * The reflog to be renamed is expected to already exist
...@@ -86,7 +69,7 @@ GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, con ...@@ -86,7 +69,7 @@ GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, con
* *
* @param repo the repository * @param repo the repository
* @param old_name the old name of the reference * @param old_name the old name of the reference
* @param new_name the new name of the reference * @param name the new name of the reference
* @return 0 on success, GIT_EINVALIDSPEC or an error code * @return 0 on success, GIT_EINVALIDSPEC or an error code
*/ */
GIT_EXTERN(int) git_reflog_rename(git_repository *repo, const char *old_name, const char *name); GIT_EXTERN(int) git_reflog_rename(git_repository *repo, const char *old_name, const char *name);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "net.h" #include "net.h"
#include "buffer.h"
/** /**
* @file git2/refspec.h * @file git2/refspec.h
...@@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char * ...@@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char *
* Transform a reference to its target following the refspec's rules * Transform a reference to its target following the refspec's rules
* *
* @param out where to store the target name * @param out where to store the target name
* @param outlen the size of the `out` buffer
* @param spec the refspec * @param spec the refspec
* @param name the name of the reference to transform * @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error * @return 0, GIT_EBUFS or another error
*/ */
GIT_EXTERN(int) git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name); GIT_EXTERN(int) git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name);
/** /**
* Transform a target reference to its source reference following the refspec's rules * Transform a target reference to its source reference following the refspec's rules
* *
* @param out where to store the source reference name * @param out where to store the source reference name
* @param outlen the size of the `out` buffer
* @param spec the refspec * @param spec the refspec
* @param name the name of the reference to transform * @param name the name of the reference to transform
* @return 0, GIT_EBUFS or another error * @return 0, GIT_EBUFS or another error
*/ */
GIT_EXTERN(int) git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name); GIT_EXTERN(int) git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name);
GIT_END_DECL GIT_END_DECL
......
...@@ -62,10 +62,10 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec( ...@@ -62,10 +62,10 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec(
const char *fetch); const char *fetch);
/** /**
* Create a remote in memory * Create an anonymous remote
* *
* Create a remote with the given refspec in memory. You can use * Create a remote with the given url and refspec in memory. You can use
* this when you have a URL instead of a remote's name. Note that in-memory * this when you have a URL instead of a remote's name. Note that anonymous
* remotes cannot be converted to persisted remotes. * remotes cannot be converted to persisted remotes.
* *
* The name, when provided, will be checked for validity. * The name, when provided, will be checked for validity.
...@@ -73,15 +73,15 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec( ...@@ -73,15 +73,15 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec(
* *
* @param out pointer to the new remote object * @param out pointer to the new remote object
* @param repo the associated repository * @param repo the associated repository
* @param fetch the fetch refspec to use for this remote.
* @param url the remote repository's URL * @param url the remote repository's URL
* @param fetch the fetch refspec to use for this remote.
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_remote_create_inmemory( GIT_EXTERN(int) git_remote_create_anonymous(
git_remote **out, git_remote **out,
git_repository *repo, git_repository *repo,
const char *fetch, const char *url,
const char *url); const char *fetch);
/** /**
* Get the information for a particular remote * Get the information for a particular remote
...@@ -108,6 +108,18 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch ...@@ -108,6 +108,18 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch
GIT_EXTERN(int) git_remote_save(const git_remote *remote); GIT_EXTERN(int) git_remote_save(const git_remote *remote);
/** /**
* Create a copy of an existing remote. All internal strings are also
* duplicated. Callbacks are not duplicated.
*
* Call `git_remote_free` to free the data.
*
* @param dest pointer where to store the copy
* @param source object to copy
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_dup(git_remote **dest, git_remote *source);
/**
* Get the remote's repository * Get the remote's repository
* *
* @param remote the remote * @param remote the remote
...@@ -182,7 +194,7 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); ...@@ -182,7 +194,7 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec);
* @param array pointer to the array in which to store the strings * @param array pointer to the array in which to store the strings
* @param remote the remote to query * @param remote the remote to query
*/ */
GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote); GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote);
/** /**
* Set the remote's list of fetch refspecs * Set the remote's list of fetch refspecs
...@@ -215,7 +227,7 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec); ...@@ -215,7 +227,7 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec);
* @param array pointer to the array in which to store the strings * @param array pointer to the array in which to store the strings
* @param remote the remote to query * @param remote the remote to query
*/ */
GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote); GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote);
/** /**
* Set the remote's list of push refspecs * Set the remote's list of push refspecs
...@@ -242,7 +254,7 @@ GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote); ...@@ -242,7 +254,7 @@ GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote);
* @param remote the remote * @param remote the remote
* @return the amount of refspecs configured in this remote * @return the amount of refspecs configured in this remote
*/ */
GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); GIT_EXTERN(size_t) git_remote_refspec_count(const git_remote *remote);
/** /**
* Get a refspec from the remote * Get a refspec from the remote
...@@ -251,7 +263,7 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); ...@@ -251,7 +263,7 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote);
* @param n the refspec to get * @param n the refspec to get
* @return the nth refspec * @return the nth refspec
*/ */
GIT_EXTERN(const git_refspec *)git_remote_get_refspec(git_remote *remote, size_t n); GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote, size_t n);
/** /**
* Open a connection to a remote * Open a connection to a remote
...@@ -307,7 +319,7 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote); ...@@ -307,7 +319,7 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote);
* @param remote the remote * @param remote the remote
* @return 1 if it's connected, 0 otherwise. * @return 1 if it's connected, 0 otherwise.
*/ */
GIT_EXTERN(int) git_remote_connected(git_remote *remote); GIT_EXTERN(int) git_remote_connected(const git_remote *remote);
/** /**
* Cancel the operation * Cancel the operation
...@@ -343,9 +355,16 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); ...@@ -343,9 +355,16 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote);
* Update the tips to the new state * Update the tips to the new state
* *
* @param remote the remote to update * @param remote the remote to update
* @param signature The identity to use when updating reflogs
* @param reflog_message The message to insert into the reflogs. If NULL, the
* default is "fetch <name>", where <name> is the name of
* the remote (or its url, for in-memory remotes).
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); GIT_EXTERN(int) git_remote_update_tips(
git_remote *remote,
const git_signature *signature,
const char *reflog_message);
/** /**
* Download new data and update tips * Download new data and update tips
...@@ -354,9 +373,15 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); ...@@ -354,9 +373,15 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote);
* disconnect and update the remote-tracking branches. * disconnect and update the remote-tracking branches.
* *
* @param remote the remote to fetch from * @param remote the remote to fetch from
* @param signature The identity to use when updating reflogs
* @param reflog_message The message to insert into the reflogs. If NULL, the
* default is "fetch"
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_remote_fetch(git_remote *remote); GIT_EXTERN(int) git_remote_fetch(
git_remote *remote,
const git_signature *signature,
const char *reflog_message);
/** /**
* Return whether a string is a valid remote URL * Return whether a string is a valid remote URL
...@@ -432,7 +457,7 @@ struct git_remote_callbacks { ...@@ -432,7 +457,7 @@ struct git_remote_callbacks {
* progress side-band will be passed to this function (this is * progress side-band will be passed to this function (this is
* the 'counting objects' output. * the 'counting objects' output.
*/ */
int (*progress)(const char *str, int len, void *data); git_transport_message_cb sideband_progress;
/** /**
* Completion is called when different parts of the download * Completion is called when different parts of the download
...@@ -443,15 +468,18 @@ struct git_remote_callbacks { ...@@ -443,15 +468,18 @@ struct git_remote_callbacks {
/** /**
* This will be called if the remote host requires * This will be called if the remote host requires
* authentication in order to connect to it. * authentication in order to connect to it.
*
* Returning GIT_PASSTHROUGH will make libgit2 behave as
* though this field isn't set.
*/ */
int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); git_cred_acquire_cb credentials;
/** /**
* During the download of new data, this will be regularly * During the download of new data, this will be regularly
* called with the current count of progress done by the * called with the current count of progress done by the
* indexer. * indexer.
*/ */
int (*transfer_progress)(const git_transfer_progress *stats, void *data); git_transfer_progress_cb transfer_progress;
/** /**
* Each time a reference is updated locally, this function * Each time a reference is updated locally, this function
...@@ -470,6 +498,18 @@ struct git_remote_callbacks { ...@@ -470,6 +498,18 @@ struct git_remote_callbacks {
#define GIT_REMOTE_CALLBACKS_INIT {GIT_REMOTE_CALLBACKS_VERSION} #define GIT_REMOTE_CALLBACKS_INIT {GIT_REMOTE_CALLBACKS_VERSION}
/** /**
* Initializes a `git_remote_callbacks` with default values. Equivalent to
* creating an instance with GIT_REMOTE_CALLBACKS_INIT.
*
* @param opts the `git_remote_callbacks` struct to initialize
* @param version Version of struct; pass `GIT_REMOTE_CALLBACKS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_remote_init_callbacks(
git_remote_callbacks *opts,
unsigned int version);
/**
* Set the callbacks for a remote * Set the callbacks for a remote
* *
* Note that the remote keeps its own copy of the data and you need to * Note that the remote keeps its own copy of the data and you need to
...@@ -482,6 +522,17 @@ struct git_remote_callbacks { ...@@ -482,6 +522,17 @@ struct git_remote_callbacks {
GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks);
/** /**
* Retrieve the current callback structure
*
* This provides read access to the callbacks structure as the remote
* sees it.
*
* @param remote the remote to query
* @return a pointer to the callbacks structure
*/
GIT_EXTERN(const git_remote_callbacks *) git_remote_get_callbacks(git_remote *remote);
/**
* Get the statistics structure that is filled in by the fetch operation. * Get the statistics structure that is filled in by the fetch operation.
*/ */
GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote);
...@@ -498,7 +549,7 @@ typedef enum { ...@@ -498,7 +549,7 @@ typedef enum {
* @param remote the remote to query * @param remote the remote to query
* @return the auto-follow setting * @return the auto-follow setting
*/ */
GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(git_remote *remote); GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *remote);
/** /**
* Set the tag auto-follow setting * Set the tag auto-follow setting
...@@ -521,18 +572,17 @@ GIT_EXTERN(void) git_remote_set_autotag( ...@@ -521,18 +572,17 @@ GIT_EXTERN(void) git_remote_set_autotag(
* *
* A temporary in-memory remote cannot be given a name with this method. * A temporary in-memory remote cannot be given a name with this method.
* *
* @param problems non-default refspecs cannot be renamed and will be
* stored here for further processing by the caller. Always free this
* strarray on succesful return.
* @param remote the remote to rename * @param remote the remote to rename
* @param new_name the new name the remote should bear * @param new_name the new name the remote should bear
* @param callback Optional callback to notify the consumer of fetch refspecs
* that haven't been automatically updated and need potential manual tweaking.
* @param payload Additional data to pass to the callback
* @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code
*/ */
GIT_EXTERN(int) git_remote_rename( GIT_EXTERN(int) git_remote_rename(
git_strarray *problems,
git_remote *remote, git_remote *remote,
const char *new_name, const char *new_name);
git_remote_rename_problem_cb callback,
void *payload);
/** /**
* Retrieve the update FETCH_HEAD setting. * Retrieve the update FETCH_HEAD setting.
...@@ -559,6 +609,35 @@ GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value); ...@@ -559,6 +609,35 @@ GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value);
*/ */
GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name); GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
/**
* Delete an existing persisted remote.
*
* All remote-tracking branches and configuration settings
* for the remote will be removed.
*
* @param remote A valid remote
* @return 0 on success, or an error code.
*/
GIT_EXTERN(int) git_remote_delete(git_remote *remote);
/**
* Retrieve the name of the remote's default branch
*
* The default branch of a repository is the branch which HEAD points
* to. If the remote does not support reporting this information
* directly, it performs the guess as git does; that is, if there are
* multiple branches which point to the same commit, the first one is
* chosen. If the master branch is a candidate, it wins.
*
* This function must only be called after connecting.
*
* @param out the buffern in which to store the reference name
* @param remote the remote
* @return 0, GIT_ENOTFOUND if the remote does not have any references
* or none of them point to HEAD's commit, or an error message.
*/
GIT_EXTERN(int) git_remote_default_branch(git_buf *out, git_remote *remote);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common.h" #include "common.h"
#include "types.h" #include "types.h"
#include "oid.h" #include "oid.h"
#include "buffer.h"
/** /**
* @file git2/repository.h * @file git2/repository.h
...@@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); ...@@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* The method will automatically detect if the repository is bare * The method will automatically detect if the repository is bare
* (if there is a repository). * (if there is a repository).
* *
* @param path_out The user allocated buffer which will * @param out A pointer to a user-allocated git_buf which will contain
* contain the found path. * the found path.
*
* @param path_size repository_path size
* *
* @param start_path The base path where the lookup starts. * @param start_path The base path where the lookup starts.
* *
...@@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); ...@@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb);
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_repository_discover( GIT_EXTERN(int) git_repository_discover(
char *path_out, git_buf *out,
size_t path_size,
const char *start_path, const char *start_path,
int across_fs, int across_fs,
const char *ceiling_dirs); const char *ceiling_dirs);
...@@ -270,6 +268,18 @@ typedef struct { ...@@ -270,6 +268,18 @@ typedef struct {
#define GIT_REPOSITORY_INIT_OPTIONS_INIT {GIT_REPOSITORY_INIT_OPTIONS_VERSION} #define GIT_REPOSITORY_INIT_OPTIONS_INIT {GIT_REPOSITORY_INIT_OPTIONS_VERSION}
/** /**
* Initializes a `git_repository_init_options` with default values. Equivalent
* to creating an instance with GIT_REPOSITORY_INIT_OPTIONS_INIT.
*
* @param opts the `git_repository_init_options` struct to initialize
* @param version Version of struct; pass `GIT_REPOSITORY_INIT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_repository_init_init_options(
git_repository_init_options *opts,
unsigned int version);
/**
* Create a new Git repository in the given folder with extended controls. * Create a new Git repository in the given folder with extended controls.
* *
* This will initialize a new git repository (creating the repo_path * This will initialize a new git repository (creating the repo_path
...@@ -398,13 +408,29 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo); ...@@ -398,13 +408,29 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
* The configuration file must be freed once it's no longer * The configuration file must be freed once it's no longer
* being used by the user. * being used by the user.
* *
* @param out Pointer to store the loaded config file * @param out Pointer to store the loaded configuration
* @param repo A repository object * @param repo A repository object
* @return 0, or an error code * @return 0, or an error code
*/ */
GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo); GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo);
/** /**
* Get a snapshot of the repository's configuration
*
* Convenience function to take a snapshot from the repository's
* configuration. The contents of this snapshot will not change,
* even if the underlying config files are modified.
*
* The configuration file must be freed once it's no longer
* being used by the user.
*
* @param out Pointer to store the loaded configuration
* @param repo the repository
* @return 0, or an error code
*/
GIT_EXTERN(int) git_repository_config_snapshot(git_config **out, git_repository *repo);
/**
* Get the Object Database for this repository. * Get the Object Database for this repository.
* *
* If a custom ODB has not been set, the default * If a custom ODB has not been set, the default
...@@ -464,21 +490,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo); ...@@ -464,21 +490,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
* Use this function to get the contents of this file. Don't forget to * Use this function to get the contents of this file. Don't forget to
* remove the file after you create the commit. * remove the file after you create the commit.
* *
* If the repository message exists and there are no errors reading it, this * @param out git_buf to write data into
* returns the bytes needed to store the message in memory (i.e. message
* file size plus one terminating NUL byte). That value is returned even if
* `out` is NULL or `len` is shorter than the necessary size.
*
* The `out` buffer will *always* be NUL terminated, even if truncation
* occurs.
*
* @param out Buffer to write data into or NULL to just read required size
* @param len Length of `out` buffer in bytes
* @param repo Repository to read prepared message from * @param repo Repository to read prepared message from
* @return GIT_ENOTFOUND if no message exists, other value < 0 for other * @return 0, GIT_ENOTFOUND if no message exists or an error code
* errors, or total bytes in message (may be > `len`) on success
*/ */
GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo); GIT_EXTERN(int) git_repository_message(git_buf *out, git_repository *repo);
/** /**
* Remove git's prepared message. * Remove git's prepared message.
...@@ -488,13 +504,13 @@ GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *re ...@@ -488,13 +504,13 @@ GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *re
GIT_EXTERN(int) git_repository_message_remove(git_repository *repo); GIT_EXTERN(int) git_repository_message_remove(git_repository *repo);
/** /**
* Remove all the metadata associated with an ongoing git merge, including * Remove all the metadata associated with an ongoing command like merge,
* MERGE_HEAD, MERGE_MSG, etc. * revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc.
* *
* @param repo A repository object * @param repo A repository object
* @return 0 on success, or error * @return 0 on success, or error
*/ */
GIT_EXTERN(int) git_repository_merge_cleanup(git_repository *repo); GIT_EXTERN(int) git_repository_state_cleanup(git_repository *repo);
typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name, typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name,
const char *remote_url, const char *remote_url,
...@@ -503,14 +519,18 @@ typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name, ...@@ -503,14 +519,18 @@ typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name,
void *payload); void *payload);
/** /**
* Call callback 'callback' for each entry in the given FETCH_HEAD file. * Invoke 'callback' for each entry in the given FETCH_HEAD file.
*
* Return a non-zero value from the callback to stop the loop.
* *
* @param repo A repository object * @param repo A repository object
* @param callback Callback function * @param callback Callback function
* @param payload Pointer to callback data (optional) * @param payload Pointer to callback data (optional)
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error * @return 0 on success, non-zero callback return value, GIT_ENOTFOUND if
* there is no FETCH_HEAD file, or other error code.
*/ */
GIT_EXTERN(int) git_repository_fetchhead_foreach(git_repository *repo, GIT_EXTERN(int) git_repository_fetchhead_foreach(
git_repository *repo,
git_repository_fetchhead_foreach_cb callback, git_repository_fetchhead_foreach_cb callback,
void *payload); void *payload);
...@@ -518,15 +538,19 @@ typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid, ...@@ -518,15 +538,19 @@ typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid,
void *payload); void *payload);
/** /**
* If a merge is in progress, call callback 'cb' for each commit ID in the * If a merge is in progress, invoke 'callback' for each commit ID in the
* MERGE_HEAD file. * MERGE_HEAD file.
* *
* Return a non-zero value from the callback to stop the loop.
*
* @param repo A repository object * @param repo A repository object
* @param callback Callback function * @param callback Callback function
* @param payload Pointer to callback data (optional) * @param payload Pointer to callback data (optional)
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error * @return 0 on success, non-zero callback return value, GIT_ENOTFOUND if
* there is no MERGE_HEAD file, or other error code.
*/ */
GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, GIT_EXTERN(int) git_repository_mergehead_foreach(
git_repository *repo,
git_repository_mergehead_foreach_cb callback, git_repository_mergehead_foreach_cb callback,
void *payload); void *payload);
...@@ -538,6 +562,10 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, ...@@ -538,6 +562,10 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
* hash a file in the repository and you want to apply filtering rules (e.g. * hash a file in the repository and you want to apply filtering rules (e.g.
* crlf filters) before generating the SHA, then use this function. * crlf filters) before generating the SHA, then use this function.
* *
* Note: if the repository has `core.safecrlf` set to fail and the
* filtering triggers that failure, then this function will return an
* error and not calculate the hash of the file.
*
* @param out Output value of calculated SHA * @param out Output value of calculated SHA
* @param repo Repository pointer * @param repo Repository pointer
* @param path Path to file on disk whose contents should be hashed. If the * @param path Path to file on disk whose contents should be hashed. If the
...@@ -547,6 +575,7 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, ...@@ -547,6 +575,7 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
* NULL, then the `path` parameter will be used instead. If * NULL, then the `path` parameter will be used instead. If
* this is passed as the empty string, then no filters will be * this is passed as the empty string, then no filters will be
* applied when calculating the hash. * applied when calculating the hash.
* @return 0 on success, or an error code
*/ */
GIT_EXTERN(int) git_repository_hashfile( GIT_EXTERN(int) git_repository_hashfile(
git_oid *out, git_oid *out,
...@@ -571,11 +600,15 @@ GIT_EXTERN(int) git_repository_hashfile( ...@@ -571,11 +600,15 @@ GIT_EXTERN(int) git_repository_hashfile(
* *
* @param repo Repository pointer * @param repo Repository pointer
* @param refname Canonical name of the reference the HEAD should point at * @param refname Canonical name of the reference the HEAD should point at
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code * @return 0 on success, or an error code
*/ */
GIT_EXTERN(int) git_repository_set_head( GIT_EXTERN(int) git_repository_set_head(
git_repository* repo, git_repository* repo,
const char* refname); const char* refname,
const git_signature *signature,
const char *log_message);
/** /**
* Make the repository HEAD directly point to the Commit. * Make the repository HEAD directly point to the Commit.
...@@ -591,11 +624,15 @@ GIT_EXTERN(int) git_repository_set_head( ...@@ -591,11 +624,15 @@ GIT_EXTERN(int) git_repository_set_head(
* *
* @param repo Repository pointer * @param repo Repository pointer
* @param commitish Object id of the Commit the HEAD should point to * @param commitish Object id of the Commit the HEAD should point to
* @param signature The identity that will used to populate the reflog entry
* @param log_message The one line long message to be appended to the reflog
* @return 0 on success, or an error code * @return 0 on success, or an error code
*/ */
GIT_EXTERN(int) git_repository_set_head_detached( GIT_EXTERN(int) git_repository_set_head_detached(
git_repository* repo, git_repository* repo,
const git_oid* commitish); const git_oid* commitish,
const git_signature *signature,
const char *log_message);
/** /**
* Detach the HEAD. * Detach the HEAD.
...@@ -611,11 +648,15 @@ GIT_EXTERN(int) git_repository_set_head_detached( ...@@ -611,11 +648,15 @@ GIT_EXTERN(int) git_repository_set_head_detached(
* Otherwise, the HEAD will be detached and point to the peeled Commit. * Otherwise, the HEAD will be detached and point to the peeled Commit.
* *
* @param repo Repository pointer * @param repo Repository pointer
* @param signature The identity that will used to populate the reflog entry
* @param reflog_message The one line long message to be appended to the reflog
* @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing
* branch or an error code * branch or an error code
*/ */
GIT_EXTERN(int) git_repository_detach_head( GIT_EXTERN(int) git_repository_detach_head(
git_repository* repo); git_repository* repo,
const git_signature *signature,
const char *reflog_message);
typedef enum { typedef enum {
GIT_REPOSITORY_STATE_NONE, GIT_REPOSITORY_STATE_NONE,
......
...@@ -19,9 +19,9 @@ GIT_BEGIN_DECL ...@@ -19,9 +19,9 @@ GIT_BEGIN_DECL
* Kinds of reset operation * Kinds of reset operation
*/ */
typedef enum { typedef enum {
GIT_RESET_SOFT = 1, /** Move the head to the given commit */ GIT_RESET_SOFT = 1, /**< Move the head to the given commit */
GIT_RESET_MIXED = 2, /** SOFT plus reset index to the commit */ GIT_RESET_MIXED = 2, /**< SOFT plus reset index to the commit */
GIT_RESET_HARD = 3, /** MIXED plus changes in working tree discarded */ GIT_RESET_HARD = 3, /**< MIXED plus changes in working tree discarded */
} git_reset_t; } git_reset_t;
/** /**
...@@ -48,10 +48,21 @@ typedef enum { ...@@ -48,10 +48,21 @@ typedef enum {
* *
* @param reset_type Kind of reset operation to perform. * @param reset_type Kind of reset operation to perform.
* *
* @param signature The identity that will used to populate the reflog entry
*
* @param log_message The one line long message to be appended to the reflog.
* The reflog is only updated if the affected direct reference is actually
* changing. If NULL, the default is "reset: moving"; if you want something more
* useful, provide a message.
*
* @return 0 on success or an error code * @return 0 on success or an error code
*/ */
GIT_EXTERN(int) git_reset( GIT_EXTERN(int) git_reset(
git_repository *repo, git_object *target, git_reset_t reset_type); git_repository *repo,
git_object *target,
git_reset_t reset_type,
git_signature *signature,
const char *log_message);
/** /**
* Updates some entries in the index from the target commit tree. * Updates some entries in the index from the target commit tree.
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_revert_h__
#define INCLUDE_git_revert_h__
#include "common.h"
#include "types.h"
#include "merge.h"
/**
* @file git2/revert.h
* @brief Git revert routines
* @defgroup git_revert Git revert routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
typedef struct {
unsigned int version;
/** For merge commits, the "mainline" is treated as the parent. */
unsigned int mainline;
git_merge_options merge_opts;
git_checkout_options checkout_opts;
} git_revert_options;
#define GIT_REVERT_OPTIONS_VERSION 1
#define GIT_REVERT_OPTIONS_INIT {GIT_REVERT_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
/**
* Initializes a `git_revert_options` with default values. Equivalent to
* creating an instance with GIT_REVERT_OPTIONS_INIT.
*
* @param opts the `git_revert_options` struct to initialize
* @param version Version of struct; pass `GIT_REVERT_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_revert_init_options(
git_revert_options *opts,
unsigned int version);
/**
* Reverts the given commit against the given "our" commit, producing an
* index that reflects the result of the revert.
*
* The returned index must be freed explicitly with `git_index_free`.
*
* @param out pointer to store the index result in
* @param repo the repository that contains the given commits
* @param revert_commit the commit to revert
* @param our_commit the commit to revert against (eg, HEAD)
* @param mainline the parent of the revert commit, if it is a merge
* @param merge_options the merge options (or null for defaults)
* @return zero on success, -1 on failure.
*/
int git_revert_commit(
git_index **out,
git_repository *repo,
git_commit *revert_commit,
git_commit *our_commit,
unsigned int mainline,
const git_merge_options *merge_options);
/**
* Reverts the given commit, producing changes in the working directory.
*
* @param repo the repository to revert
* @param commit the commit to revert
* @param given_opts merge flags
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_revert(
git_repository *repo,
git_commit *commit,
const git_revert_options *given_opts);
/** @} */
GIT_END_DECL
#endif
...@@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker); ...@@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
/** /**
* Mark a commit to start traversal from. * Mark a commit to start traversal from.
* *
* The given OID must belong to a commit on the walked * The given OID must belong to a committish on the walked
* repository. * repository.
* *
* The given commit will be used as one of the roots * The given commit will be used as one of the roots
...@@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id); ...@@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id);
* pattern will be pushed to the revision walker. * pattern will be pushed to the revision walker.
* *
* A leading 'refs/' is implied if not present as well as a trailing * A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['. * '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
* *
* @param walk the walker being used for the traversal * @param walk the walker being used for the traversal
* @param glob the glob pattern references should match * @param glob the glob pattern references should match
...@@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk); ...@@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk);
/** /**
* Mark a commit (and its ancestors) uninteresting for the output. * Mark a commit (and its ancestors) uninteresting for the output.
* *
* The given OID must belong to a commit on the walked * The given OID must belong to a committish on the walked
* repository. * repository.
* *
* The resolved commit and all its parents will be hidden from the * The resolved commit and all its parents will be hidden from the
...@@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id); ...@@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id);
* revision walk. * revision walk.
* *
* A leading 'refs/' is implied if not present as well as a trailing * A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['. * '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
* *
* @param walk the walker being used for the traversal * @param walk the walker being used for the traversal
* @param glob the glob pattern references should match * @param glob the glob pattern references should match
...@@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk); ...@@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk);
/** /**
* Push the OID pointed to by a reference * Push the OID pointed to by a reference
* *
* The reference must point to a commit. * The reference must point to a committish.
* *
* @param walk the walker being used for the traversal * @param walk the walker being used for the traversal
* @param refname the reference to push * @param refname the reference to push
...@@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname); ...@@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname);
/** /**
* Hide the OID pointed to by a reference * Hide the OID pointed to by a reference
* *
* The reference must point to a commit. * The reference must point to a committish.
* *
* @param walk the walker being used for the traversal * @param walk the walker being used for the traversal
* @param refname the reference to hide * @param refname the reference to hide
...@@ -255,6 +261,30 @@ GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk); ...@@ -255,6 +261,30 @@ GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk);
*/ */
GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk); GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk);
/**
* This is a callback function that user can provide to hide a
* commit and its parents. If the callback function returns non-zero value,
* then this commit and its parents will be hidden.
*
* @param commit_id oid of Commit
* @param payload User-specified pointer to data to be passed as data payload
*/
typedef int(*git_revwalk_hide_cb)(
const git_oid *commit_id,
void *payload);
/**
* Adds a callback function to hide a commit and its parents
*
* @param walk the revision walker
* @param hide_cb callback function to hide a commit and its parents
* @param payload data payload to be passed to callback function
*/
GIT_EXTERN(int) git_revwalk_add_hide_cb(
git_revwalk *walk,
git_revwalk_hide_cb hide_cb,
void *payload);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -68,10 +68,11 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo) ...@@ -68,10 +68,11 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo)
* *
* Call `git_signature_free()` to free the data. * Call `git_signature_free()` to free the data.
* *
* @param sig signature to duplicated * @param dest pointer where to store the copy
* @return a copy of sig, NULL on out of memory * @param sig signature to duplicate
* @return 0 or an error code
*/ */
GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig); GIT_EXTERN(int) git_signature_dup(git_signature **dest, const git_signature *sig);
/** /**
* Free an existing signature. * Free an existing signature.
......
...@@ -62,19 +62,15 @@ GIT_EXTERN(int) git_stash_save( ...@@ -62,19 +62,15 @@ GIT_EXTERN(int) git_stash_save(
unsigned int flags); unsigned int flags);
/** /**
* When iterating over all the stashed states, callback that will be * This is a callback function you can provide to iterate over all the
* issued per entry. * stashed states that will be invoked per entry.
* *
* @param index The position within the stash list. 0 points to the * @param index The position within the stash list. 0 points to the
* most recent stashed state. * most recent stashed state.
*
* @param message The stash message. * @param message The stash message.
*
* @param stash_id The commit oid of the stashed state. * @param stash_id The commit oid of the stashed state.
*
* @param payload Extra parameter to callback function. * @param payload Extra parameter to callback function.
* * @return 0 to continue iterating or non-zero to stop
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
*/ */
typedef int (*git_stash_cb)( typedef int (*git_stash_cb)(
size_t index, size_t index,
...@@ -89,12 +85,12 @@ typedef int (*git_stash_cb)( ...@@ -89,12 +85,12 @@ typedef int (*git_stash_cb)(
* *
* @param repo Repository where to find the stash. * @param repo Repository where to find the stash.
* *
* @param callback Callback to invoke per found stashed state. The most recent * @param callback Callback to invoke per found stashed state. The most
* stash state will be enumerated first. * recent stash state will be enumerated first.
* *
* @param payload Extra parameter to callback function. * @param payload Extra parameter to callback function.
* *
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_stash_foreach( GIT_EXTERN(int) git_stash_foreach(
git_repository *repo, git_repository *repo,
......
...@@ -121,6 +121,11 @@ typedef enum { ...@@ -121,6 +121,11 @@ typedef enum {
* - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of * - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of
* doing a "soft" index reload (i.e. reloading the index data if the * doing a "soft" index reload (i.e. reloading the index data if the
* file on disk has been modified outside libgit2). * file on disk has been modified outside libgit2).
* - GIT_STATUS_OPT_UPDATE_INDEX tells libgit2 to refresh the stat cache
* in the index for files that are unchanged but have out of date stat
* information in the index. It will result in less work being done on
* subsequent calls to get status. This is mutually exclusive with the
* NO_REFRESH option.
* *
* Calling `git_status_foreach()` is like calling the extended version * Calling `git_status_foreach()` is like calling the extended version
* with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED, * with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED,
...@@ -141,6 +146,7 @@ typedef enum { ...@@ -141,6 +146,7 @@ typedef enum {
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10), GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10),
GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11), GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11),
GIT_STATUS_OPT_NO_REFRESH = (1u << 12), GIT_STATUS_OPT_NO_REFRESH = (1u << 12),
GIT_STATUS_OPT_UPDATE_INDEX = (1u << 13),
} git_status_opt_t; } git_status_opt_t;
#define GIT_STATUS_OPT_DEFAULTS \ #define GIT_STATUS_OPT_DEFAULTS \
...@@ -175,6 +181,18 @@ typedef struct { ...@@ -175,6 +181,18 @@ typedef struct {
#define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION} #define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION}
/** /**
* Initializes a `git_status_options` with default values. Equivalent to
* creating an instance with GIT_STATUS_OPTIONS_INIT.
*
* @param opts The `git_status_options` instance to initialize.
* @param version Version of struct; pass `GIT_STATUS_OPTIONS_VERSION`
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_status_init_options(
git_status_options *opts,
unsigned int version);
/**
* A status entry, providing the differences between the file as it exists * A status entry, providing the differences between the file as it exists
* in HEAD and the index, and providing the differences between the index * in HEAD and the index, and providing the differences between the index
* and the working directory. * and the working directory.
...@@ -203,12 +221,12 @@ typedef struct { ...@@ -203,12 +221,12 @@ typedef struct {
* into this function. * into this function.
* *
* If the callback returns a non-zero value, this function will stop looping * If the callback returns a non-zero value, this function will stop looping
* and return GIT_EUSER. * and return that value to caller.
* *
* @param repo A repository object * @param repo A repository object
* @param callback The function to call on each file * @param callback The function to call on each file
* @param payload Pointer to pass through to callback function * @param payload Pointer to pass through to callback function
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_status_foreach( GIT_EXTERN(int) git_status_foreach(
git_repository *repo, git_repository *repo,
...@@ -223,11 +241,16 @@ GIT_EXTERN(int) git_status_foreach( ...@@ -223,11 +241,16 @@ GIT_EXTERN(int) git_status_foreach(
* in what order. See the `git_status_options` structure for details * in what order. See the `git_status_options` structure for details
* about the additional controls that this makes available. * about the additional controls that this makes available.
* *
* Note that if a `pathspec` is given in the `git_status_options` to filter
* the status, then the results from rename detection (if you enable it) may
* not be accurate. To do rename detection properly, this must be called
* with no `pathspec` so that all files can be considered.
*
* @param repo Repository object * @param repo Repository object
* @param opts Status options structure * @param opts Status options structure
* @param callback The function to call on each file * @param callback The function to call on each file
* @param payload Pointer to pass through to callback function * @param payload Pointer to pass through to callback function
* @return 0 on success, GIT_EUSER on non-zero callback, or error code * @return 0 on success, non-zero callback return value, or error code
*/ */
GIT_EXTERN(int) git_status_foreach_ext( GIT_EXTERN(int) git_status_foreach_ext(
git_repository *repo, git_repository *repo,
...@@ -238,8 +261,20 @@ GIT_EXTERN(int) git_status_foreach_ext( ...@@ -238,8 +261,20 @@ GIT_EXTERN(int) git_status_foreach_ext(
/** /**
* Get file status for a single file. * Get file status for a single file.
* *
* This is not quite the same as calling `git_status_foreach_ext()` with * This tries to get status for the filename that you give. If no files
* the pathspec set to the specified path. * match that name (in either the HEAD, index, or working directory), this
* returns GIT_ENOTFOUND.
*
* If the name matches multiple files (for example, if the `path` names a
* directory or if running on a case- insensitive filesystem and yet the
* HEAD has two entries that both match the path), then this returns
* GIT_EAMBIGUOUS because it cannot give correct results.
*
* This does not do any sort of rename detection. Renames require a set of
* targets and because of the path filtering, there is not enough
* information to check renames correctly. To check file status with rename
* detection, there is no choice but to do a full `git_status_list_new` and
* scan through looking for the path that you are interested in.
* *
* @param status_flags Output combination of git_status_t values for file * @param status_flags Output combination of git_status_t values for file
* @param repo A repository object * @param repo A repository object
...@@ -256,6 +291,11 @@ GIT_EXTERN(int) git_status_file( ...@@ -256,6 +291,11 @@ GIT_EXTERN(int) git_status_file(
/** /**
* Gather file status information and populate the `git_status_list`. * Gather file status information and populate the `git_status_list`.
* *
* Note that if a `pathspec` is given in the `git_status_options` to filter
* the status, then the results from rename detection (if you enable it) may
* not be accurate. To do rename detection properly, this must be called
* with no `pathspec` so that all files can be considered.
*
* @param out Pointer to store the status results in * @param out Pointer to store the status results in
* @param repo Repository object * @param repo Repository object
* @param opts Status options structure * @param opts Status options structure
...@@ -269,6 +309,9 @@ GIT_EXTERN(int) git_status_list_new( ...@@ -269,6 +309,9 @@ GIT_EXTERN(int) git_status_list_new(
/** /**
* Gets the count of status entries in this list. * Gets the count of status entries in this list.
* *
* If there are no changes in status (at least according the options given
* when the status list was created), this can return 0.
*
* @param statuslist Existing status list object * @param statuslist Existing status list object
* @return the number of status entries * @return the number of status entries
*/ */
......
...@@ -97,7 +97,8 @@ typedef enum { ...@@ -97,7 +97,8 @@ typedef enum {
(((S) & GIT_SUBMODULE_STATUS__INDEX_FLAGS) == 0) (((S) & GIT_SUBMODULE_STATUS__INDEX_FLAGS) == 0)
#define GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(S) \ #define GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(S) \
(((S) & GIT_SUBMODULE_STATUS__WD_FLAGS) == 0) (((S) & (GIT_SUBMODULE_STATUS__WD_FLAGS & \
~GIT_SUBMODULE_STATUS_WD_UNINITIALIZED)) == 0)
#define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \ #define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \
(((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \ (((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \
...@@ -114,30 +115,36 @@ typedef enum { ...@@ -114,30 +115,36 @@ typedef enum {
* *
* - The submodule is not mentioned in the HEAD, the index, and the config, * - The submodule is not mentioned in the HEAD, the index, and the config,
* but does "exist" in the working directory (i.e. there is a subdirectory * but does "exist" in the working directory (i.e. there is a subdirectory
* that is a valid self-contained git repo). In this case, this function * that appears to be a Git repository). In this case, this function
* returns GIT_EEXISTS to indicate the the submodule exists but not in a * returns GIT_EEXISTS to indicate a sub-repository exists but not in a
* state where a git_submodule can be instantiated. * state where a git_submodule can be instantiated.
* - The submodule is not mentioned in the HEAD, index, or config and the * - The submodule is not mentioned in the HEAD, index, or config and the
* working directory doesn't contain a value git repo at that path. * working directory doesn't contain a value git repo at that path.
* There may or may not be anything else at that path, but nothing that * There may or may not be anything else at that path, but nothing that
* looks like a submodule. In this case, this returns GIT_ENOTFOUND. * looks like a submodule. In this case, this returns GIT_ENOTFOUND.
* *
* The submodule object is owned by the containing repo and will be freed * You must call `git_submodule_free` when done with the submodule.
* when the repo is freed. The caller need not free the submodule.
* *
* @param submodule Pointer to submodule description object pointer.. * @param out Output ptr to submodule; pass NULL to just get return code
* @param repo The repository. * @param repo The parent repository
* @param name The name of the submodule. Trailing slashes will be ignored. * @param name The name of or path to the submodule; trailing slashes okay
* @return 0 on success, GIT_ENOTFOUND if submodule does not exist, * @return 0 on success, GIT_ENOTFOUND if submodule does not exist,
* GIT_EEXISTS if submodule exists in working directory only, -1 on * GIT_EEXISTS if a repository is found in working directory only,
* other errors. * -1 on other errors.
*/ */
GIT_EXTERN(int) git_submodule_lookup( GIT_EXTERN(int) git_submodule_lookup(
git_submodule **submodule, git_submodule **out,
git_repository *repo, git_repository *repo,
const char *name); const char *name);
/** /**
* Release a submodule
*
* @param submodule Submodule object
*/
GIT_EXTERN(void) git_submodule_free(git_submodule *submodule);
/**
* Iterate over all tracked submodules of a repository. * Iterate over all tracked submodules of a repository.
* *
* See the note on `git_submodule` above. This iterates over the tracked * See the note on `git_submodule` above. This iterates over the tracked
...@@ -174,9 +181,11 @@ GIT_EXTERN(int) git_submodule_foreach( ...@@ -174,9 +181,11 @@ GIT_EXTERN(int) git_submodule_foreach(
* `git_submodule_add_finalize()` to wrap up adding the new submodule and * `git_submodule_add_finalize()` to wrap up adding the new submodule and
* .gitmodules to the index to be ready to commit. * .gitmodules to the index to be ready to commit.
* *
* @param submodule The newly created submodule ready to open for clone * You must call `git_submodule_free` on the submodule object when done.
* @param repo Superproject repository to contain the new submodule *
* @param url URL for the submodules remote * @param out The newly created submodule ready to open for clone
* @param repo The repository in which you want to create the submodule
* @param url URL for the submodule's remote
* @param path Path at which the submodule should be created * @param path Path at which the submodule should be created
* @param use_gitlink Should workdir contain a gitlink to the repo in * @param use_gitlink Should workdir contain a gitlink to the repo in
* .git/modules vs. repo directly in workdir. * .git/modules vs. repo directly in workdir.
...@@ -184,7 +193,7 @@ GIT_EXTERN(int) git_submodule_foreach( ...@@ -184,7 +193,7 @@ GIT_EXTERN(int) git_submodule_foreach(
* -1 on other errors. * -1 on other errors.
*/ */
GIT_EXTERN(int) git_submodule_add_setup( GIT_EXTERN(int) git_submodule_add_setup(
git_submodule **submodule, git_submodule **out,
git_repository *repo, git_repository *repo,
const char *url, const char *url,
const char *path, const char *path,
...@@ -271,6 +280,24 @@ GIT_EXTERN(const char *) git_submodule_path(git_submodule *submodule); ...@@ -271,6 +280,24 @@ GIT_EXTERN(const char *) git_submodule_path(git_submodule *submodule);
GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule); GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule);
/** /**
* Resolve a submodule url relative to the given repository.
*
* @param out buffer to store the absolute submodule url in
* @param repo Pointer to repository object
* @param url Relative url
* @return 0 or an error code
*/
GIT_EXTERN(int) git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url);
/**
* Get the branch for the submodule.
*
* @param submodule Pointer to submodule object
* @return Pointer to the submodule branch
*/
GIT_EXTERN(const char *) git_submodule_branch(git_submodule *submodule);
/**
* Set the URL for the submodule. * Set the URL for the submodule.
* *
* This sets the URL in memory for the submodule. This will be used for * This sets the URL in memory for the submodule. This will be used for
...@@ -410,7 +437,7 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_set_update( ...@@ -410,7 +437,7 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_set_update(
* *
* @return 0 if fetchRecurseSubmodules is false, 1 if true * @return 0 if fetchRecurseSubmodules is false, 1 if true
*/ */
GIT_EXTERN(int) git_submodule_fetch_recurse_submodules( GIT_EXTERN(git_submodule_recurse_t) git_submodule_fetch_recurse_submodules(
git_submodule *submodule); git_submodule *submodule);
/** /**
...@@ -424,9 +451,9 @@ GIT_EXTERN(int) git_submodule_fetch_recurse_submodules( ...@@ -424,9 +451,9 @@ GIT_EXTERN(int) git_submodule_fetch_recurse_submodules(
* @param fetch_recurse_submodules Boolean value * @param fetch_recurse_submodules Boolean value
* @return old value for fetchRecurseSubmodules * @return old value for fetchRecurseSubmodules
*/ */
GIT_EXTERN(int) git_submodule_set_fetch_recurse_submodules( GIT_EXTERN(git_submodule_recurse_t) git_submodule_set_fetch_recurse_submodules(
git_submodule *submodule, git_submodule *submodule,
int fetch_recurse_submodules); git_submodule_recurse_t fetch_recurse_submodules);
/** /**
* Copy submodule info into ".git/config" file. * Copy submodule info into ".git/config" file.
...@@ -474,15 +501,23 @@ GIT_EXTERN(int) git_submodule_open( ...@@ -474,15 +501,23 @@ GIT_EXTERN(int) git_submodule_open(
* *
* Call this to reread cached submodule information for this submodule if * Call this to reread cached submodule information for this submodule if
* you have reason to believe that it has changed. * you have reason to believe that it has changed.
*
* @param submodule The submodule to reload
* @param force Force reload even if the data doesn't seem out of date
* @return 0 on success, <0 on error
*/ */
GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule); GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule, int force);
/** /**
* Reread all submodule info. * Reread all submodule info.
* *
* Call this to reload all cached submodule information for the repo. * Call this to reload all cached submodule information for the repo.
*
* @param repo The repository to reload submodule data for
* @param force Force full reload even if the data doesn't seem out of date
* @return 0 on success, <0 on error
*/ */
GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo); GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo, int force);
/** /**
* Get the status for a submodule. * Get the status for a submodule.
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
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