Commit 29d7242b by Vicent Marti

Merge branch 'development'

parents a50086d1 eddc1f1e
......@@ -24,8 +24,8 @@ msvc/Release/
*.sdf
*.opensdf
*.aps
CMake*
*.cmake
!cmake/Modules/*.cmake
.DS_Store
*~
tags
......
Vicent Martí <vicent@github.com> Vicent Marti <tanoku@gmail.com>
Vicent Martí <vicent@github.com> Vicent Marti <tanoku@gmail.com>
Vicent Martí <vicent@github.com> Vicent Martí <tanoku@gmail.com>
Michael Schubert <schu@schu.io> schu <schu-github@schulog.org>
Ben Straub <bs@github.com> Ben Straub <ben@straubnet.net>
Ben Straub <bs@github.com> Ben Straub <bstraub@github.com>
Carlos Martín Nieto <cmn@dwim.me> <carlos@cmartin.tk>
Carlos Martín Nieto <cmn@dwim.me> <cmn@elego.de>
nulltoken <emeric.fermas@gmail.com> <emeric.fermas@gmail.com>
Scott J. Goldman <scottjg@github.com> <scottjgo@gmail.com>
Martin Woodward <martin.woodward@microsoft.com> <martinwo@microsoft.com>
Peter Drahoš <drahosp@gmail.com> <drahosp@gmail.com>
Adam Roben <adam@github.com> <adam@roben.org>
Adam Roben <adam@github.com> <adam@github.com>
Xavier L. <xavier.l@afrosoft.tk> <xavier.l@afrosoft.ca>
Xavier L. <xavier.l@afrosoft.tk> <xavier.l@afrosoft.tk>
Sascha Cunz <sascha@babbelbox.org> <Sascha@BabbelBox.org>
Authmillenon <authmillenon@googlemail.com> <martin@ucsmail.de>
Authmillenon <authmillenon@googlemail.com> <authmillenon@googlemail.com>
......@@ -25,6 +25,10 @@ install:
# Run the Build script
script:
- mkdir _temp
- git init --bare _temp/test.git
- git daemon --listen=localhost --export-all --enable=receive-pack --base-path=_temp _temp 2>/dev/null &
- export GITTEST_REMOTE_URL="git://localhost/test.git"
- mkdir _build
- cd _build
- cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS
......
......@@ -14,6 +14,9 @@
PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# Add find modules to the path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
# Build options
#
OPTION( SONAME "Set the (SO)VERSION of the target" ON )
......@@ -24,6 +27,8 @@ OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF )
OPTION( TAGS "Generate tags" OFF )
OPTION( PROFILE "Generate profiling information" OFF )
OPTION( ENABLE_TRACE "Enables tracing support" OFF )
OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF )
IF(MSVC)
# This option is only availalbe when building with MSVC. By default,
# libgit2 is build using the stdcall calling convention, as that's what
......@@ -97,14 +102,22 @@ ELSE ()
IF (NOT AMIGA)
FIND_PACKAGE(OpenSSL)
ENDIF ()
FILE(GLOB SRC_HTTP deps/http-parser/*.c)
INCLUDE_DIRECTORIES(deps/http-parser)
FIND_PACKAGE(HTTP_Parser QUIET)
IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2)
INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS})
LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES})
ELSE()
MESSAGE("http-parser was not found or is too old; using bundled 3rd-party sources.")
INCLUDE_DIRECTORIES(deps/http-parser)
FILE(GLOB SRC_HTTP deps/http-parser/*.c)
ENDIF()
ENDIF()
# Specify sha1 implementation
IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin")
ADD_DEFINITIONS(-DWIN32_SHA1)
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
ADD_DEFINITIONS(-DWIN32_SHA1)
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin")
ADD_DEFINITIONS(-DOPENSSL_SHA1)
ELSE()
......@@ -123,14 +136,14 @@ IF(WIN32 OR AMIGA)
ENDIF()
# Optional external dependency: zlib
IF(NOT ZLIB_LIBRARY)
# It's optional, but FIND_PACKAGE gives a warning that looks more like an
# error.
FIND_PACKAGE(ZLIB QUIET)
ENDIF()
# It's optional, but FIND_PACKAGE gives a warning that looks more like an
# error.
FIND_PACKAGE(ZLIB QUIET)
IF (ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
LINK_LIBRARIES(${ZLIB_LIBRARIES})
# Fake the message CMake would have shown
MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}")
ELSE()
MESSAGE( "zlib was not found; using bundled 3rd-party sources." )
INCLUDE_DIRECTORIES(deps/zlib)
......@@ -138,10 +151,19 @@ ELSE()
FILE(GLOB SRC_ZLIB deps/zlib/*.c)
ENDIF()
IF(NOT LIBSSH2_LIBRARY)
FIND_PACKAGE(LIBSSH2 QUIET)
ENDIF()
IF (LIBSSH2_FOUND)
ADD_DEFINITIONS(-DGIT_SSH)
INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR})
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
ENDIF()
# Platform specific compilation flags
IF (MSVC)
STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
STRING(REPLACE "/Zm1000" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
# /GF - String pooling
# /MP - Parallel build
......@@ -156,7 +178,7 @@ IF (MSVC)
SET(CRT_FLAG_DEBUG "/MTd")
SET(CRT_FLAG_RELEASE "/MT")
ELSE()
SET(CRT_FLAG_DEBUG "/MDd")
SET(CRT_FLAG_DEBUG "/MDd")
SET(CRT_FLAG_RELEASE "/MD")
ENDIF()
......@@ -277,14 +299,24 @@ ELSE()
ENDIF()
FILE(GLOB SRC_GIT2 src/*.c src/transports/*.c src/xdiff/*.c)
# Determine architecture of the machine
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
ADD_DEFINITIONS(-DGIT_ARCH_64)
ELSEIF (CMAKE_SIZEOF_VOID_P EQUAL 4)
ADD_DEFINITIONS(-DGIT_ARCH_32)
ELSE()
message(FATAL_ERROR "Unsupported architecture")
ENDIF()
# Compile and link libgit2
ADD_LIBRARY(git2 ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC})
TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES})
TARGET_OS_LIBRARIES(git2)
# Workaround for Cmake bug #0011240 (see http://public.kitware.com/Bug/view.php?id=11240)
# Win64+MSVC+static libs = linker error
IF(MSVC AND NOT BUILD_SHARED_LIBS AND (${CMAKE_SIZEOF_VOID_P} MATCHES "8") )
IF(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS)
SET_TARGET_PROPERTIES(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64")
ENDIF()
......@@ -293,6 +325,10 @@ MSVC_SPLIT_SOURCES(git2)
IF (SONAME)
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
ENDIF()
ENDIF()
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libgit2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc @ONLY)
......@@ -328,7 +364,7 @@ IF (BUILD_CLAR)
ADD_CUSTOM_COMMAND(
OUTPUT ${CLAR_PATH}/clar.suite
COMMAND ${PYTHON_EXECUTABLE} generate.py -xonline .
COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline .
DEPENDS ${SRC_TEST}
WORKING_DIRECTORY ${CLAR_PATH}
)
......@@ -340,6 +376,7 @@ IF (BUILD_CLAR)
ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES})
TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES})
TARGET_OS_LIBRARIES(libgit2_clar)
MSVC_SPLIT_SOURCES(libgit2_clar)
......
......@@ -19,6 +19,7 @@ release its source code.
* Archives: <http://librelist.com/browser/libgit2/>
* Website: <http://libgit2.github.com>
* API documentation: <http://libgit2.github.com/libgit2>
* IRC: #libgit2 on irc.freenode.net.
What It Can Do
==================================
......@@ -139,7 +140,7 @@ Here are the bindings to libgit2 that are currently available:
* Parrot Virtual Machine
* parrot-libgit2 <https://github.com/letolabs/parrot-libgit2>
* Perl
* git-xs-pm <https://github.com/ingydotnet/git-xs-pm>
* Git-Raw <https://github.com/ghedo/p5-Git-Raw>
* PHP
* php-git <https://github.com/libgit2/php-git>
* Python
......@@ -155,15 +156,7 @@ we can add it to the list.
How Can I Contribute?
==================================
Fork libgit2/libgit2 on GitHub, add your improvement, push it to a branch
in your fork named for the topic, send a pull request. If you change the
API or make other large changes, make a note of it in docs/rel-notes/ in a
file named after the next release.
You can also file bugs or feature requests under the libgit2 project on
GitHub, or join us on the mailing list by sending an email to:
libgit2@librelist.com
Check the [contribution guidelines](CONTRIBUTING.md).
License
......
# - Try to find http-parser
#
# Defines the following variables:
#
# HTTP_PARSER_FOUND - system has http-parser
# HTTP_PARSER_INCLUDE_DIR - the http-parser include directory
# HTTP_PARSER_LIBRARIES - Link these to use http-parser
# HTTP_PARSER_VERSION_MAJOR - major version
# HTTP_PARSER_VERSION_MINOR - minor version
# HTTP_PARSER_VERSION_STRING - the version of http-parser found
# Find the header and library
FIND_PATH(HTTP_PARSER_INCLUDE_DIR NAMES http_parser.h)
FIND_LIBRARY(HTTP_PARSER_LIBRARY NAMES http_parser libhttp_parser)
# Found the header, read version
if (HTTP_PARSER_INCLUDE_DIR AND EXISTS "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h")
FILE(READ "${HTTP_PARSER_INCLUDE_DIR}/http_parser.h" HTTP_PARSER_H)
IF (HTTP_PARSER_H)
STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MAJOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MAJOR "${HTTP_PARSER_H}")
STRING(REGEX REPLACE ".*#define[\t ]+HTTP_PARSER_VERSION_MINOR[\t ]+([0-9]+).*" "\\1" HTTP_PARSER_VERSION_MINOR "${HTTP_PARSER_H}")
SET(HTTP_PARSER_VERSION_STRING "${HTTP_PARSER_VERSION_MAJOR}.${HTTP_PARSER_VERSION_MINOR}")
ENDIF()
UNSET(HTTP_PARSER_H)
ENDIF()
# Handle the QUIETLY and REQUIRED arguments and set HTTP_PARSER_FOUND
# to TRUE if all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HTTP_Parser REQUIRED_VARS HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
# Hide advanced variables
MARK_AS_ADVANCED(HTTP_PARSER_INCLUDE_DIR HTTP_PARSER_LIBRARY)
# Set standard variables
IF (HTTP_PARSER_FOUND)
SET(HTTP_PARSER_LIBRARIES ${HTTP_PARSER_LIBRARY})
set(HTTP_PARSER_INCLUDE_DIRS ${HTTP_PARSER_INCLUDE_DIR})
ENDIF()
if (LIBSSH2_LIBRARIES AND LIBSSH2_INCLUDE_DIRS)
set(LIBSSH2_FOUND TRUE)
else (LIBSSH2_LIBRARIES AND LIBSSH2_INCLUDE_DIRS)
find_path(LIBSSH2_INCLUDE_DIR
NAMES
libssh2.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
${CMAKE_INCLUDE_PATH}
${CMAKE_INSTALL_PREFIX}/include
)
find_library(LIBSSH2_LIBRARY
NAMES
ssh2
libssh2
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
${CMAKE_LIBRARY_PATH}
${CMAKE_INSTALL_PREFIX}/lib
)
if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
set(LIBSSH2_FOUND TRUE)
endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
if (LIBSSH2_FOUND)
set(LIBSSH2_INCLUDE_DIRS
${LIBSSH2_INCLUDE_DIR}
)
set(LIBSSH2_LIBRARIES
${LIBSSH2_LIBRARIES}
${LIBSSH2_LIBRARY}
)
endif (LIBSSH2_FOUND)
endif (LIBSSH2_LIBRARIES AND LIBSSH2_INCLUDE_DIRS)
Diff is broken into four phases:
1. Building a list of things that have changed. These changes are called
deltas (git_diff_delta objects) and are grouped into a git_diff_list.
2. Applying file similarity measurement for rename and copy detection (and
to potentially split files that have changed radically). This step is
optional.
3. Computing the textual diff for each delta. Not all deltas have a
meaningful textual diff. For those that do, the textual diff can
either be generated on the fly and passed to output callbacks or can be
turned into a git_diff_patch object.
4. Formatting the diff and/or patch into standard text formats (such as
patches, raw lists, etc).
In the source code, step 1 is implemented in `src/diff.c`, step 2 in
`src/diff_tform.c`, step 3 in `src/diff_patch.c`, and step 4 in
`src/diff_print.c`. Additionally, when it comes to accessing file
content, everything goes through diff drivers that are implemented in
`src/diff_driver.c`.
External Objects
----------------
* `git_diff_options` repesents user choices about how a diff should be
performed and is passed to most diff generating functions.
* `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
way - it contains two `git_diff_file` plus a status and other stuff.
* `git_diff_list` is a list of deltas along with information about how
those particular deltas were found.
* `git_diff_patch` represents the actual diff between a pair of items. In
some cases, a delta may not have a corresponding patch, if the objects
are binary, for example. The content of a patch will be a set of hunks
and lines.
* A `hunk` is range of lines described by a `git_diff_range` (i.e. "lines
10-20 in the old file became lines 12-23 in the new"). 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.
* 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).
Internal Objects
----------------
* `git_diff_file_content` is an internal structure that represents the
data on one side of an item to be diffed; it is an augmented
`git_diff_file` with more flags and the actual file data.
** it is created from a repository plus a) a git_diff_file, b) a git_blob,
or c) raw data and size
** there are three main operations on git_diff_file_content:
*** _initialization_ sets up the data structure and does what it can up to,
but not including loading and looking at the actual data
*** _loading_ loads the data, preprocesses it (i.e. applies filters) and
potentially analyzes it (to decide if binary)
*** _free_ releases loaded data and frees any allocated memory
* The internal structure of a `git_diff_patch` stores the actual diff
between a pair of `git_diff_file_content` items
** it may be "unset" if the items are not diffable
** "empty" if the items are the same
** otherwise it will consist of a set of hunks each of which covers some
number of lines of context, additions and deletions
** a patch is created from two git_diff_file_content items
** a patch is fully instantiated in three phases:
*** initial creation and initialization
*** loading of data and preliminary data examination
*** diffing of data and optional storage of diffs
** (TBD) if a patch is asked to store the diffs and the size of the diff
is significantly smaller than the raw data of the two sides, then the
patch may be flattened using a pool of string data
* `git_diff_output` is an internal structure that represents an output
target for a `git_diff_patch`
** It consists of file, hunk, and line callbacks, plus a payload
** There is a standard flattened output that can be used for plain text output
** Typically we use a `git_xdiff_output` which drives the callbacks via the
xdiff code taken from core Git.
* `git_diff_driver` is an internal structure that encapsulates the logic
for a given type of file
** a driver is looked up based on the name and mode of a file.
** the driver can then be used to:
*** determine if a file is binary (by attributes, by git_diff_options
settings, or by examining the content)
*** give you a function pointer that is used to evaluate function context
for hunk headers
** At some point, the logic for getting a filtered version of file content
or calculating the OID of a file may be moved into the driver.
Anc / Our / Thr represent the ancestor / ours / theirs side of a merge
from branch "branch" into HEAD. Workdir represents the expected files in
the working directory. Index represents the expected files in the index,
with stage markers.
Anc Our Thr Workdir Index
1 D D
D/F D/F D/F [0]
2 D D+ D~HEAD (mod/del) D/F [0]
D/F D/F D [1]
D [2]
3 D D D/F D/F [0]
D/F
4 D D+ D~branch (mod/del) D/F [0]
D/F D/F D [1]
D [3]
5 D D/F (add/add) D/F [2]
D/F D/F [3]
D/F
6 D/F D/F D D [0]
D
7 D/F D/F+ D/F (mod/del) D/F [1]
D D~branch (fil/dir) D/F [2]
D [3]
8 D/F D/F D D [0]
D
9 D/F D/F+ D/F (mod/del) D/F [1]
D D~HEAD (fil/dir) D [2]
D/F [3]
10 D/F D/F (fil/dir) D/F [0]
D D~HEAD D [2]
D
......@@ -3,7 +3,7 @@
CC = gcc
CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers
LFLAGS = -L../build -lgit2 -lz
APPS = general showindex diff rev-list
APPS = general showindex diff rev-list cat-file status
all: $(APPS)
......
#include <stdio.h>
#include <git2.h>
#include <stdlib.h>
#include <string.h>
static git_repository *g_repo;
static void check(int error, const char *message)
{
if (error) {
fprintf(stderr, "%s (%d)\n", message, error);
exit(1);
}
}
static void usage(const char *message, const char *arg)
{
if (message && arg)
fprintf(stderr, "%s: %s\n", message, arg);
else if (message)
fprintf(stderr, "%s\n", message);
fprintf(stderr, "usage: cat-file (-t | -s | -e | -p) [<options>] <object>\n");
exit(1);
}
static int check_str_param(
const char *arg, const char *pattern, const char **val)
{
size_t len = strlen(pattern);
if (strncmp(arg, pattern, len))
return 0;
*val = (const char *)(arg + len);
return 1;
}
static void print_signature(const char *header, const git_signature *sig)
{
char sign;
int offset, hours, minutes;
if (!sig)
return;
offset = sig->when.offset;
if (offset < 0) {
sign = '-';
offset = -offset;
} else {
sign = '+';
}
hours = offset / 60;
minutes = offset % 60;
printf("%s %s <%s> %ld %c%02d%02d\n",
header, sig->name, sig->email, (long)sig->when.time,
sign, hours, minutes);
}
static void show_blob(const git_blob *blob)
{
/* ? Does this need crlf filtering? */
fwrite(git_blob_rawcontent(blob), git_blob_rawsize(blob), 1, stdout);
}
static void show_tree(const git_tree *tree)
{
size_t i, max_i = (int)git_tree_entrycount(tree);
char oidstr[GIT_OID_HEXSZ + 1];
const git_tree_entry *te;
for (i = 0; i < max_i; ++i) {
te = git_tree_entry_byindex(tree, i);
git_oid_tostr(oidstr, sizeof(oidstr), git_tree_entry_id(te));
printf("%06o %s %s\t%s\n",
git_tree_entry_filemode(te),
git_object_type2string(git_tree_entry_type(te)),
oidstr, git_tree_entry_name(te));
}
}
static void show_commit(const git_commit *commit)
{
unsigned int i, max_i;
char oidstr[GIT_OID_HEXSZ + 1];
git_oid_tostr(oidstr, sizeof(oidstr), git_commit_tree_id(commit));
printf("tree %s\n", oidstr);
max_i = (unsigned int)git_commit_parentcount(commit);
for (i = 0; i < max_i; ++i) {
git_oid_tostr(oidstr, sizeof(oidstr), git_commit_parent_id(commit, i));
printf("parent %s\n", oidstr);
}
print_signature("author", git_commit_author(commit));
print_signature("committer", git_commit_committer(commit));
if (git_commit_message(commit))
printf("\n%s\n", git_commit_message(commit));
}
static void show_tag(const git_tag *tag)
{
char oidstr[GIT_OID_HEXSZ + 1];
git_oid_tostr(oidstr, sizeof(oidstr), git_tag_target_id(tag));;
printf("object %s\n", oidstr);
printf("type %s\n", git_object_type2string(git_tag_target_type(tag)));
printf("tag %s\n", git_tag_name(tag));
print_signature("tagger", git_tag_tagger(tag));
if (git_tag_message(tag))
printf("\n%s\n", git_tag_message(tag));
}
enum {
SHOW_TYPE = 1,
SHOW_SIZE = 2,
SHOW_NONE = 3,
SHOW_PRETTY = 4
};
int main(int argc, char *argv[])
{
const char *dir = ".", *rev = NULL;
int i, action = 0, verbose = 0;
git_object *obj = NULL;
char oidstr[GIT_OID_HEXSZ + 1];
git_threads_init();
for (i = 1; i < argc; ++i) {
char *a = argv[i];
if (a[0] != '-') {
if (rev != NULL)
usage("Only one rev should be provided", NULL);
else
rev = a;
}
else if (!strcmp(a, "-t"))
action = SHOW_TYPE;
else if (!strcmp(a, "-s"))
action = SHOW_SIZE;
else if (!strcmp(a, "-e"))
action = SHOW_NONE;
else if (!strcmp(a, "-p"))
action = SHOW_PRETTY;
else if (!strcmp(a, "-q"))
verbose = 0;
else if (!strcmp(a, "-v"))
verbose = 1;
else if (!strcmp(a, "--help") || !strcmp(a, "-h"))
usage(NULL, NULL);
else if (!check_str_param(a, "--git-dir=", &dir))
usage("Unknown option", a);
}
if (!action || !rev)
usage(NULL, NULL);
check(git_repository_open_ext(&g_repo, dir, 0, NULL),
"Could not open repository");
if (git_revparse_single(&obj, g_repo, rev) < 0) {
fprintf(stderr, "Could not resolve '%s'\n", rev);
exit(1);
}
if (verbose) {
char oidstr[GIT_OID_HEXSZ + 1];
git_oid_tostr(oidstr, sizeof(oidstr), git_object_id(obj));
printf("%s %s\n--\n",
git_object_type2string(git_object_type(obj)), oidstr);
}
switch (action) {
case SHOW_TYPE:
printf("%s\n", git_object_type2string(git_object_type(obj)));
break;
case SHOW_SIZE: {
git_odb *odb;
git_odb_object *odbobj;
check(git_repository_odb(&odb, g_repo), "Could not open ODB");
check(git_odb_read(&odbobj, odb, git_object_id(obj)),
"Could not find obj");
printf("%ld\n", (long)git_odb_object_size(odbobj));
git_odb_object_free(odbobj);
git_odb_free(odb);
}
break;
case SHOW_NONE:
/* just want return result */
break;
case SHOW_PRETTY:
switch (git_object_type(obj)) {
case GIT_OBJ_BLOB:
show_blob((const git_blob *)obj);
break;
case GIT_OBJ_COMMIT:
show_commit((const git_commit *)obj);
break;
case GIT_OBJ_TREE:
show_tree((const git_tree *)obj);
break;
case GIT_OBJ_TAG:
show_tag((const git_tag *)obj);
break;
default:
printf("unknown %s\n", oidstr);
break;
}
break;
}
git_object_free(obj);
git_repository_free(g_repo);
git_threads_shutdown();
return 0;
}
......@@ -84,6 +84,10 @@ static int check_uint16_param(const char *arg, const char *pattern, uint16_t *va
char *endptr = NULL;
if (strncmp(arg, pattern, len))
return 0;
if (arg[len] == '\0' && pattern[len - 1] != '=')
return 1;
if (arg[len] == '=')
len++;
strval = strtoul(arg + len, &endptr, 0);
if (endptr == arg)
return 0;
......@@ -110,14 +114,24 @@ static void usage(const char *message, const char *arg)
exit(1);
}
enum {
FORMAT_PATCH = 0,
FORMAT_COMPACT = 1,
FORMAT_RAW = 2
};
int main(int argc, char *argv[])
{
git_repository *repo = NULL;
git_tree *t1 = NULL, *t2 = NULL;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT;
git_diff_list *diff;
int i, color = -1, compact = 0, cached = 0;
char *a, *dir = ".", *treeish1 = NULL, *treeish2 = NULL;
int i, color = -1, format = FORMAT_PATCH, cached = 0;
char *a, *treeish1 = NULL, *treeish2 = NULL;
const char *dir = ".";
git_threads_init();
/* parse arguments as copied from git-diff */
......@@ -134,11 +148,13 @@ int main(int argc, char *argv[])
}
else if (!strcmp(a, "-p") || !strcmp(a, "-u") ||
!strcmp(a, "--patch"))
compact = 0;
format = FORMAT_PATCH;
else if (!strcmp(a, "--cached"))
cached = 1;
else if (!strcmp(a, "--name-status"))
compact = 1;
format = FORMAT_COMPACT;
else if (!strcmp(a, "--raw"))
format = FORMAT_RAW;
else if (!strcmp(a, "--color"))
color = 0;
else if (!strcmp(a, "--no-color"))
......@@ -157,12 +173,27 @@ int main(int argc, char *argv[])
opts.flags |= GIT_DIFF_INCLUDE_IGNORED;
else if (!strcmp(a, "--untracked"))
opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
else if (check_uint16_param(a, "-M", &findopts.rename_threshold) ||
check_uint16_param(a, "--find-renames",
&findopts.rename_threshold))
findopts.flags |= GIT_DIFF_FIND_RENAMES;
else if (check_uint16_param(a, "-C", &findopts.copy_threshold) ||
check_uint16_param(a, "--find-copies",
&findopts.copy_threshold))
findopts.flags |= GIT_DIFF_FIND_COPIES;
else if (!strcmp(a, "--find-copies-harder"))
findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED;
else if (!strncmp(a, "-B", 2) || !strncmp(a, "--break-rewrites", 16)) {
/* TODO: parse thresholds */
findopts.flags |= GIT_DIFF_FIND_REWRITES;
}
else if (!check_uint16_param(a, "-U", &opts.context_lines) &&
!check_uint16_param(a, "--unified=", &opts.context_lines) &&
!check_uint16_param(a, "--inter-hunk-context=",
&opts.interhunk_lines) &&
!check_str_param(a, "--src-prefix=", &opts.old_prefix) &&
!check_str_param(a, "--dst-prefix=", &opts.new_prefix))
!check_str_param(a, "--dst-prefix=", &opts.new_prefix) &&
!check_str_param(a, "--git-dir=", &dir))
usage("Unknown arg", a);
}
......@@ -200,13 +231,24 @@ int main(int argc, char *argv[])
else
check(git_diff_index_to_workdir(&diff, repo, NULL, &opts), "Diff");
if ((findopts.flags & GIT_DIFF_FIND_ALL) != 0)
check(git_diff_find_similar(diff, &findopts),
"finding renames and copies ");
if (color >= 0)
fputs(colors[0], stdout);
if (compact)
check(git_diff_print_compact(diff, printer, &color), "Displaying diff");
else
switch (format) {
case FORMAT_PATCH:
check(git_diff_print_patch(diff, printer, &color), "Displaying diff");
break;
case FORMAT_COMPACT:
check(git_diff_print_compact(diff, printer, &color), "Displaying diff");
break;
case FORMAT_RAW:
check(git_diff_print_raw(diff, printer, &color), "Displaying diff");
break;
}
if (color >= 0)
fputs(colors[0], stdout);
......@@ -216,6 +258,8 @@ int main(int argc, char *argv[])
git_tree_free(t2);
git_repository_free(repo);
git_threads_shutdown();
return 0;
}
......@@ -453,7 +453,7 @@ int main (int argc, char** argv)
// Here we will implement something like `git for-each-ref` simply listing
// out all available references and the object SHA they resolve to.
git_strarray ref_list;
git_reference_list(&ref_list, repo, GIT_REF_LISTALL);
git_reference_list(&ref_list, repo);
const char *refname;
git_reference *ref;
......
......@@ -54,6 +54,8 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
git_threads_init();
for (i = 0; commands[i].name != NULL; ++i) {
if (!strcmp(argv[1], commands[i].name))
return run_command(commands[i].fn, --argc, ++argv);
......
......@@ -117,4 +117,3 @@ int main (int argc, char **argv)
return 0;
}
......@@ -141,7 +141,7 @@ GIT_EXTERN(git_attr_t) git_attr_value(const char *attr);
*/
GIT_EXTERN(int) git_attr_get(
const char **value_out,
git_repository *repo,
git_repository *repo,
uint32_t flags,
const char *path,
const char *name);
......@@ -162,7 +162,7 @@ GIT_EXTERN(int) git_attr_get(
* Then you could loop through the 3 values to get the settings for
* the three attributes you asked about.
*
* @param values An array of num_attr entries that will have string
* @param values_out An array of num_attr entries that will have string
* pointers written into it for the values of the attributes.
* You should not modify or free the values that are written
* into this array (although of course, you should free the
......@@ -228,7 +228,7 @@ GIT_EXTERN(void) git_attr_cache_flush(
* function allows you to add others. For example, to add the default
* macro, you would call:
*
* git_attr_add_macro(repo, "binary", "-diff -crlf");
* git_attr_add_macro(repo, "binary", "-diff -crlf");
*/
GIT_EXTERN(int) git_attr_add_macro(
git_repository *repo,
......
......@@ -29,10 +29,7 @@ GIT_BEGIN_DECL
* @param id identity of the blob to locate.
* @return 0 or an error code
*/
GIT_INLINE(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git_oid *id)
{
return git_object_lookup((git_object **)blob, repo, id, GIT_OBJ_BLOB);
}
GIT_EXTERN(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git_oid *id);
/**
* Lookup a blob object from a repository,
......@@ -46,10 +43,7 @@ GIT_INLINE(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git
* @param len the length of the short identifier
* @return 0 or an error code
*/
GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, const git_oid *id, size_t len)
{
return git_object_lookup_prefix((git_object **)blob, repo, id, len, GIT_OBJ_BLOB);
}
GIT_EXTERN(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, const git_oid *id, size_t len);
/**
* Close an open blob
......@@ -62,11 +56,7 @@ GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, co
*
* @param blob the blob to close
*/
GIT_INLINE(void) git_blob_free(git_blob *blob)
{
git_object_free((git_object *) blob);
}
GIT_EXTERN(void) git_blob_free(git_blob *blob);
/**
* Get the id of a blob.
......@@ -74,11 +64,15 @@ GIT_INLINE(void) git_blob_free(git_blob *blob)
* @param blob a previously loaded blob.
* @return SHA1 hash for this blob.
*/
GIT_INLINE(const git_oid *) git_blob_id(const git_blob *blob)
{
return git_object_id((const git_object *)blob);
}
GIT_EXTERN(const git_oid *) git_blob_id(const git_blob *blob);
/**
* Get the repository that contains the blob.
*
* @param blob A previously loaded blob.
* @return Repository that contains this blob.
*/
GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob);
/**
* Get a read-only buffer with the raw content of a blob.
......
......@@ -58,7 +58,8 @@ GIT_EXTERN(int) git_branch_create(
* Delete an existing branch reference.
*
* If the branch is successfully deleted, the passed reference
* object will be freed and invalidated.
* object will be invalidated. The reference must be freed manually
* by the user.
*
* @param branch A valid reference representing a branch
* @return 0 on success, or an error code.
......@@ -237,7 +238,7 @@ GIT_EXTERN(int) git_branch_is_head(
*
* @return Number of characters in the reference name
* including the trailing NUL byte; GIT_ENOTFOUND
* when no remote matching remote was gound,
* when no remote matching remote was found,
* GIT_EAMBIGUOUS when the branch maps to several remotes,
* otherwise an error code.
*/
......
......@@ -134,6 +134,9 @@ typedef enum {
/** Treat pathspec as simple list of exact match file paths */
GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = (1u << 13),
/** Ignore directories in use, they will be left empty */
GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1u << 18),
/**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
......@@ -180,6 +183,8 @@ typedef enum {
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu
} git_checkout_notify_t;
/** Checkout notification callback function */
......@@ -231,6 +236,8 @@ typedef struct git_checkout_opts {
git_strarray paths;
git_tree *baseline; /** expected content of workdir, defaults to HEAD */
const char *target_directory; /** alternative checkout path to workdir */
} git_checkout_opts;
#define GIT_CHECKOUT_OPTS_VERSION 1
......
......@@ -51,6 +51,8 @@ GIT_BEGIN_DECL
* - `cred_acquire_cb` is a callback to be used if credentials are required
* during the initial fetch.
* - `cred_acquire_payload` is the payload for the above callback.
* - `transport_flags` is flags used to create transport if no transport is
* provided.
* - `transport` is a custom transport to be used for the initial fetch. NULL
* means use the transport autodetected from the URL.
* - `remote_callbacks` may be used to specify custom progress callbacks for
......@@ -75,6 +77,7 @@ typedef struct git_clone_options {
const char *push_spec;
git_cred_acquire_cb cred_acquire_cb;
void *cred_acquire_payload;
git_transport_flags_t transport_flags;
git_transport *transport;
git_remote_callbacks *remote_callbacks;
git_remote_autotag_option_t remote_autotag;
......
......@@ -30,10 +30,7 @@ GIT_BEGIN_DECL
* an annotated tag it will be peeled back to the commit.
* @return 0 or an error code
*/
GIT_INLINE(int) git_commit_lookup(git_commit **commit, git_repository *repo, const git_oid *id)
{
return git_object_lookup((git_object **)commit, repo, id, GIT_OBJ_COMMIT);
}
GIT_EXTERN(int) git_commit_lookup(git_commit **commit, git_repository *repo, const git_oid *id);
/**
* Lookup a commit object from a repository,
......@@ -48,10 +45,7 @@ GIT_INLINE(int) git_commit_lookup(git_commit **commit, git_repository *repo, con
* @param len the length of the short identifier
* @return 0 or an error code
*/
GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *repo, const git_oid *id, size_t len)
{
return git_object_lookup_prefix((git_object **)commit, repo, id, len, GIT_OBJ_COMMIT);
}
GIT_EXTERN(int) git_commit_lookup_prefix(git_commit **commit, git_repository *repo, const git_oid *id, size_t len);
/**
* Close an open commit
......@@ -65,10 +59,7 @@ GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *re
* @param commit the commit to close
*/
GIT_INLINE(void) git_commit_free(git_commit *commit)
{
git_object_free((git_object *) commit);
}
GIT_EXTERN(void) git_commit_free(git_commit *commit);
/**
* Get the id of a commit.
......@@ -76,10 +67,15 @@ GIT_INLINE(void) git_commit_free(git_commit *commit)
* @param commit a previously loaded commit.
* @return object identity for the commit.
*/
GIT_INLINE(const git_oid *) git_commit_id(const git_commit *commit)
{
return git_object_id((const git_object *)commit);
}
GIT_EXTERN(const git_oid *) git_commit_id(const git_commit *commit);
/**
* Get the repository that contains the commit.
*
* @param commit A previously loaded commit.
* @return Repository that contains this commit.
*/
GIT_EXTERN(git_repository *) git_commit_owner(const git_commit *commit);
/**
* Get the encoding for the message of a commit,
......@@ -168,7 +164,10 @@ GIT_EXTERN(unsigned int) git_commit_parentcount(const git_commit *commit);
* @param n the position of the parent (from 0 to `parentcount`)
* @return 0 or an error code
*/
GIT_EXTERN(int) git_commit_parent(git_commit **out, git_commit *commit, unsigned int n);
GIT_EXTERN(int) git_commit_parent(
git_commit **out,
const git_commit *commit,
unsigned int n);
/**
* Get the oid of a specified parent for a commit. This is different from
......@@ -179,7 +178,9 @@ GIT_EXTERN(int) git_commit_parent(git_commit **out, git_commit *commit, unsigned
* @param n the position of the parent (from 0 to `parentcount`)
* @return the id of the parent, NULL on error.
*/
GIT_EXTERN(const git_oid *) git_commit_parent_id(git_commit *commit, unsigned int n);
GIT_EXTERN(const git_oid *) git_commit_parent_id(
const git_commit *commit,
unsigned int n);
/**
* Get the commit object that is the <n>th generation ancestor
......@@ -201,14 +202,12 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
unsigned int n);
/**
* Create a new commit in the repository using `git_object`
* instances as parameters.
* Create new commit in the repository from a list of `git_object` pointers
*
* The message will not be cleaned up. This can be achieved
* through `git_message_prettify()`.
* The message will not be cleaned up automatically. You can do that with
* the `git_message_prettify()` function.
*
* @param id Pointer where to store the OID of the
* newly created commit
* @param id Pointer in which to store the OID of the newly created commit
*
* @param repo Repository where to store the commit
*
......@@ -219,73 +218,69 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
* make it point to this commit. If the reference doesn't
* exist yet, it will be created.
*
* @param author Signature representing the author and the authory
* time of this commit
* @param author Signature with author and author time of commit
*
* @param committer Signature representing the committer and the
* commit time of this commit
* @param committer Signature with committer and * commit time of commit
*
* @param message_encoding The encoding for the message in the
* commit, represented with a standard encoding name.
* E.g. "UTF-8". If NULL, no encoding header is written and
* UTF-8 is assumed.
* commit, represented with a standard encoding name.
* E.g. "UTF-8". If NULL, no encoding header is written and
* UTF-8 is assumed.
*
* @param message Full message for this commit
*
* @param tree An instance of a `git_tree` object that will
* be used as the tree for the commit. This tree object must
* also be owned by the given `repo`.
* be used as the tree for the commit. This tree object must
* also be owned by the given `repo`.
*
* @param parent_count Number of parents for this commit
*
* @param parents[] Array of `parent_count` pointers to `git_commit`
* objects that will be used as the parents for this commit. This
* array may be NULL if `parent_count` is 0 (root commit). All the
* given commits must be owned by the `repo`.
* @param parents Array of `parent_count` pointers to `git_commit`
* objects that will be used as the parents for this commit. This
* array may be NULL if `parent_count` is 0 (root commit). All the
* given commits must be owned by the `repo`.
*
* @return 0 or an error code
* The created commit will be written to the Object Database and
* the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_create(
git_oid *id,
git_repository *repo,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_tree *tree,
int parent_count,
const git_commit *parents[]);
git_oid *id,
git_repository *repo,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_tree *tree,
int parent_count,
const git_commit *parents[]);
/**
* Create a 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
* it will be made sure that the last line ends with a '\n'.
* The message will be cleaned up from excess whitespace and it will be made
* sure that the last line ends with a '\n'.
*
* 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 not be safe to export
* for certain languages or compilers
* 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
* not be safe to export for certain languages or compilers
*
* All other parameters remain the same
* All other parameters remain the same at `git_commit_create()`.
*
* @see git_commit_create
*/
GIT_EXTERN(int) git_commit_create_v(
git_oid *id,
git_repository *repo,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_tree *tree,
int parent_count,
...);
git_oid *id,
git_repository *repo,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_tree *tree,
int parent_count,
...);
/** @} */
GIT_END_DECL
......
......@@ -103,10 +103,10 @@ GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev);
/**
* Combinations of these values describe the capabilities of libgit2.
*/
enum {
typedef enum {
GIT_CAP_THREADS = ( 1 << 0 ),
GIT_CAP_HTTPS = ( 1 << 1 )
};
} git_cap_t;
/**
* Query compile time options for libgit2.
......@@ -114,69 +114,100 @@ enum {
* @return A combination of GIT_CAP_* values.
*
* - GIT_CAP_THREADS
* Libgit2 was compiled with thread support. Note that thread support is still to be seen as a
* 'work in progress'.
* Libgit2 was compiled with thread support. Note that thread support is
* still to be seen as a 'work in progress' - basic object lookups are
* believed to be threadsafe, but other operations may not be.
*
* - GIT_CAP_HTTPS
* Libgit2 supports the https:// protocol. This requires the open ssl library to be
* found when compiling libgit2.
* Libgit2 supports the https:// protocol. This requires the openssl
* library to be found when compiling libgit2.
*/
GIT_EXTERN(int) git_libgit2_capabilities(void);
enum {
typedef enum {
GIT_OPT_GET_MWINDOW_SIZE,
GIT_OPT_SET_MWINDOW_SIZE,
GIT_OPT_GET_MWINDOW_MAPPED_LIMIT,
GIT_OPT_SET_MWINDOW_MAPPED_LIMIT,
GIT_OPT_GET_SEARCH_PATH,
GIT_OPT_SET_SEARCH_PATH,
GIT_OPT_GET_ODB_CACHE_SIZE,
GIT_OPT_SET_ODB_CACHE_SIZE,
};
GIT_OPT_SET_CACHE_OBJECT_LIMIT,
GIT_OPT_SET_CACHE_MAX_SIZE,
GIT_OPT_ENABLE_CACHING,
GIT_OPT_GET_CACHED_MEMORY
} git_libgit2_opt_t;
/**
* Set or query a library global option
*
* Available options:
*
* opts(GIT_OPT_GET_MWINDOW_SIZE, size_t *):
* Get the maximum mmap window size
* * opts(GIT_OPT_GET_MWINDOW_SIZE, size_t *):
*
* opts(GIT_OPT_SET_MWINDOW_SIZE, size_t):
* Set the maximum mmap window size
* > Get the maximum mmap window size
*
* opts(GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, size_t *):
* Get the maximum memory that will be mapped in total by the library
* * opts(GIT_OPT_SET_MWINDOW_SIZE, size_t):
*
* opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size_t):
* Set the maximum amount of memory that can be mapped at any time
* > Set the maximum mmap window size
*
* * opts(GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, size_t *):
*
* > Get the maximum memory that will be mapped in total by the library
*
* * opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, size_t):
*
* >Set the maximum amount of memory that can be mapped at any time
* by the library
*
* opts(GIT_OPT_GET_SEARCH_PATH, int level, char *out, size_t len)
* 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
* 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.
*
* opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path)
* Set the search path for a level of config data. The search path
* applied to shared attributes and ignore files, too.
* - `path` lists directories delimited by GIT_PATH_LIST_SEPARATOR.
* Pass NULL to reset to the default (generally based on environment
* variables). Use magic path `$PATH` to include the old value
* of the path (if you want to prepend or append, for instance).
* - `level` must be GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_GLOBAL,
* or GIT_CONFIG_LEVEL_XDG.
*
* opts(GIT_OPT_GET_ODB_CACHE_SIZE):
* Get the size of the libgit2 odb cache.
*
* opts(GIT_OPT_SET_ODB_CACHE_SIZE):
* Set the size of the of the libgit2 odb cache. This needs
* to be done before git_repository_open is called, since
* git_repository_open initializes the odb layer. Defaults
* to 128.
* * opts(GIT_OPT_GET_SEARCH_PATH, int level, char *out, size_t len)
*
* > 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
* > `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.
*
* * opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path)
*
* > Set the search path for a level of config data. The search path
* > applied to shared attributes and ignore files, too.
* >
* > - `path` lists directories delimited by GIT_PATH_LIST_SEPARATOR.
* > Pass NULL to reset to the default (generally based on environment
* > variables). Use magic path `$PATH` to include the old value
* > of the path (if you want to prepend or append, for instance).
* >
* > - `level` must be GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_GLOBAL,
* > or GIT_CONFIG_LEVEL_XDG.
*
* * opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, git_otype type, size_t size)
*
* > Set the maximum data size for the given type of object to be
* > considered eligible for caching in memory. Setting to value to
* > zero means that that type of object will not be cached.
* > Defaults to 0 for GIT_OBJ_BLOB (i.e. won't cache blobs) and 4k
* > for GIT_OBJ_COMMIT, GIT_OBJ_TREE, and GIT_OBJ_TAG.
*
* * opts(GIT_OPT_SET_CACHE_MAX_SIZE, ssize_t max_storage_bytes)
*
* > Set the maximum total data size that will be cached in memory
* > across all repositories before libgit2 starts evicting objects
* > from the cache. This is a soft limit, in that the library might
* > briefly exceed it, but will start aggressively evicting objects
* > from cache when that happens. The default cache size is 256Mb.
*
* * opts(GIT_OPT_ENABLE_CACHING, int enabled)
*
* > Enable or disable caching completely.
* >
* > Because caches are repository-specific, disabling the cache
* > cannot immediately clear all cached objects, but each cache will
* > be cleared on the next attempt to update anything in it.
*
* * opts(GIT_OPT_GET_CACHED_MEMORY, ssize_t *current, ssize_t *allowed)
*
* > Get the current bytes in cache and the maximum that would be
* > allowed in the cache.
*
* @param option Option key
* @param ... value to set the option
......
......@@ -27,45 +27,41 @@ GIT_BEGIN_DECL
* git_config_open_default() and git_repository_config() honor those
* priority levels as well.
*/
enum {
GIT_CONFIG_LEVEL_SYSTEM = 1, /**< System-wide configuration file. */
GIT_CONFIG_LEVEL_XDG = 2, /**< XDG compatible configuration file (.config/git/config). */
GIT_CONFIG_LEVEL_GLOBAL = 3, /**< User-specific configuration file, also called Global configuration file. */
GIT_CONFIG_LEVEL_LOCAL = 4, /**< Repository specific configuration file. */
GIT_CONFIG_HIGHEST_LEVEL = -1, /**< Represents the highest level of a config file. */
};
typedef enum {
/** System-wide configuration file; /etc/gitconfig on Linux systems */
GIT_CONFIG_LEVEL_SYSTEM = 1,
/** XDG compatible configuration file; typically ~/.config/git/config */
GIT_CONFIG_LEVEL_XDG = 2,
/** User-specific configuration file (also called Global configuration
* file); typically ~/.gitconfig
*/
GIT_CONFIG_LEVEL_GLOBAL = 3,
/** Repository specific configuration file; $WORK_DIR/.git/config on
* non-bare repos
*/
GIT_CONFIG_LEVEL_LOCAL = 4,
/** Application specific configuration file; freely defined by applications
*/
GIT_CONFIG_LEVEL_APP = 5,
/** Represents the highest level available config file (i.e. the most
* specific config file available that actually is loaded)
*/
GIT_CONFIG_HIGHEST_LEVEL = -1,
} git_config_level_t;
typedef struct {
const char *name;
const char *value;
unsigned int level;
git_config_level_t level;
} git_config_entry;
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
/**
* Generic backend that implements the interface to
* access a configuration file
*/
struct git_config_backend {
unsigned int version;
struct git_config *cfg;
/* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *, unsigned int level);
int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);
int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload);
int (*set)(struct git_config_backend *, const char *key, const char *value);
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
int (*del)(struct git_config_backend *, const char *key);
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload);
int (*refresh)(struct git_config_backend *);
void (*free)(struct git_config_backend *);
};
#define GIT_CONFIG_BACKEND_VERSION 1
#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
typedef enum {
GIT_CVAR_FALSE = 0,
GIT_CVAR_TRUE = 1,
......@@ -123,7 +119,7 @@ GIT_EXTERN(int) git_config_find_xdg(char *out, size_t length);
* If /etc/gitconfig doesn't exist, it will look for
* %PROGRAMFILES%\Git\etc\gitconfig.
* @param global_config_path Buffer to store the path in
* @param out Buffer to store the path in
* @param length size of the buffer in bytes
* @return 0 if a system configuration file has been
* found. Its path will be stored in `buffer`.
......@@ -154,30 +150,6 @@ GIT_EXTERN(int) git_config_open_default(git_config **out);
GIT_EXTERN(int) git_config_new(git_config **out);
/**
* Add a generic config file instance to an existing config
*
* Note that the configuration object will free the file
* automatically.
*
* Further queries on this config object will access each
* of the config file instances in order (instances with
* a higher priority level will be accessed first).
*
* @param cfg the configuration to add the file to
* @param file the configuration file (backend) to add
* @param level the priority level of the backend
* @param force if a config file already exists for the given
* priority level, replace it
* @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0), or error code
*/
GIT_EXTERN(int) git_config_add_backend(
git_config *cfg,
git_config_backend *file,
unsigned int level,
int force);
/**
* Add an on-disk config file instance to an existing config
*
* The on-disk file pointed at by `path` will be opened and
......@@ -192,10 +164,9 @@ GIT_EXTERN(int) git_config_add_backend(
* a higher priority level will be accessed first).
*
* @param cfg the configuration to add the file to
* @param path path to the configuration file (backend) to add
* @param path path to the configuration file to add
* @param level the priority level of the backend
* @param force if a config file already exists for the given
* priority level, replace it
* @param force replace config file at the given priority level
* @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0),
* GIT_ENOTFOUND when the file doesn't exist or error code
......@@ -203,7 +174,7 @@ GIT_EXTERN(int) git_config_add_backend(
GIT_EXTERN(int) git_config_add_file_ondisk(
git_config *cfg,
const char *path,
unsigned int level,
git_config_level_t level,
int force);
/**
......@@ -238,9 +209,24 @@ GIT_EXTERN(int) git_config_open_ondisk(git_config **out, const char *path);
* multi-level parent config, or an error code
*/
GIT_EXTERN(int) git_config_open_level(
git_config **out,
const git_config *parent,
unsigned int level);
git_config **out,
const git_config *parent,
git_config_level_t level);
/**
* Open the global/XDG configuration file according to git's rules
*
* Git allows you to store your global configuration at
* `$HOME/.config` or `$XDG_CONFIG_HOME/git/config`. For backwards
* compatability, the XDG file shouldn't be used unless the use has
* created it explicitly. With this function you'll open the correct
* one to write to.
*
* @param out pointer in which to store the config object
* @param config the config object in which to look
*/
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
/**
* Reload changed config files
......@@ -274,7 +260,7 @@ GIT_EXTERN(void) git_config_free(git_config *cfg);
* @return 0 or an error code
*/
GIT_EXTERN(int) git_config_get_entry(
const git_config_entry **out,
const git_config_entry **out,
const git_config *cfg,
const char *name);
......@@ -349,8 +335,8 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c
* @param name the variable's name
* @param regexp regular expression to filter which variables we're
* interested in. Use NULL to indicate all
* @param fn the function to be called on each value of the variable
* @param data opaque pointer to pass to the callback
* @param callback the function to be called on each value of the variable
* @param payload opaque pointer to pass to the callback
*/
GIT_EXTERN(int) git_config_get_multivar(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload);
......@@ -492,11 +478,11 @@ GIT_EXTERN(int) git_config_foreach_match(
* @return 0 on success, error code otherwise
*/
GIT_EXTERN(int) git_config_get_mapped(
int *out,
const git_config *cfg,
const char *name,
const git_cvar_map *maps,
size_t map_n);
int *out,
const git_config *cfg,
const char *name,
const git_cvar_map *maps,
size_t map_n);
/**
* Maps a string value to an integer constant
......
......@@ -30,11 +30,11 @@ typedef struct git_cred_userpass_payload {
/**
* Stock callback usable as a git_cred_acquire_cb. This calls
* git_cred_userpass_plaintext_new unless the protocol has not specified
* GIT_CREDTYPE_USERPASS_PLAINTEXT as an allowed type.
* `GIT_CREDTYPE_USERPASS_PLAINTEXT` as an allowed type.
*
* @param cred The newly created credential object.
* @param url The resource for which we are demanding a credential.
* @param username_from_url The username that was embedded in a "user@host"
* @param user_from_url The username that was embedded in a "user@host"
* remote url, or NULL if not included.
* @param allowed_types A bitmask stating which cred types are OK to return.
* @param payload The payload provided when specifying this callback. (This is
......
......@@ -18,7 +18,7 @@
GIT_BEGIN_DECL
/** Generic return codes */
enum {
typedef enum {
GIT_OK = 0,
GIT_ERROR = -1,
GIT_ENOTFOUND = -3,
......@@ -35,7 +35,7 @@ enum {
GIT_PASSTHROUGH = -30,
GIT_ITEROVER = -31,
};
} git_error_code;
typedef struct {
char *message;
......@@ -100,7 +100,7 @@ GIT_EXTERN(void) giterr_clear(void);
*
* @param error_class One of the `git_error_t` enum above describing the
* general subsystem that is responsible for the error.
* @param message The formatted error message to keep
* @param string The formatted error message to keep
*/
GIT_EXTERN(void) giterr_set_str(int error_class, const char *string);
......
......@@ -8,31 +8,11 @@
#define _INCLUDE_git_indexer_h__
#include "common.h"
#include "types.h"
#include "oid.h"
GIT_BEGIN_DECL
/**
* This is passed as the first argument to the callback to allow the
* user to see the progress.
*/
typedef struct git_transfer_progress {
unsigned int total_objects;
unsigned int indexed_objects;
unsigned int received_objects;
size_t received_bytes;
} git_transfer_progress;
/**
* Type for progress callbacks during indexing. Return a value less than zero
* to cancel the transfer.
*
* @param stats Structure containing information about the state of the transfer
* @param payload Payload provided by caller
*/
typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload);
typedef struct git_indexer_stream git_indexer_stream;
/**
......@@ -41,7 +21,7 @@ typedef struct git_indexer_stream git_indexer_stream;
* @param out where to store the indexer instance
* @param path to the directory where the packfile should be stored
* @param progress_cb function to call with progress information
* @param progress_payload payload for the progress callback
* @param progress_cb_payload payload for the progress callback
*/
GIT_EXTERN(int) git_indexer_stream_new(
git_indexer_stream **out,
......
......@@ -283,18 +283,18 @@ _inline
#endif // STATIC_IMAXDIV ]
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
{
imaxdiv_t result;
imaxdiv_t result;
result.quot = numer / denom;
result.rem = numer % denom;
result.quot = numer / denom;
result.rem = numer % denom;
if (numer < 0 && result.rem > 0) {
// did division wrong; must fix up
++result.quot;
result.rem -= denom;
}
if (numer < 0 && result.rem > 0) {
// did division wrong; must fix up
++result.quot;
result.rem -= denom;
}
return result;
return result;
}
// 7.8.2.3 The strtoimax and strtoumax functions
......
......@@ -7,20 +7,65 @@
#ifndef INCLUDE_git_merge_h__
#define INCLUDE_git_merge_h__
#include "common.h"
#include "types.h"
#include "oid.h"
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
#include "git2/checkout.h"
#include "git2/index.h"
/**
* @file git2/merge.h
* @brief Git merge-base routines
* @defgroup git_revwalk Git merge-base routines
* @brief Git merge routines
* @defgroup git_merge Git merge routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Flags for `git_merge_tree` options. A combination of these flags can be
* passed in via the `flags` value in the `git_merge_tree_opts`.
*/
typedef enum {
/** Detect renames */
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
} git_merge_tree_flag_t;
/**
* Automerge options for `git_merge_trees_opts`.
*/
typedef enum {
GIT_MERGE_AUTOMERGE_NORMAL = 0,
GIT_MERGE_AUTOMERGE_NONE = 1,
GIT_MERGE_AUTOMERGE_FAVOR_OURS = 2,
GIT_MERGE_AUTOMERGE_FAVOR_THEIRS = 3,
} git_merge_automerge_flags;
typedef struct {
unsigned int version;
git_merge_tree_flag_t flags;
/** Similarity to consider a file renamed (default 50) */
unsigned int rename_threshold;
/** Maximum similarity sources to examine (overrides the
* `merge.renameLimit` config) (default 200)
*/
unsigned int target_limit;
/** Pluggable similarity metric; pass NULL to use internal metric */
git_diff_similarity_metric *metric;
/** Flags for automerging content. */
git_merge_automerge_flags automerge_flags;
} git_merge_tree_opts;
#define GIT_MERGE_TREE_OPTS_VERSION 1
#define GIT_MERGE_TREE_OPTS_INIT {GIT_MERGE_TREE_OPTS_VERSION}
/**
* Find a merge base between two commits
*
* @param out the OID of a merge base between 'one' and 'two'
......@@ -50,6 +95,79 @@ GIT_EXTERN(int) git_merge_base_many(
const git_oid input_array[],
size_t length);
/**
* Creates a `git_merge_head` from the given reference
*
* @param out pointer to store the git_merge_head result in
* @param repo repository that contains the given reference
* @param ref reference to use as a merge input
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_merge_head_from_ref(
git_merge_head **out,
git_repository *repo,
git_reference *ref);
/**
* Creates a `git_merge_head` from the given fetch head data
*
* @param out pointer to store the git_merge_head result in
* @param repo repository that contains the given commit
* @param branch_name name of the (remote) branch
* @param remote_url url of the remote
* @param oid the commit object id to use as a merge input
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_merge_head_from_fetchhead(
git_merge_head **out,
git_repository *repo,
const char *branch_name,
const char *remote_url,
const git_oid *oid);
/**
* Creates a `git_merge_head` from the given commit id
*
* @param out pointer to store the git_merge_head result in
* @param repo repository that contains the given commit
* @param oid the commit object id to use as a merge input
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_merge_head_from_oid(
git_merge_head **out,
git_repository *repo,
const git_oid *oid);
/**
* Frees a `git_merge_head`
*
* @param head merge head to free
*/
GIT_EXTERN(void) git_merge_head_free(
git_merge_head *head);
/**
* Merge two trees, producing a `git_index` that reflects the result of
* the merge.
*
* The returned index must be freed explicitly with `git_index_free`.
*
* @param out pointer to store the index result in
* @param repo repository that contains the given trees
* @param ancestor_tree the common ancestor between the trees (or null if none)
* @param our_tree the tree that reflects the destination tree
* @param their_tree the tree to merge in to `our_tree`
* @param opts the merge tree options (or null for defaults)
* @return zero on success, -1 on failure.
*/
GIT_EXTERN(int) git_merge_trees(
git_index **out,
git_repository *repo,
const git_tree *ancestor_tree,
const git_tree *our_tree,
const git_tree *their_tree,
const git_merge_tree_opts *opts);
/** @} */
GIT_END_DECL
#endif
......@@ -10,8 +10,6 @@
#include "common.h"
#include "types.h"
#include "oid.h"
#include "odb_backend.h"
#include "indexer.h"
/**
* @file git2/odb.h
......@@ -23,6 +21,11 @@
GIT_BEGIN_DECL
/**
* Function type for callbacks from git_odb_foreach.
*/
typedef int (*git_odb_foreach_cb)(const git_oid *id, void *payload);
/**
* Create a new object database with no backends.
*
* Before the ODB can be used for read/writing, a custom database
......@@ -53,42 +56,6 @@ GIT_EXTERN(int) git_odb_new(git_odb **out);
GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
/**
* Add a custom backend to an existing Object DB
*
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
* Read <odb_backends.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
/**
* Add a custom backend to an existing Object DB; this
* backend will work as an alternate.
*
* Alternate backends are always checked for objects *after*
* all the main backends have been exhausted.
*
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
* Writing is disabled on alternate backends.
*
* Read <odb_backends.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
/**
* Add an on-disk alternate to an existing Object DB.
*
* Note that the added path must point to an `objects`, not
......@@ -406,6 +373,60 @@ GIT_EXTERN(size_t) git_odb_object_size(git_odb_object *object);
*/
GIT_EXTERN(git_otype) git_odb_object_type(git_odb_object *object);
/**
* Add a custom backend to an existing Object DB
*
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
* Read <odb_backends.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
/**
* Add a custom backend to an existing Object DB; this
* backend will work as an alternate.
*
* Alternate backends are always checked for objects *after*
* all the main backends have been exhausted.
*
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
* Writing is disabled on alternate backends.
*
* Read <odb_backends.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
* @param priority Value for ordering the backends queue
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
/**
* Get the number of ODB backend objects
*
* @param odb object database
* @return number of backends in the ODB
*/
GIT_EXTERN(size_t) git_odb_num_backends(git_odb *odb);
/**
* Lookup an ODB backend object by index
*
* @param out output pointer to ODB backend at pos
* @param odb object database
* @param pos index into object database backend list
* @return 0 on success; GIT_ENOTFOUND if pos is invalid; other errors < 0
*/
GIT_EXTERN(int) git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos);
/** @} */
GIT_END_DECL
#endif
......@@ -7,143 +7,84 @@
#ifndef INCLUDE_git_odb_backend_h__
#define INCLUDE_git_odb_backend_h__
#include "common.h"
#include "types.h"
#include "oid.h"
#include "indexer.h"
#include "git2/common.h"
#include "git2/types.h"
/**
* @file git2/backend.h
* @brief Git custom backend functions
* @defgroup git_backend Git custom backend API
* @defgroup git_odb Git object database routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
struct git_odb_stream;
struct git_odb_writepack;
/*
* Constructors for in-box ODB backends.
*/
/**
* Function type for callbacks from git_odb_foreach.
* Create a backend for the packfiles.
*
* @param out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory
*
* @return 0 or an error code
*/
typedef int (*git_odb_foreach_cb)(const git_oid *id, void *payload);
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
/**
* An instance for a custom backend
* Create a backend for loose objects
*
* @param out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory
* @param compression_level zlib compression level to use
* @param do_fsync whether to do an fsync() after writing (currently ignored)
*
* @return 0 or an error code
*/
struct git_odb_backend {
unsigned int version;
git_odb *odb;
/* read and read_prefix each return to libgit2 a buffer which
* will be freed later. The buffer should be allocated using
* the function git_odb_backend_malloc to ensure that it can
* be safely freed later. */
int (* read)(
void **, size_t *, git_otype *,
struct git_odb_backend *,
const git_oid *);
/* To find a unique object given a prefix
* of its oid.
* The oid given must be so that the
* remaining (GIT_OID_HEXSZ - len)*4 bits
* are 0s.
*/
int (* read_prefix)(
git_oid *,
void **, size_t *, git_otype *,
struct git_odb_backend *,
const git_oid *,
size_t);
int (* read_header)(
size_t *, git_otype *,
struct git_odb_backend *,
const git_oid *);
/* The writer may assume that the object
* has already been hashed and is passed
* in the first parameter.
*/
int (* write)(
git_oid *,
struct git_odb_backend *,
const void *,
size_t,
git_otype);
int (* writestream)(
struct git_odb_stream **,
struct git_odb_backend *,
size_t,
git_otype);
int (* readstream)(
struct git_odb_stream **,
struct git_odb_backend *,
const git_oid *);
int (* exists)(
struct git_odb_backend *,
const git_oid *);
int (* refresh)(struct git_odb_backend *);
int (* foreach)(
struct git_odb_backend *,
git_odb_foreach_cb cb,
void *payload);
int (* writepack)(
struct git_odb_writepack **,
struct git_odb_backend *,
git_transfer_progress_callback progress_cb,
void *progress_payload);
void (* free)(struct git_odb_backend *);
};
GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync);
#define GIT_ODB_BACKEND_VERSION 1
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
/**
* Create a backend out of a single packfile
*
* This can be useful for inspecting the contents of a single
* packfile.
*
* @param out location to store the odb backend pointer
* @param index_file path to the packfile's .idx file
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
/** Streaming mode */
enum {
typedef enum {
GIT_STREAM_RDONLY = (1 << 1),
GIT_STREAM_WRONLY = (1 << 2),
GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY),
};
} git_odb_stream_t;
/** A stream to read/write from a backend */
struct git_odb_stream {
struct git_odb_backend *backend;
git_odb_backend *backend;
unsigned int mode;
int (*read)(struct git_odb_stream *stream, char *buffer, size_t len);
int (*write)(struct git_odb_stream *stream, const char *buffer, size_t len);
int (*finalize_write)(git_oid *oid_p, struct git_odb_stream *stream);
void (*free)(struct git_odb_stream *stream);
int (*read)(git_odb_stream *stream, char *buffer, size_t len);
int (*write)(git_odb_stream *stream, const char *buffer, size_t len);
int (*finalize_write)(git_oid *oid_p, git_odb_stream *stream);
void (*free)(git_odb_stream *stream);
};
/** A stream to write a pack file to the ODB */
struct git_odb_writepack {
struct git_odb_backend *backend;
git_odb_backend *backend;
int (*add)(struct git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats);
int (*commit)(struct git_odb_writepack *writepack, git_transfer_progress *stats);
void (*free)(struct git_odb_writepack *writepack);
int (*add)(git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats);
int (*commit)(git_odb_writepack *writepack, git_transfer_progress *stats);
void (*free)(git_odb_writepack *writepack);
};
GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);
/**
* Constructors for in-box ODB backends.
*/
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync);
GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
GIT_END_DECL
#endif
......@@ -85,11 +85,22 @@ GIT_EXTERN(void) git_oid_fromraw(git_oid *out, const unsigned char *raw);
* needed for an oid encoded in hex (40 bytes). Only the
* oid digits are written; a '\\0' terminator must be added
* by the caller if it is required.
* @param oid oid structure to format.
* @param id oid structure to format.
*/
GIT_EXTERN(void) git_oid_fmt(char *out, const git_oid *id);
/**
* Format a git_oid into a partial hex string.
*
* @param out output hex string; you say how many bytes to write.
* If the number of bytes is > GIT_OID_HEXSZ, extra bytes
* will be zeroed; if not, a '\0' terminator is NOT added.
* @param n number of characters to write into out string
* @param id oid structure to format.
*/
GIT_EXTERN(void) git_oid_nfmt(char *out, size_t n, const git_oid *id);
/**
* Format a git_oid into a loose-object path string.
*
* The resulting string is "aa/...", where "aa" is the first two
......@@ -107,7 +118,7 @@ GIT_EXTERN(void) git_oid_pathfmt(char *out, const git_oid *id);
/**
* Format a git_oid into a newly allocated c-string.
*
* @param oid the oid structure to format
* @param id the oid structure to format
* @return the c-string; NULL if memory is exhausted. Caller must
* deallocate the string with git__free().
*/
......@@ -117,10 +128,12 @@ GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *id);
* Format a git_oid into a buffer as a hex format c-string.
*
* If the buffer is smaller than GIT_OID_HEXSZ+1, then the resulting
* oid c-string will be truncated to n-1 characters. If there are
* any input parameter errors (out == NULL, n == 0, oid == NULL),
* then a pointer to an empty string is returned, so that the return
* value can always be printed.
* oid c-string will be truncated to n-1 characters (but will still be
* NUL-byte terminated).
*
* If there are any input parameter errors (out == NULL, n == 0, oid ==
* NULL), then a pointer to an empty string is returned, so that the
* return value can always be printed.
*
* @param out the buffer into which the oid string is output.
* @param n the size of the out buffer.
......@@ -145,19 +158,7 @@ GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src);
* @param b second oid structure.
* @return <0, 0, >0 if a < b, a == b, a > b.
*/
GIT_INLINE(int) git_oid_cmp(const git_oid *a, const git_oid *b)
{
const unsigned char *sha1 = a->id;
const unsigned char *sha2 = b->id;
int i;
for (i = 0; i < GIT_OID_RAWSZ; i++, sha1++, sha2++) {
if (*sha1 != *sha2)
return *sha1 - *sha2;
}
return 0;
}
GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);
/**
* Compare two oid structures for equality
......@@ -193,6 +194,16 @@ GIT_EXTERN(int) git_oid_ncmp(const git_oid *a, const git_oid *b, size_t len);
GIT_EXTERN(int) git_oid_streq(const git_oid *id, const char *str);
/**
* Compare an oid to an hex formatted object id.
*
* @param id oid structure.
* @param str input hex string of an object id.
* @return -1 if str is not valid, <0 if id sorts before str,
* 0 if id matches str, >0 if id sorts after str.
*/
GIT_EXTERN(int) git_oid_strcmp(const git_oid *id, const char *str);
/**
* Check is an oid is all zeros.
*
* @return 1 if all zeros, 0 otherwise.
......
......@@ -95,14 +95,32 @@ GIT_EXTERN(int) git_packbuilder_insert(git_packbuilder *pb, const git_oid *id, c
GIT_EXTERN(int) git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *id);
/**
* Write the new pack and the corresponding index to path
* Insert a commit object
*
* This will add a commit as well as the completed referenced tree.
*
* @param pb The packbuilder
* @param id The oid of the commit
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *id);
/**
* Write the new pack and corresponding index file to path.
*
* @param pb The packbuilder
* @param path Directory to store the new pack and index
* @param path to the directory where the packfile and index should be stored
* @param progress_cb function to call with progress information from the indexer (optional)
* @param progress_cb_payload payload for the progress callback (optional)
*
* @return 0 or an error code
*/
GIT_EXTERN(int) git_packbuilder_write(git_packbuilder *pb, const char *file);
GIT_EXTERN(int) git_packbuilder_write(
git_packbuilder *pb,
const char *path,
git_transfer_progress_callback progress_cb,
void *progress_cb_payload);
typedef int (*git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload);
/**
......
......@@ -22,22 +22,6 @@
GIT_BEGIN_DECL
/**
* Create a new reference. Either an oid or a symbolic target must be
* specified.
*
* @param refdb the reference database to associate with this reference
* @param name the reference name
* @param oid the object id for a direct reference
* @param symbolic the target for a symbolic reference
* @return the created git_reference or NULL on error
*/
GIT_EXTERN(git_reference *) git_reference__alloc(
git_refdb *refdb,
const char *name,
const git_oid *oid,
const char *symbolic);
/**
* Create a new reference database with no backends.
*
* Before the Ref DB can be used for read/writing, a custom database
......@@ -78,20 +62,6 @@ GIT_EXTERN(int) git_refdb_compress(git_refdb *refdb);
*/
GIT_EXTERN(void) git_refdb_free(git_refdb *refdb);
/**
* Sets the custom backend to an existing reference DB
*
* Read <refdb_backends.h> for more information.
*
* @param refdb database to add the backend to
* @param backend pointer to a git_refdb_backend instance
* @param priority Value for ordering the backends queue
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_refdb_set_backend(
git_refdb *refdb,
git_refdb_backend *backend);
/** @} */
GIT_END_DECL
......
......@@ -48,13 +48,26 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo,
*
* @param out Pointer to oid to be filled in
* @param repo The repository in which to look up the reference
* @param name The long name for the reference
* @param name The long name for the reference (e.g. HEAD, refs/heads/master, refs/tags/v0.1.0, ...)
* @return 0 on success, ENOTFOUND, EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_reference_name_to_id(
git_oid *out, git_repository *repo, const char *name);
/**
* Lookup a reference by DWIMing its short name
*
* Apply the git precendence rules to the given shorthand to determine
* which reference the user is refering to.
*
* @param out pointer in which to store the reference
* @param repo the repository in which to look
* @param shorthand the short name for the reference
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, const char *shorthand);
/**
* Create a new symbolic reference.
*
* A symbolic reference is a reference name that refers to another
......@@ -133,6 +146,17 @@ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo,
GIT_EXTERN(const git_oid *) git_reference_target(const git_reference *ref);
/**
* Return the peeled OID target of this reference.
*
* This peeled OID only applies to direct references that point to
* a hard Tag object: it is the result of peeling such Tag.
*
* @param ref The reference
* @return a pointer to the oid if available, NULL otherwise
*/
GIT_EXTERN(const git_oid *) git_reference_target_peel(const git_reference *ref);
/**
* Get full name to the reference pointed to by a symbolic reference.
*
* Only available if the reference is symbolic.
......@@ -174,7 +198,7 @@ GIT_EXTERN(const char *) git_reference_name(const git_reference *ref);
* If a direct reference is passed as an argument, a copy of that
* reference is returned. This copy must be manually freed too.
*
* @param resolved_ref Pointer to the peeled reference
* @param out Pointer to the peeled reference
* @param ref The reference
* @return 0 or an error code
*/
......@@ -233,11 +257,6 @@ GIT_EXTERN(int) git_reference_set_target(
* The new name will be checked for validity.
* See `git_reference_create_symbolic()` for rules about valid names.
*
* On success, the given git_reference will be deleted from disk and a
* new `git_reference` will be returned.
*
* The reference will be immediately renamed in-memory and on disk.
*
* If the `force` flag is not enabled, and there's already
* a reference with the given name, the renaming will fail.
*
......@@ -247,13 +266,13 @@ GIT_EXTERN(int) git_reference_set_target(
* the reflog if it exists.
*
* @param ref The reference to rename
* @param name The new name for the reference
* @param new_name The new name for the reference
* @param force Overwrite an existing reference
* @return 0 on success, EINVALIDSPEC, EEXISTS or an error code
*
*/
GIT_EXTERN(int) git_reference_rename(
git_reference **out,
git_reference **new_ref,
git_reference *ref,
const char *new_name,
int force);
......@@ -273,12 +292,6 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
/**
* Fill a list with all the references that can be found in a repository.
*
* Using the `list_flags` parameter, the listed references may be filtered
* by type (`GIT_REF_OID` or `GIT_REF_SYMBOLIC`) or using a bitwise OR of
* `git_ref_t` values. To include packed refs, include `GIT_REF_PACKED`.
* For convenience, use the value `GIT_REF_LISTALL` to obtain all
* references, including packed ones.
*
* The string array will be filled with the names of all references; these
* values are owned by the user and should be free'd manually when no
* longer needed, using `git_strarray_free()`.
......@@ -286,39 +299,36 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
* @param array Pointer to a git_strarray structure where
* the reference names will be stored
* @param repo Repository where to find the refs
* @param list_flags Filtering flags for the reference listing
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, unsigned int list_flags);
GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo);
typedef int (*git_reference_foreach_cb)(const char *refname, void *payload);
typedef int (*git_reference_foreach_cb)(git_reference *reference, void *payload);
typedef int (*git_reference_foreach_name_cb)(const char *name, void *payload);
/**
* Perform a callback on each reference in the repository.
*
* Using the `list_flags` parameter, the references may be filtered by
* type (`GIT_REF_OID` or `GIT_REF_SYMBOLIC`) or using a bitwise OR of
* `git_ref_t` values. To include packed refs, include `GIT_REF_PACKED`.
* For convenience, use the value `GIT_REF_LISTALL` to obtain all
* references, including packed ones.
*
* The `callback` function will be called for each reference in the
* repository, receiving the name of the reference and the `payload` value
* passed to this method. Returning a non-zero value from the callback
* will terminate the iteration.
*
* @param repo Repository where to find the refs
* @param list_flags Filtering flags for the reference listing.
* @param callback Function which will be called for every listed ref
* @param payload Additional data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
*/
GIT_EXTERN(int) git_reference_foreach(
git_repository *repo,
unsigned int list_flags,
git_reference_foreach_cb callback,
void *payload);
GIT_EXTERN(int) git_reference_foreach_name(
git_repository *repo,
git_reference_foreach_name_cb callback,
void *payload);
/**
* Free the given reference.
*
......@@ -336,6 +346,49 @@ GIT_EXTERN(void) git_reference_free(git_reference *ref);
GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2);
/**
* Create an iterator for the repo's references
*
* @param out pointer in which to store the iterator
* @param repo the repository
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reference_iterator_new(
git_reference_iterator **out,
git_repository *repo);
/**
* Create an iterator for the repo's references that match the
* specified glob
*
* @param out pointer in which to store the iterator
* @param repo the repository
* @param glob the glob to match against the reference names
* @return 0 or an error code
*/
GIT_EXTERN(int) git_reference_iterator_glob_new(
git_reference_iterator **out,
git_repository *repo,
const char *glob);
/**
* Get the next reference
*
* @param out pointer in which to store the reference
* @param iter the iterator
* @return 0, GIT_ITEROVER if there are no more; or an error code
*/
GIT_EXTERN(int) git_reference_next(git_reference **out, git_reference_iterator *iter);
GIT_EXTERN(int) git_reference_next_name(const char **out, git_reference_iterator *iter);
/**
* Free the iterator and its associated resources
*
* @param iter the iterator to free
*/
GIT_EXTERN(void) git_reference_iterator_free(git_reference_iterator *iter);
/**
* Perform a callback on each reference in the repository whose name
* matches the given pattern.
*
......@@ -349,7 +402,6 @@ GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2);
*
* @param repo Repository where to find the refs
* @param glob Pattern to match (fnmatch-style) against reference name.
* @param list_flags Filtering flags for the reference listing.
* @param callback Function which will be called for every listed ref
* @param payload Additional data to pass to the callback
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
......@@ -357,8 +409,7 @@ GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2);
GIT_EXTERN(int) git_reference_foreach_glob(
git_repository *repo,
const char *glob,
unsigned int list_flags,
git_reference_foreach_cb callback,
git_reference_foreach_name_cb callback,
void *payload);
/**
......@@ -411,6 +462,13 @@ typedef enum {
* (e.g., foo/<star>/bar but not foo/bar<star>).
*/
GIT_REF_FORMAT_REFSPEC_PATTERN = (1 << 1),
/**
* Interpret the name as part of a refspec in shorthand form
* so the `ONELEVEL` naming rules aren't enforced and 'master'
* becomes a valid name.
*/
GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1 << 2),
} git_reference_normalize_t;
/**
......@@ -448,9 +506,9 @@ GIT_EXTERN(int) git_reference_normalize_name(
* If you pass `GIT_OBJ_ANY` as the target type, then the object
* will be peeled until a non-tag object is met.
*
* @param peeled Pointer to the peeled git_object
* @param out Pointer to the peeled git_object
* @param ref The reference to be processed
* @param target_type The type of the requested object (GIT_OBJ_COMMIT,
* @param type The type of the requested object (GIT_OBJ_COMMIT,
* GIT_OBJ_TAG, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_ANY).
* @return 0 on success, GIT_EAMBIGUOUS, GIT_ENOTFOUND or an error code
*/
......@@ -475,6 +533,21 @@ GIT_EXTERN(int) git_reference_peel(
*/
GIT_EXTERN(int) git_reference_is_valid_name(const char *refname);
/**
* Get the reference's short name
*
* This will transform the reference name into a name "human-readable"
* version. If no shortname is appropriate, it will return the full
* name.
*
* The memory is owned by the reference and must not be freed.
*
* @param ref a reference
* @return the human-readable version of the name
*/
GIT_EXTERN(const char *) git_reference_shorthand(git_reference *ref);
/** @} */
GIT_END_DECL
#endif
......@@ -9,6 +9,7 @@
#include "common.h"
#include "types.h"
#include "net.h"
/**
* @file git2/refspec.h
......@@ -36,6 +37,14 @@ GIT_EXTERN(const char *) git_refspec_src(const git_refspec *refspec);
GIT_EXTERN(const char *) git_refspec_dst(const git_refspec *refspec);
/**
* Get the refspec's string
*
* @param refspec the refspec
* @returns the refspec's original string
*/
GIT_EXTERN(const char *) git_refspec_string(const git_refspec *refspec);
/**
* Get the force update setting
*
* @param refspec the refspec
......@@ -44,6 +53,14 @@ GIT_EXTERN(const char *) git_refspec_dst(const git_refspec *refspec);
GIT_EXTERN(int) git_refspec_force(const git_refspec *refspec);
/**
* Get the refspec's direction.
*
* @param spec refspec
* @return GIT_DIRECTION_FETCH or GIT_DIRECTION_PUSH
*/
GIT_EXTERN(git_direction) git_refspec_direction(const git_refspec *spec);
/**
* Check if a refspec's source descriptor matches a reference
*
* @param refspec the refspec
......
......@@ -142,39 +142,79 @@ GIT_EXTERN(int) git_remote_set_url(git_remote *remote, const char* url);
GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url);
/**
* Set the remote's fetch refspec
* Add a fetch refspec to the remote
*
* @param remote the remote
* @apram spec the new fetch refspec
* @apram refspec the new fetch refspec
* @return 0 or an error value
*/
GIT_EXTERN(int) git_remote_set_fetchspec(git_remote *remote, const char *spec);
GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec);
/**
* Get the fetch refspec
* Get the remote's list of fetch refspecs
*
* @param remote the remote
* @return a pointer to the fetch refspec or NULL if it doesn't exist
* The memory is owned by the user and should be freed with
* `git_strarray_free`.
*
* @param array pointer to the array in which to store the strings
* @param remote the remote to query
*/
GIT_EXTERN(const git_refspec *) git_remote_fetchspec(const git_remote *remote);
GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote);
/**
* Set the remote's push refspec
* Add a push refspec to the remote
*
* @param remote the remote
* @param spec the new push refspec
* @param refspec the new push refspec
* @return 0 or an error value
*/
GIT_EXTERN(int) git_remote_set_pushspec(git_remote *remote, const char *spec);
GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec);
/**
* Get the remote's list of push refspecs
*
* The memory is owned by the user and should be freed with
* `git_strarray_free`.
*
* @param array pointer to the array in which to store the strings
* @param remote the remote to query
*/
GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote);
/**
* Clear the refspecs
*
* Remove all configured fetch and push refspecs from the remote.
*
* @param remote the remote
*/
GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote);
/**
* Get the push refspec
* Get the number of refspecs for a remote
*
* @param remote the remote
* @return a pointer to the push refspec or NULL if it doesn't exist
* @return the amount of refspecs configured in this remote
*/
GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote);
/**
* Get a refspec from the remote
*
* @param remote the remote to query
* @param n the refspec to get
* @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_pushspec(const git_remote *remote);
/**
* Remove a refspec from the remote
*
* @param remote the remote to query
* @param n the refspec to remove
* @return 0 or GIT_ENOTFOUND
*/
GIT_EXTERN(int) git_remote_remove_refspec(git_remote *remote, size_t n);
/**
* Open a connection to a remote
......@@ -184,7 +224,8 @@ GIT_EXTERN(const git_refspec *) git_remote_pushspec(const git_remote *remote);
* starts up a specific binary which can only do the one or the other.
*
* @param remote the remote to connect to
* @param direction whether you want to receive or send data
* @param direction GIT_DIRECTION_FETCH if you want to fetch or
* GIT_DIRECTION_PUSH if you want to push
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction);
......@@ -218,7 +259,7 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void
* @param progress_cb function to call with progress information. Be aware that
* this is called inline with network and indexing operations, so performance
* may be affected.
* @param progress_payload payload for the progress callback
* @param payload payload for the progress callback
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_download(
......@@ -279,7 +320,7 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote);
* Return whether a string is a valid remote URL
*
* @param url the url to check
* @param 1 if the url is valid, 0 otherwise
* @return 1 if the url is valid, 0 otherwise
*/
GIT_EXTERN(int) git_remote_valid_url(const char *url);
......@@ -385,10 +426,9 @@ GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, git_remote_callback
GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote);
typedef enum {
GIT_REMOTE_DOWNLOAD_TAGS_UNSET,
GIT_REMOTE_DOWNLOAD_TAGS_NONE,
GIT_REMOTE_DOWNLOAD_TAGS_AUTO,
GIT_REMOTE_DOWNLOAD_TAGS_ALL
GIT_REMOTE_DOWNLOAD_TAGS_AUTO = 0,
GIT_REMOTE_DOWNLOAD_TAGS_NONE = 1,
GIT_REMOTE_DOWNLOAD_TAGS_ALL = 2
} git_remote_autotag_option_t;
/**
......
......@@ -124,6 +124,19 @@ GIT_EXTERN(int) git_repository_open_ext(
const char *ceiling_dirs);
/**
* Open a bare repository on the serverside.
*
* This is a fast open for bare repositories that will come in handy
* if you're e.g. hosting git repositories and need to access them
* efficiently
*
* @param out Pointer to the repo which will be opened.
* @param bare_path Direct path to the bare repository
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_open_bare(git_repository **out, const char *bare_path);
/**
* Free a previously allocated repository
*
* Note that after a repository is free'd, all the objects it has spawned
......@@ -388,21 +401,6 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo);
/**
* Set the configuration file for this repository
*
* This configuration file will be used for all configuration
* queries involving this repository.
*
* The repository will keep a reference to the config file;
* the user must still free the config after setting it
* to the repository, or it will leak.
*
* @param repo A repository object
* @param config A Config object
*/
GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
/**
* Get the Object Database for this repository.
*
* If a custom ODB has not been set, the default
......@@ -419,21 +417,6 @@ GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *con
GIT_EXTERN(int) git_repository_odb(git_odb **out, git_repository *repo);
/**
* Set the Object Database for this repository
*
* The ODB will be used for all object-related operations
* involving this repository.
*
* The repository will keep a reference to the ODB; the user
* must still free the ODB object after setting it to the
* repository, or it will leak.
*
* @param repo A repository object
* @param odb An ODB object
*/
GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
/**
* Get the Reference Database Backend for this repository.
*
* If a custom refsdb has not been set, the default database for
......@@ -450,23 +433,6 @@ GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
GIT_EXTERN(int) git_repository_refdb(git_refdb **out, git_repository *repo);
/**
* Set the Reference Database Backend for this repository
*
* The refdb will be used for all reference related operations
* involving this repository.
*
* The repository will keep a reference to the refdb; the user
* must still free the refdb object after setting it to the
* repository, or it will leak.
*
* @param repo A repository object
* @param refdb An refdb object
*/
GIT_EXTERN(void) git_repository_set_refdb(
git_repository *repo,
git_refdb *refdb);
/**
* Get the Index file for this repository.
*
* If a custom index has not been set, the default
......@@ -483,21 +449,6 @@ GIT_EXTERN(void) git_repository_set_refdb(
GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
/**
* Set the index file for this repository
*
* This index will be used for all index-related operations
* involving this repository.
*
* The repository will keep a reference to the index file;
* the user must still free the index after setting it
* to the repository, or it will leak.
*
* @param repo A repository object
* @param index An index object
*/
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
/**
* Retrieve git's prepared message
*
* Operations such as git revert/cherry-pick/merge with the -n option
......@@ -509,10 +460,19 @@ GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index
* Use this function to get the contents of this file. Don't forget to
* remove the file after you create the commit.
*
* If the repository message exists and there are no errors reading it, this
* 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 buffer in bytes
* @param len Length of `out` buffer in bytes
* @param repo Repository to read prepared message from
* @return Bytes written to buffer, GIT_ENOTFOUND if no message, or -1 on error
* @return GIT_ENOUTFOUND if no message exists, other value < 0 for other
* 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);
......@@ -559,7 +519,7 @@ typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid,
*
* @param repo A repository object
* @param callback Callback function
* @param apyload Pointer to callback data (optional)
* @param payload Pointer to callback data (optional)
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error
*/
GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
......@@ -585,11 +545,11 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
* applied when calculating the hash.
*/
GIT_EXTERN(int) git_repository_hashfile(
git_oid *out,
git_repository *repo,
const char *path,
git_otype type,
const char *as_path);
git_oid *out,
git_repository *repo,
const char *path,
git_otype type,
const char *as_path);
/**
* Make the repository HEAD point to the specified reference.
......@@ -675,6 +635,37 @@ typedef enum {
*/
GIT_EXTERN(int) git_repository_state(git_repository *repo);
/**
* Sets the active namespace for this Git Repository
*
* This namespace affects all reference operations for the repo.
* See `man gitnamespaces`
*
* @param repo The repo
* @param nmspace The namespace. This should not include the refs
* folder, e.g. to namespace all references under `refs/namespaces/foo/`,
* use `foo` as the namespace.
* @return 0 on success, -1 on error
*/
GIT_EXTERN(int) git_repository_set_namespace(git_repository *repo, const char *nmspace);
/**
* Get the currently active namespace for this repository
*
* @param repo The repo
* @return the active namespace, or NULL if there isn't one
*/
GIT_EXTERN(const char *) git_repository_get_namespace(git_repository *repo);
/**
* Determine if the repository was a shallow clone
*
* @param repo The repository
* @return 1 if shallow, zero if not
*/
GIT_EXTERN(int) git_repository_is_shallow(git_repository *repo);
/** @} */
GIT_END_DECL
#endif
......@@ -72,9 +72,9 @@ GIT_EXTERN(int) git_reset(
* @return 0 on success or an error code < 0
*/
GIT_EXTERN(int) git_reset_default(
git_repository *repo,
git_object *target,
git_strarray* pathspecs);
git_repository *repo,
git_object *target,
git_strarray* pathspecs);
/** @} */
GIT_END_DECL
......
......@@ -32,6 +32,28 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec);
/**
* Find a single object, as specified by a revision string.
* See `man gitrevisions`,
* or http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for
* information on the syntax accepted.
*
* In some cases (`@{<-n>}` or `<branchname>@{upstream}`), the expression may
* point to an intermediate reference. When such expressions are being passed
* in, `reference_out` will be valued as well.
*
* @param object_out pointer to output object
* @param reference_out pointer to output reference or NULL
* @param repo the repository to search in
* @param spec the textual specification for an object
* @return 0 on success, GIT_ENOTFOUND, GIT_EAMBIGUOUS, GIT_EINVALIDSPEC
* or an error code
*/
GIT_EXTERN(int) git_revparse_ext(
git_object **object_out,
git_reference **reference_out,
git_repository *repo,
const char *spec);
/**
* Revparse flags. These indicate the intended behavior of the spec passed to
......
......@@ -89,7 +89,7 @@ typedef int (*git_stash_cb)(
*
* @param repo Repository where to find the stash.
*
* @param callabck Callback to invoke per found stashed state. The most recent
* @param callback Callback to invoke per found stashed state. The most recent
* stash state will be enumerated first.
*
* @param payload Extra parameter to callback function.
......
......@@ -20,8 +20,8 @@ GIT_BEGIN_DECL
/** Array of strings */
typedef struct git_strarray {
char **strings;
size_t count;
char **strings;
size_t count;
} git_strarray;
/**
......
......@@ -103,20 +103,20 @@ typedef enum {
* * WD_UNTRACKED - wd contains untracked files
*/
typedef enum {
GIT_SUBMODULE_STATUS_IN_HEAD = (1u << 0),
GIT_SUBMODULE_STATUS_IN_INDEX = (1u << 1),
GIT_SUBMODULE_STATUS_IN_CONFIG = (1u << 2),
GIT_SUBMODULE_STATUS_IN_WD = (1u << 3),
GIT_SUBMODULE_STATUS_INDEX_ADDED = (1u << 4),
GIT_SUBMODULE_STATUS_INDEX_DELETED = (1u << 5),
GIT_SUBMODULE_STATUS_INDEX_MODIFIED = (1u << 6),
GIT_SUBMODULE_STATUS_WD_UNINITIALIZED = (1u << 7),
GIT_SUBMODULE_STATUS_WD_ADDED = (1u << 8),
GIT_SUBMODULE_STATUS_WD_DELETED = (1u << 9),
GIT_SUBMODULE_STATUS_WD_MODIFIED = (1u << 10),
GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED = (1u << 11),
GIT_SUBMODULE_STATUS_WD_WD_MODIFIED = (1u << 12),
GIT_SUBMODULE_STATUS_WD_UNTRACKED = (1u << 13),
GIT_SUBMODULE_STATUS_IN_HEAD = (1u << 0),
GIT_SUBMODULE_STATUS_IN_INDEX = (1u << 1),
GIT_SUBMODULE_STATUS_IN_CONFIG = (1u << 2),
GIT_SUBMODULE_STATUS_IN_WD = (1u << 3),
GIT_SUBMODULE_STATUS_INDEX_ADDED = (1u << 4),
GIT_SUBMODULE_STATUS_INDEX_DELETED = (1u << 5),
GIT_SUBMODULE_STATUS_INDEX_MODIFIED = (1u << 6),
GIT_SUBMODULE_STATUS_WD_UNINITIALIZED = (1u << 7),
GIT_SUBMODULE_STATUS_WD_ADDED = (1u << 8),
GIT_SUBMODULE_STATUS_WD_DELETED = (1u << 9),
GIT_SUBMODULE_STATUS_WD_MODIFIED = (1u << 10),
GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED = (1u << 11),
GIT_SUBMODULE_STATUS_WD_WD_MODIFIED = (1u << 12),
GIT_SUBMODULE_STATUS_WD_UNTRACKED = (1u << 13),
} git_submodule_status_t;
#define GIT_SUBMODULE_STATUS__IN_FLAGS \
......@@ -481,7 +481,7 @@ GIT_EXTERN(int) git_submodule_sync(git_submodule *submodule);
* function will return distinct `git_repository` objects. This will only
* work if the submodule is checked out into the working directory.
*
* @param subrepo Pointer to the submodule repo which was opened
* @param repo Pointer to the submodule repo which was opened
* @param submodule Submodule to be opened
* @return 0 on success, <0 if submodule repo could not be opened.
*/
......@@ -531,7 +531,7 @@ GIT_EXTERN(int) git_submodule_status(
* This can be useful if you want to know if the submodule is present in the
* working directory at this point in time, etc.
*
* @param status Combination of first four `GIT_SUBMODULE_STATUS` flags
* @param location_status Combination of first four `GIT_SUBMODULE_STATUS` flags
* @param submodule Submodule for which to get status
* @return 0 on success, <0 on error
*/
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_commit_h__
#define INCLUDE_sys_git_commit_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
/**
* @file git2/sys/commit.h
* @brief Low-level Git commit creation
* @defgroup git_backend Git custom backend APIs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Create new commit in the repository from a list of `git_oid` values
*
* See documentation for `git_commit_create()` for information about the
* parameters, as the meaning is identical excepting that `tree` and
* `parents` now take `git_oid`. This is a dangerous API in that nor
* the `tree`, neither the `parents` list of `git_oid`s are checked for
* validity.
*/
GIT_EXTERN(int) git_commit_create_from_oids(
git_oid *oid,
git_repository *repo,
const char *update_ref,
const git_signature *author,
const git_signature *committer,
const char *message_encoding,
const char *message,
const git_oid *tree,
int parent_count,
const git_oid *parents[]);
/** @} */
GIT_END_DECL
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_config_backend_h__
#define INCLUDE_sys_git_config_backend_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/config.h"
/**
* @file git2/sys/config.h
* @brief Git config backend routines
* @defgroup git_backend Git custom backend APIs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Generic backend that implements the interface to
* access a configuration file
*/
struct git_config_backend {
unsigned int version;
struct git_config *cfg;
/* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *, git_config_level_t level);
int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);
int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload);
int (*set)(struct git_config_backend *, const char *key, const char *value);
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
int (*del)(struct git_config_backend *, const char *key);
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload);
int (*refresh)(struct git_config_backend *);
void (*free)(struct git_config_backend *);
};
#define GIT_CONFIG_BACKEND_VERSION 1
#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
/**
* Add a generic config file instance to an existing config
*
* Note that the configuration object will free the file
* automatically.
*
* Further queries on this config object will access each
* of the config file instances in order (instances with
* a higher priority level will be accessed first).
*
* @param cfg the configuration to add the file to
* @param file the configuration file (backend) to add
* @param level the priority level of the backend
* @param force if a config file already exists for the given
* priority level, replace it
* @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0), or error code
*/
GIT_EXTERN(int) git_config_add_backend(
git_config *cfg,
git_config_backend *file,
git_config_level_t level,
int force);
/** @} */
GIT_END_DECL
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_index_h__
#define INCLUDE_sys_git_index_h__
/**
* @file git2/sys/index.h
* @brief Low-level Git index manipulation routines
* @defgroup git_backend Git custom backend APIs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/** Representation of a rename conflict entry in the index. */
typedef struct git_index_name_entry {
char *ancestor;
char *ours;
char *theirs;
} git_index_name_entry;
/** Representation of a resolve undo entry in the index. */
typedef struct git_index_reuc_entry {
unsigned int mode[3];
git_oid oid[3];
char *path;
} git_index_reuc_entry;
/** @name Conflict Name entry functions
*
* These functions work on rename conflict entries.
*/
/**@{*/
/**
* Get the count of filename conflict entries currently in the index.
*
* @param index an existing index object
* @return integer of count of current filename conflict entries
*/
GIT_EXTERN(unsigned int) git_index_name_entrycount(git_index *index);
/**
* Get a filename conflict entry from the index.
*
* The returned entry is read-only and should not be modified
* or freed by the caller.
*
* @param index an existing index object
* @param n the position of the entry
* @return a pointer to the filename conflict entry; NULL if out of bounds
*/
GIT_EXTERN(const git_index_name_entry *) git_index_name_get_byindex(
git_index *index, size_t n);
/**
* Record the filenames involved in a rename conflict.
*
* @param index an existing index object
* @param ancestor the path of the file as it existed in the ancestor
* @param ours the path of the file as it existed in our tree
* @param theirs the path of the file as it existed in their tree
*/
GIT_EXTERN(int) git_index_name_add(git_index *index,
const char *ancestor, const char *ours, const char *theirs);
/**
* Remove all filename conflict entries.
*
* @param index an existing index object
* @return 0 or an error code
*/
GIT_EXTERN(void) git_index_name_clear(git_index *index);
/**@}*/
/** @name Resolve Undo (REUC) index entry manipulation.
*
* These functions work on the Resolve Undo index extension and contains
* data about the original files that led to a merge conflict.
*/
/**@{*/
/**
* Get the count of resolve undo entries currently in the index.
*
* @param index an existing index object
* @return integer of count of current resolve undo entries
*/
GIT_EXTERN(unsigned int) git_index_reuc_entrycount(git_index *index);
/**
* Finds the resolve undo entry that points to the given path in the Git
* index.
*
* @param at_pos the address to which the position of the reuc entry is written (optional)
* @param index an existing index object
* @param path path to search
* @return 0 if found, < 0 otherwise (GIT_ENOTFOUND)
*/
GIT_EXTERN(int) git_index_reuc_find(size_t *at_pos, git_index *index, const char *path);
/**
* Get a resolve undo entry from the index.
*
* The returned entry is read-only and should not be modified
* or freed by the caller.
*
* @param index an existing index object
* @param path path to search
* @return the resolve undo entry; NULL if not found
*/
GIT_EXTERN(const git_index_reuc_entry *) git_index_reuc_get_bypath(git_index *index, const char *path);
/**
* Get a resolve undo entry from the index.
*
* The returned entry is read-only and should not be modified
* or freed by the caller.
*
* @param index an existing index object
* @param n the position of the entry
* @return a pointer to the resolve undo entry; NULL if out of bounds
*/
GIT_EXTERN(const git_index_reuc_entry *) git_index_reuc_get_byindex(git_index *index, size_t n);
/**
* Adds a resolve undo entry for a file based on the given parameters.
*
* The resolve undo entry contains the OIDs of files that were involved
* in a merge conflict after the conflict has been resolved. This allows
* conflicts to be re-resolved later.
*
* If there exists a resolve undo entry for the given path in the index,
* it will be removed.
*
* This method will fail in bare index instances.
*
* @param index an existing index object
* @param path filename to add
* @param ancestor_mode mode of the ancestor file
* @param ancestor_id oid of the ancestor file
* @param our_mode mode of our file
* @param our_id oid of our file
* @param their_mode mode of their file
* @param their_id oid of their file
* @return 0 or an error code
*/
GIT_EXTERN(int) git_index_reuc_add(git_index *index, const char *path,
int ancestor_mode, const git_oid *ancestor_id,
int our_mode, const git_oid *our_id,
int their_mode, const git_oid *their_id);
/**
* Remove an resolve undo entry from the index
*
* @param index an existing index object
* @param n position of the resolve undo entry to remove
* @return 0 or an error code
*/
GIT_EXTERN(int) git_index_reuc_remove(git_index *index, size_t n);
/**
* Remove all resolve undo entries from the index
*
* @param index an existing index object
* @return 0 or an error code
*/
GIT_EXTERN(void) git_index_reuc_clear(git_index *index);
/**@}*/
/** @} */
GIT_END_DECL
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_odb_backend_h__
#define INCLUDE_sys_git_odb_backend_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
#include "git2/odb.h"
/**
* @file git2/sys/backend.h
* @brief Git custom backend implementors functions
* @defgroup git_backend Git custom backend APIs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* An instance for a custom backend
*/
struct git_odb_backend {
unsigned int version;
git_odb *odb;
/* read and read_prefix each return to libgit2 a buffer which
* will be freed later. The buffer should be allocated using
* the function git_odb_backend_malloc to ensure that it can
* be safely freed later. */
int (* read)(
void **, size_t *, git_otype *, git_odb_backend *, const git_oid *);
/* To find a unique object given a prefix
* of its oid.
* The oid given must be so that the
* remaining (GIT_OID_HEXSZ - len)*4 bits
* are 0s.
*/
int (* read_prefix)(
git_oid *, void **, size_t *, git_otype *,
git_odb_backend *, const git_oid *, size_t);
int (* read_header)(
size_t *, git_otype *, git_odb_backend *, const git_oid *);
/* The writer may assume that the object
* has already been hashed and is passed
* in the first parameter.
*/
int (* write)(
git_oid *, git_odb_backend *, const void *, size_t, git_otype);
int (* writestream)(
git_odb_stream **, git_odb_backend *, size_t, git_otype);
int (* readstream)(
git_odb_stream **, git_odb_backend *, const git_oid *);
int (* exists)(
git_odb_backend *, const git_oid *);
int (* refresh)(git_odb_backend *);
int (* foreach)(
git_odb_backend *, git_odb_foreach_cb cb, void *payload);
int (* writepack)(
git_odb_writepack **, git_odb_backend *,
git_transfer_progress_callback progress_cb, void *progress_payload);
void (* free)(git_odb_backend *);
};
#define GIT_ODB_BACKEND_VERSION 1
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);
GIT_END_DECL
#endif
......@@ -4,12 +4,12 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_refdb_backend_h__
#define INCLUDE_git_refdb_backend_h__
#ifndef INCLUDE_sys_git_refdb_backend_h__
#define INCLUDE_sys_git_refdb_backend_h__
#include "common.h"
#include "types.h"
#include "oid.h"
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
/**
* @file git2/refdb_backend.h
......@@ -20,9 +20,45 @@
*/
GIT_BEGIN_DECL
/**
* Every backend's iterator must have a pointer to itself as the first
* element, so the API can talk to it. You'd define your iterator as
*
* struct my_iterator {
* git_reference_iterator parent;
* ...
* }
*
* and assign `iter->parent.backend` to your `git_refdb_backend`.
*/
struct git_reference_iterator {
git_refdb *db;
/**
* Return the current reference and advance the iterator.
*/
int (*next)(
git_reference **ref,
git_reference_iterator *iter);
/**
* Return the name of the current reference and advance the iterator
*/
int (*next_name)(
const char **ref_name,
git_reference_iterator *iter);
/**
* Free the iterator
*/
void (*free)(
git_reference_iterator *iter);
};
/** An instance for a custom backend */
struct git_refdb_backend {
unsigned int version;
unsigned int version;
/**
* Queries the refdb backend to determine if the given ref_name
......@@ -30,7 +66,7 @@ struct git_refdb_backend {
*/
int (*exists)(
int *exists,
struct git_refdb_backend *backend,
git_refdb_backend *backend,
const char *ref_name);
/**
......@@ -39,43 +75,35 @@ struct git_refdb_backend {
*/
int (*lookup)(
git_reference **out,
struct git_refdb_backend *backend,
git_refdb_backend *backend,
const char *ref_name);
/**
* Enumerates each reference in the refdb. A refdb implementation must
* provide this function.
*/
int (*foreach)(
struct git_refdb_backend *backend,
unsigned int list_flags,
git_reference_foreach_cb callback,
void *payload);
/**
* Enumerates each reference in the refdb that matches the given
* glob string. A refdb implementation may provide this function;
* if it is not provided, foreach will be used and the results filtered
* against the glob.
* Allocate an iterator object for the backend.
*
* A refdb implementation must provide this function.
*/
int (*foreach_glob)(
int (*iterator)(
git_reference_iterator **iter,
struct git_refdb_backend *backend,
const char *glob,
unsigned int list_flags,
git_reference_foreach_cb callback,
void *payload);
const char *glob);
/**
/*
* Writes the given reference to the refdb. A refdb implementation
* must provide this function.
*/
int (*write)(struct git_refdb_backend *backend, const git_reference *ref);
int (*write)(git_refdb_backend *backend,
const git_reference *ref, int force);
int (*rename)(
git_reference **out, git_refdb_backend *backend,
const char *old_name, const char *new_name, int force);
/**
* Deletes the given reference from the refdb. A refdb implementation
* must provide this function.
*/
int (*delete)(struct git_refdb_backend *backend, const git_reference *ref);
int (*delete)(git_refdb_backend *backend, const char *ref_name);
/**
* Suggests that the given refdb compress or optimize its references.
......@@ -84,25 +112,46 @@ struct git_refdb_backend {
* implementation may provide this function; if it is not provided,
* nothing will be done.
*/
int (*compress)(struct git_refdb_backend *backend);
int (*compress)(git_refdb_backend *backend);
/**
* Frees any resources held by the refdb. A refdb implementation may
* provide this function; if it is not provided, nothing will be done.
*/
void (*free)(struct git_refdb_backend *backend);
void (*free)(git_refdb_backend *backend);
};
#define GIT_ODB_BACKEND_VERSION 1
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
/**
* Constructors for default refdb backends.
* Constructors for default filesystem-based refdb backend
*
* Under normal usage, this is called for you when the repository is
* opened / created, but you can use this to explicitly construct a
* filesystem refdb backend for a repository.
*
* @param backend_out Output pointer to the git_refdb_backend object
* @param repo Git repository to access
* @return 0 on success, <0 error code on failure
*/
GIT_EXTERN(int) git_refdb_backend_fs(
struct git_refdb_backend **backend_out,
git_repository *repo,
git_refdb *refdb);
git_refdb_backend **backend_out,
git_repository *repo);
/**
* Sets the custom backend to an existing reference DB
*
* The `git_refdb` will take ownership of the `git_refdb_backend` so you
* should NOT free it after calling this function.
*
* @param refdb database to add the backend to
* @param backend pointer to a git_refdb_backend instance
* @return 0 on success; error code otherwise
*/
GIT_EXTERN(int) git_refdb_set_backend(
git_refdb *refdb,
git_refdb_backend *backend);
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_sys_git_refdb_h__
#define INCLUDE_sys_git_refdb_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/oid.h"
/**
* Create a new direct reference from an OID.
*
* @param name the reference name
* @param oid the object id for a direct reference
* @param symbolic the target for a symbolic reference
* @return the created git_reference or NULL on error
*/
GIT_EXTERN(git_reference *) git_reference__alloc(
const char *name,
const git_oid *oid,
const git_oid *peel);
/**
* Create a new symbolic reference.
*
* @param name the reference name
* @param symbolic the target for a symbolic reference
* @return the created git_reference or NULL on error
*/
GIT_EXTERN(git_reference *) git_reference__alloc_symbolic(
const char *name,
const char *target);
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_sys_git_repository_h__
#define INCLUDE_sys_git_repository_h__
/**
* @file git2/sys/repository.h
* @brief Git repository custom implementation routines
* @defgroup git_backend Git custom backend APIs
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Create a new repository with neither backends nor config object
*
* Note that this is only useful if you wish to associate the repository
* with a non-filesystem-backed object database and config store.
*
* @param out The blank repository
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_new(git_repository **out);
/**
* Reset all the internal state in a repository.
*
* This will free all the mapped memory and internal objects
* of the repository and leave it in a "blank" state.
*
* There's no need to call this function directly unless you're
* trying to aggressively cleanup the repo before its
* deallocation. `git_repository_free` already performs this operation
* before deallocation the repo.
*/
GIT_EXTERN(void) git_repository__cleanup(git_repository *repo);
/**
* Set the configuration file for this repository
*
* This configuration file will be used for all configuration
* queries involving this repository.
*
* The repository will keep a reference to the config file;
* the user must still free the config after setting it
* to the repository, or it will leak.
*
* @param repo A repository object
* @param config A Config object
*/
GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
/**
* Set the Object Database for this repository
*
* The ODB will be used for all object-related operations
* involving this repository.
*
* The repository will keep a reference to the ODB; the user
* must still free the ODB object after setting it to the
* repository, or it will leak.
*
* @param repo A repository object
* @param odb An ODB object
*/
GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
/**
* Set the Reference Database Backend for this repository
*
* The refdb will be used for all reference related operations
* involving this repository.
*
* The repository will keep a reference to the refdb; the user
* must still free the refdb object after setting it to the
* repository, or it will leak.
*
* @param repo A repository object
* @param refdb An refdb object
*/
GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb);
/**
* Set the index file for this repository
*
* This index will be used for all index-related operations
* involving this repository.
*
* The repository will keep a reference to the index file;
* the user must still free the index after setting it
* to the repository, or it will leak.
*
* @param repo A repository object
* @param index An index object
*/
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
/** @} */
GIT_END_DECL
#endif
......@@ -30,12 +30,8 @@ GIT_BEGIN_DECL
* @param id identity of the tag to locate.
* @return 0 or an error code
*/
GIT_INLINE(int) git_tag_lookup(
git_tag **out, git_repository *repo, const git_oid *id)
{
return git_object_lookup(
(git_object **)out, repo, id, (git_otype)GIT_OBJ_TAG);
}
GIT_EXTERN(int) git_tag_lookup(
git_tag **out, git_repository *repo, const git_oid *id);
/**
* Lookup a tag object from the repository,
......@@ -49,12 +45,8 @@ GIT_INLINE(int) git_tag_lookup(
* @param len the length of the short identifier
* @return 0 or an error code
*/
GIT_INLINE(int) git_tag_lookup_prefix(
git_tag **out, git_repository *repo, const git_oid *id, size_t len)
{
return git_object_lookup_prefix(
(git_object **)out, repo, id, len, (git_otype)GIT_OBJ_TAG);
}
GIT_EXTERN(int) git_tag_lookup_prefix(
git_tag **out, git_repository *repo, const git_oid *id, size_t len);
/**
* Close an open tag
......@@ -66,12 +58,7 @@ GIT_INLINE(int) git_tag_lookup_prefix(
*
* @param tag the tag to close
*/
GIT_INLINE(void) git_tag_free(git_tag *tag)
{
git_object_free((git_object *)tag);
}
GIT_EXTERN(void) git_tag_free(git_tag *tag);
/**
* Get the id of a tag.
......@@ -82,6 +69,14 @@ GIT_INLINE(void) git_tag_free(git_tag *tag)
GIT_EXTERN(const git_oid *) git_tag_id(const git_tag *tag);
/**
* Get the repository that contains the tag.
*
* @param tag A previously loaded tag.
* @return Repository that contains this tag.
*/
GIT_EXTERN(git_repository *) git_tag_owner(const git_tag *tag);
/**
* Get the tagged object of a tag
*
* This method performs a repository lookup for the
......@@ -183,6 +178,37 @@ GIT_EXTERN(int) git_tag_create(
int force);
/**
* Create a new tag in the object database pointing to a git_object
*
* The message will not be cleaned up. This can be achieved
* through `git_message_prettify()`.
*
* @param oid Pointer where to store the OID of the
* newly created tag
*
* @param repo Repository where to store the tag
*
* @param tag_name Name for the tag
*
* @param target Object to which this tag points. This object
* must belong to the given `repo`.
*
* @param tagger Signature of the tagger for this tag, and
* of the tagging time
*
* @param message Full message for this tag
*
* @return 0 on success or an error code
*/
GIT_EXTERN(int) git_tag_annotation_create(
git_oid *oid,
git_repository *repo,
const char *tag_name,
const git_object *target,
const git_signature *tagger,
const char *message);
/**
* Create a new tag in the repository from a buffer
*
* @param oid Pointer where to store the OID of the newly created tag
......
......@@ -32,7 +32,7 @@ typedef enum {
/** Errors that do not impact the program's execution */
GIT_TRACE_ERROR = 2,
/** Warnings that suggest abnormal data */
GIT_TRACE_WARN = 3,
......@@ -65,4 +65,3 @@ GIT_EXTERN(int) git_trace_set(git_trace_level_t level, git_trace_callback cb);
/** @} */
GIT_END_DECL
#endif
......@@ -11,6 +11,10 @@
#include "net.h"
#include "types.h"
#ifdef GIT_SSH
#include <libssh2.h>
#endif
/**
* @file git2/transport.h
* @brief Git transport interfaces and functions
......@@ -27,6 +31,8 @@ GIT_BEGIN_DECL
typedef enum {
/* git_cred_userpass_plaintext */
GIT_CREDTYPE_USERPASS_PLAINTEXT = 1,
GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE = 2,
GIT_CREDTYPE_SSH_PUBLICKEY = 3,
} git_credtype_t;
/* The base structure for all credential types */
......@@ -43,6 +49,27 @@ typedef struct git_cred_userpass_plaintext {
char *password;
} git_cred_userpass_plaintext;
#ifdef GIT_SSH
typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback));
/* A ssh key file and passphrase */
typedef struct git_cred_ssh_keyfile_passphrase {
git_cred parent;
char *publickey;
char *privatekey;
char *passphrase;
} git_cred_ssh_keyfile_passphrase;
/* A ssh public key and authentication callback */
typedef struct git_cred_ssh_publickey {
git_cred parent;
char *publickey;
size_t publickey_len;
void *sign_callback;
void *sign_data;
} git_cred_ssh_publickey;
#endif
/**
* Creates a new plain-text username and password credential object.
* The supplied credential parameter will be internally duplicated.
......@@ -57,6 +84,42 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new(
const char *username,
const char *password);
#ifdef GIT_SSH
/**
* Creates a new ssh key file and passphrase credential object.
* The supplied credential parameter will be internally duplicated.
*
* @param out The newly created credential object.
* @param publickey The path to the public key of the credential.
* @param privatekey The path to the private key of the credential.
* @param passphrase The passphrase of the credential.
* @return 0 for success or an error code for failure
*/
GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new(
git_cred **out,
const char *publickey,
const char *privatekey,
const char *passphrase);
/**
* Creates a new ssh public key credential object.
* The supplied credential parameter will be internally duplicated.
*
* @param out The newly created credential object.
* @param publickey The bytes of the public key.
* @param publickey_len The length of the public key in bytes.
* @param sign_callback The callback method for authenticating.
* @param sign_data The abstract data sent to the sign_callback method.
* @return 0 for success or an error code for failure
*/
GIT_EXTERN(int) git_cred_ssh_publickey_new(
git_cred **out,
const char *publickey,
size_t publickey_len,
git_cred_sign_callback,
void *sign_data);
#endif
/**
* Signature of a function which acquires a credential object.
*
......@@ -319,6 +382,17 @@ GIT_EXTERN(int) git_smart_subtransport_git(
git_smart_subtransport **out,
git_transport* owner);
/**
* Create an instance of the ssh subtransport.
*
* @param out The newly created subtransport
* @param owner The smart transport to own this subtransport
* @return 0 or an error code
*/
GIT_EXTERN(int) git_smart_subtransport_ssh(
git_smart_subtransport **out,
git_transport* owner);
/*
*** End interface for subtransports for the smart transport ***
*/
......
......@@ -29,11 +29,8 @@ GIT_BEGIN_DECL
* @param id Identity of the tree to locate.
* @return 0 or an error code
*/
GIT_INLINE(int) git_tree_lookup(
git_tree **out, git_repository *repo, const git_oid *id)
{
return git_object_lookup((git_object **)out, repo, id, GIT_OBJ_TREE);
}
GIT_EXTERN(int) git_tree_lookup(
git_tree **out, git_repository *repo, const git_oid *id);
/**
* Lookup a tree object from the repository,
......@@ -41,21 +38,17 @@ GIT_INLINE(int) git_tree_lookup(
*
* @see git_object_lookup_prefix
*
* @param tree pointer to the looked up tree
* @param out pointer to the looked up tree
* @param repo the repo to use when locating the tree.
* @param id identity of the tree to locate.
* @param len the length of the short identifier
* @return 0 or an error code
*/
GIT_INLINE(int) git_tree_lookup_prefix(
GIT_EXTERN(int) git_tree_lookup_prefix(
git_tree **out,
git_repository *repo,
const git_oid *id,
size_t len)
{
return git_object_lookup_prefix(
(git_object **)out, repo, id, len, GIT_OBJ_TREE);
}
size_t len);
/**
* Close an open tree
......@@ -67,10 +60,7 @@ GIT_INLINE(int) git_tree_lookup_prefix(
*
* @param tree The tree to close
*/
GIT_INLINE(void) git_tree_free(git_tree *tree)
{
git_object_free((git_object *)tree);
}
GIT_EXTERN(void) git_tree_free(git_tree *tree);
/**
* Get the id of a tree.
......@@ -107,7 +97,7 @@ GIT_EXTERN(size_t) git_tree_entrycount(const git_tree *tree);
* @return the tree entry; NULL if not found
*/
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(
git_tree *tree, const char *filename);
const git_tree *tree, const char *filename);
/**
* Lookup a tree entry by its position in the tree
......@@ -120,7 +110,7 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(
* @return the tree entry; NULL if not found
*/
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(
git_tree *tree, size_t idx);
const git_tree *tree, size_t idx);
/**
* Lookup a tree entry by SHA value.
......@@ -146,12 +136,12 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid(
*
* @param out Pointer where to store the tree entry
* @param root Previously loaded tree which is the root of the relative path
* @param subtree_path Path to the contained entry
* @param path Path to the contained entry
* @return 0 on success; GIT_ENOTFOUND if the path does not exist
*/
GIT_EXTERN(int) git_tree_entry_bypath(
git_tree_entry **out,
git_tree *root,
const git_tree *root,
const char *path);
/**
......@@ -222,7 +212,7 @@ GIT_EXTERN(int) git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entr
*
* You must call `git_object_free()` on the object when you are done with it.
*
* @param object pointer to the converted object
* @param object_out pointer to the converted object
* @param repo repository where to lookup the pointed object
* @param entry a tree entry
* @return 0 or an error code
......@@ -261,7 +251,7 @@ GIT_EXTERN(void) git_treebuilder_clear(git_treebuilder *bld);
/**
* Get the number of entries listed in a treebuilder
*
* @param tree a previously loaded treebuilder.
* @param bld a previously loaded treebuilder.
* @return the number of entries in the treebuilder
*/
GIT_EXTERN(unsigned int) git_treebuilder_entrycount(git_treebuilder *bld);
......
......@@ -131,6 +131,9 @@ typedef struct git_treebuilder git_treebuilder;
/** Memory representation of an index file. */
typedef struct git_index git_index;
/** An interator for conflicts in the index. */
typedef struct git_index_conflict_iterator git_index_conflict_iterator;
/** Memory representation of a set of config files */
typedef struct git_config git_config;
......@@ -165,6 +168,16 @@ typedef struct git_signature {
/** In-memory representation of a reference. */
typedef struct git_reference git_reference;
/** Iterator for references */
typedef struct git_reference_iterator git_reference_iterator;
/** Merge heads, the input to merge */
typedef struct git_merge_head git_merge_head;
/** Representation of a status collection */
typedef struct git_status_list git_status_list;
/** Basic type of any Git reference. */
typedef enum {
GIT_REF_INVALID = 0, /** Invalid reference */
......@@ -196,6 +209,26 @@ typedef struct git_push git_push;
typedef struct git_remote_head git_remote_head;
typedef struct git_remote_callbacks git_remote_callbacks;
/**
* This is passed as the first argument to the callback to allow the
* user to see the progress.
*/
typedef struct git_transfer_progress {
unsigned int total_objects;
unsigned int indexed_objects;
unsigned int received_objects;
size_t received_bytes;
} git_transfer_progress;
/**
* Type for progress callbacks during indexing. Return a value less than zero
* to cancel the transfer.
*
* @param stats Structure containing information about the state of the transfer
* @param payload Payload provided by caller
*/
typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload);
/** @} */
GIT_END_DECL
......
......@@ -7,9 +7,9 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.18.0"
#define LIBGIT2_VERSION "0.19.0"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 18
#define LIBGIT2_VER_MINOR 19
#define LIBGIT2_VER_REVISION 0
#endif
/*
* 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_array_h__
#define INCLUDE_array_h__
#include "util.h"
/*
* Use this to declare a typesafe resizable array of items, a la:
*
* git_array_t(int) my_ints = GIT_ARRAY_INIT;
* ...
* int *i = git_array_alloc(my_ints);
* GITERR_CHECK_ALLOC(i);
* ...
* git_array_clear(my_ints);
*
* You may also want to do things like:
*
* typedef git_array_t(my_struct) my_struct_array_t;
*/
#define git_array_t(type) struct { type *ptr; uint32_t size, asize; }
#define GIT_ARRAY_INIT { NULL, 0, 0 }
#define git_array_init(a) \
do { (a).size = (a).asize = 0; (a).ptr = NULL; } while (0)
#define git_array_clear(a) \
do { git__free((a).ptr); git_array_init(a); } while (0)
#define GITERR_CHECK_ARRAY(a) GITERR_CHECK_ALLOC((a).ptr)
typedef git_array_t(void) git_array_generic_t;
/* use a generic array for growth so this can return the new item */
GIT_INLINE(void *) git_array_grow(git_array_generic_t *a, size_t item_size)
{
uint32_t new_size = (a->size < 8) ? 8 : a->asize * 3 / 2;
void *new_array = git__realloc(a->ptr, new_size * item_size);
if (!new_array) {
git_array_clear(*a);
return NULL;
} else {
a->ptr = new_array; a->asize = new_size; a->size++;
return (((char *)a->ptr) + (a->size - 1) * item_size);
}
}
#define git_array_alloc(a) \
((a).size >= (a).asize) ? \
git_array_grow((git_array_generic_t *)&(a), sizeof(*(a).ptr)) : \
(a).ptr ? &(a).ptr[(a).size++] : NULL
#define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL)
#define git_array_get(a, i) (((i) < (a).size) ? &(a).ptr[(i)] : NULL)
#define git_array_size(a) (a).size
#endif
......@@ -36,7 +36,7 @@ static int collect_attr_files(
int git_attr_get(
const char **value,
git_repository *repo,
git_repository *repo,
uint32_t flags,
const char *pathname,
const char *name)
......@@ -88,10 +88,10 @@ typedef struct {
int git_attr_get_many(
const char **values,
git_repository *repo,
git_repository *repo,
uint32_t flags,
const char *pathname,
size_t num_attr,
size_t num_attr,
const char **names)
{
int error;
......@@ -151,7 +151,7 @@ cleanup:
int git_attr_foreach(
git_repository *repo,
git_repository *repo,
uint32_t flags,
const char *pathname,
int (*callback)(const char *name, const char *value, void *payload),
......@@ -312,7 +312,7 @@ static int load_attr_blob_from_index(
entry = git_index_get_byindex(index, pos);
if (old_oid && git_oid_cmp(old_oid, &entry->oid) == 0)
if (old_oid && git_oid__cmp(old_oid, &entry->oid) == 0)
return GIT_ENOTFOUND;
if ((error = git_blob_lookup(blob, repo, &entry->oid)) < 0)
......@@ -596,26 +596,33 @@ static int collect_attr_files(
}
static int attr_cache__lookup_path(
const char **out, git_config *cfg, const char *key, const char *fallback)
char **out, git_config *cfg, const char *key, const char *fallback)
{
git_buf buf = GIT_BUF_INIT;
int error;
const char *cfgval = NULL;
if (!(error = git_config_get_string(out, cfg, key)))
return 0;
*out = NULL;
if (!(error = git_config_get_string(&cfgval, cfg, key))) {
if (error == GIT_ENOTFOUND) {
/* expand leading ~/ as needed */
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' &&
!git_futils_find_global_file(&buf, &cfgval[2]))
*out = git_buf_detach(&buf);
else if (cfgval)
*out = git__strdup(cfgval);
} else if (error == GIT_ENOTFOUND) {
giterr_clear();
error = 0;
if (!git_futils_find_xdg_file(&buf, fallback))
*out = git_buf_detach(&buf);
else
*out = NULL;
git_buf_free(&buf);
}
git_buf_free(&buf);
return error;
}
......@@ -696,6 +703,12 @@ void git_attr_cache_flush(
git_pool_clear(&cache->pool);
git__free(cache->cfg_attr_file);
cache->cfg_attr_file = NULL;
git__free(cache->cfg_excl_file);
cache->cfg_excl_file = NULL;
cache->initialized = 0;
}
......
......@@ -397,7 +397,8 @@ int git_attr_fnmatch__parse(
*base = scan;
spec->length = scan - pattern;
if ((spec->length = scan - pattern) == 0)
return GIT_ENOTFOUND;
if (pattern[spec->length - 1] == '/') {
spec->length--;
......@@ -497,7 +498,7 @@ int git_attr_assignment__parse(
assert(assigns && !assigns->length);
assigns->_cmp = sort_by_hash_and_name;
git_vector_set_cmp(assigns, sort_by_hash_and_name);
while (*scan && *scan != '\n') {
const char *name_start, *value_start;
......
......@@ -47,14 +47,14 @@ typedef struct {
typedef struct {
git_refcount unused;
const char *name;
uint32_t name_hash;
uint32_t name_hash;
} git_attr_name;
typedef struct {
git_refcount rc; /* for macros */
char *name;
uint32_t name_hash;
const char *value;
uint32_t name_hash;
const char *value;
} git_attr_assignment;
typedef struct {
......
......@@ -13,10 +13,10 @@
typedef struct {
int initialized;
git_pool pool;
git_strmap *files; /* hash path to git_attr_file of rules */
git_strmap *macros; /* hash name to vector<git_attr_assignment> */
const char *cfg_attr_file; /* cached value of core.attributesfile */
const char *cfg_excl_file; /* cached value of core.excludesfile */
git_strmap *files; /* hash path to git_attr_file of rules */
git_strmap *macros; /* hash name to vector<git_attr_assignment> */
char *cfg_attr_file; /* cached value of core.attributesfile */
char *cfg_excl_file; /* cached value of core.excludesfile */
} git_attr_cache;
extern int git_attr_cache__init(git_repository *repo);
......
......@@ -8,8 +8,10 @@
#include "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/odb_backend.h"
#include "common.h"
#include "filebuf.h"
#include "blob.h"
#include "filter.h"
#include "buf_text.h"
......@@ -17,32 +19,34 @@
const void *git_blob_rawcontent(const git_blob *blob)
{
assert(blob);
return blob->odb_object->raw.data;
return git_odb_object_data(blob->odb_object);
}
git_off_t git_blob_rawsize(const git_blob *blob)
{
assert(blob);
return (git_off_t)blob->odb_object->raw.len;
return (git_off_t)git_odb_object_size(blob->odb_object);
}
int git_blob__getbuf(git_buf *buffer, git_blob *blob)
{
return git_buf_set(
buffer, blob->odb_object->raw.data, blob->odb_object->raw.len);
buffer,
git_odb_object_data(blob->odb_object),
git_odb_object_size(blob->odb_object));
}
void git_blob__free(git_blob *blob)
void git_blob__free(void *blob)
{
git_odb_object_free(blob->odb_object);
git_odb_object_free(((git_blob *)blob)->odb_object);
git__free(blob);
}
int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
int git_blob__parse(void *blob, git_odb_object *odb_obj)
{
assert(blob);
git_cached_obj_incref((git_cached_obj *)odb_obj);
blob->odb_object = odb_obj;
((git_blob *)blob)->odb_object = odb_obj;
return 0;
}
......@@ -314,8 +318,8 @@ int git_blob_is_binary(git_blob *blob)
assert(blob);
content.ptr = blob->odb_object->raw.data;
content.size = min(blob->odb_object->raw.len, 4000);
content.ptr = blob->odb_object->buffer;
content.size = min(blob->odb_object->cached.size, 4000);
return git_buf_text_is_binary(&content);
}
......@@ -17,8 +17,8 @@ struct git_blob {
git_odb_object *odb_object;
};
void git_blob__free(git_blob *blob);
int git_blob__parse(git_blob *blob, git_odb_object *obj);
void git_blob__free(void *blob);
int git_blob__parse(void *blob, git_odb_object *obj);
int git_blob__getbuf(git_buf *buffer, git_blob *blob);
#endif
......@@ -11,6 +11,7 @@
#include "config.h"
#include "refspec.h"
#include "refs.h"
#include "remote.h"
#include "git2/branch.h"
......@@ -123,40 +124,48 @@ on_error:
return error;
}
typedef struct {
git_branch_foreach_cb branch_cb;
void *callback_payload;
unsigned int branch_type;
} branch_foreach_filter;
static int branch_foreach_cb(const char *branch_name, void *payload)
{
branch_foreach_filter *filter = (branch_foreach_filter *)payload;
if (filter->branch_type & GIT_BRANCH_LOCAL &&
git__prefixcmp(branch_name, GIT_REFS_HEADS_DIR) == 0)
return filter->branch_cb(branch_name + strlen(GIT_REFS_HEADS_DIR), GIT_BRANCH_LOCAL, filter->callback_payload);
if (filter->branch_type & GIT_BRANCH_REMOTE &&
git__prefixcmp(branch_name, GIT_REFS_REMOTES_DIR) == 0)
return filter->branch_cb(branch_name + strlen(GIT_REFS_REMOTES_DIR), GIT_BRANCH_REMOTE, filter->callback_payload);
return 0;
}
int git_branch_foreach(
git_repository *repo,
unsigned int list_flags,
git_branch_foreach_cb branch_cb,
git_branch_foreach_cb callback,
void *payload)
{
branch_foreach_filter filter;
git_reference_iterator *iter;
git_reference *ref;
int error = 0;
if (git_reference_iterator_new(&iter, repo) < 0)
return -1;
while ((error = git_reference_next(&ref, iter)) == 0) {
if (list_flags & GIT_BRANCH_LOCAL &&
git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0) {
if (callback(ref->name + strlen(GIT_REFS_HEADS_DIR),
GIT_BRANCH_LOCAL, payload)) {
error = GIT_EUSER;
}
}
if (list_flags & GIT_BRANCH_REMOTE &&
git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) == 0) {
if (callback(ref->name + strlen(GIT_REFS_REMOTES_DIR),
GIT_BRANCH_REMOTE, payload)) {
error = GIT_EUSER;
}
}
git_reference_free(ref);
filter.branch_cb = branch_cb;
filter.branch_type = list_flags;
filter.callback_payload = payload;
/* check if the callback has cancelled iteration */
if (error == GIT_EUSER)
break;
}
if (error == GIT_ITEROVER)
error = 0;
return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
git_reference_iterator_free(iter);
return error;
}
int git_branch_move(
......@@ -175,18 +184,21 @@ int git_branch_move(
if (!git_reference_is_branch(branch))
return not_a_local_branch(git_reference_name(branch));
if ((error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name)) < 0 ||
(error = git_buf_printf(&old_config_section, "branch.%s", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR))) < 0 ||
(error = git_buf_printf(&new_config_section, "branch.%s", new_branch_name)) < 0)
error = git_buf_joinpath(&new_reference_name, GIT_REFS_HEADS_DIR, new_branch_name);
if (error < 0)
goto done;
git_buf_printf(&old_config_section,
"branch.%s", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
git_buf_printf(&new_config_section, "branch.%s", new_branch_name);
if ((error = git_config_rename_section(git_reference_owner(branch),
git_buf_cstr(&old_config_section),
git_buf_cstr(&new_config_section))) < 0)
goto done;
if ((error = git_reference_rename(out, branch, git_buf_cstr(&new_reference_name), force)) < 0)
goto done;
error = git_reference_rename(out, branch, git_buf_cstr(&new_reference_name), force);
done:
git_buf_free(&new_reference_name);
......@@ -275,6 +287,8 @@ int git_branch_upstream__name(
goto cleanup;
if (!*remote_name || !*merge_name) {
giterr_set(GITERR_REFERENCE,
"branch '%s' does not have an upstream", canonical_branch_name);
error = GIT_ENOTFOUND;
goto cleanup;
}
......@@ -283,12 +297,10 @@ int git_branch_upstream__name(
if ((error = git_remote_load(&remote, repo, remote_name)) < 0)
goto cleanup;
refspec = git_remote_fetchspec(remote);
if (refspec == NULL
|| refspec->src == NULL
|| refspec->dst == NULL) {
error = GIT_ENOTFOUND;
goto cleanup;
refspec = git_remote__matching_refspec(remote, merge_name);
if (!refspec) {
error = GIT_ENOTFOUND;
goto cleanup;
}
if (git_refspec_transform_r(&buf, refspec, merge_name) < 0)
......@@ -333,11 +345,8 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
if ((error = git_remote_load(&remote, repo, remote_list.strings[i])) < 0)
continue;
fetchspec = git_remote_fetchspec(remote);
/* Defensivly check that we have a fetchspec */
if (fetchspec &&
git_refspec_dst_matches(fetchspec, canonical_branch_name)) {
fetchspec = git_remote__matching_dst_refspec(remote, canonical_branch_name);
if (fetchspec) {
/* If we have not already set out yet, then set
* it to the matching remote name. Otherwise
* multiple remotes match this reference, and it
......@@ -346,6 +355,9 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
remote_name = remote_list.strings[i];
} else {
git_remote_free(remote);
giterr_set(GITERR_REFERENCE,
"Reference '%s' is ambiguous", canonical_branch_name);
error = GIT_EAMBIGUOUS;
goto cleanup;
}
......@@ -358,6 +370,8 @@ static int remote_name(git_buf *buf, git_repository *repo, const char *canonical
git_buf_clear(buf);
error = git_buf_puts(buf, remote_name);
} else {
giterr_set(GITERR_REFERENCE,
"Could not determine remote for '%s'", canonical_branch_name);
error = GIT_ENOTFOUND;
}
......@@ -377,7 +391,7 @@ int git_branch_remote_name(char *buffer, size_t buffer_len, git_repository *repo
if (buffer)
git_buf_copy_cstr(buffer, buffer_len, &buf);
ret = git_buf_len(&buf) + 1;
ret = (int)git_buf_len(&buf) + 1;
git_buf_free(&buf);
return ret;
......@@ -494,8 +508,11 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
local = 1;
else if (git_branch_lookup(&upstream, repo, upstream_name, GIT_BRANCH_REMOTE) == 0)
local = 0;
else
else {
giterr_set(GITERR_REFERENCE,
"Cannot set upstream for branch '%s'", shortname);
return GIT_ENOTFOUND;
}
/*
* If it's local, the remote is "." and the branch name is
......@@ -515,16 +532,17 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name)
goto on_error;
if (local) {
if (git_buf_puts(&value, git_reference_name(branch)) < 0)
git_buf_clear(&value);
if (git_buf_puts(&value, git_reference_name(upstream)) < 0)
goto on_error;
} else {
/* Get the remoe-tracking branch's refname in its repo */
if (git_remote_load(&remote, repo, git_buf_cstr(&value)) < 0)
goto on_error;
fetchspec = git_remote_fetchspec(remote);
fetchspec = git_remote__matching_dst_refspec(remote, git_reference_name(upstream));
git_buf_clear(&value);
if (git_refspec_transform_l(&value, fetchspec, git_reference_name(upstream)) < 0)
if (!fetchspec || git_refspec_transform_l(&value, fetchspec, git_reference_name(upstream)) < 0)
goto on_error;
git_remote_free(remote);
......
......@@ -11,100 +11,270 @@
#include "thread-utils.h"
#include "util.h"
#include "cache.h"
#include "odb.h"
#include "object.h"
#include "git2/oid.h"
int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
GIT__USE_OIDMAP
bool git_cache__enabled = true;
ssize_t git_cache__max_storage = (256 * 1024 * 1024);
git_atomic_ssize git_cache__current_storage = {0};
static size_t git_cache__max_object_size[8] = {
0, /* GIT_OBJ__EXT1 */
4096, /* GIT_OBJ_COMMIT */
4096, /* GIT_OBJ_TREE */
0, /* GIT_OBJ_BLOB */
4096, /* GIT_OBJ_TAG */
0, /* GIT_OBJ__EXT2 */
0, /* GIT_OBJ_OFS_DELTA */
0 /* GIT_OBJ_REF_DELTA */
};
int git_cache_set_max_object_size(git_otype type, size_t size)
{
if (type < 0 || (size_t)type >= ARRAY_SIZE(git_cache__max_object_size)) {
giterr_set(GITERR_INVALID, "type out of range");
return -1;
}
git_cache__max_object_size[type] = size;
return 0;
}
void git_cache_dump_stats(git_cache *cache)
{
if (size < 8)
size = 8;
size = git__size_t_powerof2(size);
git_cached_obj *object;
cache->size_mask = size - 1;
cache->lru_count = 0;
cache->free_obj = free_ptr;
if (kh_size(cache->map) == 0)
return;
git_mutex_init(&cache->lock);
printf("Cache %p: %d items cached, %d bytes\n",
cache, kh_size(cache->map), (int)cache->used_memory);
cache->nodes = git__malloc(size * sizeof(git_cached_obj *));
GITERR_CHECK_ALLOC(cache->nodes);
kh_foreach_value(cache->map, object, {
char oid_str[9];
printf(" %s%c %s (%d)\n",
git_object_type2string(object->type),
object->flags == GIT_CACHE_STORE_PARSED ? '*' : ' ',
git_oid_tostr(oid_str, sizeof(oid_str), &object->oid),
(int)object->size
);
});
}
memset(cache->nodes, 0x0, size * sizeof(git_cached_obj *));
int git_cache_init(git_cache *cache)
{
memset(cache, 0, sizeof(*cache));
cache->map = git_oidmap_alloc();
if (git_mutex_init(&cache->lock)) {
giterr_set(GITERR_OS, "Failed to initialize cache mutex");
return -1;
}
return 0;
}
/* called with lock */
static void clear_cache(git_cache *cache)
{
git_cached_obj *evict = NULL;
if (kh_size(cache->map) == 0)
return;
kh_foreach_value(cache->map, evict, {
git_cached_obj_decref(evict);
});
kh_clear(oid, cache->map);
git_atomic_ssize_add(&git_cache__current_storage, -cache->used_memory);
cache->used_memory = 0;
}
void git_cache_clear(git_cache *cache)
{
if (git_mutex_lock(&cache->lock) < 0)
return;
clear_cache(cache);
git_mutex_unlock(&cache->lock);
}
void git_cache_free(git_cache *cache)
{
size_t i;
git_cache_clear(cache);
git_oidmap_free(cache->map);
git_mutex_free(&cache->lock);
git__memzero(cache, sizeof(*cache));
}
/* Called with lock */
static void cache_evict_entries(git_cache *cache)
{
uint32_t seed = rand();
size_t evict_count = 8;
ssize_t evicted_memory = 0;
for (i = 0; i < (cache->size_mask + 1); ++i) {
if (cache->nodes[i] != NULL)
git_cached_obj_decref(cache->nodes[i], cache->free_obj);
/* do not infinite loop if there's not enough entries to evict */
if (evict_count > kh_size(cache->map)) {
clear_cache(cache);
return;
}
git_mutex_free(&cache->lock);
git__free(cache->nodes);
while (evict_count > 0) {
khiter_t pos = seed++ % kh_end(cache->map);
if (kh_exist(cache->map, pos)) {
git_cached_obj *evict = kh_val(cache->map, pos);
evict_count--;
evicted_memory += evict->size;
git_cached_obj_decref(evict);
kh_del(oid, cache->map, pos);
}
}
cache->used_memory -= evicted_memory;
git_atomic_ssize_add(&git_cache__current_storage, -evicted_memory);
}
void *git_cache_get(git_cache *cache, const git_oid *oid)
static bool cache_should_store(git_otype object_type, size_t object_size)
{
uint32_t hash;
git_cached_obj *node = NULL, *result = NULL;
size_t max_size = git_cache__max_object_size[object_type];
return git_cache__enabled && object_size < max_size;
}
memcpy(&hash, oid->id, sizeof(hash));
static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
{
khiter_t pos;
git_cached_obj *entry = NULL;
if (git_mutex_lock(&cache->lock)) {
giterr_set(GITERR_THREAD, "unable to lock cache mutex");
if (!git_cache__enabled || git_mutex_lock(&cache->lock) < 0)
return NULL;
}
{
node = cache->nodes[hash & cache->size_mask];
pos = kh_get(oid, cache->map, oid);
if (pos != kh_end(cache->map)) {
entry = kh_val(cache->map, pos);
if (node != NULL && git_oid_cmp(&node->oid, oid) == 0) {
git_cached_obj_incref(node);
result = node;
if (flags && entry->flags != flags) {
entry = NULL;
} else {
git_cached_obj_incref(entry);
}
}
git_mutex_unlock(&cache->lock);
return result;
return entry;
}
void *git_cache_try_store(git_cache *cache, void *_entry)
static void *cache_store(git_cache *cache, git_cached_obj *entry)
{
git_cached_obj *entry = _entry;
uint32_t hash;
khiter_t pos;
memcpy(&hash, &entry->oid, sizeof(uint32_t));
git_cached_obj_incref(entry);
if (git_mutex_lock(&cache->lock)) {
giterr_set(GITERR_THREAD, "unable to lock cache mutex");
return NULL;
if (!git_cache__enabled && cache->used_memory > 0) {
git_cache_clear(cache);
return entry;
}
{
git_cached_obj *node = cache->nodes[hash & cache->size_mask];
if (!cache_should_store(entry->type, entry->size))
return entry;
/* increase the refcount on this object, because
* the cache now owns it */
git_cached_obj_incref(entry);
if (git_mutex_lock(&cache->lock) < 0)
return entry;
if (node == NULL) {
cache->nodes[hash & cache->size_mask] = entry;
} else if (git_oid_cmp(&node->oid, &entry->oid) == 0) {
git_cached_obj_decref(entry, cache->free_obj);
entry = node;
} else {
git_cached_obj_decref(node, cache->free_obj);
cache->nodes[hash & cache->size_mask] = entry;
/* soften the load on the cache */
if (git_cache__current_storage.val > git_cache__max_storage)
cache_evict_entries(cache);
pos = kh_get(oid, cache->map, &entry->oid);
/* not found */
if (pos == kh_end(cache->map)) {
int rval;
pos = kh_put(oid, cache->map, &entry->oid, &rval);
if (rval >= 0) {
kh_key(cache->map, pos) = &entry->oid;
kh_val(cache->map, pos) = entry;
git_cached_obj_incref(entry);
cache->used_memory += entry->size;
git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size);
}
}
/* found */
else {
git_cached_obj *stored_entry = kh_val(cache->map, pos);
/* increase the refcount again, because we are
* returning it to the user */
git_cached_obj_incref(entry);
if (stored_entry->flags == entry->flags) {
git_cached_obj_decref(entry);
git_cached_obj_incref(stored_entry);
entry = stored_entry;
} else if (stored_entry->flags == GIT_CACHE_STORE_RAW &&
entry->flags == GIT_CACHE_STORE_PARSED) {
git_cached_obj_decref(stored_entry);
git_cached_obj_incref(entry);
kh_key(cache->map, pos) = &entry->oid;
kh_val(cache->map, pos) = entry;
} else {
/* NO OP */
}
}
git_mutex_unlock(&cache->lock);
git_mutex_unlock(&cache->lock);
return entry;
}
void *git_cache_store_raw(git_cache *cache, git_odb_object *entry)
{
entry->cached.flags = GIT_CACHE_STORE_RAW;
return cache_store(cache, (git_cached_obj *)entry);
}
void *git_cache_store_parsed(git_cache *cache, git_object *entry)
{
entry->cached.flags = GIT_CACHE_STORE_PARSED;
return cache_store(cache, (git_cached_obj *)entry);
}
git_odb_object *git_cache_get_raw(git_cache *cache, const git_oid *oid)
{
return cache_get(cache, oid, GIT_CACHE_STORE_RAW);
}
git_object *git_cache_get_parsed(git_cache *cache, const git_oid *oid)
{
return cache_get(cache, oid, GIT_CACHE_STORE_PARSED);
}
void *git_cache_get_any(git_cache *cache, const git_oid *oid)
{
return cache_get(cache, oid, GIT_CACHE_STORE_ANY);
}
void git_cached_obj_decref(void *_obj)
{
git_cached_obj *obj = _obj;
if (git_atomic_dec(&obj->refcount) == 0) {
switch (obj->flags) {
case GIT_CACHE_STORE_RAW:
git_odb_object__free(_obj);
break;
case GIT_CACHE_STORE_PARSED:
git_object__free(_obj);
break;
default:
git__free(_obj);
break;
}
}
}
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